9.4.5. Calling SWIs dynamically from an application

In some circumstances it may be necessary to call a SWI whose number is not known until runtime. This situation can occur, for example, when there are a number of related operations that can be performed on an object, and each operation has its own SWI. In such a case, the methods described above are not appropriate.

There are several ways of dealing with this. For example:

The second mechanism can be implemented in assembly language by passing the required operation number in a register, typically r0 or r12. The SWI handler can then be rewritten to act on the value in the appropriate register. Because some value has to be passed to the SWI in the comment field, it would be possible for a combination of these two methods to be used.

For example, an operating system might make use of only a single SWI instruction and employ a register to pass the number of the required operation. This leaves the rest of the SWI space available for application-specific SWIs. This method can also be used if the overhead of extracting the SWI number from the instruction is too great in a particular application.

A mechanism is included in the compiler to support the use of r12 to pass the value of the required operation. Under the ARM Procedure Call Standard, r12 is the ip register and has a dedicated role only during function call. At other times it may be used as a scratch register. The arguments to the generic SWI are passed in registers r0-r3 and values are optionally returned in r0-r3 as described earlier. The operation number passed in r12 could be, but need not be, the number of the SWI to be called by the generic SWI.

Example 9.10 shows a C fragment that uses a generic, or indirect SWI.

Example 9.10. 

__swi_indirect(0x80)
	unsigned SWI_ManipulateObject(unsigned operationNumber,
								unsigned object,unsigned parameter);
unsigned DoSelectedManipulation(unsigned object,
								unsigned parameter, unsigned operation)
{ return SWI_ManipulateObject(operation, object, parameter);
}

This produces the following code:

EXPORT DoSelectedManipulation
DoSelectedManipulation
0x000000:  e1a0c002  .... : MOV      r12,r2
0x000004:  ef000080  .... : SWI      0x80
0x000008:  	e1a0f00e  	.... 	: 	MOV     	 pc,r14

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

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

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

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

However, using r0 in this way means that only three registers are available for passing parameters to the SWI. Usually, if more parameters need to be passed to a subroutine in addition to r0-r3, this can be done using the stack. However, stacked parameters are not easily accessible to a SWI handler, because they typically exist on the user mode stack rather than the supervisor stack employed by the SWI handler.

Alternatively, one of the registers (typically r1) can be used to point to a block of memory storing the other parameters.

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