| |||
| Home > Handling Processor Exceptions > Determining the processor state | |||
An exception handler might have to determine whether the processor was in ARM or Thumb® state when the exception occurred.
SWI handlers, especially, might have to read the processor
state. This is done by examining the SPSR T-bit. This
bit is set for Thumb state and clear for ARM state.
Both ARM and Thumb instruction sets have the SWI instruction.
When calling SWIs from Thumb state, you must consider the following:
The instruction address is at (lr–2), rather than (lr–4).
The instruction itself is 16-bit, and so requires a halfword load (see Figure 6.1).
The SWI number is held in 8 bits instead of the 24 bits in ARM state.
Example 6.1 shows
ARM code that handles a SWI from both sources.
Consider the following:
Each
of the do_swi_x routines could carry out a switch
to Thumb state and back again to improve code density if required.
You can replace the jump table by a call to a C
function containing a switch() statement to implement
the SWIs.
It is possible for a SWI number to be handled differently depending on the state it is called from.
The range of SWI numbers accessible from Thumb state can be increased by calling SWIs dynamically (as described in SWI handlers).
Example 6.1. SWI handler
T_bit EQU 0x20 ; Thumb bit of CPSR/SPSR, that is,
; bit 5.
:
:
SWIHandler
STMFD sp!, {r0-r3,r12,lr} ; Store registers.
MRS r0, spsr ; Move SPSR into
; general purpose register.
TST r0, #T_bit ; Occurred in Thumb state?
LDRNEH r0,[lr,#-2] ; Yes: load halfword and...
BICNE r0,r0,#0xFF00 ; ...extract comment field.
LDREQ r0,[lr,#-4] ; No: load word and...
BICEQ r0,r0,#0xFF000000 ; ...extract comment field.
; r0 now contains SWI number
CMP r0, #MaxSWI ; Rangecheck
LDRLS pc, [pc, r0, LSL#2] ; Jump to the appropriate routine.
B SWIOutOfRange
switable
DCD do_swi_1
DCD do_swi_2
:
:
do_swi_1
; Handle the SWI.
LDMFD sp!, {r0-r3,r12,pc}^ ; Restore the registers and return.
do_swi_2
: