archiveFeb 10, 2021
ARM: loading constants into registers
Why you cannot load an arbitrary 32-bit immediate in one ARM instruction, and how MOV and MVN cover the common cases without a separate memory load.
Loading a constant into a register
You cannot load an arbitrary 32-bit constant into a register with a single instruction unless you also load from memory. ARM instructions are only 32 bits wide. Thumb has a similar limit.
You can load a full 32-bit value with a data load, but many common constants have a cheaper path. Plenty of them can also sit directly as operands inside data-processing instructions, with no separate load at all.
Direct loading with MOV and MVN
MOV
MOV can load any 8-bit constant in the range 0x0–0xFF (0–255). Those values can also be rotated by an even amount.
MVN
MVN can load the bitwise complement of those same values. Numerically that is -(n+1).
You do not need to compute the rotation by hand — the assembler does. You also do not need to choose between MOV and MVN; the assembler picks the right one. That matters when the value is an assembly-time variable.
If you write an immediate the assembler cannot encode, you get:
Immediate n out of range for this operation.