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

为什么gcc在arm FIQ中断处理程序中保存r4?,arm,interrupt-handling,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

考虑以下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-r3
ip
被保存,因为对dummy的调用可能会更改它们的值。另外,在更正了lr后,它最终被推入并弹出到pc中。这是相当标准的

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


那么gcc为什么要保存r4呢?我看不出有任何理由这样做,因为对dummy的调用不会损坏这个寄存器。

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

仅供参考