Every effort has been made to ensure that the information in this document is true and correct at the date of issue. Products described in this document, however, are subject to continuous development and improvements and Advanced RISC Machines Ltd (and other contributors) reserve the right to change their specifications at any time. Advanced RISC Machines Ltd cannot accept liability for any loss or damage arising from the use of any information or particulars in this document.
This document lists the instruction code sequences to be avoided. It is *STRONGLY* recommended that you take the time to familiarise yourself with these cases because some will only fail under particular circumstances which may not arise during testing.
TSTP Rn,<Op2>
TEQP Rn,<Op2>
CMPP Rn,<Op2>
CMNP Rn,<Op2>
These are the only operations that change all the bits in the PSR (including the mode bits) without affecting the PC (thereby forcing a pipeline refill during which time the register bank select logic settles).
e.g. Assume processor starts in Supervisor mode in each case:-
a) TEQP PC,#0
MOV R0,R0 SAFE: NOP added between mode change and access ADD R0,R1,R13_usr to a banked register (R13_usr).
b) TEQP PC,#0
ADD R0,R1,R2 SAFE: No access made to a banked register
c) TEQP PC,#0
ADD R0,R1,R13_usr *FAILS*: Data NOT read from Register R13_usr!
The safest default is always to add a NOP (e.g. MOV R0,R0) after a mode changing instruction; this will guarantee correct operation regardless of the code sequence that follows it.
# Applicability: ARM2,ARM3 ####################################################################
For STM instructions the S bit is redundant as the PSR is always stored
with the PC whenever R15 is in the transfer list. In user mode programs the
S bit is ignored, but in other modes it has a second interpretation. S=1 is
used to force transfers to take values from the user register bank instead
of the current register bank. This is useful for saving the user state on
process switches.
Similarly, in LDM instructions the S bit is redundant if R15 is not in the
transfer list. In user mode programs, the S bit is ignored, but in non-user
mode programs where R15 is not in the transfer list, S=1 is used to force
loaded values to go to the user registers instead of the current register
bank.
In both cases where the processor is in a non-user mode and transfer
to/from the user bank is forced by setting the S bit, write back of the base
will also be to the user bank though the base will be fetched from the
current bank. Therefore don't use write back when forcing user bank transfer
in LDM/STM.
e.g. In all cases, the processor is assumed to be in a non-user mode and
<Rlist> is assumed not to include R15:-
STMxx Rn!,<Rlist> SAFE: Storing non-user registers with write back to the non-user base register
LDMxx Rn!,<Rlist> SAFE: Loading non-user registers with write back to the non-user base register
STMxx Rn,<Rlist>^ SAFE: Storing user registers, but no base write-back
STMxx Rn!,<Rlist>^ *FAILS*: Base fetched from non-user register, but written back into user register
LDMxx Rn!,<Rlist>^ *FAILS*: Base fetched from non-user register, but written back into user register
# following instruction. Accesses to the unbanked registers # # (R0-R7,R15) are safe. #######################################################################
# Applicability: ARM2,ARM3 #######################################################################
Because the register bank switches from user mode to non-user mode during the first cycle of the instruction following an "LDM Rn,<Rlist>^", an attempt to access a banked register in that cycle may cause the wrong register to be accessed.
e.g. In all cases, the processor is assumed to be in a non-user mode and
<Rlist> is assumed not to include R15:-
LDM Rn,<Rlist>^
ADD R0,R1,R2 SAFE: Access to unbanked registers after LDM^
LDM Rn,<Rlist>^
MOV R0,R0 SAFE: NOP inserted before banked register used ADD R0,R1,R13_svc following an LDM^
LDM Rn,<Rlist>^
ADD R0,R1,R13_svc *FAILS*: Accessing a banked register immediately after an LDM^ returns the wrong data!
ADR R14_svc, saveblock
LDMIA R14_svc, {R0 - R14_usr}^
LDR R14_svc, [R14_svc,#15*4] *FAILS*: Banked base register (R14_svc)
MOVS PC, R14_svc used immediately after the LDM^
ADR R14_svc, saveblock
LDMIA R14_svc, {R0 - R14_usr}^
MOV R0,R0 SAFE: NOP inserted before banked LDR R14_svc, [R14_svc,#15*4] register (R14_svc) usedMOVS PC, R14_svc NOTE:
# to allow for an unexpected call from a SWI instruction. ## The erroneous SWI call should be intercepted and redirected to the #
# software interrupt handler #######################################################################
# Applicability: ARM2 #######################################################################
The implementation of the CDP instruction on ARM2 causes a Software
Interrupt (SWI) to take the Undefined Instruction trap if the SWI was the
next instruction after the CDP.
e.g.
SIN F0,F1
SWI &11 *FAILS*: ARM2 will take the undefined instruction trap instead of software interrupt trap.
All Undefined Instruction handler code should check the failed instruction to see if it is a SWI, and if so pass it over to the software interrupt handler.
# allow for an unexpected call due to an undefined instruction #######################################################################
# Applicability: ARM2,ARM3 #######################################################################
When an undefined instruction is fetched from the last word of a page,
where the next page is absent from memory, the undefined instruction will
cause the undefined instruction trap to be taken, and the following
(aborted) instructions will cause a prefetch abort trap. One might expect
the undefined instruction trap to be taken first, then the return to the
succeeding code will cause the abort trap. In fact the prefetch abort has a
higher priority than the undefined instruction trap, so the prefetch abort
handler is entered _before_ the undefined instruction trap, indicating a
fault at the address of the undefined instruction (which is in a page which
is actually present). A normal return from the prefetch abort handler (after
loading the absent page) will cause the undefined instruction to execute and
take the trap correctly. However the indicated page is already present, so
the prefetch abort handler may simply return control, causing an infinite
loop to be entered.
Therefore, the prefetch abort handler should check whether the indicated
fault is in a page which is actually present. If so, the above condition
must be present and so control should be passed to the undefined instruction
handler. This will restore the expected sequential nature of the execution
sequence; a normal return from the undefined instruction handler will cause
the next instruction to be fetched (which will abort), the prefetch abort
handler will be reentered (with an address pointing to the absent page), and
execution can proceed normally.
e.g. Consider data operations of the type:-
<opcode>{cond}{S} Rd,Rn,Rm or <opcode>{cond}{S} Rd,Rn,Rm,<shiftname> Rsa) When R15 is used in the Rm position, it will give the value of the PC
together with the PSR flags.b) When R15 is used in the Rn or Rs positions, it will give the value of
the PC without the PSR flags (PSR bits replaced by zeros).
MOV R0,#0
ORR R1,R0,R15 ; R1:=PC+PSR (bits 31:26,1:0 reflect PSR flags)
ORR R2,R15,R0 ; R2:=PC (bits 31:26,1:0 set to zero)NOTE:
e.g.
MOV R5,#&1000
STMIA R5!,{R5-R6} ; Stores value of R5=&1000
MOV R5,#&1000
STMIA R5!,{R4-R5} ; Stores value of R5=&1008
e.g. Assume processor is in a non-user mode & MEMC being accessed:-
{these examples are very contrived}
MOV R0,#&04000000 ; R0=&04000000 STMIA R0,{R1-R2} ; Address exception reported (base address illegal)
MOV R0,#&04000000
SUB R0,R0,#4 ; R0=&03FFFFFCSTMIA R0,{R1-R2} ; No address exception reported (base address legal)
; code will overwrite data at address &00000000NOTE:
e.g. Assume processor is in a non-user mode & MEMC being accessed:-
{these examples are very contrived}
MOV R0,#&04000000 ; R0=&04000000 STC CP1,CR0,[R0] ; Address exception reported (base address illegal)
MOV R0,#&04000000
SUB R0,R0,#4 ; R0=&03FFFFFC STFD F0,[R0] ; No address exception reported (base address legal) ; code will overwrite data at address &00000000NOTE:
e.g. Assume processor is in a non-user mode, FPU hardware attached and MEMC
being accessed:- {this example is very contrived}
MOV R13,#&03000000 ; R13=Address of I/O space STFD F0,[R13,#-8]! ; Store F.P. register 0 at top of physical memory
; (two words of data transferred)LDFD F1,[R13],#8 ; Load F.P. register 1 from top of physical memory
; but THREE words of data are transferred, and the ; third access will read from I/O space which may be ; read sensitive! *** BEWARE ***