简体   繁体   中英

Which Registers are Saved and Not Saved in RISC-V

I'm taking a computer architecture course and am a bit lost on a few topics in the course. Which registers are saved and not saved across a procedure call? What does this mean?

On the list of registers, my book says that x8-x9 and x18-27 are saved registers. Does this mean that all others are not saved? I've read a bit about callee and caller - does it have anything to do with this? I've read through the book and tried googling and cannot find a straight-forward answer, so I came here. I'm taking this class just because there is not another option offered and do not have all of the prerequisites and background studies for it. I'm struggling to keep up as a result, so please explain simply.

What is implemented right now in riscv-gcc:
Call saved GPR: X8-X9 x18-x27
Call saved FPR (if floating point is enabled): F8-F9 F18-F27
All the other registers are fixed or Call clobbered.

#define REG_ALLOC_ORDER                         \
{ \
  /* Call-clobbered GPRs.  */                       \
  15, 14, 13, 12, 11, 10, 16, 17, 6, 28, 29, 30, 31, 5, 7, 1,       \
  /* Call-saved GPRs.  */                       \
  8, 9, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27,                 \
  /* GPRs that can never be exposed to the register allocator.  */  \
  0, 2, 3, 4,                               \
  /* Call-clobbered FPRs.  */                       \
  47, 46, 45, 44, 43, 42, 32, 33, 34, 35, 36, 37, 38, 39, 48, 49,   \
  60, 61, 62, 63,                           \
  /* Call-saved FPRs.  */                       \
  40, 41, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,           \
  /* None of the remaining classes have defined call-saved      \
     registers.  */                         \
  64, 65                                \
}  

ra is handled by the caller an d if you want you can take a look at riscv.c, you will see when ra is saved by riscv_save_reg_p .

For the LLVM Porting: The Callee saved GPR are: X1, X3-X4, X8-X9 and X18-X27 The Callee saved FPR (if floating point is enabled): F8-F9 F18-F27

def CSR_ILP32_LP64
    : CalleeSavedRegs<(add X1, X3, X4, X8, X9, (sequence "X%u", 18, 27))>;

def CSR_ILP32F_LP64F
    : CalleeSavedRegs<(add CSR_ILP32_LP64,
                       F8_F, F9_F, (sequence "F%u_F", 18, 27))>;

def CSR_ILP32D_LP64D
    : CalleeSavedRegs<(add CSR_ILP32_LP64,
                       F8_D, F9_D, (sequence "F%u_D", 18, 27))>;

which is a little bit different from what gcc do. In gcc X3 and X4 are considered fixed.

For X2 in LLVM it is handled by setStackPointerRegisterToSaveRestore.

To try to explain in a simple way. If a function uses a callee register (x8 for example) it will save it and restore it, which means that afterwards we will have the same value. if it uses a register which is not part of this list (ra for example with gcc), it will not do this job and it is up to the caller function to manage to restore the value before using it.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM