h6. [[Programmer's Reference Manuals]] h6(. » Introduction to SWIs <b>S</b>oft<b>w</b>are <b>I</b>nterrupts, 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: # Program issues a specific SWI instruction # ARM leaves the program and jumps to a fixed location in memory where there is normally a branch instruction into the RISC OS kernel # SWI instruction is examined the particular OS routine to be run is determined # The OS routine is called, as specified by the SWI # Control returned back to program 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. h3(#names). SWI Names and Numbers 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". h4. SWI Numbers 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 3<sup>rd</sup> 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. h4(#address). 24-bit Address Field The 24-bit SWI number consists of the following: |_<^{width:8em}. Bits|_<^{width:12em}. 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":#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| h4(#group). SWI Groups |_<^{width:8em}. Bit 19|_<^{width:12em}. Bit 18|_<^. Meaning| |<^. 0|<^. 0|<^. Operating System| |<^. 0|<^. 1|<^. Operating System modules| |<^. 1|<^. 0|<^. Third party applications| |<^. 1|<^. 1|<^. User applications| h4. SWI Names 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| h3(#parameters). Parameters and Results The ARM registers R0-R9 are used to pass parameters and results to and from SWI routines. Unlike the [[ARM Procedure Call Standard|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":#error) 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. h4. PSR fields as inputs * On 26bit OS versions, SWI handlers are entered with R14 containing the caller's NZCIF flags. * On 32bit OS versions, there is no way for a SWI to determine the caller's NZCIF flags. * For all OS versions, the SWI handler is entered with the V flag clear (in both the PC/PSR and R14, as appropriate). * For all OS versions, there is no way to determine the caller's processor mode. The above rules do not apply to kernel SWIs, which are able to fully examine the caller's PSR. h4. PSR fields as outputs h5. NZC flags 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: * For 26bit OS versions, the convention is for modules (including 32bit compatible modules) to preserve the flags. However because this is dependent on the implementation of the module, there are no guarantees as to the behaviour. * For 32bit OS versions, flags should always be considered to be corrupt (because the SWI handler is not passed the original flags on entry). h5. V flag The V flag is used to indicate an error state (see "Error handling":#error). 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. h5. Other fields 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. h3(#error). Error handling RISC OS provides error handling facilities for SWIs. There are two possible steps to the error checking process: # Check if an error occurred during the execution of the SWI routine #* If an error has been generated by the SWI routine, the V flag is set, and R0 points to an error block on exit, and then proceed to the second step in the error checking process #* If no error has been generated by the SWI routine, the V flag is clear on exit # Check if the "X bit":#address (bit 17) of the SWI instruction was set prior to entering the SWI routine #* If the X bit was set before the routine, then RISC OS returns control back to the program, which must then deal with the error. The V flag remains set, and R0 points to an error block on exit (known as _error-returning_) #* If the X bit was clear before the routine, then RISC OS deals with the error itself. It does this by passing the error to the error handler used by the program (known as _error-generating_) 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: * Add the value &20000 to the SWI number * Add the letter 'X' in front of the SWI name; thus [[OS_WriteC]] becomes XOS_WriteC 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. # RISC OS informs modules of the error using [[OS_ServiceCall]] (service number 6) so that it can tidy up. e.g. close files, and so on, before RISC OS handles the error # RISC OS then calls the error vector ([[ErrorV]]), so it may tidy up (if required). The vector can be claimed, however, the error handler must deal with the error, and not your program h4. Error numbers 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 [[SWI Error Block|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: * The bottom byte is known as the basic error number * The middle two bytes identifies the cause of the error * The top byte contains flags; as detailed below |_<^{width:4em}. 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| h4. Generating errors 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. h3(#modules). Writing system extension code 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). h3(#allocate). Allocating SWIs 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":/content/allocate. When registering a SWI, a Chunk Name must be provided, and this will be used as part of the SWI name. e.g. <i>ChunkName</i>_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":#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. h6. Controlling sources: "Hdr:SWIs":https://gitlab.riscosopen.org/RiscOS/Sources/Programmer/HdrSrc/-/blob/master/hdr/SWIs managed by the "allocations manager":/content/allocate h4. See also * [[SWI Error Block]]