**S**oft**w**are **I**nterrupts, or SWIs for short, is a set of powerful instructions to allow developers to interact with the Operating System, without allowing any direct control in Supervisor Mode. The process of using a SWI is as follows:
A SWI consists of a unique name, number and usually requires parameters to be passed.
Because the RISC OS is modular, different modules implement specific SWIs.
SWIs can be used by either referring to it’s unique name or number. The 24-bit number, known as the SWI number is used by RISC OS to identify the routine.
The exact method that RISC OS uses to decode the SWI is unimportant. As long as the correct SWI name or number along with any parameters (if required) are used, then the correct result will be returned.
It is strongly advised to use the SWI names when calling SWIs as it greatly improves readability and helps create code that can be updated with ease.
It is also important to note that SWI names are case sensitive. It must be typed exactly correct, otherwise RISC OS will not indentify the SWI, and an error will be returned. The names are usually typed provided in Camel Case e.g BinaryToDecimal.
A list of SWIs broken down by Module is available here?.
A SWI instruction is allocated a unique number. 24-bits are used to specify the SWI number (0 – &FFFFFF), although only SWIs from &400000 upwards are available for 3^rd^ party use, as the others are assigned for internal use by RISC OS (although only a small percentage are currently used).
Modules can also provide their own SWIs, and must provide unique SWI numbers. This feature allows for SWIs that perform related functions to be grouped together as part of module, making it a modular Operating System.
If a program executes a SWI that is not recognised, the OS calls a special routine called the ‘Unused SWI Vector’ or UKSWIV vector for short. This usually returns the generic ‘No such SWI’ error message, however, it is possible for an application to claim this vector and if the SWI number is recognised by the program perform the appropriate task.
The 24-bit SWI number consists of the following:
Bits | Identifier | Information |
---|---|---|
0 – 5 | Chunk Offset Number | Identify individual SWIs in a chunk |
6 – 16 | Chunk Number | Specifies a block of 64 consecutive SWIs for use by application or module |
17 | Error Flag (X bit) | Determine the action taken on errors |
18 – 19 | SWI Group | Specifies which part of the system implements the SWI. Possible values are shown in the table below |
20 – 23 | OS Flag | Specify which OS the SWI expects to execute the SWI. RISC OS requires this bit to be zero |
Bit 19 | Bit 18 | Meaning |
---|---|---|
0 | 0 | Operating System |
0 | 1 | Operating System modules |
1 | 0 | Third party applications |
1 | 1 | User applications |
SWI names are broken into two discrete parts separated by the underscore character ‘_’. The prefix specifies which part of the system will deal with the SWI. The prefix name usually specifies by the module which implements the SWI. e.g. Wimp, Font, ADFS, FileCore.
The suffix specifies the function of the SWI, and when added to the prefix specifies the Chunk Name. The chunk name is usually the name of the module that provides the SWI, although it is dependant on the name when registering the SWI. Some examples are shown below:
SWI name | Chunk Name | SWI Function |
---|---|---|
OS_ReadSysInfo | OS | ReadSysInfo |
FileCore_FreeSpace | FileCore | FreeSpace |
PCI_RAMFree | PCI | RAMFree |
Parameters are used to pass values to and from the SWI routines. The ARM registers are used to pass information as required. SWIs may use R0 to R9 inclusive, although there is a restriction to using only R0 to R7 via BASIC, although this is rarely a problem as most SWIs seldom use more than 4 or 5 registers.
When a number, character or address needs to be passed to/from a SWI, the actual data itself is passed.
When a string or a large amount of data needs to be passed, a pointer to the data is used instead.
As you would expect, RISC OS provides error handling facilities for SWIs. There are two possible steps to the error checking process:
The state of the X bit determines how RISC OS deals with an SWI error. It is sometimes useful for RISC OS to deal with an error, while other times it is best if your own program deals with an error. And error-returning SWI can be specified by two different methods:
As the most common method of using SWIs is by name; appending the letter X to the name is the most common approach.
A detailed summary of how RISC OS handled Error-generating SWIs is provided below, although it is not necessary to understand this low-level information.
If an error has been generated, R0 points to an error block that identifies the type of error.
The format of the error block is described here
The error number contained as part of the error block specifies the type of error. The error number is a 32-bit number, and is divided into three discrete parts:
Bit | Meaning if set |
---|---|
24 – 29 | Sometimes used as a sub-error indicator if bit 31 is set. e.g. ADFS uses them to identify the type of disc error |
30 | Defined to be clear, so can be safely used by developers to flag internal errors |
31 | Specifies a serious error, such as a hardware exception or floating point exception. In these cases, different error number ranges are used |
When calling SWIs normally, it is safe to assume that the V flag of the return address (R14_svc) has been cleared, before a SWI routine is entered. This ensures that return address in the correct format to indicate that no errors occurred.
However, it is not safe to assume this with SWI routines that are vectored. This is because any of these routines may have been called using OS_CallAVector, which does not clear the V flag.
When claiming a vector and replacing a SWI routine, the replacement routine must not assume the state of the V flag. It must explicitly clear the V flag if there was no error, or set it there was an error.
It is possible to generate an error by calling OS_GenerateError. The routine does not return.
When writing system extension code, such as a module or interrupt handler, it is vital that it does not generate errors. This is because users expect it to ‘just work’. When issuing SWIs in system extension code, they must always have their X bit set. i.e. either add the value &20000 to the SWI number, or add the letter ‘X’ in front of the SWI name.
The exception to the rule is when reporting exception-type errors. i.e. when bit 31 of the error number is set (indicating a serious error).
SWIs names and numbers can be allocated through RISC OS Open using their Allocate tool (RISC OS software only) and is available here.
When registering a SWI, a Chunk name must be provided, and this will be used as part of the SWI name. e.g. __ChunkName___Function.