Core registers
Sixteen 32-bit registers are visible at a time. The decoder writes them as LLVM does: r0 to r12, then sp, lr and pc.
GNU objdump uses the older names sl (r10), fp (r11) and ip (r12) for some of them; the tests treat them as the same.
| Register | Name | Role |
|---|---|---|
| r0 to r3 | a1 to a4 | Arguments and results in the AAPCS calling convention; caller-saved |
| r4 to r8, r10, r11 | v1 to v5, v7, v8 | Callee-saved. In Thumb-1 (T16) most instructions reach only r0 to r7, the “low registers”. |
| r9 | sb, tr, v6 | Platform register (static base, thread register) or callee-saved |
| r12 | ip | Intra-procedure-call scratch register, used by veneers and PLT stubs |
| r13 | sp | Stack pointer, 4-byte aligned (8-byte at public interfaces); banked per mode |
| r14 | lr | Link register: bl and blx put the return address here; banked per mode |
| r15 | pc | Program counter. In ARM state reading it gives the address of the instruction plus 8, in Thumb state plus 4 (rounded down to a multiple of 4 for adr, ldr literal and blx). The decoder shows each branch target and each PC-relative address already computed. |
The program status register
APSR holds the condition flags that instructions test; CPSR is the whole register, with the interrupt masks, the instruction-set state and the mode.
| Bits | Name | Meaning |
|---|---|---|
| 31 | N | Negative: the result’s bit 31 |
| 30 | Z | Zero |
| 29 | C | Carry (not-borrow after a subtraction), shifter carry out |
| 28 | V | Overflow |
| 27 | Q | Sticky saturation (DSP instructions) |
| 19:16 | GE | Greater-or-equal flags of the parallel add and subtract instructions, read by sel |
| 9 | E | Data endianness (setend), deprecated in ARMv8 |
| 8, 7, 6 | A, I, F | Asynchronous abort, IRQ and FIQ masks (cpsid, cpsie) |
| 5 | T | Thumb state; 1 in Thumb. bx, blx and loads into the PC set it from bit 0 of the target address |
| 4:0 | M | Processor mode (next table) |
The decoder names the status register in mrs and msr as LLVM does: apsr_nzcvq and apsr_g for the flag-only writes, cpsr_fsxc and spsr_fsxc with the field letters f (bits 31:24), s (23:16), x (15:8) and c (7:0).
On the M profile the registers are apsr, iapsr, eapsr, xpsr, ipsr, epsr, iepsr, msp, psp, primask, basepri, faultmask, control, and on ARMv8-M also msplim, psplim and the _ns forms.
Processor modes
| M[4:0] | Mode | Banked registers |
|---|---|---|
| 10000 | User (usr) | none |
| 10001 | FIQ | r8 to r12, sp, lr, spsr |
| 10010 | IRQ | sp, lr, spsr |
| 10011 | Supervisor (svc) | sp, lr, spsr |
| 10110 | Monitor (mon), Security Extensions | sp, lr, spsr |
| 10111 | Abort (abt) | sp, lr, spsr |
| 11010 | Hyp, Virtualization Extensions | sp, elr, spsr |
| 11011 | Undefined (und) | sp, lr, spsr |
| 11111 | System (sys) | none (the User registers) |
The mode number is the operand of cps, srs (srsdb sp!, #19 stores to the supervisor stack) and the rfe family.
Condition codes
In A32, bits 31:28 of every instruction are a condition; the instruction runs only when the flags satisfy it. The decoder writes the condition as a suffix: addeq, ldrbne, with the S flag-setting suffix before it (addseq). The assembler spellings LLVM uses are hs and lo where older documents write cs and cc; GNU objdump writes cs and cc, and the tests treat them as the same.
In T16 only the conditional branch b<cond> has a condition field; in T32 only b<cond>.w. Every other Thumb instruction is made conditional by an IT block.
| Bits | Suffix | Meaning | Flags tested |
|---|---|---|---|
| 0000 | eq | Equal | Z = 1 |
| 0001 | ne | Not equal | Z = 0 |
| 0010 | hs (cs) | Unsigned higher or same (carry set) | C = 1 |
| 0011 | lo (cc) | Unsigned lower (carry clear) | C = 0 |
| 0100 | mi | Negative | N = 1 |
| 0101 | pl | Positive or zero | N = 0 |
| 0110 | vs | Overflow | V = 1 |
| 0111 | vc | No overflow | V = 0 |
| 1000 | hi | Unsigned higher | C = 1 and Z = 0 |
| 1001 | ls | Unsigned lower or same | C = 0 or Z = 1 |
| 1010 | ge | Signed greater or equal | N = V |
| 1011 | lt | Signed less | N ≠ V |
| 1100 | gt | Signed greater | Z = 0 and N = V |
| 1101 | le | Signed less or equal | Z = 1 or N ≠ V |
| 1110 | (none) | Always (AL); not written | – |
| 1111 | (none) | The unconditional space | see below |
Condition 1111. Before ARMv5 this meant “never”. Since ARMv5 the 0xF space holds instructions that have no condition: blx with an immediate offset (the H bit is bit 1 of the offset), the barriers dmb, dsb, isb, clrex and sb, pld and pli and pldw, cps and setend, srs and rfe, the ‘2’ coprocessor forms (cdp2, mcr2, ldc2 …, removed in ARMv8), the ARMv8 floating-point additions (vsel, vmaxnm, vrint*, vcvta/n/p/m) and the Advanced SIMD data-processing and load/store instructions. Any other word with condition 1111 is undefined.