Instructions#

  • Operation Syntax Semantic Flags
    Addition add{s} {Rd,} Rn, Rm {, shift} Rd(n) := Rn + Rmshifted NZCV
    adc{s} {Rd,} Rn, Rm {, shift} Rd(n) := Rn + Rmshifted + C NZCV
    add{s} {Rd,} Rn, #const Rd(n) := Rn + const NZCV
    adc{s} {Rd,} Rn, #const Rd(n) := Rn + const + C NZCV
    qadd {Rd,} Rn, Rm Rd(n) := saturated(Rn + Rm) Q
    Subtraction sub{s} {Rd,} Rn, Rm {, shift} Rd(n) := Rn − Rmshifted NZCV
    sbc{s} {Rd,} Rn, Rm {, shift} Rd(n) := Rn − Rmshifted + C NZCV
    rsb{s} {Rd,} Rn, Rm {, shift} Rd(n) := Rmshifted − Rn NZCV
    sub{s} {Rd,} Rn, #const Rd(n) := Rn − const NZCV
    sbc{s} {Rd,} Rn, #const Rd(n) := Rn − const + C NZCV
    rsb{s} {Rd,} Rn, #const Rd(n) := const − Rn NZCV
    qsub{s} {Rd,} Rn, Rm Rd(n) := saturated(Rn − Rm) Q
    Multiplication mul {Rd,} Rn, Rm Rd(n) := Rn × Rm -
    mla Rd, Rn, Rm, Ra Rd := Ra + (Rn × Rm) -
    mls Rd, Rn, Rm, Ra Rd := Ra - (Rn × Rm) -
    umull RdLo, RdHi, Rn, Rm RdHi:RdLo := (uint64) Rn × Rm -
    umlal RdLo, RdHi, Rn, Rm RdHi:RdLo := (uint64) RdHi:RdLo + (Rn × Rm) -
    smull RdLo, RdHi, Rn, Rm RdHi:RdLo := (int64) Rn × Rm -
    smlal RdLo, RdHi, Rn, Rm RdHi:RdLo := (int64) RdHi:RdLo + (Rn × Rm) -
    Division udiv Rd, Rn, Rm Rd := (uint32) Rn ÷ Rm (rounded to 0) -
    sdiv Rd, Rn, Rm Rd := (int32) Rn ÷ Rm (rounded to 0) -
  • Operation Syntax Semantic Flags
    Logic and{s} {Rd,} Rn, Rm {, shift} Rd(n) := Rn ∧ Rmshifted NZCV
    bic{s} {Rd,} Rn, Rm {, shift} Rd(n) := Rn ∧ ¬Rmshifted NZCV
    orr{s} {Rd,} Rn, Rm {, shift} Rd(n) := Rn ∨ Rmshifted NZCV
    orn{s} {Rd,} Rn, Rm {, shift} Rd(n) := Rn ∨ ¬Rmshifted NZCV
    eor{s} {Rd,} Rn, Rm {, shift} Rd(n) := Rn ⊕ Rmshifted NZCV
    and{s} {Rd,} Rn, #const Rd(n) := Rn ∧ const NZCV
    bic{s} {Rd,} Rn, #const Rd(n) := Rn ∧ ¬const NZCV
    orr{s} {Rd,} Rn, #const Rd(n) := Rn ∨ const NZCV
    orn{s} {Rd,} Rn, #const Rd(n) := Rn ∨ ¬const NZCV
    eor{s} {Rd,} Rn, #const Rd(n) := Rn ⊕ const NZCV
    Test cmp Rn, Rm {, shift} Rn − Rmshifted NZCV
    cmn Rn, Rm {, shift} Rn + Rmshifted NZCV
    tst Rn, Rm {, shift} Rn ∧ Rmshifted NZCV
    teq Rn, Rm {, shift} Rn ⊕ Rmshifted NZCV
    cmp Rn, #const Rn − const NZCV
    cmn Rn, #const Rn + const NZCV
    tst Rn, #const Rn ∧ const NZCV
    teq Rn, #const Rn ⊕ const NZCV
  • Operation Syntax Semantic Flags
    Move mov{s} Rd, Rm Rd := Rm NZ
    mov{s} Rd, #const Rd := const NZC
    Shift/Rotate lsl{s} Rd, Rm, Rs Rd := Rm << Rs NZC
    lsr{s} Rd, Rm, Rs Rd := (uint32) Rm >> Rs NZC
    asr{s} Rd, Rm, Rs Rd := (int32) Rm >> Rs NZC
    ror{s} Rd, Rm, Rs Rd := Rm << (32 − Rs) ∨ Rm >> Rs NZC
    lsl{s} Rd, Rm, #const Rd := Rm << const NZC
    lsr{s} Rd, Rm, #const Rd := (uint32) Rm >> const NZC
    asr{s} Rd, Rm, #const Rd := (int32) Rm >> const NZC
    ror{s} Rd, Rm, #const Rd := Rm << (32 - const) ∨ Rm >> const NZC
    rrx{s} Rd, Rm Rd := C << 31 ∨ Rm >> 1 NZC
    For the difference between ASR and LSR see the shifts with the same names.
  • Operation Syntax Semantic Flags
    Offset ldr Rd, [Rb {, #const}] Rd := [Rb + const] -
    str Rs, [Rb {, #const}] [Rb + const] := Rs -
    Pre-offset ldr Rd, [Rb {, #const}]! Rb += const; Rd := [Rb] -
    str Rs, [Rb {, #const}]! Rb += const; [Rb] := Rs -
    Post-offset ldr Rd, [Rb], #const Rd := [Rb]; Rb += const -
    str Rs, [Rb], #const [Rb] := Rs; Rb += const -
    Indexed ldr Rd, [Rb, Ri {, LSL n}] Rd := [Rb + (Ri << n)] -
    str Rs, [Rb, Ri {, LSL n}] [Rb + (Ri << n)] := Rs -
    Literal ldr Rd, label Rd := [label] -
    ldr Rd, [PC, #offset] Rd := [PC + offset] -
    Positive stack stmia Rs!, registers for Ri in registers do [Rs] := Ri; Rs += 4 -
    ldmdb Rs!, registers for Ri in rev(registers) do Rs -= 4; Ri := [Rs] -
    Negative stack stmdb Rs!, registers for Ri in rev(registers) do Rs -= 4; [Rs] := Ri -
    ldmia Rs!, registers for Ri in registers do Ri := [Rs]; Rs += 4 -

    Note: most of the ldr/str memory instructions can have h or b appended to them to change to halfword (16 bit) / byte (8 bit) operations respectively.
    Eg: ldrh r0, [r1] or strb r2, [r3]

  • Operation Syntax Semantic Flags
    General b<c> label if c then PC := label -
    bx Rm PC := Rm -
    Test & branch cbz Rn, label if Rn = 0 then PC := label -
    cbnz Rn, label if Rn ≠ 0 then PC := label -
    Table based tbb [Rn, Rm] PC += (byte) [PC + Rm] -
    tbh [Rn, Rm {, LSL 1}] PC += (hword) [PC + Rm << shift] -
    <c> denotes a condition suffix. For example, use beq to branch only when the zero flag is set.
  • Syntax Semantic Flags
    ldrex Rd, [Rn {, #const}] Rd := [Rn + const]; EX=True -
    strex Rt, Rs, [Rn {, #const}] if EX then [Rn + const] := Rs; Rd := 0 else Rd := 1 -

    The synchronisation instructions work with a special "exclusive monitor" (denoted EX in the table) that tracks the "exclusive state" of the CPU.

    • Every LDREX instruction will succeed and set the exclusive state to true.
    • An STREX instruction will check the exclusive state, and if true, will execute the store, write 0 to Rd, and set the state to false. If the state was already false, the store is not executed and Rd is set to 1. This entire sequence is done atomically.
    • A context switch (such as an interrupt) will set the exclusive state to false.
    The end effect is that only the first STREX performed after the latest LDREX with no context switches in between will execute its store.
  • Instructions with an optional s suffix will only change the flags if this suffix is added.
  • Optional constants and shifts default to 0 / no shift.
  • Square brackets such as in [Rd] denote the memory stored at the given address, in this case the address held in Rd.

Shifts#

Shift Meaning Description
LSL n Logical shift left Shift the bits left by \(n\), discarding the higher bits and filling the lower ones with 0
LSR n Logical shift right Shift the bits right by \(n\), filling the higher bits with 0 and discarding the lower ones
ASR n Arithmetic shift right Shift the bits right by \(n\), filling the higher bits with copies of bit 15 and discarding the lower ones. This preserves the sign of a signed number
ROR n Rotate right Rotate the bits right by \(n\), filling the higher bits with the lower bits being shifted out
RRX Rotate right with carry Rotate the bits right by 1, filling bit 15 with the carry flag and discarding bit 0

Flags#

Flag Meaning Description
N Negative The result, viewed as a two's complement signed number, is negative
Z Zero The result equals 0
C Carry Instruction dependent. For addition, the result wrapped past 232
V Overflow Instruction dependent. For addition, the inputs have the same sign that is different than the results
Q Saturated Signed overflow (result saturated)

Conditions#

Condition Meaning Flags
eq Equal Z = 1
ne Not equal Z = 0
cs, hs Carry set, unsigned higher or same C = 1
cc, lo Carry clear, unsigned lower C = 0
mi Minus, negative N = 1
pl Plus, positive or zero N = 0
vs Overflow set V = 1
vc Overflow clear V = 0
hi Unsigned higher C = 1 ∧ Z = 0
ls Unsigned lower or same C = 0 ∨ Z = 1
ge Signed greater or equal N = V
lt Signed less N ≠ V
gt Signed greater Z = 0 ∧ N = V
le Signed less or equal Z = 1 ∨ N ≠ V
al, <omit> Always any

Width#

Suffix Meaning Opcode width
.n Narrow 16 bits
.w Wide 32 bits
<omit> Unset Assembler decides

The width is an optional suffix on the instruction name (after any condition).

bars search times arrow-up