【问题标题】:Which Registers are Saved and Not Saved in RISC-VRISC-V中保存哪些寄存器,哪些不保存
【发布时间】:2021-02-09 04:12:13
【问题描述】:

我正在学习计算机体系结构课程,但对课程中的一些主题有点迷茫。在过程调用中保存和不保存哪些寄存器?这是什么意思?

在寄存器列表中,我的书上说 x8-x9 和 x18-27 是已保存的寄存器。这是否意味着所有其他人都没有得救?我读过一些关于被调用者和调用者的文章——这和这个有什么关系吗? 我已经通读了这本书并尝试使用谷歌搜索并找不到直接的答案,所以我来到了这里。我参加这门课只是因为没有提供其他选择并且没有所有的先决条件和背景研究。结果我很难跟上,所以请简单解释一下。

【问题讨论】:

标签: assembly cpu-registers calling-convention riscv


【解决方案1】:

现在在 riscv-gcc 中实现了什么:
呼叫保存的 GPR:X8-X9 x18-x27
调用保存的 FPR(如果启用了浮点):F8-F9 F18-F27
所有其他寄存器都是固定的或调用破坏。

#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 由调用者处理,如果您愿意,可以查看 riscv.c ,您将看到 ra 何时被 riscv_save_reg_p 保存。

对于 LLVM 移植: 被调用者保存的 GPR 是:X1、X3-X4、X8-X9 和 X18-X27 被调用方保存的 FPR(如果启用了浮点):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))>;

这与 gcc 所做的有点不同。在 gcc 中 X3 和 X4 被认为是固定的。

对于 LLVM 中的 X2,它由 setStackPointerRegisterToSaveRestore 处理。

尝试用简单的方式解释。如果一个函数使用一个被调用寄存器(例如 x8),它将保存并恢复它,这意味着之后我们将拥有相同的值。 如果它使用了一个不属于这个列表的寄存器(例如使用 gcc 的 ra),它就不会做这个工作,由调用者函数在使用它之前设法恢复值。

【讨论】:

    猜你喜欢
    • 2012-03-25
    • 1970-01-01
    • 2010-09-20
    • 2020-08-27
    • 2012-04-28
    • 1970-01-01
    • 2014-11-19
    相关资源
    最近更新 更多