Why is s3 / x19 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.
Callee-saved register 3; must be preserved across function calls.
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.
s3 / x19 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.
s* registers are callee-saved: if a function borrows them, it must restore them before return.
Callers may assume s* remain unchanged after the call returns.
Changing s* usually implies save-on-entry and restore-on-exit.
addi sp, sp, -16
sd s3, 0(sp)
addi s3, a0, 0
call foo
# s3 still keeps the value needed after the call
ld s3, 0(sp)
addi sp, sp, 16
rets0-s11 are preserved across calls; a callee that modifies them must restore them, so callers can rely on their values after return.
The callee restores it before returning.