RISC-V Calling Convention

In RISC-V, there are some rules which the programmer is advised to follow. The following are rules for callee-saved registers (registers saved by the function being called):

  1. The register x2 is reserved as a “stack pointer” (sp), and points to the bottom of the stack. Data above x2 is (technically) immutable, and x2 can be decremented during a function call to allocate more space on the stack if its value is returned back to its pre-function call value after the call.

  2. The registers s0 to s11 are “saved” registers, meaning that just as x2, they need to be restored at the end of the function call. We can do so using sw s0 0(sp) in the beginning of the function, and lw s0 0(sp) towards the end.

The following are caller-saved registers (saved and restored by the function that is calling):

  1. The register x1 (aka ra) is reserved as the register to store return addresses in . There are two pseudoinstructions, jal label and ret (ja label), which assume x1 as the return address.
  2. The registers a0 to a7 are registers used for function arguments, and a0 and a1 can alsobe used for return values.
  3. If a function needs more than 8 arguments, the temporary registers t0 to t6 can be used as addresses.

The following are miscellaneous registers:

  1. The register x0 always stores 0/0x0.
  2. The register x3 is the “global pointer”, used to store a reference on the heap.
  3. The register x4 is the “thread pointer,” used to separate stacks for threads.

Examples

Callee-Saved Registers

Caller-Saved Registers