3

是否可以为 C 代码的特定部分保留寄存器?

-fixed-reg 选项或声明全局寄存器变量不是我正在寻找的答案。我想保留特定范围的寄存器值(比如说特定功能)。

使用本地寄存器变量是不可能的,因为它不能保证在整个范围内保留寄存器的值。我正在寻找带有 asm volatile 的 clobber list 之类的东西,但是对于 C 语句。

4

1 回答 1

1

GCC 提供了三种机制,

  1. asm破坏者
  2. 本地寄存器变量
  3. 全局寄存器变量

重要的是要注意编译器寄存器分配是现代优化的基础,保留寄存器会生成更糟糕的编译代码。使用 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));
}

了解变量的使用很重要,因为有更有效的方法(如asmclobber)可以对某些变量的生命周期和使用获得相同的效果。在大多数情况下,人们只会声明一个参数。即,最好让编译器知道您使用它的目的是什么,因为它可以就何时溢出或不溢出做出明智的决定。

很难想象保留寄存器不会被误导的情况。这可能有用的一个例子是与跨语言/解释器交互。上面的宏应该是一种通过保留寄存器在例程之间传递信息的快速方法。

你不应该使用R0-R3,因为你会限制可以在例程之间传递的参数。ARM ABI 将参数传递到R0-R3. 鉴于您可以灵活地选择寄存器,请选择R4-R9(甚至可能R9不受限制),因为这些是“被调用者”保存的寄存器,没有任何特殊用途。同样,如果您选择,R0-R3您可能不会调用标准的“C”库例程,否则保留的寄存器将保存在堆栈中。

参考: GCC 局部寄存器变量
                    ARM 寄存器调用约定

于 2017-06-01T13:50:25.797 回答