我正在上一门计算机体系结构课程,对课程中的一些主题有点迷失。哪些寄存器是在过程调用中保存的,而不是保存的?这是什么意思?
在寄存器列表中,我的书中说x8-x9和x18-27是保存的寄存器。这是否意味着其他人都没有得救?我读过一些关于被调用者和调用者的文章——这和这个有关系吗?我通读了这本书,试着在谷歌上搜索,但找不到直接的答案,所以我来到了这里。我上这门课只是因为没有其他选择,也没有所有的先决条件和背景研究。因此,我很难跟上,所以请简单解释。
目前在riscv gcc中实现的内容:
调用保存的GPR:X8-X9 x18-x27
呼叫保存的FPR(如果启用了浮点(:F8-F9 F18-F27
所有其他寄存器都已修复或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
由调用方处理,如果您愿意,可以查看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(,它将保存并恢复它,这意味着之后我们将具有相同的值。如果它使用了一个不在这个列表中的寄存器(例如ra和gcc(,它将不会完成这项工作,而是由调用方函数在使用它之前设法恢复值。