auipc

auipc

RISC-V Assembly Reference

lyszt.net covers auipc and other RISC-V instructions in more detail.

Encoding format

R
31–25funct7
24–20rs2
19–15rs1
14–12funct3
11–7rd
6–0opcode
I
31–20imm[11:0]
19–15rs1
14–12funct3
11–7rd
6–0opcode
S
31–25imm[11:5]
24–20rs2
19–15rs1
14–12funct3
11–7imm[4:0]
6–0opcode
B
31–25imm[12,10:5]
24–20rs2
19–15rs1
14–12funct3
11–7imm[4:1,11]
6–0opcode
U
31–12imm[31:12]
11–7rd
6–0opcode
J
31–12imm[20,10:1,11,19:12]
11–7rd
6–0opcode

Description

auipc stands for add upper immediate to PC. It works like lui, taking a 20-bit constant as the upper part of a value. auipc adds that value to the program counter, which holds the address of the instruction currently running (see the beq page). The result is an address measured relative to where this instruction sits in memory.

Relative addresses solve a real problem. A program does not always know where in memory it will be loaded. Code that refers to its data by fixed absolute addresses fails when it is loaded somewhere else. Code that computes addresses relative to the current instruction works wherever it is placed. This property is called position independence.

auipc supplies the coarse part of such an address, and a following instruction adds the fine 12-bit remainder. The la instruction, which loads the address of a label, is built from this pair, and so are calls to distant functions.

The RISC-V manual says the current pc can be obtained by setting the constant of auipc to 0. An auipc followed by a jalr can transfer control to any 32-bit pc-relative address, and an auipc followed by a load or store with a 12-bit offset can access any 32-bit pc-relative data address.

la and call exist so you do not have to write auipc by hand, and it appears often in the simulator's trace and in disassembled code. An auipc followed by an instruction with a small offset, forming one address together, is a useful pattern to recognize.

Example

auipc t0, 1      # t0 = pc + 0x1000