RISCOS.com

www.riscos.com Technical Support:
Programmer's Reference Manual

 

Hardware vectors


Introduction and Overview

This chapter describes the ways in which the 32 bit processor configuration used by RISC OS 3.5 and later affects exception handling. If you are writing any exception handler, you must read both this chapter and Hardware vectors.

Exceptions

Introduction

Exceptions arise whenever there is a need for the normal flow of program execution to be broken, so that (for instance) the processor can be diverted to handle an interrupt from a peripheral. The processor state just prior to handling the exception must be preserved so that the original program can be resumed when the exception routine has completed. Many exceptions may arise at the same time.

ARM handles exceptions by making use of the banked registers to save state. The old PC and PSR are copied, under RISC OS 3.1 or earlier (ie on a 26 bit addressing ARM) to the appropriate R14, or under RISC OS 3.5 or later (ie on a 32 bit configured ARM) to the appropriate R14 and SPSR. The PC and processor mode bits are forced to a value which depends on the exception. Interrupt disable flags are set where required to prevent otherwise unmanageable nestings of exceptions. In the case of a re-entrant interrupt handler, R14 should be saved onto a stack in main memory before re-enabling the interrupt. When multiple exceptions arise simultaneously a fixed priority determines the order in which they are handled.

FIQ (Fast interrupt request)

The FIQ (Fast Interrupt reQuest) exception is externally generated by taking the FIQ pin LOW. This input can accept asynchronous transitions, and is delayed by one clock cycle for synchronisation before it can affect the processor execution flow. It is designed to support a data transfer or channel process, and has sufficient private registers to remove the need for register saving in such applications, so that the overhead of context switching is minimised.

The FIQ exception may be disabled by setting the F flag in the PSR (but note that this is not possible from User mode). If the F flag is clear ARM checks for a LOW level on the output of the FIQ synchroniser at the end of each instruction.

When ARM is successfully FIQed it will:

  1. Save R15 in R14_fiq, and (for RISC OS 3.5 or later) save the CPSR in SPSR_fiq.
  2. Force the mode bits to FIQ mode and set the F and I bits in the PSR.
  3. Force the PC to fetch the next instruction from address &1C.

To return normally from FIQ use:

SUBS PC,R14_fiq,#4

This will resume execution of the interrupted code sequence, and restore the original mode and interrupt enable state.

IRQ (Interrupt request)

The IRQ (Interrupt ReQuest) exception is a normal interrupt caused by a LOW level on the IRQ pin. This input can accept asynchronous transitions, and is delayed by one clock cycle for synchronisation before it can affect processor execution. It has a lower priority than FIQ, and is masked out when a FIQ sequence is entered. Its effect may be masked out at any time by setting the I bit in the PC (but note that this is not possible from user mode). If the I flag is clear ARM checks for a LOW level on the output of the IRQ synchroniser at the end of each instruction.

When ARM is successfully IRQed it will:

  1. Save R15 in R14_irq, and (for RISC OS 3.5 or later) save the CPSR in SPSR_irq.
  2. Force the mode bits to IRQ mode and set the I bit in the PSR.
  3. Force the PC to fetch the next instruction from address &18.

To return normally from IRQ use:

SUBS PC,R14_irq,#4

This will restore the original processor state and thereby re-enable IRQ.

Address exception trap

Under RISC OS 3.5 or later, address exceptions are never generated, and you may therefore ignore this section.

Under RISC OS 3.1 or earlier, an address exception arises whenever a data transfer is attempted with a calculated address above &3FFFFFF. The ARM address bus is 26 bits wide, but an address calculation has a 32 bit result. If this result has a logic '1' in any of the top 6 bits it is assumed that the address overflow is an error, and the address exception trap is taken.

Note that a branch cannot cause an address exception, and a block data transfer instruction which starts in the legal area but increments into the illegal area will not trap (it wraps round to address 0 instead). The check is performed only on the address of the first word to be transferred.

When an address exception is seen ARM will:

  1. If the data transfer was a store, force it to load. (This protects the memory from spurious writing.)
  2. Complete the instruction, but prevent internal state changes where possible. The state changes are the same as if the instruction had aborted on the data transfer.
  3. Save R15 in R14_svc.
  4. Force the mode bits to SVC mode and set the I bit in the PSR.
  5. Force the PC to fetch the next instruction from address &14.

Normally an address exception is caused by erroneous code, and it is inappropriate to resume execution. If a return is required from this trap, use SUBS PC,R14_svc,#4. This will return to the instruction after the one causing the trap.

