是否可以为 C 代码的特定部分保留寄存器?
-ffixed-reg 选项或声明全局寄存器变量不是我正在寻找的答案。我想保留特定范围(比如说特定函数)的寄存器值。
使用局部寄存器变量是不可能的,因为它不能保证在整个范围内保留寄存器的值。
我正在寻找类似 clobber list 的东西,带有 asm 易失性,但用于 C 语句。
GCC给出了三种机制,
-
asm
clobber
- 局部寄存器变量 https://gcc.gnu.org/onlinedocs/gcc-6.3.0/gcc/Local-Register-Variables.html
- 全局寄存器变量 https://gcc.gnu.org/onlinedocs/gcc-6.3.0/gcc/Global-Register-Variables.html
值得注意的是,编译器寄存器分配是现代优化的基础,保留寄存器可能会生成更糟糕的编译代码。使用 ARM 模式和 16 个寄存器(仅 13 个可用),您应该能够为某个功能保留一个这样的寄存器,而不会造成太大损害。然而,您不应该轻易使用这些设施,发现一些性能问题也就不足为奇了。
听起来全局寄存器变量最适合你。只要有register int *foo asm ("r4");
在每个需要它的“C”模块的开头。
如果您有一个小的函数簇/树,您可以使用宏来保留并将其包含到一个“C”单元。
#define RESERVE_REG(reg) register int RR_##reg asm (#reg) \
__attribute__((unused))
int bar(int a) {
RESERVE_REG(R4);
int b;
b += CRAZY_ASM(a);
return b;
}
void foo(void) {
RESERVE_REG(R4);
CRAZY_ASM_SET_R4(82);
printf("value is %d\n", bar(1));
}
了解变量的使用很重要,因为有更有效的方法(例如asm
clobber)对于某些可变的寿命和用途获得相同的效果。在大多数情况下,人们只会声明一个参数。也就是说,最好让编译器知道您使用它的目的,因为它可以就何时溢出或不溢出做出明智的决定。
很难想象保留寄存器不会被误导的情况。这可能有用的一个例子是与跨语言/解释器交互。上述宏应该作为通过保留寄存器在例程之间传递信息的快速方法。
你不应该使用R0-R3
因为您将限制可以在例程之间传递的参数。 ARM ABI 将参数传递给R0-R3
。鉴于您可以灵活选择寄存器,请选择R4-R9
(甚至可能R9
是禁止的),因为这些是“被调用者”保存的寄存器,没有任何特殊用途。同样,如果你选择R0-R3
您可以NOT调用标准“C”库例程或保留寄存器将保存在堆栈上。
参考: GCC 局部寄存器变量 https://gcc.gnu.org/onlinedocs/gcc-6.3.0/gcc/Local-Register-Variables.html
ARM 寄存器调用约定 https://stackoverflow.com/questions/261419/arm-to-c-calling-convention-registers-to-save
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)