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

RegisterABI NameUse
x0zeroAlways Zero
x1raReturn address
x2spStack pointer
x3gpGlobal pointer
x4tpThread pointer
x5t0Temporary / Alternate link register
x6 - x7t1 - t2Temporary
x8s0 or fpSaved register / Frame pointer
x9s1Saved register
x10 - x11a0 - a1Function argument / Return value
x12 - x17a2 - a7Function argument
x18 - x27s2 - s11Saved register
x28 - x31t3 - t6Temporary
pc(none)Program counter
f0 - f7ft0 - ft7Floating-point Temporary
f8 - f9fs0 - fs1Floating-point Saved register
f10 - f11fa0 - fa1Floating-point Function argument / Return value
f12 - f17fa2 - fa7Floating-point Function argument
f18 - f27fs2 - fs11Floating-point Saved register
f28 - f31ft8 - ft11Floating-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.