Watch out for the sign bit ========================== [Written 2019-10-12] In RISC-V, immediate values are usually sign-extended before they are stored in registers or used for some computation. Sign extension means that the highest significant bit in the specified number is repeated to the higher bit positions so that the two's complement value stays the same. Example of two 8-bit values that are sign-extended to 16 bits: 00011001 -> 00000000_00011001 10010111 -> 11111111_10010111 The RISC-V instruction addi is an example that does sign-extension on the 12-bit value imm: addi rd, rs1, imm That makes it possible to add two numbers even if they have a different number of bits (register rs1 is 32 bits on 32-bit RISC-V and imm is 12 bits). The value of imm is sign-extended to 32 bits so it can be added to rs1 and the sum is written to register rd. Something less expected is that sign-extension is used for logic instruction like `andi` and `ori` too. andi rd, rs1, imm ori rd, rs1, imm In both of these instructions imm is 12 bits. Let's look at what happens when imm gets big. Assume rs1 = -1 (32 ones in binary). andi rd, rs1, 0b10_00000000 -> rd = 2^9 andi rd, rs1, 0b100_00000000 -> rd = 2^10 andi rd, rs1, 0b1000_00000000 -> rd = (2^32-1) - (2^11-1) On the last line we do not get 2^11. This happens because in the last line, imm has the most significant of its 12 bits set and that bit is repeated before used with rs1. In other words, the value that is used is in binary 21 ones followed by 11 zeros. This means that if you want to extract one bit from a number and that bit is 2^11, you cannot use addi even if it takes a 12-bit immediate value. You can only use it to extract up to bit 2^10. Assemblers should check this and never accept values larger than 2^11-1 for 12-bit immediates. To use the most significant bit of the 12 bits you should specify a negative value to make it clear that you know what is happening and that it will be sign-extended.