# Inline assembly language The LLVM compilers support inline assembly language (assembly instructions in a C function). Although this chapter provides an overview of inline assembly usage, Qualcomm discourages the use of inline assembly because it is error-prone and difficult to maintain. If assembly language is required, use a separate file containing the assembly code. ## ASM statement The LLVM compiler uses the ASM statement to support the inline assembly language: asm ("nop"); Copy to clipboard In this example, the processor instruction specified in the string is inserted directly into the generated assembly code at its current position in the C program. The LLVM compiler also allows the operands of inline assembly instructions to be specified as C expressions, which allows you write assembly code that is more tightly integrated with the surrounding C code. For example: asm ("%0=add(%1,#%2)" : "=r" (result) : "r" (myvar), "i" (4)); Copy to clipboard This example is equivalent to the C statement, `result=myvar+4`, where `result` and `myvar` are C variables declared in the program. The strings preceding each operand specify the operand type, and whether the operand is an input or output. The `asm` instruction has the following syntax: asm ( instruction_template [: output_operands ] [: input_operands ] [: clobber_registers ] ); Copy to clipboard - The instruction template consists of a character string containing the text of the inline assembly code, with embedded parameters specifying where the operands are to be substituted (for example, `%0=add(%1,#%2)`). The parameter numbers (`%n`) correspond to the declaration order of the operands following the template. - Each input or output operand consists of an operand constraint string followed by a C expression in parentheses (for example, `"=r" (result)`). Typical operand constraint characters are `r` (for register operands), `i` (for integer constant operands), and `m` (for memory operands). - Each clobber register consists of a string containing the name of a register. - Colons are used to separate the instruction template, output operand list, input operand list, and clobber register list. The lists are optional; however, if a list (such as output operands) is omitted while a following list (such as input operands) is not, two consecutive colons must appear to indicate the omitted list. - Commas are used to separate the operands (or registers) within each list. Branches from one ASM statement to another ASM statement are not supported. The compiler code optimizer is not aware of such branches, and therefore it cannot take them into account when deciding how to optimize. Input and output operands can be specified using symbolic names that can be referenced within the assembly code. These names are specified inside square brackets preceding the constraint string, and they can be referenced inside the assembly code using `%[name]` instead of a percentage sign followed by the operand number. Using named operands, the example can be specified as: asm ("%[dest]=add(%[src1],#%[src2])" : [dest] "=r" (result) : [src1] "r" (myvar), [src2] "i" (4)); Copy to clipboard Note Symbolic operand names have no relation to other C identifiers. They can be assigned any name (including those of existing C symbols), but no two operands within the same ASM statement can use the same symbolic name. ## Operand constraints Operand constraints are specified with the input and output operands of an ASM statement. Constraints specify the following properties of an operand: - Whether an operand can be in a register, and what kind of register - Whether the operand can be a memory reference, and what kind of address - Whether the operand can be an immediate constant, and what possible values Constraints can also require two operands to match. ### Simple constraints Following are the most common constraints supported by inline assembly code: - `m` - Memory address operand - `r` - Register in the general purpose register class of the target: `r0-r31` - `i` - Integer constant (of target-specific width); allows either a simple immediate or a relocatable value - `l` - Low integer register: `r0-r7` - `a` - Modifier register: `m0-m1` - `v` - Vector register: `v0-v31` - `q` - Vector predicate register: `q0-q3` ### Constraint modifiers In addition to the constraints described in [Simple constraints](https://docs.qualcomm.com/doc/80-N3040-23/topic/inline-assembly-language.html#hccpp-operan-const-simple-contraints-sub), constraint modifiers can be added to specify the behavior for operands. If constraint modifiers are specified, they should be the first character of the constraint string. Following are commonly used modifiers: - `=` - Operand is write-only for this instruction; the output data discards and replaces the previous value - `+` - Instruction reads and writes the operand In processing operands to satisfy the constraints, the compiler identifies which operands are inputs and outputs for the inline assembly code. = identifies an output; + identifies an operand that is both input and output; all other operands are assumed to be input only. Last Published: Oct 06, 2026 [Previous Topic Predefined symbols for HVX coprocessor versions](https://docs.qualcomm.com/bundle/publicresource/80-N3040-23/topics/language-extensions.md) [Next Topic Attributes](https://docs.qualcomm.com/bundle/publicresource/80-N3040-23/topics/attributes.md)