9.4.3. Using SWIs in supervisor mode

When a SWI instruction is executed, the processor enters supervisor mode, the CPSR is stored into spsr_SVC, and the return address is stored in lr_SVC (see The processor response to an exception). If the processor is already in supervisor mode, lr_SVC and spsr_SVC are corrupted.

If you call a SWI while in supervisor mode you must store lr_SVC and spsr_SVC to ensure that the original values of the link register and the SPSR are not lost. For example, if the handler routine for a particular SWI number calls another SWI, you must ensure that the handler routine stores both lr_SVC and spsr_SVC on the stack. This ensures that each invocation of the handler saves the information needed to return to the instruction following the SWI that invoked it. Example 9.8 shows how to do this.

Example 9.8.  SWI Handler

	STMFD		sp!,{r0-r3,lr}						; Store registers.
	LDR 		r0,[lr,#-4]						; Calculate address of SWI instruction...
									; ...and load it into r0.
	BIC 		r0,r0,#0xff000000						; Mask off top 8 bits of 
									; instruction to give SWI number.
	MOV 		r1, sp						; Second parameter to C routine...
									; ...is pointer to register values.
	MRS 		r2, spsr						; Move the spsr into a general purpose register.
	STMFD 		sp!, {r2}						; Store spsr onto stack. This is 
									; only really needed in case of 
									; nested SWIs.
	BL		C_SWI_Handler						; Call C routine to handle the SWI.
	LDMFD 		sp!, {r2}						; Restore spsr from stack into r2...
	MSR 		spsr, r2						; ... and restore it into spsr.
	LDMFD		sp!, {r0-r3,pc}^						; Restore registers and return.
	END								; Mark end of this file.

Nested SWIs in C

By default, the ARM compilers do not take into account the fact that an inline SWI will overwrite the contents of the link register if it is called from Supervisor mode. If the nested SWI handlers are written in C or C++, you must use the -fz compiler option to instruct the compiler to generate code that stores lr_SVC. For example, if the C function is in module c_swi_handle.c, the following command produces the object code file:

armcc -c -fz c_swi_handle.c

Copyright © 1997, 1998 ARM Limited. All rights reserved.ARM DUI 0040D