I���ve been working on supporting RISC-V (RV64I) as a target for the CakeML compiler (https://cakeml.org). To do this I���ve been using a specification written by Prashanth Mundkur at SRI. I discussed one aspect of the architecture with him and he suggested that I share this with the ISA-dev list.
Page 14 of The RISC-V Instruction Set Manual (Volume 1) discusses using AUIPC (with a 20-bit immediate) in combination with a regular load or store (with a 12-bit immediate). The question is whether or not any 32-bit PC-relative data address can be accessed in RV64I? For example, consider the pair of instruction
AUPIC rs, imm20
LB rd, rs, imm12
If X is a 64-bit offset in the (signed) 32-bit range
0xFFFFFFFF80000000 <= X <= 0x7FFFFFFF
then imm12 would be the bottom twelve bits, i.e. imm12 = X<11:0>. The top twenty bits could then be computed as follows
imm20 = (X - SignExtend (imm12))<31:12>
This method works fine when X is in the range
0xFFFFFFFF80000000 <= X <= 0x7FFFF7FF
but fails when X is within the range
0x7FFFF800 <= X <= 0x7FFFFFFF
For example, if we want PC + 0x7FFFF800 then imm12 is 0x800 and imm20 is computed to be 0x80000, which gives us PC - 0x80000800 (which is PC + 0xFFFFFFFF7FFFF800).
This is based on the following instruction semantics:
��� AUPIC is specified as computing the address
PC + SignExtend (imm20 : 0`12) // Pad to the right with zero (12-bits wide) and then sign-extend
��� LB computes the address
GPR(rs) + SignExtend (imm12)
A similar situation seems to arise for LUI and ADDI when trying to construct a 32-bit value. As a workaround I used
LUI rd, ~(X<31:12>) // 1���s complement of top 20 bits
XORI rd, rd, X<11:0> // bottom 12 bits
when imm<11> is ���1���. (Building up large immediate values was easier in ARMv8, since MOVK, MOVN and MOVZ are quite nice to work with.)
Regards,
Anthony
GCC uses LUI+XORI to construct constants like you describe. You could
alternatively use LUI+ADDIW for generating any 32-bit sign-extended
constant, since the ADDIW forces sign-extension from bit 31.