Documentation: Software Vectors
Programmer’s Reference Manuals
» Part 1 – Introduction
» Vectors
» Software Vectors
Overview
The kernel is responsible for the overall control of the Operating System. Extra functionality is provided by modules. Each module is responsible for a handling a specific task, such as font handing, filer windows and sound scheduling. The end result is a modular Operating System that can be easily developed, updated and extended.
Unlike modules, the kernel cannot be altered in any way. However, RISC OS does provide a method of allowing certain key routines used by the kernel to be changed or replaced. This is achieved by use of software vectors, or vectors for short.
Vector basics
When an ordinary SWI instruction is issued, RISC OS must determine which routine is requested. It does this by looking up the address of the SWI routine, and then branching to it, thereby running the routine. However, if the SWI instruction issued has a corresponding software vector (known as a vectored SWI), the required address is returned from the vector. Normally this would return the address of the standard SWI routine, although this can be altered.
By changing the address of a vectored SWI, this is called claiming a vector, To claim a vector, you use OS_Claim.
As detailed above, vectors store the address of the vectored SWI routine. This address is used by the kernel to determine which routine should be called. However, instead of just replacing an address, it is possible for multiple addresses to be added to a vector. In summary:- Multiple routines (addresses) can be added to a vector
- Vectors always points to the next address to be called
- No routine that has claimed the vector needs know about any other routine that has claimed the same vector
- Vectors can be claimed and released by any piece of software running, and in any order
- Routines are called in the reverse order to which they were claimed
If your routine completely replaces the standard routine, then it is deemed to interpret the call, otherwise it is known to pass on the call.
A vector can be claimed by any application resulting in multiple addresses being added to a vector. This means your routine can:- Replace the original SWI routine, passing control directly back to the caller
- Call the first address pointed to by the vector (which may be your routine) before calling the next address (which may be the standard routine) which then passes control back to the caller
- Call the first address pointed to by the vector (which may be the standard routine), before calling the next address (which may be your routine) and then pass control back to the caller
Claiming software vectors
To claim a vector, you use OS_Claim. This SWI actually removes any identical earlier instances of the routine from the list of addresses. If this is not desired, then it is possible to simply add an address to the list by using OS_AddToVector.
Any routine that uses a vector must use the same registers as the default routine for both entry and exit conditions.
If your routine passes the call on, you can deliberately alter some of the registers values to change the effect of the call, however, you must arrange for control to return to your routine again to restore to those that the original routine would have returned. It should then return control back to the calling program.
To remove a routine from the list of those that claim a vector, use OS_Release.
When not to intercept a vector
There are some vectors that must not be intercepted, that is, to completely replace the standard routine. This is because the standard routine (also known as the default owner), might perform an important action that must executed. A good example of this is the ErrorV? vector, which be default calls the error handler. If this vector was to be intercepted, then the error handler would never be called, and thus never dealt with.
Multitasking
RISC OS is a co-operative multitasking Operating System, that is, where each application is written to pass control back to the Window Manager after it has done what it needed to do. When multiple tasks are running concurrently, the application memory of the active task is mapped into memory at &8000. When the next application is to assume control, the current task is mapped out of memory, and the new application is mapped into the same space (at &8000).
Because of this process, any application that claims a vector, must release the vector each time it is mapped out of application space, and then reclaim it again when mapped back in. This is achieved by two SWIs:- OS_DelinkApplication – Release vectors when an application is about to be mapped out
- OS_RelinkApplication – Reclaim vectors when an application is about to be mapped back in
Error Handling
Like normal SWIs, routines using most of the vectors can return errors by setting the V flag, and making R0 point to an error block.
If an error has occurred, then the routine must not pass on the call, as R0 has changed, and this would cause problems for the next routine on the vector (if any). Instead, the routine must intercept the call, returning control back to the calling program.
However, some vectors cannot be intercepted (such as those involving IRQ calls), as there is nowhere to send the errors to.
Processor modes
The processor mode used by the routine depends on the vector:- Routines via IrqV are always executed in IRQ mode
- Routines via EventV, InsV, RemV, CmpV? and TickerV are generally executed in IRQ mode. However, they may be executed in SVC mode if called using OS_CallAVector, and in certain other unspecified circumstances
- All other routines are executed in SVC mode (the same mode when the SWI instruction is executed)
If you call a SWI from a routine that is in SVC mode you will corrupt the return address held in R14. Therefore your routine should use the full, descending stack address by R13 to save R14 first.
If your routine will entered in IRQ mode, then further restrictions apply. These are detailed in full within the Interrupts and handling them.
Returning from a vectored routine
When returning from a vectored routine, the method differs depending on whether the vector is intercepted or whether you are passing on the call. The methods are shows below:
| Passing on the call | Return by copying R14 into the Program counter |
| Intercepting the call | Pull an exit address from the stack and jump to it |
List of Software Vectors
There are many different software vectors available. The complete list is available here.