The two U-type instructions introduced here operate on the program counter (PC) rather than the general-purpose registers (x0-x31), and are represented by the AUIPC opcode.
Figure 1 shows the machine code formats of LUI and AUIPC, and comparing them with the machine code of the I-type instructions, it can be seen that the U-type instructions do not have rs1 and funct3 fields, but instead have a 20-bit immediate value (including the 12-bit immediate value in the I-type instructions).
Note that the opcode of U-type instructions is different from that of I-type instructions. Like the I-type instructions, the immediate value in U-type instructions is fixed at 20 bits and is named U-immediate[31:12], as shown in Figure 1.
1. LUI
Load Upper Immediate
Instruction Format:
LUI rd,immediate。x[rd] = sext(immediate[31:12] << 12)
The machine code for LUI is shown in Figure 2, with opcode 011_0111. This instruction writes the U-immediate value to the top 20 bits of the rd register, with the lower 12 bits of rd set to zero.
1.1 Example
LUI x8,0xf0000
To load 0xf000_0000 into the x8 register:
- opcode [o-6]: 011_0111
- rd [7-11]: 5’b01000
- immediate[31:12] :1111_0000_0000_0000_0000
- 32 bit machine code: 1111_0000_0000_0000_0000_01000_0110111 ( 32’hF000_0437)
Notice:
- 32′ – 32 bit
- b01000 b – binary
- hF000_0437 h – Hex
2. AUIPC
Add Upper Immediate to PC
Instruction Format:
AUIPC rd,immediate。x[rd] = pc + sext(immediate[31:12] << 12)
The machine code for AUIPC is shown in Figure 3, with opcode 001_0111. This instruction sign-extends the 20-bit immediate value, left-shifts it by 12 bits, adds it to the current PC value, and writes the result to the rd register.
2.1 Example
AUIPC x12,0xf00
To add 0xf0_0000 to the current PC and load the result into the x12 register
- The instruction opcode for AUIPC is
0x17
(binary:0010111
). - The destination register is
x12
, encoded asrd=0x0C
(binary:01100
). - The immediate value is
0xF0
, which is sign-extended to fill bits 31:12 of the 32-bit immediate field. Therefore,imm[31:12]
is0xFFFFF000
. - When assembled, the immediate field is shifted left by 12 bits to obtain the final immediate value of
0xFFFFF000 << 12
, which is0xFFFFF000_00000000
. - Finally, the bytes are arranged in little-endian order to obtain the 32-bit machine code value
1000_0111_0000_0000_0110_0000_0001_0111
of0x8700_6017
.
Notice:
Most immediates are either very small or require all XLEN bits. RISC-V has chosen asymmetric immediate encoding (12 bits for regular instructions, plus 20 bits for special “upward” instructions like LUI) to increase the opcode space available for regular instructions.
The combination of the 12-bit immediate in AUIPC and JALR (which we will cover in a subsequent article) can be used to transfer control to any 32-bit PC-relative address, while AUIPC added to the 12-bit immediate offset in a regular load or store instruction can access any 32-bit PC-relative data address.
The current PC can be obtained by setting the U-immediate of AUIPC to 0.