Project F

RISC-V Assembler: Logical

Published · Updated

In this post we look at RISC-V logical instructions, such as and and xori. These instructions are included in RV32I, the base integer instruction set. New to the assembler series? Check out the first part on RISC-V arithmetic instructions.

In the last few years, we’ve seen an explosion of RISC-V CPU designs, especially on FPGA. Thankfully, RISC-V is ideal for assembly programming with its compact, easy-to-learn instruction set. This series will help you learn and understand 32-bit RISC-V instructions (RV32) and the RISC-V ABI.

Share your thoughts with @WillFlux on Mastodon or Twitter. If you like what I do, sponsor me. 🙏

AND

The and and andi instructions perform logical AND on individual bits (bitwise). The “and” instructions are commonly used to mask parts of a register. Immediates are sign extended, see arithmetic sign extension for details.

and  rd, rs1, rs2  # rd = rs1 AND rs2
andi rd, rs, imm   # rd = rs AND imm

These examples select the 4 least significant bits from the register t0:

li   t0, 42       # t0 = 42 (0...101010)
li   t1, 15       # t1 = 15 (0...001111)

and  t2, t0, t1   # t2 = 42 (0...101010) AND 15 (0...001111) = 10 (0...001010)
andi t3, t0, 15   # t3 = 42 (0...101010) AND 15 (0...001111) = 10 (0...001010)

Binary values are in brackets with ... indicating many identical bits.

OR

The or and ori instructions perform logical OR on individual bits.

or  rd, rs1, rs2  # rd = rs1 OR rs2
ori rd, rs, imm   # rd = rs OR imm

Examples:

li   t0, 42      # t0 = 42 (0...101010)
li   t1, 15      # t1 = 15 (0...001111)

or   t2, t0, t1  # t2 = 42 (0...101010) OR 15 (0...001111) = 47 (0...101111)
ori  t3, t0, 15  # t3 = 42 (0...101010) OR 15 (0...001111) = 47 (0...101111)

XOR

The xor and xori instructions perform logical XOR (exclusive OR) on individual bits.

xor  rd, rs1, rs2  # rd = rs1 XOR rs2
xori rd, rs, imm   # rd = rs XOR imm

Examples:

li   t0, 42      # t0 = 42 (0...101010)
li   t1, 15      # t1 = 15 (0...001111)

xor  t2, t0, t1  # t2 = 42 (0...101010) XOR 15 (0...001111) = 37 (0...100101)
xori t3, t0, 15  # t3 = 42 (0...101010) XOR 15 (0...001111) = 37 (0...100101)

NOT

The not pseudoinstruction inverts the bits in a register (0 → 1 and 1 → 0). The assembler converts not to an xori instruction (see example below).

not  rd, rs      # rd = NOT rs (pseudoinstruction)

Example:

li   t0, 42      # t0 = 42 (0...101010)

# these two examples generate the same machine code
not  t2, t0      # t2 = NOT (0...101010) = (1...010101)
xori t3, t0, -1  # t3 = (0...101010) XOR (1...111111) = (1...010101)

Notice how -1 is sign extended to 32-bits so all the bits of the immediate are 1.

What’s Next?

If you enjoyed this post, please sponsor me. Sponsors help me create more FPGA and RISC-V projects for everyone, and they get early access to blog posts and source code. 🙏

The next instalment of RISC-V Assembler covers Shift Instructions.

Other parts of this series include: Arithmetic, Load Store, and Branch Set. Or check out all my FPGA & RISC-V Tutorials and my series on early Macintosh History.

References