5.23 Calling SVCs dynamically from an application

In some circumstances it might be necessary to call an SVC whose number is not known until run-time.

This situation might occur, for example, when there are a number of related operations that can be performed on an object, and each operation has its own SVC. In this case, the methods described in this topic are appropriate.

There are several ways of dealing with this, for example:

  • Construct the SVC instruction from the SVC number, store it somewhere, then execute it.

  • Use a generic SVC that takes, as an extra argument, a code for the actual operation to be performed on its arguments. The generic SVC decodes the operation and performs it.

The second mechanism can be implemented in assembly language by passing the required operation number in a register, typically R0 or R12. You can then rewrite the SVC handler to act on the value in the appropriate register.

Because some value has to be passed to the SVC in the comment field, it is possible for a combination of these two methods to be used.

For example, an operating system might make use of only a single SVC instruction and employ a register to pass the number of the required operation. This leaves the rest of the SVC space available for application-specific SVCs. You can use this method if the overhead of extracting the operation number from the instruction is too great in a particular application. This is how the ARM and Thumb semihosted instructions are implemented.

The following example shows how to use __svc to map a C function call onto a semihosting call:

Mapping a C function onto a semihosting call
#ifdef __thumb
/* Thumb Semihosting */
#define SemiSVC 0xAB
/* ARM Semihosting */
#define SemiSVC 0x123456
/* Semihosting call to write a character */ 
__svc(SemiSVC) void Semihosting(unsigned op, char *c);
#define WriteC(c) Semihosting (0x3,c)
void write_a_character(int ch)
    char tempch = ch;
    WriteC( &tempch );

The compiler includes a mechanism to support the use of R12 to pass the value of the required operation. Under the AAPCS, R12 is the ip register and has a dedicated role only during function calls. At other times, you can use it as a scratch register. The arguments to the generic SVC are passed in registers R0-R3 and values are optionally returned in R0-R3. The operation number passed in R12 can be the number of the SVC to be called by the generic SVC. However, this is not required.

The following example shows a C fragment that uses a generic, or indirect SVC.

Using indirect SVC
    unsigned SVC_ManipulateObject(unsigned operationNumber,
                                  unsigned object,unsigned parameter);
unsigned DoSelectedManipulation(unsigned object,
                                unsigned parameter, unsigned operation)
  return SVC_ManipulateObject(operation, object, parameter);

This produces the following code:

        PUSH     {R4,lr}
        MOV      R12,R2
        SVC      #0x80
        POP      {R4,pc}

It is also possible to pass the SVC number in R0 from C using the __svc mechanism. For example, if SVC 0x0 is used as the generic SVC, operation 0 is a character read, and operation 1 is a character write, you can set up the following:

__svc (0) char __ReadCharacter (unsigned op);
__svc (0) void __WriteCharacter (unsigned op, char c);

These can be used in a more reader-friendly way by defining the following:

#define ReadCharacter () __ReadCharacter (0);
#define WriteCharacter (c) __WriteCharacter (1, c);

However, if you use R0 in this way, then only three registers are available for passing parameters to the SVC. Usually, if you have to pass more parameters to a subroutine in addition to R0-R3, you can do this using the stack. However, stacked parameters are not easily accessible to an SVC handler, because they typically exist on the User mode stack rather than the Supervisor mode stack employed by the SVC handler.

Alternatively, you can use one of the registers, typically R1, to point to a block of memory storing the other parameters.

Non-ConfidentialPDF file icon PDF versionARM DUI0471M
Copyright © 2010-2016 ARM Limited or its affiliates. All rights reserved.