6.6.3. SVC handlers in C and assembly language

Although the top-level handler must always be written in ARM assembly language, the routines that handle each SVC can be written in either assembly language or in C. See Using SVCs in Supervisor mode for a description of restrictions.

The top-level handler uses a BL (Branch with Link) instruction to jump to the appropriate C function. Because the SVC number is loaded into r0 by the assembly routine, this is passed to the C function as the first parameter. The function can use this value in, for example, a switch() statement.

You can add the following line to the SVC_Handler routine in Example 6.6:


    BL    C_SVC_Handler     ; Call C routine to handle the SVC

Example 6.8 shows how to implement the C function.

Example 6.8. 

void C_SVC_handler (unsigned number)
{
    switch (number)
    {
        case 0 :                 /* SVC number 0 code */
            break;
        case 1 :                 /* SVC number 1 code */
            break;
        ...
        default :                /* Unknown SVC - report error */
    }
}

The supervisor stack space might be limited, so avoid using functions that require a large amount of stack space.


    MOV     r1, sp        ; Second parameter to C routine...
                          ; ...is pointer to register values.
    BL    C_SVC_Handler   ; Call C routine to handle the SVC

You can pass values in and out of an SVC handler written in C, provided that the top-level handler passes the stack pointer value into the C function as the second parameter (in r1):

and the C function is updated to access it:


void C_SVC_handler(unsigned number, unsigned *reg)

The C function can now access the values contained in the registers at the time the SVC instruction was encountered in the main application code (see Figure 6.4). It can read from them:


    value_in_reg_0 = reg [0];
    value_in_reg_1 = reg [1];
    value_in_reg_2 = reg [2];
    value_in_reg_3 = reg [3];

and also write back to them:


    reg [0] = updated_value_0;
    reg [1] = updated_value_1;
    reg [2] = updated_value_2;
    reg [3] = updated_value_3;

This causes the updated value to be written into the appropriate stack position, and then restored into the register by the top-level handler.

Figure 6.4. Accessing the supervisor stack

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