为什么arm-linux-gcc在进入IRQ模式时只保留r0-r4

时间:2014-10-13 14:54:57

标签: c gcc assembly arm cortex-a8

我使用的是基于ARM cortex-A8的S5PV210

当我声明这样的中断例程时:

void isr_routine(void)  __attribute__ ((interrupt ("IRQ")));

并像这样编译

arm-linux-gcc -c -march=armv7-a -fpie -fno-builtin $< -o $@

我知道gcc会通过推送一些寄存器为我切换上下文。在我知道这一点之前,我手动完成。所以我很好奇gcc是如何做到的。 拆解后,我找到了如下代码

PUSH     {r0-r4,r11,r12,lr}

这与我关于如何切换上下文的概念背道而驰。 在Arm cortex-A8官方文档中,明确表示r0-r12由用户模式和IRQ模式共享。但是用户模式中的lr独立于IRQ模式。所以,我曾经像这样切换上下文

PUSH     {r0-r12}

可以吗?为什么gcc push lr注册,为什么gcc不推r5-r10 rigsters?

2 个答案:

答案 0 :(得分:7)

r4-r11作为ARM ABI的一部分保留在函数调用中,因此中断例程不需要保存它们,除非函数本身将破坏它们。如果中断例程调用的另一个函数想要修改这些寄存器,则它已经有义务将它们保存并恢复为正常ABI的一部分。看来在这个集合中,编译器只想使用r4和r11(不使用r5-r10)。

虽然非权威,维基百科的文章很容易阅读,可能会有所帮助:http://en.wikipedia.org/wiki/Calling_convention#ARM

答案 1 :(得分:3)

r5-r10是ARM中的被调用者保存寄存器,因此如果在isr_routine中使用它们,gcc将推送它们。如果它们没有被使用(并且如果可能的话它会尽量不使用它们),它就不会为了保存/恢复它们的价值而烦恼,因为它是不必要的。我猜你的isr_routine很简单,不需要它们(一切都适合r0-r4或r11-r12)