How the opcode space is divided
Bits 31:28 are the condition. The decoder then reads bits 27:25 (and 4 and 7 where they separate the groups):
| Bits 27:25 | Group |
|---|---|
| 000 | Data processing (register), multiply, synchronisation and extra load/store when bits 7 and 4 are both 1, and the miscellaneous group (status register, bx, clz, saturating arithmetic, bkpt, DSP multiply) where bits 24:23 are 10 and S is 0 |
| 001 | Data processing (immediate), movw/movt, msr (immediate) and hints |
| 010 | Load and store word or byte (immediate offset) |
| 011 | Load and store word or byte (register offset); when bit 4 is 1: media instructions and udf |
| 100 | Load and store multiple |
| 101 | Branch and branch with link |
| 110 | Coprocessor load and store, 64-bit transfers; VFP loads and stores |
| 111 | Bit 24 set: svc. Otherwise coprocessor data processing (bit 4 clear) and register transfers (bit 4 set); VFP |
Data processing
Bits 24:21 select the operation, bit 20 is S (set the flags), Rn is bits 19:16 and Rd bits 15:12. The second operand is an 8-bit immediate rotated right by twice bits 11:8 (when bit 25 is 1), or a register Rm shifted by an immediate (bits 11:7) or by a register (bit 4 set, Rs in bits 11:8). Shift types in bits 6:5: 00 lsl, 01 lsr, 10 asr, 11 ror; lsr and asr with a zero amount mean 32, and ror with zero is rrx.
| Bits 24:21 | Mnemonic | Operation |
|---|---|---|
| 0000 | and | Rd = Rn & op2 |
| 0001 | eor | Rd = Rn ^ op2 |
| 0010 | sub | Rd = Rn − op2 |
| 0011 | rsb | Rd = op2 − Rn |
| 0100 | add | Rd = Rn + op2 |
| 0101 | adc | Rd = Rn + op2 + C |
| 0110 | sbc | Rd = Rn − op2 − !C |
| 0111 | rsc | Rd = op2 − Rn − !C |
| 1000 | tst | Flags of Rn & op2 (S must be 1; Rd should be 0) |
| 1001 | teq | Flags of Rn ^ op2 |
| 1010 | cmp | Flags of Rn − op2 |
| 1011 | cmn | Flags of Rn + op2 |
| 1100 | orr | Rd = Rn | op2 |
| 1101 | mov | Rd = op2 (Rn should be 0). With a shift: lsl, lsr, asr, ror, rrx (see pseudo-instructions) |
| 1110 | bic | Rd = Rn & ~op2 |
| 1111 | mvn | Rd = ~op2 |
The decoder writes a modified immediate as LLVM does: the value (mov r0, #-16777216 for 0xFF000000), or #imm8, #rotate when the encoding is not the one with the smallest rotation (bic r12, pc, #3, #30), so the exact encoding stays visible. movw and movt (ARMv6T2 and later: cond 0011 0000 imm4 Rd imm12 and 0011 0100) load a 16-bit immediate to the low half and the high half. A data-processing instruction with S set and Rd = PC (subs pc, lr, #4) is an exception return.
Multiply
| Pattern (after cond) | Mnemonic | Operands | Level |
|---|---|---|---|
| 0000 000S Rd 0000 Rs 1001 Rm | mul | Rd, Rm, Rs | ARMv4T (ARMv2) |
| 0000 001S Rd Ra Rs 1001 Rm | mla | Rd, Rm, Rs, Ra | ARMv4T |
| 0000 0100 RdHi RdLo Rs 1001 Rm | umaal | RdLo, RdHi, Rm, Rs | ARMv6 |
| 0000 0110 Rd Ra Rs 1001 Rm | mls | Rd, Rm, Rs, Ra | ARMv6T2 |
| 0000 100S, 101S, 110S, 111S … 1001 | umull, umlal, smull, smlal | RdLo, RdHi, Rm, Rs | ARMv4T (ARMv3M) |
Saturating arithmetic and DSP multiplies (ARMv5TE)
| Pattern (after cond) | Mnemonic | Operands |
|---|---|---|
| 0001 0000 Rn Rd 0000 0101 Rm | qadd | Rd, Rm, Rn (saturating Rm + Rn) |
| 0001 0010 … 0101, 0100 … 0101, 0110 … 0101 | qsub, qdadd, qdsub | Rd, Rm, Rn |
| 0001 0000 Rd Ra Rm 1yx0 Rn | smla<x><y> | Rd, Rn, Rm, Ra: 16 × 16 + 32 (x, y select the top or bottom half) |
| 0001 0010 Rd Ra Rm 1y00 Rn | smlaw<y> | Rd, Rn, Rm, Ra: 32 × 16 » 16 + 32 |
| 0001 0010 Rd 0000 Rm 1y10 Rn | smulw<y> | Rd, Rn, Rm |
| 0001 0100 RdHi RdLo Rm 1yx0 Rn | smlal<x><y> | RdLo, RdHi, Rn, Rm |
| 0001 0110 Rd 0000 Rm 1yx0 Rn | smul<x><y> | Rd, Rn, Rm |
| 0111 0000 Rd Ra Rm 00x1 Rn, 01x1 | smlad, smuad (Ra = 15), smlsd, smusd | Rd, Rn, Rm, Ra; x swaps the halves of Rm (ARMv6) |
| 0111 0100 RdHi RdLo Rm 00x1 Rn, 01x1 | smlald, smlsld | RdLo, RdHi, Rn, Rm |
| 0111 0101 Rd Ra Rm 00r1 Rn, 11r1 | smmla, smmul (Ra = 15), smmls | Rd, Rn, Rm, Ra; r rounds |
Media instructions (ARMv6 and later)
Condition, then 011, then bit 4 set: bits 24:20 and 7:5 select the instruction.
| Bits 24:20 | Mnemonics | Operands |
|---|---|---|
| 00001, 00010, 00011, 00101, 00110, 00111 | {s, q, sh, u, uq, uh} × {add16, asx, sax, sub16, add8, sub8} | Rd, Rn, Rm. Bits 7:5: 000 add16, 001 asx, 010 sax, 011 sub16, 100 add8, 111 sub8. The signed and unsigned forms set GE. |
| 01000 | pkhbt, pkhtb, sel, sxtb16, sxtab16 | pkhbt Rd, Rn, Rm{, lsl #n}; pkhtb with asr; sel Rd, Rn, Rm picks bytes by GE; the extends take Rm rotated by 0, 8, 16 or 24 |
| 01010, 01011 | ssat, ssat16, sxtb, sxtab, sxth, sxtah, rev, rev16 | ssat Rd, #1-32, Rm{, shift}; rev Rd, Rm (bits 19:16 and 11:8 should be 1111) |
| 01100 | uxtb16, uxtab16 | As sxtb16 |
| 01110, 01111 | usat, usat16, uxtb, uxtab, uxth, uxtah, rbit, revsh | usat Rd, #0-31, Rm{, shift}; rbit reverses the bits |
| 11000 | usad8, usada8 | Rd, Rn, Rm{, Ra} |
| 1101x | sbfx | Rd, Rn, #lsb, #width |
| 11110, 1111x | ubfx | Rd, Rn, #lsb, #width |
| 1110x | bfi, bfc (Rn = 15) | Rd, Rn, #lsb, #width |
| 10001, 10011 (bits 15:12 = 1111, 7:4 = 0001) | sdiv, udiv | Rd, Rn, Rm (ARMv7VE, ARMv8-A) |
| 11111 with 7:4 = 1111 | udf | #imm16: permanently undefined |
clz (cond 0001 0110 1111 Rd 1111 0001 Rm, ARMv5T) and the CRC instructions are in the miscellaneous group: crc32b, crc32h, crc32w (cond 0001 0sz0 Rn Rd 0000 0100 Rm) and the c forms with bit 9 set (ARMv8-A); the CRC instructions are not conditional.
Load and store
Word and byte: cond 01 I P U B W L Rn Rt, with I = 0 an immediate offset of 12 bits and I = 1 a register Rm shifted (bits 11:7 amount, 6:5 type). P = 1 is an offset (W = 0) or pre-indexed (W = 1, written !); P = 0 is post-indexed, and P = 0 with W = 1 is the unprivileged ldrt/strt form. U selects add or subtract. With Rn = PC and an immediate offset the address is PC + 8 ± offset; the decoder reports it as the address the instruction refers to.
| Pattern | Mnemonics | Operands |
|---|---|---|
| cond 010 PUBWL Rn Rt imm12; cond 011 PUBWL Rn Rt shift Rm | ldr, str, ldrb, strb, ldrt, strt, ldrbt, strbt | Rt, [Rn, #±imm]{!}; Rt, [Rn], #±imm; Rt, [Rn, ±Rm{, shift}] |
| cond 000 PU1WL Rn Rt imm4H 1011 imm4L | strh, ldrh, strht, ldrht | The same addressing, 8-bit offset |
| cond 000 PU0W0 Rn Rt 0000 1011 Rm | strh, ldrh (register offset) | Bits 11:8 should be 0 |
| … 1101 with L = 1 | ldrsb, ldrsbt | Sign-extending byte load |
| … 1111 with L = 1 | ldrsh, ldrsht | Sign-extending halfword load |
| … 1101 / 1111 with L = 0 | ldrd, strd (ARMv5TE) | Rt, Rt2 (the next register), address; Rt even and not r14 |
| cond 0101 U R01 Rn 1111 ...; 1111 0101 U101 … (cond 1111) | pld, pldw, pli | [Rn, #±imm] or [Rn, ±Rm{, shift}]. ARMv5TE; pldw needs the multiprocessing extension, pli ARMv7. |
Load and store multiple: cond 100 P U S W L Rn, then a 16-bit register list. P and U select the mode: IA (P = 0, U = 1), IB (P = 1, U = 1), DA (P = 0, U = 0), DB (P = 1, U = 0). The decoder writes ldm and stm for IA, ldmib, ldmda, ldmdb and so on for the others, and push for stmdb sp! and pop for ldm sp! (pseudo-instructions). S (bit 22) writes ^: the user-mode registers, or an exception return when the PC is in a load list. rfe<mode> Rn{!} (cond 1111 100 PU0W1 Rn 0000 1010 0000 0000) and srs<mode> sp{!}, #mode (cond 1111 100 PU1W0 1101 0000 0101 000 mode) load or store the PC and the status register.
Exclusive access, acquire/release and swap
| Pattern (after cond) | Mnemonic | Operands | Level |
|---|---|---|---|
| 0001 1000 Rn Rd 1111 1001 Rt | strex | Rd, Rt, [Rn] (Rd = 0 on success) | ARMv6 |
| 0001 1001 Rn Rt 1111 1001 1111 | ldrex | Rt, [Rn] | ARMv6 |
| 0001 1010 / 1011, 1100 / 1101, 1110 / 1111 … 1111 1001 | strexd, ldrexd; strexb, ldrexb; strexh, ldrexh | As above; the double forms use Rt and Rt+1 | ARMv6K |
| 0001 1000 Rn 1111 1100 1001 Rt; 0001 1001 Rn Rt 1100 1001 1111 | stl, lda (and the b, h forms) | Rt, [Rn] | ARMv8 |
| 0001 1000 Rn Rd 1110 1001 Rt; 0001 1001 Rn Rt 1110 1001 1111 | stlex, ldaex (b, h, d forms) | As strex and ldrex | ARMv8 |
| 0001 0B00 Rn Rt 0000 1001 Rm | swp, swpb | Rt, Rm, [Rn]. Deprecated; removed in ARMv8 (the ARMv8 level shows it as undefined) | ARMv4T |
Branches, supervisor calls and exceptions
| Pattern | Mnemonic | Operands and notes |
|---|---|---|
| cond 1010 imm24; cond 1011 imm24 | b, bl | Target = address + 8 + imm24 × 4 (sign-extended). Condition AL is a jump or call; others are conditional branches. |
| 1111 101H imm24 | blx (immediate) | Target = address + 8 + imm24 × 4 + H × 2, Thumb state (ARMv5T) |
| cond 0001 0010 1111 1111 1111 0001 Rm | bx | bx lr is a return |
| cond 0001 0010 … 0011 Rm | blx (register) | ARMv5T |
| cond 0001 0010 … 0010 Rm | bxj | Jazelle: acts as bx where Jazelle is absent (ARMv5TEJ) |
| cond 1111 imm24 | svc | #imm24: supervisor call (called swi before) |
| cond 0001 0010 imm12 0111 imm4 | bkpt | #imm16: breakpoint, not conditional (ARMv5T) |
| cond 0001 0000 imm12 0111 imm4 | hlt | #imm16: halting debug (ARMv8) |
| cond 0001 0100 imm12 0111 imm4; cond 0001 0110 0000 0000 0111 imm4 | hvc, smc | Hypervisor and secure monitor calls (virtualisation and security extensions) |
| cond 0001 0110 0000 0000 0000 0110 1110 | eret | Exception return from Hyp mode (ARMv7VE) |
Status register access and processor state
| Pattern | Mnemonic | Operands |
|---|---|---|
| cond 0001 0R00 1111 Rd 0000 0000 0000 | mrs | Rd, cpsr or spsr |
| cond 0001 0R10 mask 1111 0000 0000 Rm | msr (register) | cpsr_<fields>, Rm; apsr_nzcvq, apsr_g, apsr_nzcvqg; spsr_<fields> |
| cond 0011 0R10 mask 1111 rot imm8 | msr (immediate) | The same, with a modified immediate (written unsigned) |
| 1111 0001 0000 imod M 0 0000000 A I F 0 mode | cpsie, cpsid, cps | Interrupt flags a, i, f and optional mode (ARMv6) |
| 1111 0001 0000 0001 0000 00E0 0000 0000 | setend | le or be; deprecated in ARMv8 |
Hints, barriers and the unconditional space
| Pattern | Mnemonic | Notes |
|---|---|---|
| cond 0011 0010 0000 1111 0000 0000 hint | nop (0), yield (1), wfe (2), wfi (3), sev (4), sevl (5), esb (16), csdb (20), dbg #n (0xF0 to 0xFF) | Other hint numbers are unallocated and execute as NOP: shown as nop, status reserved |
| 1111 0101 0111 1111 1111 0000 0100 option | dsb | Options sy, st, ld, ish, ishst, ishld, nsh, nshst, nshld, osh, oshst, oshld, else #n; option 0 is ssbb, 4 is pssbb |
| … 0101 option | dmb | As dsb |
| … 0110 option | isb | isb (sy is 1111; others as #n) |
| … 0001 1111 | clrex | Clears the exclusive monitor |
| … 0111 0000 | sb | Speculation barrier (ARMv8.5) |
Coprocessor instructions
Coprocessor numbers 10 and 11 are the floating-point unit (VFP and NEON). Coprocessor 14 is debug and trace and 15 is system control (the MMU, caches, TLBs). The others are for implementations.
| Pattern | Mnemonic | Operands |
|---|---|---|
| cond 1110 opc1 CRn CRd cp opc2 0 CRm | cdp | p<cp>, #opc1, c<CRd>, c<CRn>, c<CRm>, #opc2 |
| cond 1110 opc1 L CRn Rt cp opc2 1 CRm | mcr, mrc | p<cp>, #opc1, Rt, c<CRn>, c<CRm>, #opc2 (a read into r15 is apsr_nzcv) |
| cond 1100 010L Rt2 Rt cp opc1 CRm | mcrr, mrrc | p<cp>, #opc1, Rt, Rt2, c<CRm> (ARMv5TE) |
| cond 110 PUNWL Rn CRd cp imm8 | ldc, stc, ldcl, stcl | p<cp>, c<CRd>, [Rn, #±imm × 4]{!} or [Rn], #±imm or [Rn], {option} |
| cond = 1111, the same layouts | cdp2, mcr2, mrc2, mcrr2, mrrc2, ldc2, stc2 | ARMv5T to ARMv7; undefined in ARMv8 |
For ARMv8-A AArch32 the decoder follows LLVM: coprocessors 0 to 9, 12 and 13 do not exist, cdp exists only for the floating-point coprocessors, and ldc and stc exist only for coprocessor 14; the ‘2’ forms are undefined. The ARMv7-A and earlier levels (and the “every encoding” level used to compare with GNU objdump) allow all sixteen coprocessors.