Hi
I am testing the exception handling in omapl138 ARM. here is the interrupt vector table:
.sect ".intvecs"
_intvecs: ;Exception Address
LDR PC,init ;Reset 0xffff0000
.word 0 ;undefined instruction 0xffff0004
MOV PC,R14 ;soft ware interrupt 0xffff0008
.word 0 ;pre-fetch abort 0xffff000c
.word 0 ;data abort 0xffff0010
.word 0 ;reserved 0xffff0014
LDR PC,irq_handler ;irq 0xffff0018
LDR PC,fiq_handler ;fiq 0xffff001c
And in my main function, which is in USR mode, I generated a software interrupt using swi #12. Theoretically, ARM will go to this intvec and go back to main function without change any registers' value.
When I debug it step by step, I found that after swi #12, ARM goes to this intvec. At this moment, R13 is updated by R13_SVC, R14 stores the return address in main function, CPSR goes to SVC mode. All these are reasonable. SPSR_SVC is supposed to save the value of CPSR right before swi #12 instruction but its higher bits remained unchanged while only mode field is updated.
What's more, after execution of MOV PC,R14, ARM does go back to the main function as expected. However, CPSR was recovered by SPSR_SVC. i.e. CPSR is still in SVC mode without being changed back to USR mode.
So I was wondering whether CPSR is updated by core automatically when exit from exception? or We have to recover CPSR explicitly in our interrupt handler? I we do have to recover CPSR explicitly in our interrupt handler, how can we do it? because in our interrupt handler, it usually looks like this:
STMFD SP!,{R0-R12,R14}
...
LDMFD SP!,{R0-R12,R14}
MOV PC,R14
To recover CPSR explicitly, we have move value from SPSR to CPSR. Since there is no instruction that can move data between these two registers, we have to use a general purpose register as a temporary register (for example R0). We can not use R0 after instruction LDMFD SP!,{R0-R12,R14} because R0 maybe used in the functions that was interrupted. And we can't use R0 to recover CPSR before LDMFD SP!{R0-R14} neither, because if CPSR was updated and mode was changed, R13 would be changed to USR stack, thus making LDMFD SP!,{R0-R14} can't recover R0-R12,R14 from SVC stack.
Does anybody know how to deal with this case?
Thanks,
Fu