The EPSR (External Physical State Register) is a 32-bit register present in ARM Cortex processors that indicates the current physical state of the processor. It provides information about the instruction set state, endian state, overflow and carry flag values, and more. Understanding the layout and meaning of the bits in the EPSR register is important for effective debugging and exception handling on Cortex devices.
Overview of the EPSR Register
The EPSR register contains processor state information that is updated continuously by the processor hardware as instructions are executed. It is divided into several bitfields indicating different aspects of the processor state:
- Bits 0-4 hold exception-related status flags like the overflow flag and carry flag.
- Bits 5-15 hold information about the current instruction set state like Thumb state vs ARM state.
- Bits 22-28 encode the endianness and floating point context status.
- The remaining bits are reserved for future use.
The EPSR can be read using the special register access instructions like MRS to transfer the EPSR contents into a general purpose register. It can be written using the MSR instruction to update the EPSR state bits. However, some EPSR bits like the exception flags are read-only and cannot be explicitly set.
Breakdown of the EPSR Bitfields
Exception Status Flags
The lowest 5 bits of the EPSR are the exception status flags:
- Bit 0 – Overflow flag (O): Set to 1 if an overflow occurred in the last arithmetic instruction.
- Bit 1 – Carry/Borrow flag (C): Contains carry/borrow value from last arithmetic operation.
- Bit 2 – Zero flag (Z): Set if the result of the last arithmetic/logic operation was zero.
- Bit 3 – Negative/Less than flag (N): Stores sign bit of last operation result.
- Bit 4 – Greater than or Equal flags (GE): Stores the >= comparison result of previous instr.
These flags are updated by arithmetic, logical, and comparison instructions. They can be tested using conditional execution instructions like BEQ, BGT, etc. Writes to these bits are ignored since they are set by the processor logic.
Instruction Set State
Bits 5 to 15 of the EPSR hold information about the current instruction set state of the processor:
- Bits 5-7: IT block state bits for Thumb conditional execution.
- Bit 9: Endianness state (E): 0 = Little endian, 1 = Big endian.
- Bit 10: Vector Length bit in Advanced SIMD state.
- Bits 11-12: Indicate ARM instruction set – ARM (00), Thumb (01), Jazelle (10).
- Bits 13-14: Stack Pointer Select – Main (0b00) or Process (0b01).
- Bit 15: T bit – Indicates Thumb (1) or ARM (0) state.
These instruction state bits control processor operation during instruction fetch and execution. The processor automatically sets these bits when transitioning between different instruction sets.
Execution State Bits
The EPSR also contains bits that relate to instruction execution modalities:
- Bit 16: Async Abort Mask – Determines if asynchronous aborts are masked.
- Bit 17: Write Asynchronous Aborts bit – Controls reporting of async aborts.
- Bit 19: Overflow on Vector flag – Sticky overflow flag for Advanced SIMD ops.
- Bit 20: Divide by Zero flag – Set if divide by zero occurs.
- Bit 21: Density Control bit – Controls vector length in Advanced SIMD ops.
Software needs to handle these modes and flags appropriately to maintain proper processor behavior during exceptional conditions.
Endianness and Context Bits
The upper bits 22-28 of the EPSR relate to floating point context and endianness:
- Bits 22-23: Floating Point Context Control bits – Indicate FP mode.
- Bits 24-26: Endianness of data access – Big or Little endian.
- Bits 27-28: Endianness of instruction fetches – Big or Little endian.
These bits control the byte ordering and floating point settings used by load/store instructions and vector floating point code respectively.
Typical Uses of the EPSR Register
Here are some common uses of the information contained in the EPSR register on ARM Cortex CPUs:
Checking Exception Flags
Test the exception flags using conditional instructions to detect overflow, carry, zero, negative results after arithmetic operations. This avoids having to copy flag values to general purpose registers.
ADD R1, R2, R3 // perform addition
BVS overflow // branch if overflow flag set
Identifying Current Instruction Set State
Check the instruction set state bits before executing sensitive code sequences to ensure the processor is in the expected ARM/Thumb/Jazelle state.
MRS R0, EPSR // read EPSR
ANDS R0, R0, #0x10 // test for Thumb state bit
BEQ not_in_thumb // branch if Thumb mode not active
Handling Endianness
Use the endianness bits to perform byte-swapping operations before accessing data in a different endian format.
MRS R1, EPSR // check endianness
TST R1, #1<<24 // test for big endian
BEQ little_endian
REV R0, R0 // byte-swap R0 for big endian access
little_endian:
STR R0, [R2] // store R0 to memory
Saving/Restoring on Exceptions
Store EPSR on exception entry and restore it on exception return to maintain flag and execution state across the exception handling routine.
SUB LR, LR, #4 // adjust LR to point to exception instruction
MRS R0, EPSR // save EPSR
(...) // handle exception
MSR EPSR, R0 // restore EPSR
BX LR // return from exception
Reading and Writing the EPSR
The EPSR register can be accessed using the MRS and MSR instructions:
MRS R0, EPSR // Read EPSR into R0
MSR EPSR, R1 // Write R1 value into EPSR
Some key points regarding EPSR access:
- The exception status flags are read-only and cannot be explicitly set via MSR.
- Not all EPSR bits can be written – refer to documentation for write constraints.
- Writing the EPSR requires privilege, meaning unprivileged code cannot modify EPSR state.
- Additional operations like instruction synchronization may be needed when updating certain EPSR bits.
Consult the architectural reference for the specific ARM processor to determine EPSR accessibility and write behavior.
EPSR and Debugging
The EPSR register plays an important role in debugging ARM software:
- Its state flags indicate if overflow, divide by zero, or other exceptional conditions occurred.
- The instruction set state bits reveal any unexpected transitions between ARM, Thumb, Jazelle mode.
- Endianness and context bits could hint at mixed endian issues.
Debuggers and exception handlers rely on the EPSR contents to help identify and diagnose errors in the software. Masking EPSR bits like asynchronous aborts during debugging could lead to problems going unnoticed.
Conclusion
The EPSR register is a key component of the ARM CPU programming model. Tracking the EPSR state enables understanding the current processor mode, flag values, endianness, and other aspects of execution. Proper handling of the EPSR contents is necessary for robust exception handling, mixed-endian code, context switching, and debugging of ARM software across different instruction sets.