archiveFeb 9, 2021
ARM and Thumb instructions
Load/store and 3-address data processing on ARM, conditional execution, barrel-shifter operands, and how Thumb differs on registers, flags, and branches.
ARM instruction model
Load/store architecture
ARM does not operate on memory operands directly in ALU ops. Data moves between memory and registers with LDR / STR (and friends).
3-address data processing
Typical data-processing instructions take two source operands and write a separate result.
Conditional execution
Every ARM instruction can execute conditionally against the CPSR ALU flags. When a run of instructions shares one condition, you can avoid a branch just to skip them. Data-processing ops can optionally update those flags (S bit). Flags set by one instruction can steer later ones even when unrelated work sits in between.
Register access
In ARM state, instructions can reach r0–r14, and most can touch r15 (PC). MRS / MSR move CPSR and SPSR contents into or out of general-purpose registers so status can be manipulated like ordinary data.
Inline barrel shifter
The ALU includes a 32-bit barrel shifter for shifts and rotates. For data-processing and single-register transfers, the second operand can be shifted as part of the same instruction — useful for extended addressing, multiply-by-constant patterns, and building immediates.
Thumb instruction set
Thumb is a subset of ARM, tuned for denser C/C++ code.
- Every Thumb instruction is 16 bits and halfword-aligned in memory
- In Thumb state the instruction address LSB is always 0
- Some branch encodings use the LSB to mark whether the target is Thumb or ARM
- Ops still work on full 32-bit register values and use full 32-bit addresses for data and fetch
Thumb behavior details
Conditional execution
Only conditional branches are conditionally executed in Thumb. Almost every data-processing instruction updates the CPSR ALU flags, except when a high register is an operand of MOV or ADD. You cannot park unrelated data-processing ops between a flag-setting instruction and the branch that depends on it — put a conditional branch above the work you want to skip.
Register access
Most Thumb instructions only see r0–r7 (low registers). r8–r15 are high registers with limited access — FIQ banking is one place that shows up.
Thumb vs ARM
Branch instructions
Thumb branches cover backward loops, forward conditionals, subroutine calls, and switching the processor from Thumb state to ARM state.
Data-processing instructions
They operate on general-purpose registers, but results usually overwrite one of the source registers instead of a third destination. Fewer ops are available than in ARM state, and access to r8–r15 is restricted. ALU flags update on these instructions unless MOV/ADD touch high registers — those high-register forms do not update flags.
Single-register load and store
LDM / STM load and store subsets of r0–r7.
Multi-register load and store
PUSH / POP use the stack pointer (r13) for a full descending stack. Besides r0–r7, PUSH can save the link register and POP can restore the program counter.