7. Non-user Modes
In the previous chapters, we have restricted ourselves to discussing the ARM while it is
operating in user mode. For most purposes, this is all that is required. For example, large
ARM programs such as the BBC BASIC interpreter manage to function entirely in user
mode. There are times, however, when a program must execute in one of the other modes
to work correctly. In this chapter, we discuss the characteristics of the non-user modes.
7.1 Extended programmer's model
Register set
As described in Chapter Two, there are four modes in which the ARM may operate. The
bottom two bits of R15 (called s1 and s0) determine the modes, as summarised below:
When the ARM is in a non-user mode, its register set differs slightly from the user mode
model. The numbering of the registers is identical, but some of the higher numbers refer to
physically distinct registers in modes 1 to 3. The complete register model for all modes is
shown overleaf. Each column shows the registers which are visible in mode 0, 1, 2 and 3
respectively.
The register names without a suffix refer to the user registers that we are used to dealing
with. As the diagram shows, each of the non- user modes has at least two registers which
are physically separate from the user mode ones. R14 is the link register, so all modes have
their own link register, and R13 is traditionally used as the stack pointer, so each mode can
have its own stack. FIQ mode has five additional private registers. These are provided so
that important information may be stored in the processor for instant access when FIQ
mode is entered.
one of the other modes. These can be divided roughly into two groups, exceptions and
interrupts. An exception occurs because a program has tried to perform an operation
which is illegal for the current mode. For example, it might attempt to access a protected
memory location, or execute an illegal instruction.
Interrupts on the other hand, occur independently of the program's actions, and are
initiated by some external device signalling the CPU. Interrupts are known as
asynchronous events, because their timing has no relationship to what occurs in the
When an exception or interrupt occurs, the processor stops what it is doing and enters one
of the non-user modes. It saves the current value of R15 in the appropriate link register
(R14_FIQ, R14_IRQ or R14_SVC), and then jumps to one of the vector locations which
The table shows the address of the vector, what causes the jump there, how the IRQ and
FIQ disable flags are affected (X meaning it's unaffected), and what mode the processor
enters. All events disable IRQs, and RESET and FIQ disable FIQs too. All events except the
interrupts cause SVC mode to be entered.
Note that the FIQ vector is the last one, and the processor has no special use for the
Vector Cause I F Mode
&0000000 RESET 1 1 SVC
&0000004 Undefined instruction 1 X SVC
&0000008 Software interrupt (SWI) 1 X SVC
&000000C Abort (prefetch) 1 X SVC
&0000010 Abort (data) 1 X SVC
&0000014 Address exception 1 X SVC
&0000018 IRQ 1 X IRQ
most readers will only ever be interested in using the interrupt vectors, and possibly the
SWIand undefined instruction ones. The rest are usually looked after by the operating
system. However, fairly detailed descriptions of what happens when all the vectors are
called are given. If nothing else, this may help you to understand the code that your
system's OS uses to deal with them.
It is important to note that many of the routines entered through the vectors expect to
return to the user program which was interrupted. To do this in a transparent way, all of
the user's registers must be preserved. The PC and flags are automatically saved whenever
a vector is called, so these can easily be restored. Additionally, all the supervisor modes
have at least two private registers the contents or which are hidden from user programs.
However, if the routine uses any registers which are not private to the appropriate mode,
these must be saved and restored before the user program is restarted. If this is not done,
programs will find register contents changing 'randomly' causing errors which are
The RESET signal is used to ensure that the whole system is in a well-defined state from
which it can start operating. RESET is applied in two situations on most systems. Firstly,
when power is first applied to the system, so- called power -on reset circuitry ensures that
the appropriate levels are applied to the RESET signals of the integrated circuits in the
computer. Secondly, there is usually a switch or button which may be used to RESET the
system manually, should this be required.
On typical ARM systems, the MEMC chip, which contains the power-on reset circuitry, is
used to control the resetting of the rest of the computer.
Upon receiving a RESET signal, the ARM immediately stops executing the current
instruction. It then waits in an 'idle' state until the RESET signal is removed. When this
happens, the following steps take place:
? SVC mode is entered
? R15 is saved in R14_SVC
? The FIQ and IRQ disable bits are set
? The PC is set to address &0000000
Although the program counter value when the RESET occurred is saved, it is not likely
that an attempt will be made to return to the program that was executing. Amongst other
reasons, the ARM may have been halfway through a long instruction (e.g. STMwith many
registers), so the affect of returning is unpredictable. However, the address and status bits
could be printed by the operating system as part of 'debugging' information.
Likely actions that are taken on reset are initialisation of I/O devices, setting up of system
memory locations, possibly ending with control being passed to some user mode program,
Not all of the possible 32-bit opcodes that the ARM may encounter are defined. Those
which are not defined to do anything are 'trapped' when the ARM attempts to decode
them. When such an unrecognised instruction code is encountered, the following occurs:
? SVC mode is entered
? R15 is saved in R14_SVC
? The IRQ disable bit is set
? The PC is set to address &0000004
The program counter that is stored in R14_SVC holds the address of the instruction after
the one which caused the trap. The usual action of the routine which handles this trap is to
try to decode the instruction and perform the appropriate operation. For example the
Acorn IEEE floating- point emulator interprets a range of floating point arithmetic
instructions. Having done this, the emulator can jump back to the user's program using
the PC saved in R15_SVC.
By trapping undefined instructions in this way, the ARM allows future expansions to the
instruction set to be made in a transparent manner. For example, an assembler could
generate the (currently unrecognised) machine codes for various operations. These would
be interpreted in software using the undefined instruction trap for now, but when a new
version of the ARM (or a co- processor) is available which recognises the instructions, they
would be executed in hardware and the undefined instruction trap would not be
This vector is used when a SWIinstruction is executed. SWIis not really an exception, nor is
it a proper interrupt since it is initiated synchronously by the program. It is, however, a
very useful feature since it enables user programs to call routines, usually part of the
operating system, which are executed in the privileged supervisor mode.
When a SWIis executed, the following happens:
? SVC mode is entered
? R15 is saved in R14_SVC
? The IRQ disable bit is set
? The PC is set to address &0000008
As with undefined instructions, the PC value stored in R14_SVC is one word after the SWI
itself. The routine called through the SWIvector can examine the code held in the lower 24
bits of the SWIinstruction and take the appropriate actions. Most systems have a welldefined set of operations which are accessible through various SWIs, and open -ended
systems also allow for the user to add his or her own SWIhandlers.
An 'abort' is caused by an attempt to access a memory or I/O location which is out of
bounds to the program that is currently executing. An abort is signalled by some device
external to the ARM asserting a signal on the CPU's ABORT line. In a typical system, this
will be done by the MEMC, which controls all accesses to memory and I/O. Typical
reasons for an abort occurring are attempts to:
? write to a read-only logical RAM page
? access physical RAM or I/O in user mode
? access a supervisor mode- only logical page in user or OS mode
? access an OS mode-only logical page in user mode
? access a logical page which has no corresponding physical page
There are two types of abort, each with its own vector. The one which is used depends on
what the ARM was trying to do when the illegal access took place. If it happened as the
ARM was about to fetch a new instruction, it is known as a pre-fetch abort. If it occurred
while the ARM was trying to load or store data in an LDR/STR/LDM/STMinstruction, it is
known as a data abort.
Virtual memory
Except for programming errors, by far the most common cause of an abort is when the
system is running what is known as virtual memory. When virtual memory is used, not all
of the program is kept in physical RAM at once. A (possible majority) part of it is kept on a
fast mass storage medium such as a Winchester disk.
Suppose a computer is fitted with 1M byte of RAM, and it is required that a program 'sees'
a memory space of 4M bytes. This 4M bytes might be located in the first part of the logical
memory map, from address &0000000 to &003FFFFF. On the Winchester disk, 4M bytes
are set aside to represent the virtual address space of the program. Now as only 1M byte
RAM is available, only a quarter of this virtual address space can be physically stored in
the computer's RAM. In the diagram overleaf, the first 1M byte of the disk area is loaded
into physical RAM and mapped into the lowest megabyte of the logical address space.
As long as the program only accesses instructions and data which lie in the
first megabyte of the logical address space, a mapping into physical RAM
will be found by the MEMC and no problems will occur. Suppose, however, that the
program attempts to access logical address 2,000,0000. There is no physical RAM which
corresponds to this logical address, so MEMC will signal this fact to the processor using its
ABORT line.
The abort handler program responds to an abort in the following way. First, it discovers
what logical address the program was trying to access. It then allocates a page of physical
RAM which can hold the page of virtual memory corresponding to this address. The
appropriate data is loaded in from the disk, and the logical to physical address map in the
MEMC adjusted so that when the processor next tries to access the location which caused
the abort, the newly- loaded data will be accessed.
Now when a new page of virtual memory is loaded from disk, the previous contents of the
area of physical memory used to store it must be discarded. This means that a range of
addresses which used to be accessible will now cause an abort if an attempt is made to
access them. Moreover, if that page contained data which has changed since it was first
loaded from the disk, it must be re -written to the disk before the new page can be loaded.
This ensures that the virtual memory on the disk is consistent with what is held in the
RAM.
It is up to the software which deals with aborts to decide which page to discard when
fetching a new page from the disk, and whether it needs to be written out before it is
destroyed by the new data. (If the re - allocated page contain a part of the program, or read
only data, then it is not necessary to write it to the disk first, since the copy already stored
there will be correct.) There are several algorithms which are used to decide the way in
which pages are re-allocated in response to aborts (which are often called 'page faults').
For example, the so -called 'least recently used' algorithm will use the page which has not
been accessed for the longest period of time, on the assumption that it is not likely to be
required in the near future.
This may all seem incredibly slow and cumbersome, but in practice demand -paged virtual
memory systems work well for the following reasons. Aborts are relatively infrequent as
programs spend a lot of their time in small loops. ARM systems using MEMC have a fairly
large page size (between 8K and 32K) so a program can spend a lot of its time in a single
page without encountering 'missing' RAM. Additionally, virtual memory is often used on
multi- tasking systems, where more than one program runs at once by sharing the CPU for
short time slots. While the relatively slow transfer of data between RAM and disk is taking
place, another program can be using the CPU. This means that although one program
might be held up waiting for a segment of its virtual address space to be loaded from disk,
another program whose program and data are in physical RAM can proceed.
The subject of virtual memory is a complex one which is covered in a variety of text books.
A good one is 'The Design of the Unix Operating System' by MJ Bach, published by
When a pre-fetch abort occurs, the ARM completes the instruction(s) before the one which
'aborted'. When this instruction comes to be executed, it is ignored and the following takes
place:
? SVC mode is entered
? R15 is saved in R14_SVC
? The IRQ disable bit is set
? The PC is set to address &000000C
The PC value saved is the one after the instruction which caused the abort. The routine
which deals with the pre-fetch abort must perform some action, as outlined above, which
will enable the instruction to be re-tried and this time succeed.
A simple single-tasking (one program at once) operating system running virtual memory
might take the following steps on receiving a pre -fetch abort:
? verify that it is a missing page problem (not access violation)
? enable IRQs
? find a suitable page of physical RAM
? load the page corresponding to the required logical address
? set-up MEMC to map the physical to logical page
? re-try the instruction by jumping to R14_SVC minus 4
It is important to re - enable IRQs so that the normal servicing of interrupts is not disturbed
while the new page is being loaded in. The third step may itself be quite involved, since a
decision has to be made about which physical page is suitable for loading in the new
section of the program and whether its current contents must be saved, as mentioned
A data abort is a little more complex, since the ARM is halfway through the instruction by
the time the abort occurs. If the instruction was an LDRor STR, it is abandoned and no
registers are altered (in particular, the base register is unchanged, even if write -back was
specified).
If the instruction was an LDMor STM, the instruction completes (though no registers are
altered in an LDM), and the base register is updated if write - back was enabled. Note that if
the base register was included in the list of registers to be loaded, it is not over -written as
would normally be the case. The (possibly written-back) value is left intact. Then:
? SVC mode is entered
? R15 is saved in R14_SVC
? The IRQ disable bit is set
? The PC is set to address &0000010
This time, R14_SVC is set to the instruction two words after the aborted one, not one. The
abort handler routine must take the following action. It must examine the aborted
instruction to find out the type and address mode, and undo the affect of any adjustment
of the base register due to write - back. It can derive the address of the data which caused
the abort to occur from the base register, and perform a similar paging process to that
described for pre -fetch aborts. It can then re -execute the instruction, by jumping to address
R14_SVC minus 8 using an instruction such as:
SUB pc,link,#8
The time taken to decode the instruction which caused the abort and perform the
appropriate operations varies according to instruction type, number of registers (for
LDM/STM), type of indexing (for LDR/STR) and whether write -back was enabled. Calculations
made from typical abort- handler code result in times of between 20 s+41n -cycles for the
best case and 121 s+36 n - cycles for the worst case. On an 8MHz ARM system, these
translate into approximately 13.4us and 27.1us respectively.
7.7 Address exception
An address exception occurs if an attempt is made to access a location outside the range of
the ARM's 26 -bit address bus. This can be caused by the effective address (base plus any
offset) of an LDR/STRinstruction exceeding the value &3FFFFFF, or if the base register in an
LDM/STMinstruction contains a value greater than this.
Note that in the latter case, the exception will only occur if the base register is illegal when
the instruction starts to execute. If it is legal for the first data transfer, and subsequently
exceeds &3FFFFFF having been auto-incremented, no exception occurs. Instead the
address 'wraps round' and subsequent loads or stores take place in the first few locations
of the memory map.
Unlike the aborts described above, the address exception is detected internally by the
ARM, and not by the assertion of a signal by some external device. Like data aborts,
however, the incorrect instruction is abandoned or 'completed' as described above.
On detecting the address error, the ARM causes the following to take place:
? SVC mode is entered
? R15 is saved in R14_SVC
? The IRQ disable bit is set
? The PC is set to address &0000014
If it is required that the instruction be re -started after an address exception has been
generated, the address in R14_SVC minus 4 can be used. However, there is usually not
much point and the usual action is to enter a 'monitor' program which can be used to try
IRQ stands for Interrupt ReQuest, and is one of two interrupt inputs on the ARM. An
external device signals to the ARM that it requires attention by asserting the IRQ line. At
the end of every instruction's execution, the ARM checks for the presence of an IRQ. If an
interrupt request has been made, and IRQs are enabled, the following happens:
? IRQ mode is entered
? R15 is saved in R14_IRQ
? The IRQ disable bit is set
? The PC is set to address &0000018
If IRQs are disabled, because the IRQ disable bit in the status register is set, the interrupt is
ignored and the ARM continues its normal processing. Note that on initiating an IRQ
routine, the ARM stes the IRQ, so further IRQs are disabled.
The routine handling the interrupt must take the appropriate action, which will result in
the interrupting device removing its request. For example, a serial communications device
might cause an IRQ when a byte is available for reading. The IRQ routine, on discovering
which device caused the interrupt, would read the data byte presented by the serial chip,
and buffer it somewhere for later reading by a program. The action of reading a byte from
the serial chip typically informs the device that its IRQ has been serviced and it 'drops' the
interrupt request.
On the ARM, the interrupt disable bits and processor mode bits in the status register
cannot be altered in user mode. This means that user mode programs typically execute
with both types of interrupt enabled, so that the 'background' work of servicing
interrupting devices can take place. However, it is sometimes desirable to disable all
interrupts, and there is typically a SWIcall provided by the operating system which allows
the interrupt masks to be changed by user mode programs.
The following few paragraphs refer to the writing of both IRQ and FIQ routines.
Interrupt routines must be quick in execution, because while the interrupt is being
serviced, the main program cannot progress. The Acorn IOC (I/O controller) chip provides
some support for dealing with interrupts which makes their processing more efficient. For
example, it provides several IRQ inputs so that many devices may share the ARM's single
IRQ line. These inputs may be selectively enabled/disabled, and a register in the IOC may
be read to find which devices at any time require servicing.
An interrupt routine usually has limitations imposed on what it can do. For example, it is
undesirable for an interrupt handler to re -enable interrupts. If it does, another IRQ may
come along which causes the handler to be called again, i.e. the routine is re-entered.
It is possible to write code which can cope with this, and such routines are known as reentrant. Amongst other things, re -entrant routines must not use any absolute workspace,
and must preserve the contents of all registers that they use (which all interrupt routines
should do anyway). The first restriction means that the stack should be used for all
workspace requirements of the routine, including saving the registers. This ensures that
each re -entered version of the routine will have its own work area.
Unfortunately, it is common to find that operating system routines are impossible to write
in a re-entrant fashion. This means that it is not possible to use many operating system
routines from within interrupt service code. A common example is to find that a machine's
output character routine is executed with interrupts enabled and is not re - entrant. (The
reason is that in some circumstances, e.g. clearing the screen, the output routine might
take several milliseconds, or even seconds, and it would be unwise to disable interrupts
for this long.)
You should consult your system's documentation to find out the exact restrictions about
using OS routines from within interrupt service code.
Interrupt routines should also be careful about not corrupting memory that might be used
by the 'foreground' program. Using the stack for all workspace is one way to avoid this
problem. However, this is not always possible (for example, if the IRQ routine has to
access a buffer used by the foreground program). You should always endeavour to restrict
the sharing of locations by interrupt and non-interrupt code to a bare minimum. It is very
hard to track down bugs which are caused by locations being changed by something
outside the control of the program under consideration.
To return to the user program, the IRQ routine subtracts 4 from the PC saved in R14_IRQ
and places this in R15. Note that this saved version will have the IRQ disable bit clear, so
as well as returning to the main program, the transfer causes IRQs to be re -enabled.
7.9 FIQ
FIQ stands for Fast Interrupt reQuest. A signal on the ARM's FIQ input causes FIQ mode
to be entered, if enabled. As with IRQs, the ARM checks at the end of each instruction for a
FIQ. If both types of interrupt occur at the same time, the FIQ is handled first. In this
respect, it has a higher priority than IRQ. On responding to a FIQ, the ARM initiates the
following actions:
? FIQ mode is entered
? R15 is saved in R14_FIQ
? The FIQ and IRQ disable bits are set
? The PC is set to address &000001C
Notice that a FIQ disables subsequent FIQs and IRQs, so that whereas a FIQ can interrupt
an IRQ, the reverse is not true (unless the FIQ handler explicitly enables IRQs).
The term 'fast' for this type of interrupt is derived from a couple of its properties. First, FIQ
mode has more 'private' registers than the other supervisor modes. This means that in
order for a FIQ routine to do its job, it has to spend less time preserving any user registers
that it uses than an IRQ routine would. Indeed, it is common for a FIQ routine not to use
any user registers at all, the private ones being sufficient. Secondly, the FIQ vector was
cleverly made the last one. This means that there is no need to have a branch instruction at
address &000001C. Instead, the routine itself can start there, saving valuable microseconds
(or fractions thereof).
To return to the user program, the FIQ routine subtracts 4 from the PC saved in R14_FIQ
and places this in R15 (i.e. the PC). Note that this saved version will have the FIQ disable
bit clear, so as well as returning to the interrupted program, the transfer causes FIQs to be
re-enabled.
In the previous chapters, we have restricted ourselves to discussing the ARM while it is
operating in user mode. For most purposes, this is all that is required. For example, large
ARM programs such as the BBC BASIC interpreter manage to function entirely in user
mode. There are times, however, when a program must execute in one of the other modes
to work correctly. In this chapter, we discuss the characteristics of the non-user modes.
7.1 Extended programmer's model
Register set
As described in Chapter Two, there are four modes in which the ARM may operate. The
bottom two bits of R15 (called s1 and s0) determine the modes, as summarised below:
When the ARM is in a non-user mode, its register set differs slightly from the user mode
model. The numbering of the registers is identical, but some of the higher numbers refer to
physically distinct registers in modes 1 to 3. The complete register model for all modes is
shown overleaf. Each column shows the registers which are visible in mode 0, 1, 2 and 3
respectively.
The register names without a suffix refer to the user registers that we are used to dealing
with. As the diagram shows, each of the non- user modes has at least two registers which
are physically separate from the user mode ones. R14 is the link register, so all modes have
their own link register, and R13 is traditionally used as the stack pointer, so each mode can
have its own stack. FIQ mode has five additional private registers. These are provided so
that important information may be stored in the processor for instant access when FIQ
mode is entered.
7.2 Leaving user mode
There are several circumstances in which a program executing in user mode might enterone of the other modes. These can be divided roughly into two groups, exceptions and
interrupts. An exception occurs because a program has tried to perform an operation
which is illegal for the current mode. For example, it might attempt to access a protected
memory location, or execute an illegal instruction.
Interrupts on the other hand, occur independently of the program's actions, and are
initiated by some external device signalling the CPU. Interrupts are known as
asynchronous events, because their timing has no relationship to what occurs in the
program.
When an exception or interrupt occurs, the processor stops what it is doing and enters one
of the non-user modes. It saves the current value of R15 in the appropriate link register
(R14_FIQ, R14_IRQ or R14_SVC), and then jumps to one of the vector locations which
starts at address &0000000.
There are eight vectors, corresponding to eight possible types of situation which cause the
current operation to be abandoned. They are listed overleaf:
The table shows the address of the vector, what causes the jump there, how the IRQ and
FIQ disable flags are affected (X meaning it's unaffected), and what mode the processor
enters. All events disable IRQs, and RESET and FIQ disable FIQs too. All events except the
interrupts cause SVC mode to be entered.
Note that the FIQ vector is the last one, and the processor has no special use for the
Vector Cause I F Mode
&0000000 RESET 1 1 SVC
&0000004 Undefined instruction 1 X SVC
&0000008 Software interrupt (SWI) 1 X SVC
&000000C Abort (prefetch) 1 X SVC
&0000010 Abort (data) 1 X SVC
&0000014 Address exception 1 X SVC
&0000018 IRQ 1 X IRQ
&000001C FIQ 1 1 FIQ
placed at location directly &1C, instead of a branch to it.
most readers will only ever be interested in using the interrupt vectors, and possibly the
SWIand undefined instruction ones. The rest are usually looked after by the operating
system. However, fairly detailed descriptions of what happens when all the vectors are
called are given. If nothing else, this may help you to understand the code that your
system's OS uses to deal with them.
It is important to note that many of the routines entered through the vectors expect to
return to the user program which was interrupted. To do this in a transparent way, all of
the user's registers must be preserved. The PC and flags are automatically saved whenever
a vector is called, so these can easily be restored. Additionally, all the supervisor modes
have at least two private registers the contents or which are hidden from user programs.
However, if the routine uses any registers which are not private to the appropriate mode,
these must be saved and restored before the user program is restarted. If this is not done,
programs will find register contents changing 'randomly' causing errors which are
exceedingly difficult to track down.
The RESET signal is used to ensure that the whole system is in a well-defined state from
which it can start operating. RESET is applied in two situations on most systems. Firstly,
when power is first applied to the system, so- called power -on reset circuitry ensures that
the appropriate levels are applied to the RESET signals of the integrated circuits in the
computer. Secondly, there is usually a switch or button which may be used to RESET the
system manually, should this be required.
On typical ARM systems, the MEMC chip, which contains the power-on reset circuitry, is
used to control the resetting of the rest of the computer.
Upon receiving a RESET signal, the ARM immediately stops executing the current
instruction. It then waits in an 'idle' state until the RESET signal is removed. When this
happens, the following steps take place:
? SVC mode is entered
? R15 is saved in R14_SVC
? The FIQ and IRQ disable bits are set
? The PC is set to address &0000000
Although the program counter value when the RESET occurred is saved, it is not likely
that an attempt will be made to return to the program that was executing. Amongst other
reasons, the ARM may have been halfway through a long instruction (e.g. STMwith many
registers), so the affect of returning is unpredictable. However, the address and status bits
could be printed by the operating system as part of 'debugging' information.
Likely actions that are taken on reset are initialisation of I/O devices, setting up of system
memory locations, possibly ending with control being passed to some user mode program,
e.g. BASIC.
Not all of the possible 32-bit opcodes that the ARM may encounter are defined. Those
which are not defined to do anything are 'trapped' when the ARM attempts to decode
them. When such an unrecognised instruction code is encountered, the following occurs:
? SVC mode is entered
? R15 is saved in R14_SVC
? The IRQ disable bit is set
? The PC is set to address &0000004
The program counter that is stored in R14_SVC holds the address of the instruction after
the one which caused the trap. The usual action of the routine which handles this trap is to
try to decode the instruction and perform the appropriate operation. For example the
Acorn IEEE floating- point emulator interprets a range of floating point arithmetic
instructions. Having done this, the emulator can jump back to the user's program using
the PC saved in R15_SVC.
By trapping undefined instructions in this way, the ARM allows future expansions to the
instruction set to be made in a transparent manner. For example, an assembler could
generate the (currently unrecognised) machine codes for various operations. These would
be interpreted in software using the undefined instruction trap for now, but when a new
version of the ARM (or a co- processor) is available which recognises the instructions, they
would be executed in hardware and the undefined instruction trap would not be
triggered. The only difference the user would notice is a speed-up in his programs.
This vector is used when a SWIinstruction is executed. SWIis not really an exception, nor is
it a proper interrupt since it is initiated synchronously by the program. It is, however, a
very useful feature since it enables user programs to call routines, usually part of the
operating system, which are executed in the privileged supervisor mode.
When a SWIis executed, the following happens:
? SVC mode is entered
? R15 is saved in R14_SVC
? The IRQ disable bit is set
? The PC is set to address &0000008
As with undefined instructions, the PC value stored in R14_SVC is one word after the SWI
itself. The routine called through the SWIvector can examine the code held in the lower 24
bits of the SWIinstruction and take the appropriate actions. Most systems have a welldefined set of operations which are accessible through various SWIs, and open -ended
systems also allow for the user to add his or her own SWIhandlers.
To return to the user's program, the SWIroutine transfers R14_SVC into R15.
An 'abort' is caused by an attempt to access a memory or I/O location which is out of
bounds to the program that is currently executing. An abort is signalled by some device
external to the ARM asserting a signal on the CPU's ABORT line. In a typical system, this
will be done by the MEMC, which controls all accesses to memory and I/O. Typical
reasons for an abort occurring are attempts to:
? write to a read-only logical RAM page
? access physical RAM or I/O in user mode
? access a supervisor mode- only logical page in user or OS mode
? access an OS mode-only logical page in user mode
? access a logical page which has no corresponding physical page
There are two types of abort, each with its own vector. The one which is used depends on
what the ARM was trying to do when the illegal access took place. If it happened as the
ARM was about to fetch a new instruction, it is known as a pre-fetch abort. If it occurred
while the ARM was trying to load or store data in an LDR/STR/LDM/STMinstruction, it is
known as a data abort.
Virtual memory
Except for programming errors, by far the most common cause of an abort is when the
system is running what is known as virtual memory. When virtual memory is used, not all
of the program is kept in physical RAM at once. A (possible majority) part of it is kept on a
fast mass storage medium such as a Winchester disk.
Suppose a computer is fitted with 1M byte of RAM, and it is required that a program 'sees'
a memory space of 4M bytes. This 4M bytes might be located in the first part of the logical
memory map, from address &0000000 to &003FFFFF. On the Winchester disk, 4M bytes
are set aside to represent the virtual address space of the program. Now as only 1M byte
RAM is available, only a quarter of this virtual address space can be physically stored in
the computer's RAM. In the diagram overleaf, the first 1M byte of the disk area is loaded
into physical RAM and mapped into the lowest megabyte of the logical address space.
As long as the program only accesses instructions and data which lie in the
first megabyte of the logical address space, a mapping into physical RAM
will be found by the MEMC and no problems will occur. Suppose, however, that the
program attempts to access logical address 2,000,0000. There is no physical RAM which
corresponds to this logical address, so MEMC will signal this fact to the processor using its
ABORT line.
The abort handler program responds to an abort in the following way. First, it discovers
what logical address the program was trying to access. It then allocates a page of physical
RAM which can hold the page of virtual memory corresponding to this address. The
appropriate data is loaded in from the disk, and the logical to physical address map in the
MEMC adjusted so that when the processor next tries to access the location which caused
the abort, the newly- loaded data will be accessed.
Now when a new page of virtual memory is loaded from disk, the previous contents of the
area of physical memory used to store it must be discarded. This means that a range of
addresses which used to be accessible will now cause an abort if an attempt is made to
access them. Moreover, if that page contained data which has changed since it was first
loaded from the disk, it must be re -written to the disk before the new page can be loaded.
This ensures that the virtual memory on the disk is consistent with what is held in the
RAM.
It is up to the software which deals with aborts to decide which page to discard when
fetching a new page from the disk, and whether it needs to be written out before it is
destroyed by the new data. (If the re - allocated page contain a part of the program, or read
only data, then it is not necessary to write it to the disk first, since the copy already stored
there will be correct.) There are several algorithms which are used to decide the way in
which pages are re-allocated in response to aborts (which are often called 'page faults').
For example, the so -called 'least recently used' algorithm will use the page which has not
been accessed for the longest period of time, on the assumption that it is not likely to be
required in the near future.
This may all seem incredibly slow and cumbersome, but in practice demand -paged virtual
memory systems work well for the following reasons. Aborts are relatively infrequent as
programs spend a lot of their time in small loops. ARM systems using MEMC have a fairly
large page size (between 8K and 32K) so a program can spend a lot of its time in a single
page without encountering 'missing' RAM. Additionally, virtual memory is often used on
multi- tasking systems, where more than one program runs at once by sharing the CPU for
short time slots. While the relatively slow transfer of data between RAM and disk is taking
place, another program can be using the CPU. This means that although one program
might be held up waiting for a segment of its virtual address space to be loaded from disk,
another program whose program and data are in physical RAM can proceed.
The subject of virtual memory is a complex one which is covered in a variety of text books.
A good one is 'The Design of the Unix Operating System' by MJ Bach, published by
Prentice -Hall.
When a pre-fetch abort occurs, the ARM completes the instruction(s) before the one which
'aborted'. When this instruction comes to be executed, it is ignored and the following takes
place:
? SVC mode is entered
? R15 is saved in R14_SVC
? The IRQ disable bit is set
? The PC is set to address &000000C
The PC value saved is the one after the instruction which caused the abort. The routine
which deals with the pre-fetch abort must perform some action, as outlined above, which
will enable the instruction to be re-tried and this time succeed.
A simple single-tasking (one program at once) operating system running virtual memory
might take the following steps on receiving a pre -fetch abort:
? verify that it is a missing page problem (not access violation)
? enable IRQs
? find a suitable page of physical RAM
? load the page corresponding to the required logical address
? set-up MEMC to map the physical to logical page
? re-try the instruction by jumping to R14_SVC minus 4
It is important to re - enable IRQs so that the normal servicing of interrupts is not disturbed
while the new page is being loaded in. The third step may itself be quite involved, since a
decision has to be made about which physical page is suitable for loading in the new
section of the program and whether its current contents must be saved, as mentioned
above.
A data abort is a little more complex, since the ARM is halfway through the instruction by
the time the abort occurs. If the instruction was an LDRor STR, it is abandoned and no
registers are altered (in particular, the base register is unchanged, even if write -back was
specified).
If the instruction was an LDMor STM, the instruction completes (though no registers are
altered in an LDM), and the base register is updated if write - back was enabled. Note that if
the base register was included in the list of registers to be loaded, it is not over -written as
would normally be the case. The (possibly written-back) value is left intact. Then:
? SVC mode is entered
? R15 is saved in R14_SVC
? The IRQ disable bit is set
? The PC is set to address &0000010
This time, R14_SVC is set to the instruction two words after the aborted one, not one. The
abort handler routine must take the following action. It must examine the aborted
instruction to find out the type and address mode, and undo the affect of any adjustment
of the base register due to write - back. It can derive the address of the data which caused
the abort to occur from the base register, and perform a similar paging process to that
described for pre -fetch aborts. It can then re -execute the instruction, by jumping to address
R14_SVC minus 8 using an instruction such as:
SUB pc,link,#8
The time taken to decode the instruction which caused the abort and perform the
appropriate operations varies according to instruction type, number of registers (for
LDM/STM), type of indexing (for LDR/STR) and whether write -back was enabled. Calculations
made from typical abort- handler code result in times of between 20 s+41n -cycles for the
best case and 121 s+36 n - cycles for the worst case. On an 8MHz ARM system, these
translate into approximately 13.4us and 27.1us respectively.
7.7 Address exception
An address exception occurs if an attempt is made to access a location outside the range of
the ARM's 26 -bit address bus. This can be caused by the effective address (base plus any
offset) of an LDR/STRinstruction exceeding the value &3FFFFFF, or if the base register in an
LDM/STMinstruction contains a value greater than this.
Note that in the latter case, the exception will only occur if the base register is illegal when
the instruction starts to execute. If it is legal for the first data transfer, and subsequently
exceeds &3FFFFFF having been auto-incremented, no exception occurs. Instead the
address 'wraps round' and subsequent loads or stores take place in the first few locations
of the memory map.
Unlike the aborts described above, the address exception is detected internally by the
ARM, and not by the assertion of a signal by some external device. Like data aborts,
however, the incorrect instruction is abandoned or 'completed' as described above.
On detecting the address error, the ARM causes the following to take place:
? SVC mode is entered
? R15 is saved in R14_SVC
? The IRQ disable bit is set
? The PC is set to address &0000014
If it is required that the instruction be re -started after an address exception has been
generated, the address in R14_SVC minus 4 can be used. However, there is usually not
much point and the usual action is to enter a 'monitor' program which can be used to try
to diagnose what went wrong.
IRQ stands for Interrupt ReQuest, and is one of two interrupt inputs on the ARM. An
external device signals to the ARM that it requires attention by asserting the IRQ line. At
the end of every instruction's execution, the ARM checks for the presence of an IRQ. If an
interrupt request has been made, and IRQs are enabled, the following happens:
? IRQ mode is entered
? R15 is saved in R14_IRQ
? The IRQ disable bit is set
? The PC is set to address &0000018
If IRQs are disabled, because the IRQ disable bit in the status register is set, the interrupt is
ignored and the ARM continues its normal processing. Note that on initiating an IRQ
routine, the ARM stes the IRQ, so further IRQs are disabled.
The routine handling the interrupt must take the appropriate action, which will result in
the interrupting device removing its request. For example, a serial communications device
might cause an IRQ when a byte is available for reading. The IRQ routine, on discovering
which device caused the interrupt, would read the data byte presented by the serial chip,
and buffer it somewhere for later reading by a program. The action of reading a byte from
the serial chip typically informs the device that its IRQ has been serviced and it 'drops' the
interrupt request.
On the ARM, the interrupt disable bits and processor mode bits in the status register
cannot be altered in user mode. This means that user mode programs typically execute
with both types of interrupt enabled, so that the 'background' work of servicing
interrupting devices can take place. However, it is sometimes desirable to disable all
interrupts, and there is typically a SWIcall provided by the operating system which allows
the interrupt masks to be changed by user mode programs.
The following few paragraphs refer to the writing of both IRQ and FIQ routines.
Interrupt routines must be quick in execution, because while the interrupt is being
serviced, the main program cannot progress. The Acorn IOC (I/O controller) chip provides
some support for dealing with interrupts which makes their processing more efficient. For
example, it provides several IRQ inputs so that many devices may share the ARM's single
IRQ line. These inputs may be selectively enabled/disabled, and a register in the IOC may
be read to find which devices at any time require servicing.
An interrupt routine usually has limitations imposed on what it can do. For example, it is
undesirable for an interrupt handler to re -enable interrupts. If it does, another IRQ may
come along which causes the handler to be called again, i.e. the routine is re-entered.
It is possible to write code which can cope with this, and such routines are known as reentrant. Amongst other things, re -entrant routines must not use any absolute workspace,
and must preserve the contents of all registers that they use (which all interrupt routines
should do anyway). The first restriction means that the stack should be used for all
workspace requirements of the routine, including saving the registers. This ensures that
each re -entered version of the routine will have its own work area.
Unfortunately, it is common to find that operating system routines are impossible to write
in a re-entrant fashion. This means that it is not possible to use many operating system
routines from within interrupt service code. A common example is to find that a machine's
output character routine is executed with interrupts enabled and is not re - entrant. (The
reason is that in some circumstances, e.g. clearing the screen, the output routine might
take several milliseconds, or even seconds, and it would be unwise to disable interrupts
for this long.)
You should consult your system's documentation to find out the exact restrictions about
using OS routines from within interrupt service code.
Interrupt routines should also be careful about not corrupting memory that might be used
by the 'foreground' program. Using the stack for all workspace is one way to avoid this
problem. However, this is not always possible (for example, if the IRQ routine has to
access a buffer used by the foreground program). You should always endeavour to restrict
the sharing of locations by interrupt and non-interrupt code to a bare minimum. It is very
hard to track down bugs which are caused by locations being changed by something
outside the control of the program under consideration.
To return to the user program, the IRQ routine subtracts 4 from the PC saved in R14_IRQ
and places this in R15. Note that this saved version will have the IRQ disable bit clear, so
as well as returning to the main program, the transfer causes IRQs to be re -enabled.
7.9 FIQ
FIQ stands for Fast Interrupt reQuest. A signal on the ARM's FIQ input causes FIQ mode
to be entered, if enabled. As with IRQs, the ARM checks at the end of each instruction for a
FIQ. If both types of interrupt occur at the same time, the FIQ is handled first. In this
respect, it has a higher priority than IRQ. On responding to a FIQ, the ARM initiates the
following actions:
? FIQ mode is entered
? R15 is saved in R14_FIQ
? The FIQ and IRQ disable bits are set
? The PC is set to address &000001C
Notice that a FIQ disables subsequent FIQs and IRQs, so that whereas a FIQ can interrupt
an IRQ, the reverse is not true (unless the FIQ handler explicitly enables IRQs).
The term 'fast' for this type of interrupt is derived from a couple of its properties. First, FIQ
mode has more 'private' registers than the other supervisor modes. This means that in
order for a FIQ routine to do its job, it has to spend less time preserving any user registers
that it uses than an IRQ routine would. Indeed, it is common for a FIQ routine not to use
any user registers at all, the private ones being sufficient. Secondly, the FIQ vector was
cleverly made the last one. This means that there is no need to have a branch instruction at
address &000001C. Instead, the routine itself can start there, saving valuable microseconds
(or fractions thereof).
To return to the user program, the FIQ routine subtracts 4 from the PC saved in R14_FIQ
and places this in R15 (i.e. the PC). Note that this saved version will have the FIQ disable
bit clear, so as well as returning to the interrupted program, the transfer causes FIQs to be
re-enabled.