The following was compiled with arm-elf-gcc -S -g -O2 -Wall -mcpu=arm7tdmi void int_handler(void) __attribute__((interrupt("IRQ"))); void foo(void) { } void int_handler(void) { foo(); } It emitted this assembly for int_handler: int_handler: .LFB5: .loc 1 8 0 @ Interrupt Service Routine. @ args = 0, pretend = 0, frame = 0 @ frame_needed = 1, uses_anonymous_args = 0 str ip, [sp, #-4]! mov ip, sp .LCFI0: stmfd sp!, {r0, r1, r2, r3, fp, ip, lr, pc} .LCFI1: sub fp, ip, #4 .LCFI2: .loc 1 9 0 bl foo ldmea fp, {r0, r1, r2, r3, fp, sp, lr} ldmfd sp!, {ip} subs pc, lr, #4 1) The stack pointer is not being reset to its original location. 2) One of those ldm** needs a ^ after it to restore the correct CPSR. This seems to be the same bug as in 3.2
Created attachment 4667 [details] C file show below with bug
Created attachment 4668 [details] Generated Assembler file from bug.c
You are incorrect on both counts: > 1) The stack pointer is not being reset to its original location. Yes it is. The first ldm reloads the stack pointer with the value it when mov ip, sp was executed. The second ldm pops the original ip value off the stack and restores sp to the value it had before the interrupt was taken. > 2) One of those ldm** needs a ^ after it to restore the correct CPSR. No. Neither of the ldm instructions restores the PC, so it must not use ^ or it would end up accessing the user-bank register set. Instead, the final subs (note use of condition flag) instruction restores the CPSR.