The Program Status Register (PSR) is one of the most important registers in ARM processors. It contains condition code flags like negative, zero, carry, overflow etc. that are set based on the result of arithmetic and logical operations. The PSR register also contains the current state of the processor like the processor mode, interrupt disables and other status flags. Understanding the PSR register is key to writing efficient ARM assembly code.
Contents of PSR Register
The PSR register in ARM is 32 bits wide and contains the following fields:
- N – Negative flag
- Z – Zero flag
- C – Carry flag
- V – Overflow flag
- Q – Saturation flag
- J – Java mode
- GE – Greater than or Equal flags
- E – Endianness flag
- A – Abort disable
- I – IRQ disable
- F – FIQ disable
- T – Thumb state
- Mode – Processor mode bits
Condition Code Flags
The N, Z, C and V flags are the condition code flags that indicate the result of arithmetic and logical operations. For example, after an ADD instruction, if the result is negative, the N flag will be set. If the result is zero, the Z flag will be set. These flags can be tested using conditional execution instructions like BEQ, BNE, BMI etc.
The Q flag is set if overflow occurs during signed saturation. It indicates that the result was saturated to the 8-bit signed minimum or maximum value.
The J flag is set when executing Java bytecodes. It indicates Java mode.
The GE bits contain the greater than or equal flags for each processor condition code. This is used to speed up conditional execution.
The E flag contains the endianness state of the processor. 0 indicates little endian, 1 indicates big endian memory accesses.
A, I, F Flags
The A, I and F flags are used to disable aborts, IRQs and FIQs respectively. This is used for critical sections of code.
The T flag indicates the instruction set state of the processor. 0 means ARM state and 1 means Thumb/ThumbEE state.
The mode bits encode the current processor mode like USR, SVC, IRQ etc. This indicates the privilege level the processor is currently executing at.
Reading PSR Register
To read the PSR register, the MRS instruction is used like: MRS R0, CPSR ; Read CPSR into R0
This will copy the contents of the CPSR to the destination register R0. CPSR is the Current Program Status Register which contains the flags and mode bits for the program currently executing.
Writing to PSR Register
To write to the PSR register, the MSR instruction is used. For example: MSR CPSR_fc, R0 ; Write R0 flags to CPSR
This will update the condition code flags in the CPSR using the contents of R0. We use CPSR_fc to specify that only the flag bits should be changed.
To update the mode bits, MSR CPSR_c can be used. For example, to switch to IRQ mode: MOV R0, #0xD2 MSR CPSR_c, R0 ; Switch to IRQ mode
This will update the mode field of CPSR to switch to IRQ mode. The _c suffix indicates mode bits.
To change the processor mode, the mode value is written to the CPSR mode bits using an MSR instruction. For example: MOV R0, #0xDF MSR CPSR_c, R0 ; Change to System mode
Here 0xDF encodes System mode. The LR and SPSR registers will be banked automatically when changing modes.
To disable interrupts, the I and F bits in CPSR can be cleared like: MRS R0, CPSR BIC R0, R0, #0xC0 ; Clear I and F bits MSR CPSR_c, R0 ; Disable IRQ and FIQ interrupts
This will prevent IRQ and FIQ interrupts from triggering while executing the critical region of code.
The condition code flags N, Z, C, V can be tested using conditional execution instructions like: BEQ label ; Branch if Z set BMI label ; Branch if N set
This allows code to execute conditionally based on the result of arithmetic or logical instructions which set the flags in CPSR automatically.
PSR in Thumb State
In Thumb state, the APSR register holds the condition flags and GE flags. While modes and interrupt disables are held in the EPSR. For example: MRS R0, APSR ; Read flags MSR EPSR, R1 ; Write mode bits
So APSR and EPSR have to be used instead of CPSR in Thumb state.
PSR in Exception Handling
On taking an exception like IRQ or undefined instruction, the CPSR is automatically saved in SPSR of the new mode. The LR is also saved to link back after handling the exception.
For example on IRQ entry: CPSR -> SPSR_irq LR -> LR_irq Enter IRQ mode and jump to handler
The handler can then recover the original context by restoring SPSR_irq to CPSR and LR_irq to PC after finishing interrupt processing.
Typical Uses of PSR
Here are some typical uses of the PSR register in ARM programming:
- Enable/disable interrupt requests
- Set processor mode like USR, SVC, IRQ etc
- Save/restore context during exception handling
- Conditional execution of code based on arithmetic flags
- Determine processor endianness
- Determine ARM vs Thumb execution state
Understanding the PSR register is key to writing robust and efficient code on ARM platforms.