20.2 Using Inline Assembly Language
Within a C/C++ function, the asm statement may be used to insert a line of assembly language code into the assembly language that the compiler generates. Inline assembly has two forms: simple and extended, both of which are described below.
Regardless of the form used to inline assembly into the body of a C function, care must be taken if the function containing this assembly is itself inlined by the compiler optimizer. (This form of optimization replaces calls to a function with the statements contained by that function.) If the inline assembly defines labels, these will appear in every instance of the inlined function and might trigger errors relating to multiply defined symbols. If your assembly code requires labels, you can prevent functions from being inlined by using the noinline attribute with the function containing the inline assembly, or use the -fno-inline or -fno-inline-functions options when building the project.
Using the simple form, assembler instructions can be inlined using the syntax:
asm ("instruction");
where instruction is a valid assembly-language construct. If you are writing inline assembly in ANSI C programs, write __asm__ instead of asm.
In the extended assembler instruction form, the operands of the inlined instruction are specified using C/C++ expressions. The extended syntax is:
asm("template" [ : [ "constraint"(output-operand) [ , ... ] ]
[ : [ "constraint"(input-operand) [ , ... ] ]
[ "clobber" [ , ... ] ]
]
]);You must specify an assembler instruction template, plus an operand constraint string for each operand. The template specifies the instruction mnemonic, and optionally placeholders for the operands. The constraint strings specify operand constraints, for example, that an operand must be in a register (the usual case), or that an operand must be an immediate value.
Constraint letters and modifiers supported by the compiler are listed in the following tables.
| Letter | Constraint |
|---|---|
| Any general register. |
l | In Thumb State, the core registers r0-r7. In Arm state, this is an alias for the 'r' constraint. |
h | In Thumb state, the core registers r8-r15. |
t | In Arm/Thumb-2 state, the VFP floating-point registers s0-s31. |
w | In Arm/Thumb-2 state, the VFP floating-point registers d0-d15, or d0-d31 for VFPv3. |
x | In Arm/Thumb-2 state, the VFP floating-point registers d0-d7. |
Ts | If -mrestrict-it is specified (for Arm-v8), the core registers r0-r7. Otherwise, GENERAL_REGS (r0-r12 and r14). |
| Letter | Constraint |
|---|---|
G | In Arm/Thumb-2 state, the floating-point constant 0. |
I | In Arm /Thumb-2 state, a constant that can be used as an immediate value in a Data Processing instruction (that is, an integer in the range 0 to 255 rotated by a multiple of 2). In Thumb-1 state, a constant in the range 0..255. |
j | In Arm /Thumb-2 state, a constant suitable for a MOVW instruction. |
J | In Arm /Thumb-2 state, a constant in the range -4095..4095. In Thumb-1 state, a constant in the range -255..-1. |
K | In Arm /Thumb-2 state, a constant that satisfies the 'I' constraint if inverted (one's complement). In Thumb-1 state, a constant that satisfies the 'I' constraint multiplied by any power of 2. |
L | In Arm /Thumb-2 state, a constant that satisfies 'I' constraint if negated (two's complement). In Thumb-1 state, a constant in the range -7..7. |
M | In Thumb-1 state, a constant that is a multiple of 4 in the range 0..1020. |
N | In Thumb-1 state, a constant in the range 0-31. |
O | In Thumb-1 state, a constant that is a multiple of 4 in the range -508..508. |
Pf | Memory models except relaxed, consume or release ones. |
| Letter | Constraint |
|---|---|
= | Means that this operand is write-only for this instruction: the previous value is discarded and replaced by output data. |
+ | Means that this operand is both read and written by the instruction. |
& | Means that this operand is an earlyclobber
operand, which is modified before the instruction is finished using the input
operands. Therefore, this operand may not lie in a register that is used as an input
operand or as part of any memory address. |
