Search code examples
cgccassemblyarmcortex-a8

Why does arm-linux-gcc only reserve r0-r4 when entering IRQ mode


I'm using S5PV210 which is based on ARM cortex-A8

When i declare a interrupt routine like this:

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

And compile like this

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

I know that gcc will switch context for me by push some registers.Before i know this, i did it manually.So i'm curious about how gcc do it. After disassembling, I found codes like below

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

It goes against my conception about how to switch context. In Arm cortex-A8 official document, it's explicit that r0-r12 is shared by user mode and IRQ mode.However lr in user mode is independent from IRQ mode.So, I used to switch context like this

PUSH     {r0-r12}

Is it OK? Why does gcc push lr register and why doesn't gcc push r5-r10 rigsters?


Solution

  • r4-r11 are preserved across function calls as part of the ARM ABI, so the interrupt routine does not need to save them unless the function itself is going to clobber them. If another function the interrupt routine calls wants to modify these registers, it's already obligated to save and restore them as part of the normal ABI. It seems that among this set, the compiler only wanted to use r4 and r11 (r5-r10 are not used).

    While non-authoritative, the Wikipedia article is easy to read and may be helpful: http://en.wikipedia.org/wiki/Calling_convention#ARM