The ARM C Compiler provides a mechanism which allows many SWIs to be called efficiently from C. SWIs which conform to the following rules can be compiled in-line, without additional calling overhead:
In the examples below, the following options are used with armcc:
-------------------------------------------------------- Option |Use -------------------------------------------------------- -li |Specifies that the the target is a little |endian ARM. -------------------------------------------------------- -apcs 3/32bit |Specifies that the 32 bit variant of APCS |3 should be used. --------------------------------------------------------
This SWI is intended to write a byte to the debugging channel. The byte to be written is passed in r0.
The following C code, intended to write a Carriage Return / Line Feed sequence to the debugging channel, can be found in the examples directory as newline.c:
Look carefully at the declaration of SWI_WriteC. __swi(0) is the way in
which the SWI_WriteC 'function' is declared to be in-line SWI number 0.
void __swi(0) SWI_WriteC(int ch);
void output_newline(void)
{ SWI_WriteC(13);
SWI_WriteC(10);
}
This code can be compiled to produce ARM Assembly Language source using:
The code produced for the output_newline function is:
armcc -S -li -apcs 3/32bit newline.c -o newline.s
output_newline
MOV a1,#&d
SWI &0
MOV a1,#&a
SWI &0
MOV pc,lr
This SWI is intended to read a byte from the debug channel, returning it in r0.
The following C code, a naive read a line routine, can be found in the examples directory as readline.c:
Again, the way in which SWI_ReadC is declared should be noted: it is a
function which takes no arguments and returns a char, and is implemented
as in-line SWI number 4.
char __swi(4) SWI_ReadC(void);
void readline(char *buffer)
{
char ch;
do {
*buffer++=ch=SWI_ReadC();
} while (ch!=13);
*buffer=0;
}
This code can be compiled to produce ARM Assembler source using:
The code produced for the readline function is:
armcc -S -li -apcs 3/32bit readline.c -o readline.s
readline
STMDB sp!,{lr}
MOV lr,a1
|L000008.J4.readline|
SWI &4
STRB a1,[lr],#1
CMP a1,#&d
BNE |L000008.J4.readline|
MOV a1,#0
STRB a1,[lr,#0]
LDMIA sp!,{pc}
As an example consider SWI_InstallHandler, which we want to be SWI number 0x70.
On entry r0 contains the exception number, r1 contains the workspace pointer, r2 contains the address of the handler.
On exit r0 is undefined, r2 contains the address of the previous handler and r1 the previous handler's workspace pointer.
The following C code fragment demonstrates how this SWI could be declared and used in C:
This code is provided in the examples directory as
installh.c, and can be compiled to produce ARM Assembler source
using:
typedef struct SWI_InstallHandler_struct
{
unsigned exception;
unsigned workspace;
unsigned handler;
} SWI_InstallHandler_block;
SWI_InstallHandler_block
__value_in_regs
__swi(0x70) SWI_InstallHandler
(unsigned r0, unsigned r1, unsigned r2);
void InstallHandler(SWI_InstallHandler_block *regs_in,
SWI_InstallHandler_block *regs_out)
{ *regs_out=SWI_InstallHandler(regs_in->exception,
regs_in->workspace,
regs_in->handler);
}
The code which armcc produces is:
armcc -S -li -apcs 3/32bit installh.c -o installh.s
InstallHandler
STMDB sp!,{lr}
MOV lr,a2
LDMIA a1,{a1-a3}
SWI &70
STMIA lr,{a1-a3}
LDMIA sp!,{pc}
This situation might occur when there are a number of related operations which can be performed on a object, and these various operations are implemented by SWIs with different numbers.
There are several ways to deal with this, including:
Here is an C fragment which uses a 'generic', or 'indirect' SWI:
This code is provided in the examples directory as
swimanip.c, and can be compiled to produce ARM Assembler source
using:
unsigned __swi_indirect(0x80)
SWI_ManipulateObject(unsigned operationNumber, unsigned object,
unsigned parameter);
unsigned DoSelectedManipulation(unsigned object,
unsigned parameter, unsigned operation)
{ return
SWI_ManipulateObject(operation, object, parameter);
}
The code which armcc produces is:
armcc -S -li -apcs 3/32bit swimanip.c -o swimanip.s
DoSelectedManipulation
MOV ip,a3
SWI &80
MOV pc,lr