User guide

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, you can:
Construct the SWI instruction from the SWI number, store it somewhere, then execute it.
Use a generic SWI that takes, as an extra argument, a code for the actual operation to be performed on its
arguments. The generic SWI 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 SWI handler 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. You
can use this method if the overhead of extracting the SWI number from the instruction is too great in a particular
application. This is how the ARM (0x123456) and Thumb (0xAB) semihosted SWIs are implemented.
Example 5-11 shows how __swi can be used to map a C function call onto a semihosting SWI. It is derived from
Examples\embedded\embed\retarget.c.
Example 5-11 Mapping a C function onto a semihosting SWI
#ifdef __thumb
/* Thumb Semihosting SWI */
#define SemiSWI 0xAB
#else
/* ARM Semihosting SWI */
#define SemiSWI 0x123456
#endif
/* Semihosting SWI to write a character */
__swi(SemiSWI) void Semihosting(unsigned op, char *c);
#define WriteC(c) Semihosting (0x3,c)
void write_a_character(int ch)
{
char tempch = ch;
WriteC( &tempch );
}
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, you can use it 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 5-12 shows a C fragment that uses a generic, or indirect SWI.
Example 5-12
__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:
DoSelectedManipulation PROC
STMFD sp!,{r3,lr}
MOV r12,r2
SWI 0x80
LDMFD sp!,{r3,pc}
ENDP
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, you can set up the
following:
Handling Processor Exceptions
Copyright ?1999 2001 ARM Limited 5-12