Is ra / x1 automatically preserved across calls?
No. The psABI marks ra as not preserved across calls; save it explicitly when it must survive a call.
ra is the return-address register in the RISC-V calling convention. JAL or JALR writes the next instruction address to ra when x1 is its destination; the ret pseudoinstruction returns through that address. The psABI marks ra as not preserved across calls.
The psABI names x1 as ra for the return address. It is marked not preserved across calls; code must explicitly save a value that needs to survive a call.
ra / x1 is the psABI return-address register. A call sequence that uses x1 as its link destination writes the next instruction address here; it is not preserved across calls, so a value that must survive a call must be saved explicitly.
jal / jalr write the next instruction address into ra unless rd is something else.
ret expands to jalr x0, 0(ra), so it depends on the address stored in ra.
If the function calls others, saving and restoring ra becomes this function's own responsibility.
addi sp, sp, -16
sd ra, 8(sp)
call foo # ra is overwritten; use sw/lw for 32-bit RV32 saves
ld ra, 8(sp)
addi sp, sp, 16
retNo. The psABI marks ra as not preserved across calls; save it explicitly when it must survive a call.
Because a JAL or JALR that uses ra/x1 as its link destination writes a new next-instruction address and overwrites the old value.