19.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.

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 instruction 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.

Note: Only a single string can be passed to the simple form of inline assembly.

In the extended assembler instruction form,, the operands of the 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.

Table 19-1. Register Constraint Letters Supported by the Compiler
LetterConstraint
cA register suitable for use in an indirect jump.
dAn address register. This is equivalent to @code{r} unless generating MIPS16 code.
kaRegisters that can be used as the target of multiply-accumulate instructions.
lThe @code{lo} register. Use this register to store values that are no bigger than a word.
xThe concatenated @code{hi} and @code{lo} registers. Use this register to store double-word values.
Table 19-2. Integer Constraint Letters Supported by the Compiler
LetterConstraint
IA signed 32-bit constant (for arithmetic instructions)
JInteger zero
KAn unsigned 32-bit constant (for logic instructions)
LA signed 32-bit constant in which the lower 32 bits are zero. Such constants can be loaded using @code{lui}
MA constant that cannot be loaded using @code{lui}, @code{addiu} or @code{ori}
NA constant in the range -65535 to -1 (inclusive)
OA signed 15-bit constant
PA constant in the range 1 to 65535 (inclusive)
Table 19-3. General Constraint Letters Supported by the Compiler
LetterConstraint
RAn address that can be used in a non-macro load or store.
Table 19-4. Constraint Modifiers Supported by the Compiler
LetterConstraint
=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.
dSecond register for operand number n, that is, %dn..
qFourth register for operand number n, that is, %qn..
tThird register for operand number n, that is, %tn..