RISC-V has 32 general-purpose integer registers, x0 through x31, 32 floating-point registers, f0 through f31, and a Program Counter, which holds the address of the current instruction and determines where the processor fetches the next instruction.
Cheatsheet
| Register | ABI Name | Use |
|---|---|---|
x0 | zero | Always Zero |
x1 | ra | Return address |
x2 | sp | Stack pointer |
x3 | gp | Global pointer |
x4 | tp | Thread pointer |
x5 | t0 | Temporary / Alternate link register |
x6 - x7 | t1 - t2 | Temporary |
x8 | s0 or fp | Saved register / Frame pointer |
x9 | s1 | Saved register |
x10 - x11 | a0 - a1 | Function argument / Return value |
x12 - x17 | a2 - a7 | Function argument |
x18 - x27 | s2 - s11 | Saved register |
x28 - x31 | t3 - t6 | Temporary |
pc | (none) | Program counter |
f0 - f7 | ft0 - ft7 | Floating-point Temporary |
f8 - f9 | fs0 - fs1 | Floating-point Saved register |
f10 - f11 | fa0 - fa1 | Floating-point Function argument / Return value |
f12 - f17 | fa2 - fa7 | Floating-point Function argument |
f18 - f27 | fs2 - fs11 | Floating-point Saved register |
f28 - f31 | ft8 - ft11 | Floating-point Temporary |
Terminology
Caller-saved
Refers to registers whose values may be changed by a function call. If the caller needs their values after the call, the caller must save them before making the call.
Callee-saved
Refers to registers whose values must be preserved across a function call. The callee may change them during the function, but must save and restore their original values before returning.
Note: Restoring the original value is not enforced by hardware, but failing to do so is considered a bug and an ABI violation.
Zero
This register always carries the value 0. Writes to it are ignored, so its value can never be changed.
Think of it like /dev/zero: it always gives you a zero.
Return address
This register holds the address of the instruction that execution should return to after the called function finishes.
The ret instruction uses the address stored in ra to set pc, continuing execution from that address.
Stack pointer
This register points to the current top of the stack, the lowest-addressed part of the currently allocated stack.
See also: Stack.
Global pointer
This register points to a region in memory containing global/static data, allowing it to be accessed efficiently using offsets.
Thread pointer
This register points to a region in memory containing data specific to the currently running thread.
Temporary
This register is general-purpose and caller-saved. It is used for temporary values.
Its contents are not guaranteed to survive a function call.
Saved register
This register is similar to a temporary register, with the exception that its contents must be preserved across a function call.
Frame pointer
This register points to a fixed location in the current stack frame, providing a stable reference for accessing local variables and other stack data.
Function argument
This register is used to pass function arguments to a callee.
Return value
This register is used by a function to pass its return value back to the caller.
Program counter
This register holds the address of the current instruction and determines where the processor fetches the next instruction.
It cannot be accessed explicitly as a general-purpose register; instructions such as jal or jalr, and conditional branches modify it implicitly.