Register Guide

RISC-V s0 / fp / x8 Register: Saved Register and Optional Frame Pointer

s0 is a callee-saved register in the psABI: if a function modifies it, the function must restore it before returning. The psABI also says that if code uses a frame pointer, it must reside in x8, namely s0/fp.

psABI: x8-x9 / s0-s1 are callee-saved registers.
psABI: a frame pointer is optional; if present, it must reside in x8/s0.
Beginner rule: restore s0 after borrowing it; if it is used as fp, do not modify it casually.
Physical Name x8ABI Name s0Save Rule Callee
Role
Saved register / Frame pointer
Convention
Callee-saved
Remember This First
s* registers are callee-saved: if a function borrows them, it must restore them before return.
psABI Reference

Saved register

The psABI marks s0-s11 as preserved across calls. A callee that modifies them must restore their original values before returning; s0 may also serve as the frame pointer.

Preserved across calls: Yes
RISC-V psABI integer register convention
Quick Understanding & Search Notes

s0 / x8 belongs to the s0-s11 saved-register group. The psABI marks it preserved across calls; a callee that modifies it must restore it before returning.

s0-s11 are saved registers preserved across calls.
If a frame pointer exists, the psABI says it must reside in x8/s0.

When It Fits Best

  • - Keep values that still matter after calling another function.
  • - Preserve data that must remain available after nested calls.
  • - s0/fp may also be used as a frame pointer for stable frame access.

When Not To Use It This Way

  • - Do not modify s* and return without restoring it.
  • - Prefer t* for short-lived temporaries instead of occupying s* for brief calculations.

What Happens Around A Call

1

s* registers are callee-saved: if a function borrows them, it must restore them before return.

2

Callers may assume s* remain unchanged after the call returns.

3

Changing s* usually implies save-on-entry and restore-on-exit.

Save And Restore callee-saved Registers On RV64

Examples explain the rule, not a complete program
addi sp, sp, -16
sd   s0, 0(sp)
addi s0, a0, 0
call foo
# s0 still keeps the value needed after the call
ld   s0, 0(sp)
addi sp, sp, 16
ret

FAQ

Why is s0 / x8 suitable for values that survive calls?

s0-s11 are preserved across calls; a callee that modifies them must restore them, so callers can rely on their values after return.

Who restores s0 if a function modifies it?

The callee restores it before returning.