Abort

The Abort signal comes from an external Memory Management system, and indicates that the current memory access cannot be completed. ARM checks for an Abort at the end of the first phase of each bus cycle. When successfully Aborted ARM will respond in one of three ways.

Abort during instruction prefetch

If abort is signalled during an instruction prefetch (a Prefetch abort), the prefetched instruction is marked as invalid; when it comes to execution, it is reinterpreted as below. (If the instruction is not executed, for example as a result of a branch being taken while it is in the pipeline, the abort will have no effect.)

Then ARM will:

  1. Save R15 in R14_svc, or (for RISC OS 3.5 or later) save R15 in R14_abt and save the CPSR in SPSR_abt.
  2. Force the mode bits to SVC mode or (for RISC OS 3.5 or later) ABT mode and set the I bit in the PSR.
  3. Force the PC to fetch the next instruction from address &0C.

To continue after a Prefetch abort use SUBS PC,R14,#4 (where R14 is R14_svc or R14_abt depending on the version of RISC OS). The ARM will then re-execute the aborting instruction, so you should ensure that you have removed the cause of the original abort.

Abort during data access

If the abort command occurs during a data access (a Data Abort), the action depends on the instruction type.

  • Single data transfer instructions (LDR and STR) are aborted as though the instruction had not executed.
  • Block data transfer instructions (LDM and STM) complete, and if writeback is set, the base is updated. If the instruction would normally have overwritten the base with data (ie LDM with the base in the transfer list), this overwriting is prevented. All register overwriting is prevented after the Abort is indicated, which means in particular that R15 (which is always last to be transferred) is preserved in an aborted LDM instruction.

Then ARM will:

  1. Save R15 in R14_svc, or (for RISC OS 3.5 or later) save R15 in R14_abt and save the CPSR in SPSR_abt.
  2. Force the mode bits to SVC mode or (for RISC OS 3.5 or later) ABT mode and set the I bit in the PSR.
  3. Force the PC to fetch the next instruction from address &10.

To continue after a data abort, remove the cause of the abort, then reverse any auto-indexing that the original instruction may have done, then return to the original instruction with SUBS PC,R14,#8 (where R14 is R14_svc or R14_abt depending on the processor configuration).

Abort during an internal cycle

The ARM ignores aborts signalled during internal cycles.

Using aborts to implement virtual memory systems

The abort mechanism allows a 'demand paged virtual memory system' to be implemented when a suitable memory management unit (such as MEMC) is available. The processor is allowed to generate arbitrary addresses, and when the data at an address is unavailable the memory manager signals an abort. The processor traps into system software which must work out the cause of the abort, make the requested data available, and retry the aborted instruction. The application program needs no knowledge of the amount of memory available to it, nor is its state in any way affected by the abort.

Software interrupt

The software interrupt instruction is used for getting into supervisor mode, usually to request a particular supervisor function. ARM will:

  1. Save R15 in R14_svc, and (for RISC OS 3.5 or later) save the CPSR in SPSR_svc.
  2. Force the mode bits to SVC mode and set the I bit in the PSR.
  3. Force the PC to fetch the next instruction from address &8.

To return from a SWI, use MOVS PC,R14_svc. This returns to the instruction following the SWI.

Undefined instruction trap

When ARM executes a coprocessor instruction or an undefined instruction, it offers it to any coprocessors which may be present. If a coprocessor can perform this instruction but is busy at that moment, ARM will wait until the coprocessor is ready. If no coprocessor can handle the instruction ARM will take the undefined instruction trap.

When the undefined instruction trap is taken ARM will:

  1. Save R15 in R14_svc, or (for RISC OS 3.5 or later) save R15 in R14_und and save the CPSR in SPSR_und.
  2. Force the mode bits to SVC mode or (for RISC OS 3.5 or later) UND mode and set the I bit in the PSR.
  3. Force the PC to fetch the next instruction from address &4.

The undefined instruction trap may be used for software emulation of a coprocessor in a system which does not have the coprocessor hardware; or for general purpose instruction set extension by software emulation (the floating point instruction set is implemented in software this way).

To return from this trap (after performing a suitable emulation of the required function), use MOVS PC,R14 (where R14 is R14_svc or R14_und depending on the processor configuration). This will return to the instruction following the undefined instruction.

Reset

