Take the 2-minute tour ×

In ARM architecture, returning from exception can be done in two ways which I know,(there might be others). But main logic is to modify PC, which will make processor trigger into mode set in CPSR.

So pop {...,pc} would make a switch to say user from supervisor or mov pc,lr would do the same.

My Question is, would a BX lr make the switch ? Assuming I am handling IRQ and I call a assembly routine say do_IRQ and then return from do_IRQ is via BX LR. Would this make the code after bl do_IRQ in my fault handler irrelevant ?

    push    {lr}
    push {ro-r12}
    mrs     r0, spsr
    push    {r0}

     bl do_IRQ

     pop {r0}
     msr  cpsr, r0
     pop {r0,-r12}
     pop {lr}
     subs pc, lr, #4

share|improve this question
Note: This question was edited after the answer was accepted. Tangrs comments apply to the original post. mov pc,lr was used as a return for instance. –  artless noise Sep 13 '13 at 13:47
The ARM ARM clearly defines the exact instruction you are supposed to use for each exception, yes? –  dwelch Sep 13 '13 at 14:38
Ahh, I see the newer ARM ARM's are different, they now say recommended return... –  dwelch Sep 13 '13 at 14:57

1 Answer 1

up vote 4 down vote accepted

It does not make it irrelevant since you called do_IRQ with bl instead of just a branch so you've already overwritten lr. Furthermore, even if you just did a branch, your stack would be messed up (you push r0-r12 but never pop them before returning).

Also, the code you show doesn't seem to return from the exception correctly either. Most of the time, when you return from an exception, you want to restore the program status registers as well as the registers which a mov pc, lr won't do nor will a bx lr.

Furthermore, the address contained in lr will actually be offsetted by a few words (it varies depending on the type of exception) so you're not returning to the correct instruction anyway. For IRQ, I believe it is off by 1 word.

The recommended way to return from an IRQ exception is a subs pc, lr, #4 instruction (after you've pop'd all your registers beforehand of course) which is special in that it also restores the CPSR.

share|improve this answer
would the modified code make sense? –  mSO Sep 13 '13 at 9:52
You're restoring the SPSR, not the CPSR. Also, the lr address will still be wrong (it's one instruction ahead of the one you're supposed to be returning to). You should understand that returning from an exception is different to returning from a function. –  tangrs Sep 13 '13 at 9:55
thanks. I fixed that as well. Do you think this would work? –  mSO Sep 13 '13 at 9:57
Getting better but still has some issues. When you restore the CPSR, you're (possibly) changing processor modes and your stack will change and the pop will clobber your registers. Besides, it's all redundant. Just push {r0-r12, lr} at the start and pop {r0-r12, lr}, subs pc, lr, #4 at the end. The subs instruction will restore the CPSR for you. –  tangrs Sep 13 '13 at 10:00
"subs instruction will restore the CPSR for you." I didnt get that. Can you please elaborate. Also how would the code change if I were to add a rfe or a eret –  mSO Sep 13 '13 at 10:04

Your Answer


