Return from Interrupts for ARM-ELF
Richard Earnshaw
rearnsha@arm.com
Wed Aug 13 10:13:00 GMT 2003
> Hi folks,
>
> Just a quick question with regards to the interrupt attribute for functions.
>
>
> For example
>
> void ADI_IRQ_Interrupt_Setup(void) __attribute__ ((interrupt ("IRQ")));
>
> void ADI_IRQ_Interrupt_Setup(void)
> {
> IRQ();
> return ;
> }
>
> Generates the following code
>
>
> 0: e52dc004 str ip, [sp, -#4]!
> 4: e1a0c00d mov ip, sp
> 8: e24ee004 sub lr, lr, #4 ; 0x4
> c: e92dd80f stmdb sp!, {r0, r1, r2, r3, fp, ip, lr, pc}
> 10: e24cb004 sub fp, ip, #4 ; 0x4
> IRQ();
> 14: e59f3014 ldr r3, [pc, #20] ; 30 <ADI_IRQ_Interrupt_Setup+0x
>
> 30>
> 18: e5933000 ldr r3, [r3]
> 1c: e1a0e00f mov lr, pc
> 20: e12fff13 bx r3
> return 0 ;
> 24: e3a03000 mov r3, #0 ; 0x0
> }
> 28: e1a00003 mov r0, r3
> 2c: e95b580f ldmdb fp, {r0, r1, r2, r3, fp, ip, lr}^
> 30: 000001c0 andeq r0, r0, r0, asr #3
This disassembly cannot possibly come from the example code you cite above.
1) It calls a pointer to a function
2) It tries to return a value (interrupt functions must be void).
>
> How does GCC return to the code that calls this as it does not directly affect
> the PC?
>
> Should the following liner be replaced:
>
> ldmdb fp, {r0, r1, r2, r3, fp, ip, lr}^
>
> with:
>
> ldmdb fp, {r0, r1, r2, r3, fp, ip, PC}^
Nope, it needs to play more games after that to restore the stack
correctly:
>
> To switch back to the previous user mode and jump back to the Link Register
> location.
>
> Any ideas?
>
Yes, use gcc-3.3.1. There have been a large number of problems with
generating code that returns from interrupts. Hopefully these are now all
fixed.
Putting your *source* code into gcc 3.3.1 gives:
str ip, [sp, #-4]!
mov ip, sp
stmfd sp!, {r0, r1, r2, r3, fp, ip, lr, pc}
sub fp, ip, #4
bl IRQ
ldmea fp, {r0, r1, r2, r3, fp, sp, lr}
ldmfd sp!, {ip}
subs pc, lr, #4
Which I believe is correct, if not the world's most efficient interrupt
handler.
R.
------
Want more information? See the CrossGCC FAQ, http://www.objsw.com/CrossGCC/
Want to unsubscribe? Send a note to crossgcc-unsubscribe@sources.redhat.com
More information about the crossgcc
mailing list