ARM can be reset by pulling its RESET pin HIGH. If this happens, ARM will stop the currently executing instruction and start executing no-ops. When RESET goes LOW again, it will:

  1. Save R15 in R14_svc, and (for RISC OS 3.5 or later) save the CPSR in SPSR_svc.
  2. Force the mode bits to SVC mode and set the F and I bits in the PSR.
  3. Force the PC to fetch the next instruction from address &0.
Vector summary

The first eight words of store normally contain branch instructions pointing to the relevant routines. The FIQ routine may reside at &000001C onwards, and thereby avoid the need for (and execution time of) a branch instruction.

Address Definition
&0000000 Reset
&0000004 Undefined instruction
&0000008 Software interrupt
&000000C Abort (prefetch)
&0000010 Abort (data)
&0000014 Address exception
&0000018 IRQ
&000001C FIQ
Exception Priorities

When multiple exceptions arise at the same time, a fixed priority system determines the order in which they will be handled:

  1. Reset (highest priority)
  2. Address exception, Data abort
  3. FIQ
  4. IRQ
  5. Prefetch abort
  6. Undefined Instruction, Software interrupt (lowest priority)

Note that not all exceptions can occur at once. Address exception and data abort are mutually exclusive, since if an address is illegal the ARM will ignore the ABORT input. Undefined instruction and software interrupt are also mutually exclusive since they each correspond to particular (non-overlapping) decodings of the current instruction.

If an address exception or data abort occurs at the same time as a FIQ, and FIQs are enabled (ie the F flag in the PSR is clear), ARM will enter the address exception or data abort handler and then immediately proceed to the FIQ vector. A normal return from FIQ will cause the address exception or data abort handler to resume execution. Placing address exception and data abort at a higher priority than FIQ is necessary to ensure that the transfer error does not escape detection, but the time for this exception entry should be added to worst case FIQ latency calculations.

The pre-veneers

To ensure easy backward compatibility, versions of RISC OS from 3.5 onwards install a pre-veneer on all hardware vectors apart from FIQ (see the chapter entitled Writing to the FIQ vector) and address exception (which is never generated by a 32 bit configured ARM). Each pre-veneer first sets up R14 to contain a combined PC and PSR that will return the processor to the 26 bit mode it was in when the exception arose. It then places the processor in the privileged 26 bit mode used by the earlier 26 bit chips for that exception. It thus effectively fakes the behaviour of earlier versions of RISC OS that run on those chips.

The pre-veneer is called before any exception handlers that are installed with software interfaces such as OS_ChangeEnvironment, so you can usually use such exception handlers unchanged on all versions of RISC OS (hardware dependencies excepted).

Entering 32 bit modes

One consequence of this is that you may not enter a 32 bit mode with IRQs enabled. Were you to do so, and an IRQ were to occur, the IRQ pre-veneer would be entered; then the IRQ handler would return you to a 26 bit mode, rather than the 32 bit mode you were in at the time of the IRQ.

Note that you shouldn't use 32 bit modes except for writing exception handlers; see the chapter entitled Running 32 bit code.

Claiming the hardware vectors

Under earlier versions of RISC OS, you could also claim the hardware vectors directly, by overwriting the existing instruction on the vector, and replacing it afterwards. It was your responsibility to do any housekeeping, in particular checking for subsequent claimants before restoring the original instruction.

Under 32 bit aware versions of RISC OS, if you attempt to write to any hardware vector other than FIQ a data abort is generated. You must instead call the new SWI OS_ClaimProcessorVector, passing it the address of your exception handler. The handler is installed on the vector, and is called directly, before the pre-veneers. Such handlers are therefore entered in a 32 bit mode.

For handlers installed directly on the vector to work across all versions of RISC OS, you must therefore change the method of claiming and releasing the vector depending on the version of RISC OS:

  • On versions up to RISC OS 3.1, you must write directly to the vector, doing any appropriate housekeeping yourself
  • On later versions you must call OS_ClaimProcessorVector.

Your handler must also cope with running in both 26 bit and 32 bit modes.

Writing to the FIQ vector

On a 32 bit architecture ARM, the FIQ vector is entered in FIQ mode (i.e. the 32 bit form of the mode). There are no pre-veneers to simulate 26 bit behaviour. To install a FIQ handler, you must write directly to the FIQ vector, just as always.

The sample code below is the recommended way to write to the FIQ vector on both 26 and 32 bit configured processors - you can use the same code on all versions of RISC OS. Obviously the handler you install must cope with running in both 26 bit and 32 bit FIQ modes. In practice this is unlikely to be a problem, and most existing handlers will run unchanged once installed.

