5
votes

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?

2

2 Answers

7
votes

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

3
votes

r5-r10 are callee save registers in ARM, so gcc will push them if they are used in isr_routine. If they are not used (and it will try not to use them if possible), it won't bother to save/restore their value, because it is unnecessary. I'm guessing that your isr_routine is simple enough that they are not needed (everything fits in r0-r4 or r11-r12)