Showing changes from revision #11 to #12:
Added | Removed | Changed
Software Interrupts, or SWIs for short, are 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 RISC OS is modular, different modules implement specific SWIs.
A SWI can be used by either referring to its 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 generally advised to use the SWI names when calling SWIs as it improves readability and helps create code that can be updated more easily. It is also important to note that SWI names are case sensitive. They must be typed exactly as documented, otherwise RISC OS will not identify the SWI, and an error will be returned. The names usually follow ‘Camel Case’ rules; e.g. “BinaryToDecimal”.
A SWI instruction is allocated a unique number. 24-bits are used to specify the SWI number (0 – &FFFFFF), although only SWIs from &40000 (bit 19 must be set) upwards are available for 3rd 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 a module.
If a program executes a SWI that is not recognised, the OS calls a special routine called the ‘Unused SWI Vector’, or UKSWIV, 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, etc.).
The suffix specifies the function of the SWI, and when added to the prefix forms the chunk name . The chunk name is usually the name of the module that provides the SWI, although it is dependent 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 |
The ARM registers R0-R9 are used to pass parameters and results to and from SWI routines. Unlike the APCS? standard that’s used with most C code, there is no global standard for how the registers are used by SWIs – you must consult the documentation of each SWI call to determine whether a register is an input or an output. However, it is always the case that a SWI which returns an error will return the error block pointer in R0 (see Error handling)
For the OS SWIs documented on this wiki, it’s generally the case that any register which isn’t used as an input or an output will be preserved across the SWI call. However for some SWIs certain registers will be corrupted – these cases will be noted in the SWI documentation.
The above rules do not apply to kernel SWIs, which are able to fully examine the caller’s PSR.
Some SWIs use the NZC flags to return values. Normally this is limited to just returning a value in the C flag, but the N and Z flags can be used as well.
If a value isn’t explicitly being returned in an NZC flag, the behaviour differs by OS version:
The V flag is used to indicate an error state (see Error handling). If the SWI generates an error the V flag will be set; if the SWI does not generate an error then the V flag will be cleared, even if the flag was set on entry.
Only kernel SWIs are able to return to the caller in a different CPU mode or with altered interrupt states. However there are a number of SWIs which will temporarily enable IRQs or FIQs during execution.
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 a 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. An error-returning SWI can be specified by two different methods:
As the most common method of using SWIs is by name.
A detailed summary of how RISC OS handles Error-generating SWIs is provided below, although it is not usually 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 |
It is possible to generate an error by calling OS_GenerateError. The error will be passed to the current error handler, and the SWI call will not return to the caller.
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).
For software that is to be released to the general public, SWI names and numbers must be allocated through RISC OS Open using their Allocate tool (RISC OS software only), 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.
For software which is for private use only, the author is free to pick any SWI names and chunk numbers, so long as the ‘User Applications’ SWI group (bits 18-19 set to 2_11) is used. In this case, it is the author’s responsibility to ensure the name and chunk does not clash with any other SWIs on their system.