In the code, comments that are prefixed by '32:' apply to a 32 bit configured processor, and comments that are prefixed by '26:' apply to a 26 bit configured processor.

; We assume that at this point, you are already in a privileged 26 bit mode.
        ; 26: Does not alter processor mode. Reads as follows:
        ; NOP                           ; 26: Encodes a NOP (TST Ra,R0)
        ; Push  Ra                      ; 26: Pushes entry Ra onto stack
        ; ORR   Ra, Ra, #2_11000000     ; 26: Corrupts Ra
        ; NOP                           ; 26: Encodes a NOP (TEQ R9,Ra)
        ; ORR   Ra, Ra, #2_10000        ; 26: Corrupts Ra
        ; NOP                           ; 26: Encodes a NOP (TEQ R9,Rb)
        ; 32: Switch to _32 mode with IRQs and FIQs off.
        ; 32: Must switch interrupts off before switching mode as there can be
        ; 32: an interrupt after the MSR instruction but before the next one.
        MRS     Ra, CPSR_all            ; 32: Read privileged 26 bit mode,
        Push    Ra                      ; 32: and push it onto the stack
        ORR     Ra, Ra, #2_11000000     ; 32: Set IRQ and FIQ disable bits
        MSR     CPSR_all, Ra            ; 32: Disable IRQs and FIQs
        ORR     Ra, Ra, #2_10000        ; 32: Set M4 bit (for 32 bit mode)
        MSR     CPSR_all, Ra            ; 32: Change to 32 bit mode
        ; Now do a NOP, to let things settle down:
        NOP                             ; e.g. MOV R0,R0
; Now in a suitable mode to write FIQ handler code to FIQ vector
; (&1C-&FC incl.), whatever the processor configuration.
; Code written should be able to run in both fiq_32 and fiq_26 modes,
; and should end with a SUBS PC,R14,#4 to return normally.
; For example we might write the handler code like this:
        ; Assume Rb already points to location from which to copy the handler.
        MOV     LR, #FIQVector          ; Get address of FIQ vector
40      LDR     Ra, [Rb], #4            ; Get opcode.
        TEQS    Ra, #0                  ; All done?
        STRNE   Ra, [LR], #4            ; No, so copy to FIQ area...
        BNE     %BT40                   ; ...and repeat for next opcode.
        ; The above may not be optimal, and is for illustration only.
; Having written FIQ vector, now need to restore the original
; privileged 26 bit mode.
        ; 26: Does not alter processor mode. Reads as follows:
        ; PULL  Ra                      ; 26: Pull entry Ra from stack
        ; NOP                           ; 26: Encodes a NOP (TST Ra,R0)
        PULL    Ra                      ; 32: Pull saved CPSR, and
        MSR     CPSR_all, Ra            ; 32: Restore privileged 26 bit mode
; Now back where we started, except Ra and Rb should be treated as corrupted.
; (We must assume neither is preserved, because we don't know the processor
; configuration.)

SWI Calls


OS_ClaimProcessorVector
(SWI &69)

Provides a means for a module to attach itself to one of the processor's vectors

On entry

R0 = vector and flags:

Bit Meaning
0 - 7 vector number:
0 'Branch through 0' vector
1 Undefined instruction
2 SWI
3 Prefetch abort
4 Data abort
5 Address exception (only on ARM 2 and 3)
6 IRQ
(all other values reserved for future use)
8 0 => RELEASE_ 1 => claim
9 - 31 reserved, must be 0

R1 = replacement address of exception handler
R2 = address which should currently be on vector (only needed for release)

On exit

R0 preserved
R1 = address which has been replaced (only returned on claim)
R2 preserved

Interrupts

Interrupt status is undefined
Fast interrupts are enabled

Processor mode

Processor is in SVC mode

Re-entrancy

Not defined

Use

This SWI provides a means for a module to attach itself to one of the processor's vectors. This is a direct attachment; you get no environment except what the processor provides.

As such, claiming and releasing the vectors is somewhat primitive - the claims and releases must occur in the right order (the release order being the reverse of claim order). On release if the value in R2 doesn't match what is currently on the vector then an error will be returned. This ensures correct chaining of claims and releases.

Related SWIs

None

Related vectors

None

This edition Copyright © 3QD Developments Ltd 2015
Last Edit: Tue,03 Nov 2015