6.6.4. Using SVCs in Supervisor mode

When a SVC instruction is executed:

  1. The processor enters Supervisor mode.

  2. The CPSR is stored into spsr_SVC.

  3. 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 an SVC 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 SVC number calls another SVC, you must ensure that the handler routine stores both lr_SVC and spsr_SVC on the stack. This guarantees that each invocation of the handler saves the information required to return to the instruction following the SVC that invoked it. Example 6.9 shows how to do this.

Example 6.9. SVC Handler

        AREA SVC_Area, CODE, READONLY

    PRESERVE8

    EXPORT SVC_Handler
    IMPORT C_SVC_Handler

T_bit EQU 0x20

SVC_Handler

    STMFD    sp!,{r0-r3,r12,lr}   ; Store registers.
    MOV      r1, sp               ; Set pointer to parameters.
    MRS      r0, spsr             ; Get spsr.
    STMFD    sp!, {r0, r3}        ; Store spsr onto stack and another register to maintain
                                  ; 8-byte-aligned stack. This is only really needed in case of
                                  ; nested SVCs.

        ; the next two instructions only work for SVC calls from ARM state.
        ; See Example 6.18 for a version that works for calls from either ARM or Thumb.

    LDR      r0,[lr,#-4]          ; Calculate address of SVC instruction and load it into r0.
    BIC      r0,r0,#0xFF000000    ; Mask off top 8 bits of instruction to give SVC number.

        ; r0 now contains SVC number
        ; r1 now contains pointer to stacked registers

    BL       C_SVC_Handler        ; Call C routine to handle the SVC.
    LDMFD    sp!, {r0, r3}        ; Get spsr from stack.
    MSR      spsr_cf, r0          ; Restore spsr.
    LDMFD    sp!, {r0-r3,r12,pc}^ ; Restore registers and return.

    END

Nested SVCs in C and C++

You can write nested SVCs in C or C++. Code generated by the ARM compiler stores and reloads lr_SVC as necessary.

Copyright © 2002-2006 ARM Limited. All rights reserved.ARM DUI 0203G
Non-Confidential