August 8, 2025

GCC inline assembly - constraints

First of all, there are a general set of constraint "letters" that are not specific to any given architecture:
m - a memory operand with any kind of address
o - a memory operand that must be offsettable
v - a memory operand that is not offsettable
< - a memory operand that allows autodecrement
> - a memory operand that allows autoincrement
r - a general register
{r} - bound to hard register
i - immediate integer
n - immediate integer less than a word wide
E - immediate floating point
s - immediate operand not an explicit integer
g - general integer operand
x - any operand whatsoever
p - valid memory address
We also have "contraint modifiers" ---
= - the operand is written to by this instruction
& - early clobber
% - operand is commutative
Heaven only knows what "early clobber" means.

m68k constraints

Augmenting these, each architecture has its own collection of "constraint" letters. Here is a list for the m68k, found in this document

a - address register
d - data register
f - floating point register
I - integer in range 1-8
J - 16 bit signed number
K - signed number with magnitude > 0x80
L - integer in range -8 to -1
M - signed number > 0x100
N - rotate, 8 to 1 expressed as range 24-31
O - 16 (for rotate using swap)
P - rotate 8-15 
R - numbers that mov3q can handle
G - floating point constant, not 68881
S - operand that satisfie "m" with -mpcrel
T - operand that satisfie "s" without -mpcrel
Q - address register, indirect addressing
U - register offset addressing
W - const_call operand
Cs - symbol ref or constant
Ci - const-int
C0 - const-int-0
Cj - signed numbers that don't fit in 16 bits
Cmvq - integers valid for moveq
Capsw - integers valid for moveq followed by swap
Cmvz - integers valid for mvz
Cmvs - integers valid for mvs
Ap - push operand
Ac - non register operands allowed in clr
That is the list, much of which is clear as mud. Clearly, experimenting is essential.

ARM constraints

Here is the list for ARM (32 bit, not Aarch64)
h - core registers r8-r15 in thumb state
k - the stack pointer
l - core registers r0-r7 in thumb state
t - VFP floating point register s0-s31, for 32 bit
w - VFP floating point register d0-d31, for 64 bit
G - the floating point constant 0.0
I - integer valid as an immediate (i.e. 0-255 rotated by 2^n)
J - integer in range -4095 to 4095
K - integer that satisfies "I" when inverted
L - integer that satisfies "I" when negated
M - integer 0-32
Q - memory reference with exact address in a single register (see m)
R - an item in the constant pool
S - a symbol in the text segment
Uv - memory reference suitable for VFP load/store
Uq - memory reference suitable for ARM ldrsb instruction
The careful reader will notice that "m" is not in this list. It is one of the general constraints listed at the start of this document.
Feedback? Questions? Drop me a line!

Tom's Computer Info / tom@mmto.org