为什么gcc将r4保存在arm FIQ中断处理程序中?

时间:2014-08-27 15:40:01

标签: arm interrupt-handling

考虑以下C代码:

extern void dummy(void);

void foo1(void) __attribute__(( interrupt("IRQ") ));
void foo2(void) __attribute__(( interrupt("FIQ") ));

void foo1() {
  dummy();
  return;
}
void foo2() {
  dummy();
  return;
}

arm gnueabi gcc生成的代码基本上是这样的:

foo1:
    sub lr, lr, #4
    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
    bl  dummy
    ldmfd   sp!, {r0, r1, r2, r3, ip, pc}^
foo2:
    sub lr, lr, #4
    stmfd   sp!, {r0, r1, r2, r3, r4, lr}
    bl  dummy
    ldmfd   sp!, {r0, r1, r2, r3, r4, pc}^

foo1的代码没有任何意外。保存r0-r3ip,因为对虚拟的调用可能会改变其值。此外,在纠正lr之后,它最终会被推送到pc中。这是相当标准的。

然而,foo2的代码令人惊讶。不需要保存ip的值,因为它是一个库存寄存器。但是gcc保存r4是令人惊讶的。

那为什么gcc会保存r4?我没有看到任何理由这样做,因为对假人的调用不会破坏这个寄存器。

1 个答案:

答案 0 :(得分:1)

我怀疑它是为了确保EABI所需的8字节堆栈对齐。使用的实际寄存器无关紧要,它可能是r12或其他任何东西 - 它只用于额外的4字节调整。