/* Copyright (c) 2001, 2002, Harald Kipp
   Copyright (c) 2007 Eric B. Weddington
   All rights reserved.

   Redistribution and use in source and binary forms, with or without
   modification, are permitted provided that the following conditions are met:

   * Redistributions of source code must retain the above copyright
     notice, this list of conditions and the following disclaimer.
   * Redistributions in binary form must reproduce the above copyright
     notice, this list of conditions and the following disclaimer in
     the documentation and/or other materials provided with the
     distribution.

   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   POSSIBILITY OF SUCH DAMAGE. */


/** \page inline_asm Inline Assembler Cookbook

AVR-GCC<br>
Inline Assembler Cookbook

- \ref inline_asm_about
- \ref inline_asm_building_blocks "Building Blocks"
  - \ref inline_asm_anatomy
  - \ref inline_asm_special_sequences
  - \ref inline_asm_constraints
    - \ref constraint_modifiers "Constraint Modifiers"
    - \ref instructions_and_constraints "Instructions and Constraints"
  - \ref inline_asm_print_modifiers
  - \ref assembly_operand_modifiers
- \ref inline_asm_examples
  - \ref inline_asm_swap_nibbles
  - \ref inline_asm_swap_bytes
  - \ref inline_asm_access_memory
  - \ref inline_asm_bytes
  - \ref builtin_constant_p_in_inline_functions
         "Inline Functions and __builtin_constant_p"
  - \ref inline_asm_jumping
- \ref inline_asm_local_vars
  - \ref inline_asm_abi_interface
- \ref c_names_in_asm
- \ref inline_asm_fails

\section inline_asm_about About this Document

The GNU C/C++ compiler for AVR RISC processors offers to embed assembly
language code into C/C++ programs. This cool feature may be used for manually
optimizing time critical parts of the software, or to use specific processor
instructions which are not available in the C language.

It's assumed that you are familiar with writing AVR assembler programs,
because this is not an AVR assembler programming tutorial. It's not a C/C++
tutorial either.

Note that this document does not cover files written completely in assembly
language, refer to \ref assembler for this.

Copyright (C) 2001-2002 by egnite Software GmbH

Permission is granted to copy and distribute verbatim copies of this manual
provided that the copyright notice and this permission notice are preserved on
all copies. Permission is granted to copy and distribute modified versions of
this manual provided that the entire resulting derived work is distributed
under the terms of a permission notice identical to this one.

This document describes version 4.7 of the compiler or newer.

Herne, 17th of May 2002
Harald Kipp
harald.kipp-at-egnite.de

\anchor inline_asm_building_blocks

\section inline_asm_anatomy The Anatomy of a GCC asm Statement

A GCC inline assembly statement starts with the keyword \c asm, \c __asm
or \c __asm__, where the first one is not available in strict ANSI mode.

In its simplest form, the inline assembly statement has no operands and
injects just one instruction into the code stream, like in
\code
__asm ("nop");
\endcode
In its generic form, an asm statements can have one of the following three
forms:

<dl>
<dt>A simple asm without operands</dt>
<dd>
  \code{none}
  __asm (code-string);
  \endcode
  \c code-string is a string literal that will be added as is into the
  generated assembly code.  This even applies to the \% character.
  The only replacement is that \\n and \\t are interpreted as newline resp.
  TAB character.

  This type of asm statement may occur at top level, outside any function
  as global asm.  When its placement relative to functions is important,
  consider \c -fno-toplevel-reorder.
</dd>

<dt>An asm with operands</dt>
<dd>
  \code{none}
  __asm volatile (code-string : output-operands : input-operands : clobbers);
  \endcode
  This is the most widely used form of an asm statement.  It must be located
  in a function.

  \c output-operands, \c input-operands and \c clobbers are comma-separated
  lists of operands resp. clobber specifications.  Any of them may be empty,
  for example when the asm has no outputs.  At least one \c : (colon) must be
  present, otherwise it will be a simple asm without operands and without
  \c \% replacements.
</dd>

<dt>An asm goto statement</dt>
<dd>
  \code{none}
  __asm goto (code-string : : input-operands : clobbers : labels);
  \endcode
  Like the asm above, but \c labels is a comma-separated list of C/C++
  code labels which would be valid in a \c goto statement.
  And \c output-operands must be empty, because it is impossible to generate
  output reloads after the code has transferred control to one of the labels.
  <br>
  As there are no output operands, asm goto is implicitly volatile.
  When \c volatile is specified explicitly, the \c goto keyword may be
  placed after or before the \c volatile.
</dd>
</dl>

Notes on the various parts:

<dl>
<dt>Volatility</dt>
<dd>
  Keyword  \c volatile is optional and means that the asm statement has side
  effects that are not expressed in terms of the operands or clobbers.
  The asm statement must not be optimized away or reordered with respect
  to other volatile statements like volatile memory accesses or other
  volatile asm.

  Any asm statement without \c output-operands is implicitly volatile.

  A non-volatile asm statement with output operands that are all unused
  may be optimized away when all output operands are unused.

  Instead of \c volatile, \c __volatile or \c __volatile__ can be used.
</dd>

<dt><tt>code-string</tt></dt>
<dd>
  A string literal that contains the code that is to be injected in the
  assembly code generated by the compiler.  \c %-expressions are replaced
  by the string representations of the operands, and the number of lines
  is determined to estimate the code size of the asm.<br>
  Apart from that, <b>the compiler does not analyze the code provided in
	the code template.</b><br>
  This means that the code appears to the compiler <em>as if it was
	executed in one parallel chunk, all at once</em>.  It is important to
  keep that in mind, in particular for cases where input and output operands
  may overlap.
</dd>

<dt><tt>output-operands</tt></dt>
<dt><tt>input-operands</tt></dt>
<dd>
  A comma-separated list of operands, which may take the following forms.
  In any case, the first operand can be referred to as \c "%0" in
  \c code-string, the second one as \c "%1" etc.
  <dl>
  <dt><tt>"constraints" (expr)</tt></dt>
  <dd>
    \c expr is a C expression that's an input or output (or both) to the
    asm statement. An output expression must be an lvalue, i.e. it must
    be valid to assign a value to it.
    <br>
    \c "constraints" is a string literal with \ref constraints and
    \ref constraint_modifiers "constraint modifiers".
    For example,
    constraint \c "r" stands for <em>general-purpose register</em>.
    A simple input operand would be
    \code
    "r" (value + 1)
    \endcode
    The compiler computes <tt>value + 1</tt> and supplies it in some
    general-purpose register R2...R31.  In many cases, an upper d-register
    R16...R31 is required for instructions like \c LDI or \c ANDI.
    A respective output operand specification is
    \code
    "=d" (result)
    \endcode
    <b>Notice that this operand may overlap with input operands!</b><br>
    When an operand is written before all input operands are consumed, then
    in almost all cases the output operand requires an early-clobber modifier
    \c \& so that it won't overlap with any input operand:
    \code
    "=&d" (result)
    \endcode
    An operand that's both an output and an input can be expressed with
    the \c + constraint modifier:
    \code
    "+d" (result)
    \endcode
    Such an operand is both output and input, and hence it won't overlap
    with other operands.
  </dd>
  <dt><tt>[name] "constraints" (expr)</tt></dt>
  <dd>
    Like above. In addition, a named operand can be referred to as
    <tt>\%[name]</tt> in \c code-string.  This is useful in long asm
    statements with many operands.
  </dd>
  </dl>
</dd>

<dt><tt>clobbers</tt></dt>
<dd>
  A comma-separated list of string literals like \c "16", "r16" or "memory".

  The first two clobbers mean that the asm destroys register R16. Only the
  lower-case form is allowed, and register names like Z are not recognized.

  \c "memory" means that the asm touches memory in some way.
  When the asm writes to some RAM location for example, the compiler must not
  optimize RAM accesses across the asm because the memory may change.

  Clobbering <tt>\ref tmp_reg "__tmp_reg__"</tt> by means of
  \c "r0" has no effect, but such
  a clobber may be added to indicate to the reader that the asm clobbers R0.

  Clobbering <tt>\ref zero_reg "__zero_reg__"</tt> by means of
  \c "r1" has no effect.
  When the asm destroys the zero register, for example by means of
  a \c MUL instruction, then the code must restore the register at
  the end by means of <tt>"clr __zero_reg__"</tt>
</dd>

<dt>The size of an asm\anchor inline_asm_size</dt>
<dd>
  The code size of an asm statement is the number of lines multiplied by
  4&nbsp;bytes, the maximal possible AVR instruction length.
  The length is needed when (conditional) jumps cross the
  asm statement in order to compute (upper bounds for) jump offsets
  of PC-relative jumps.

  The number of lines is one plus the number of line breaks in
  \c code-string.  These may be physical line breaks from \c \\n characters
  and logical line breaks from \c \$ characters.
</dd>
</dl>

Before we start with the first examples, we list all the bells and
whistles that can be used to compose an inline assembly statement:
\ref special_sequences "special sequences",
\ref constraints,
\ref constraint_modifiers "constraint modifiers",
\ref print_modifiers "print modifiers" and
\ref operand_modifiers "operand modifiers".

\section inline_asm_special_sequences Special Sequences

There are special sequences that can be used in the assembly template.

\anchor special_sequences
<table>
<caption>Inline asm Special Sequences</caption>
<tr>
  <th>Sequence
  <th>Description
</tr>
<tr>
  <td><tt>__SREG__</tt></td>
  <td>The I/O address of the status register SREG at 0x3F</td>
</tr>
<tr>
  <td><tt>__tmp_reg__</tt></td>
  <td>The \ref tmp_reg "temporary register" R0 (R16 on reduced Tiny)</td>
</tr>
<tr>
  <td><tt>__zero_reg__</tt></td>
  <td>The \ref zero_reg "zero register" R1, always zero (R17 on reduced Tiny)</td>
</tr>
<tr>
  <td><tt>$</tt>
  <td>A logical line separator, used to separate multiple instruction in
    one physical line
</tr>
<tr>
  <td><tt>\\n</tt>
  <td>A physical newline, used to separate multiple instructions
</tr>
<tr>
  <td><tt>\\t</tt>
  <td>A TAB character, can be used for better legibility of the generated asm
</tr>
<tr>
  <td><tt>\\\"</tt>
  <td>A \c \" character (double quote)
</tr>
<tr>
  <td><tt>\\\\</tt>
  <td>A \c \\ character (backslash)
</tr>
<tr>
  <td><tt>\%\%</tt>
  <td>A \c \% charater (percent)
</tr>
<tr>
  <td><tt>%~</tt>
  <td>\c "r" or \c "", used to construct \c call or \c rcall by means of
    \c "%~call", depending on the architecture
</tr>
<tr>
  <td><tt>%!</tt>
  <td>\c "" or \c "e", used to construct indirect calls like \c icall
    or \c eicall by means of \c "%!icall", depending on the architecture
</tr>
<tr>
  <td><tt>%=</tt>
  <td>A number that's unique for the compilation unit and the respective
    inline asm code, used to construct unique labels
</tr>
<tr>
  <th>Comment
  <th>Description
</tr>
<tr>
  <td><tt>; text</tt>
  <td>A single-line assembly comment that extends to the end of the
    physical line
</tr>
<tr>
  <td><tt>/* text *<!-- -->/</tt>
  <td>A multi-line C comment
</tr>
</table>

- Moreover, the following I/O addresses are defined provided the device
supports the respective SFR: <tt>__SP_L__</tt>, <tt>__SP_H__</tt>,
<tt>__CCP__</tt>, <tt>__RAMPX__</tt>, <tt>__RAMPY__</tt>,
<tt>__RAMPZ__</tt>, <tt>__RAMPD__</tt>.

- Register \c __tmp_reg__ may be freely used by inline assembly code and
need not be restored at the end of the code.

- Register \c __zero_reg__ contains a value of zero.  When that value is
destroyed, for example by a \c MUL instruction, its value has to be
restored at the end of the code by means of
\code
clr __zero_reg__
\endcode

- In inline asm without operands (i.e without a single colon), a \c \% will
always insert a single \c \%. No \c %-codes are available.

Sequences like \c __SREG__ are not evaluated as part of the inline asm,
they are just copied to the asm code as they are.  At the top of each
assembly file, the compiler prints definitions like
\code
__SREG__ = 0x3f
\endcode
so that they can also be used in inline assembly.

\section inline_asm_constraints Constraints

The most up-to-date and detailed information on constraints for the AVR
can be found in the
<a href="https://gcc.gnu.org/wiki/avr-gcc#Constraints">avr-gcc Wiki</a>.

\anchor constraints
<table>
  <caption>Inline asm Operand Constraints</caption>
  <tr>
    <th>Constraint
    <th>Registers
    <th>Range
  </tr>
  <tr><td>\c a</td><td>Simple upper registers that support \c FMUL</td>
    <td>R16 ... R23</td></tr>
  <tr><td>\c b</td><td>Base pointer registers that support \c LDD, \c STD</td>
    <td>Y, Z (R28 ... R31)</td></tr>
  <tr><td>\c d</td><td>Upper registers</td><td>R16 ... R31</td></tr>
  <tr><td>\c e</td><td>Pointer registers that support \c LD, \c ST</td>
    <td>X, Y, Z (R26 ... R31)</td></tr>
  <tr><td>\c l</td><td>Lower registers</td><td>R2 ... R15</td></tr>
  <tr><td>\c r</td><td>Any register</td><td>R2 ... R31</td></tr>
  <tr><td>\c w</td><td>Upper registers that support \c ADIW</td>
    <td>R24 ... R31</td></tr>
  <tr><td>\c x</td><td>X pointer registers</td><td>R26, R27</td></tr>
  <tr><td>\c y</td><td>Y pointer registers</td><td>R28, R29</td></tr>
  <tr><td>\c z</td><td>Z pointer registers</td><td>R30, R31</td></tr>
  <tr>
    <th>Constraint
    <th>Constant
    <th>Range
  </tr>
  <tr><td>\c I</td><td>6-bit unsigned integer constant</td><td>0 to 63</td></tr>
  <tr><td>\c J</td><td>6-bit negative integer constant</td><td>&minus;63 to 0</td></tr>
  <tr><td>\c M</td><td>8-bit unsigned integer constant</td><td>0 to 255</td></tr>
  <tr><td>\c n</td><td>Integer constant</td><td></td></tr>
  <tr><td>\c i</td><td>Immediate value known at link-time, like the
    address of a variable in static storage</td><td></td></tr>
  <tr><td>\c EF</td><td>Floating-point constant</td><td></td></tr>
  <tr><td>\c Ynn</td><td>Fixed-point or integer constant</td><td></td></tr>
  <tr>
    <th>Constraint
    <th>Explanation
    <th>Notes
  </tr>
  <tr><td>\c m</td><td>A memory location</td><td></td></tr>
  <tr><td>\c X</td><td>Any valid operand</td><td></td></tr>
  <tr><td>\c 0 ... \c 9</td><td>Matches the respective operand number</td><td></td></tr>
</table>

\anchor constraint_modifiers
- Constraints without a modifier specify input operands.
- Constraints with a modifier specify output operands.
- More than one constraint like in \c "rn" specifies the union of the
  specified constraints; \c "r" and \c "n" in this case.
- All constraints listed above are single-letter constraints, except \c Ynn
  which is a 3-letter constraint.

Constraint modifiers are:

<table>
  <caption>Constraint Modifiers</caption>
  <tr>
    <th>Modifier
    <th>Meaning
  </tr>
  <tr>
    <td>\c =
    <td>Output-only operand. Without \c \& it may overlap with
      input operands
  </tr>
  <tr>
    <td>\c +
    <td>Output operand that's also an input</td>
  </tr>
  <tr>
    <td>\c =\&
    <td>"Early-clobber". Register should be used for output only
    and won't overlap with any input operand(s)
  </tr>
</table>

The selection of
the proper constraint depends on the range of the constants or registers, which
must be acceptable to the AVR instruction they are used with. The C compiler
doesn't check any line of your assembler code. But it is able to check the
constraint against your C expression. However, if you specify the wrong
constraints, then the compiler may silently pass wrong code to the assembler.
And, of course, the assembler will fail with some cryptic output or internal
errors, or in the worst case wrong code may be the result.

For example, if you specify the constraint \c "r" and you are using
this register with an \c ORI instruction, then the
compiler may select any register. This will fail if the compiler chooses
\c R2 to \c R15. (It will never choose \c R0 or \c R1, because these are
uses for special purposes.) That's why the correct constraint in that case is
<tt>"d"</tt>. On the other hand, if you use the constraint <tt>"M"</tt>, the
compiler will make sure that you don't pass anything else but an 8-bit
unsigned integer value known at compile-time.

The following table shows all AVR assembler mnemonics which require
operands, and the related constraints.

\anchor instructions_and_constraints
<table>
<caption>AVR Instructions and
  Constraints</caption>
<tr>
  <th>Mnemonic
  <th>Constraints
  <td>
  <th>Mnemonic
  <th>Constraints
</tr>
<tr>
  <td><tt>adc</tt>    <td><tt>r,r</tt>
  <td rowspan="36">
  <td><tt>add</tt>    <td><tt>r,r</tt>
</tr>
<tr>
  <td><tt>adiw</tt>   <td><tt>w,I</tt>
  <td><tt>and</tt>    <td><tt>r,r</tt>
</tr>
<tr>
  <td><tt>andi</tt>   <td><tt>d,M</tt>
  <td><tt>asr</tt>    <td><tt>r</tt>
</tr>
<tr>
  <td><tt>bclr</tt>   <td><tt>I</tt>
  <td><tt>bld</tt>    <td><tt>r,I</tt>
</tr>
<tr>
  <td><tt>brbc</tt>   <td><tt>I,label</tt>
  <td><tt>brbs</tt>   <td><tt>I,label</tt>
</tr>
<tr>
  <td><tt>bset</tt>   <td><tt>I</tt>
  <td><tt>bst</tt>    <td><tt>r,I</tt>
</tr>
<tr>
  <td><tt>call</tt>   <td><tt>i</tt>
  <td><tt>cbi</tt>    <td><tt>I,I</tt>
</tr>
<tr>
  <td><tt>cbr</tt>    <td><tt>d,I</tt>
  <td><tt>clr</tt>    <td><tt>r</tt>
</tr>
<tr>
  <td><tt>com</tt>    <td><tt>r</tt>
  <td><tt>cp</tt>     <td><tt>r,r</tt>
</tr>
<tr>
  <td><tt>cpc</tt>    <td><tt>r,r</tt>
  <td><tt>cpi</tt>    <td><tt>d,M</tt>
</tr>
<tr>
  <td><tt>cpse</tt>   <td><tt>r,r</tt>
  <td><tt>dec</tt>    <td><tt>r</tt>
</tr>
<tr>
  <td><tt>elpm</tt>   <td><tt>r,z</tt>
  <td><tt>eor</tt>    <td><tt>r,r</tt>
</tr>
<tr>
  <td><tt>fmul</tt>   <td><tt>a,a</tt>
  <td><tt>fmuls</tt>  <td><tt>a,a</tt>
</tr>
<tr>
  <td><tt>fmulsu</tt> <td><tt>a,a</tt>
  <td><tt>in</tt>     <td><tt>r,I</tt>
</tr>
<tr>
  <td><tt>inc</tt>    <td><tt>r</tt>
  <td><tt>jmp</tt>    <td><tt>i</tt>
</tr>
<tr>
  <td><tt>lac</tt>    <td><tt>z,r</tt>
  <td><tt>las</tt>    <td><tt>z,r</tt>
</tr>
<tr>
  <td><tt>lat</tt>    <td><tt>z,r</tt>
  <td><tt>ld</tt>     <td><tt>r,e</tt>
</tr>
<tr>
  <td><tt>ldd</tt>    <td><tt>r,b</tt>
  <td><tt>ldi</tt>    <td><tt>d,M</tt>
</tr>
<tr>
  <td><tt>lds</tt>    <td><tt>r,i</tt>
  <td><tt>lpm</tt>    <td><tt>r,z</tt>
</tr>
<tr>
  <td><tt>lsl</tt>    <td><tt>r</tt>
  <td><tt>lsr</tt>    <td><tt>r</tt>
</tr>
<tr>
  <td><tt>mov</tt>    <td><tt>r,r</tt>
  <td><tt>movw</tt>   <td><tt>r,r</tt>
</tr>
<tr>
  <td><tt>mul</tt>    <td><tt>r,r</tt>
  <td><tt>muls</tt>   <td><tt>r,r</tt>
</tr>
<tr>
  <td><tt>mulsu</tt>  <td><tt>a,a</tt>
  <td><tt>neg</tt>    <td><tt>r</tt>
</tr>
<tr>
  <td><tt>or</tt>     <td><tt>r,r</tt>
  <td><tt>ori</tt>    <td><tt>d,M</tt>
</tr>
<tr>
  <td><tt>out</tt>    <td><tt>I,r</tt>
  <td><tt>pop</tt>    <td><tt>r</tt>
</tr>
<tr>
  <td><tt>push</tt>   <td><tt>r</tt>
  <td><tt>rcall</tt>  <td><tt>i</tt>
</tr>
<tr>
  <td><tt>rjmp</tt>   <td><tt>i</tt>
  <td><tt>rol</tt>    <td><tt>r</tt>
</tr>
<tr>
  <td><tt>ror</tt>    <td><tt>r</tt>
  <td><tt>sbc</tt>    <td><tt>r,r</tt>
</tr>
<tr>
  <td><tt>sbci</tt>   <td><tt>d,M</tt>
  <td><tt>sbi</tt>    <td><tt>I,I</tt>
</tr>
<tr>
  <td><tt>sbic</tt>   <td><tt>I,I</tt>
  <td><tt>sbiw</tt>   <td><tt>w,I</tt>
</tr>
<tr>
  <td><tt>sbr</tt>    <td><tt>d,M</tt>
  <td><tt>sbrc</tt>   <td><tt>r,I</tt>
</tr>
<tr>
  <td><tt>sbrs</tt>   <td><tt>r,I</tt>
  <td><tt>ser</tt>    <td><tt>d</tt>
</tr>
<tr>
  <td><tt>st</tt>     <td><tt>e,r</tt>
  <td><tt>std</tt>    <td><tt>b,r</tt>
</tr>
<tr>
  <td><tt>sts</tt>    <td><tt>i,r</tt>
  <td><tt>sub</tt>    <td><tt>r,r</tt>
</tr>
<tr>
  <td><tt>subi</tt>   <td><tt>d,M</tt>
  <td><tt>swap</tt>   <td><tt>r</tt>
</tr>
<tr>
  <td><tt>tst</tt>
  <td><tt>r</tt>
  <td><tt>xch</tt>
  <td><tt>z,r</tt>
</tr>
</table>

\section inline_asm_print_modifiers Print Modifiers

The %-operands in the inline assembly template can be adjusted by special
print-modify characters.  The one-letter modifier follows the \c \%
and precedes the operand number like in <tt>"%a0"</tt>, or precedes the
name in named operands like in <tt>"%a[address]"</tt>.

\anchor print_modifiers
<table>
<caption>Inline asm Print Modifiers</caption>
<tr>
  <th>Modifier
  <th>Number of<br>Arguments
  <th>Explanation
  <th>Suitable<br>Constraints
</tr>
<tr>
  <td><tt>\%a0</tt> <td> 1
  <td> Print pointer register as address <tt>X</tt>, <tt>Y</tt> or <tt>Z</tt>,
    like in <tt>"LD r0, %a0+"</tt>
  <td> <tt>x</tt>, <tt>y</tt>, <tt>z</tt>, <tt>b</tt>, <tt>e</tt>
</tr>
<tr>
  <td><tt>\%i0</tt> <td> 1
  <td> Print compile-time RAM address as I/O address,
    like in <tt>"OUT %i0, r0"</tt> with argument <tt>"n"(&SREG)</tt>
  <td> <tt>n</tt>
</tr>
<tr>
  <td><tt>\%n0</tt> <td> 1
  <td> Print the negative of a compile-time integer constant
  <td><tt>n</tt>
</tr>
<tr>
  <td><tt>\%r0</tt> <td> 1
  <td> Print the register number of a register, like in <tt>"CLR %r0+7"</tt>
    for the MSB of a 64-bit register
  <td> reg
</tr>
<tr>
  <td><tt>\%x0</tt> <td> 1
  <td> Print a function name without <tt>gs()</tt> modifier, like in
    <tt>"%~CALL %x0"</tt> with argument <tt>"s"(main)</tt>
  <td> <tt>s</tt>
</tr>
<tr>
  <td><tt>\%A0</tt> <td> 1
  <td> Add 0 to the register number (no effect)
  <td> reg
</tr>
<tr>
  <td><tt>\%B0</tt> <td> 1
  <td> Add 1 to the register number
  <td> reg
</tr>
<tr>
  <td><tt>\%C0</tt> <td> 1
  <td> Add 2 to the register number
  <td> reg
</tr>
<tr>
  <td><tt>\%D0</tt> <td> 1
  <td> Add 3 to the register number
  <td> reg
</tr>
<tr>
  <td><tt>\%T0\%t1</tt> <td> 2
  <td> Print the register that holds bit number <tt>%1</tt> of register
    <tt>%0</tt>
  <td> reg + <tt>n</tt>
</tr>
<tr>
  <td><tt>\%T0\%T1</tt> <td> 2
  <td> Print operands suitable for <tt>BLD</tt>/<tt>BST</tt>, like in
    <tt>"BST %T0%T1"</tt>, including the required <tt>,</tt>
  <td> reg + <tt>n</tt>
</tr>
</table>

- Register constraints are: <tt>r</tt>, <tt>d</tt>, <tt>w</tt>, <tt>x</tt>,
<tt>y</tt>, <tt>z</tt>, <tt>b</tt>, <tt>e</tt>, <tt>a</tt>, <tt>l</tt>.

\section assembly_operand_modifiers Operand Modifiers

\anchor operand_modifiers
<table>
<caption>Assembly Code Operand Modifiers</caption>
<tr>
  <th>Modifier
  <th>Explanation
  <th>Purpose
</tr>
<tr>
  <td><tt>lo8()</tt>
  <td> 1<sup>st</sup> Byte of a link-time constant, bits 0...7
  <td rowspan="5"> Getting parts<br>of a byte-address
</tr>
<tr>
  <td><tt>hi8()</tt>
  <td> 2<sup>nd</sup> Byte of a link-time constant, bits 8...15
</tr>
<tr>
  <td><tt>hlo8()</tt>
  <td> 3<sup>rd</sup> Byte of a link-time constant, bits 16...23
</tr>
<tr>
  <td><tt>hhi8()</tt>
  <td> 4<sup>th</sup> Byte of a link-time constant, bits 24...31
</tr>
<tr>
  <td><tt>hh8()</tt>
  <td> Same like <tt>hlo8</tt>
</tr>
<tr>
  <td><tt>pm_lo8()</tt>
  <td> 1<sup>st</sup> Byte of a link-time constant divided by 2, bits 1...8
    <td rowspan="3"> Getting parts<br>of a word-address
</tr>
<tr>
  <td><tt>pm_hi8()</tt>
  <td> 2<sup>nd</sup> Byte of a link-time constant divided by 2, bits 9...16
</tr>
<tr>
  <td><tt>pm_hh8()</tt>
  <td> 3<sup>rd</sup> Byte of a link-time constant divided by 2, bits 17...24
</tr>
<tr>
  <td><tt>pm()</tt>
  <td> Link-time constant divided by 2 in order to get a <b>p</b>rogram
    <b>m</b>emory (word) addresses, like in <tt>lo8(pm(main))</tt>
    <td>Word-address
</tr>
<tr>
  <td><tt>gs()</tt>
  <td> Function address divided by 2 in order to get a (word) addresses,
    like in <tt>lo8(gs(main))</tt>. <b>G</b>enerate <b>s</b>tub (trampoline)
    as needed. This is required to calculate the address of a code label on
    devices with more than 128&nbsp;KiB of program memory that's supposed
    to be used in \c EICALL. For rationale, see the
    <a href="https://gcc.gnu.org/onlinedocs/gcc/AVR-Options.html#eind"
       >GCC documentation</a>. On devices with less program memory,
    <tt>gs()</tt> behaves like <tt>pm()</tt>
  <td>Function address<br>for <tt>[E]ICALL</tt>
</tr>
</table>

When the argument of a modifier is not computable at assembler-time,
then the assembler has to encode the expression in an abstract form using
<a href="https://github.com/bminor/binutils-gdb/blob/master/include/elf/avr.h"
   >RELOCs</a>.
Consequence is that only a very limited number of argument expressions is
supported when they are not computable at assembler-time.

\section inline_asm_examples Examples

Some examples show the assembly code as generated by the compiler.
It's the code from the \c \.s files as generated with option \c -save-temps.
Adding the high-level source to the generated assembly can be turned on
with <tt>\ref opt_fverbose_asm "-fverbose-asm"</tt> since GCC v8.

\subsection inline_asm_swap_nibbles Swapping Nibbles

The fist example uses the \c swap instruction to swap the nibbles of
a byte.  Input and output of \c swap are located in the same general
purpose register.
This means the input operand, operand 1 below, must be located in the
same register(s) like operand 0, so that the right \ref constraints
"constraint" for operand 1 is \c "0":
\code
asm ("swap" : "=r" (value) : "0" (value));
\endcode
All side effects of the code are described by the constraints and the clobbers,
so that there is no need for this asm to be volatile.  In particular, this
asm may be optimized out when the output value is unused.<br>
A shorter pattern to state that \c value is both input and output is by
means of \ref constraint_modifiers "constraint modifier" \c +
\code
asm ("swap" : "+r" (value));
\endcode

\subsection inline_asm_swap_bytes Swapping Bytes

Swapping nibbles was a piece of cake, so let's swap the bytes of a
16-bit value.  In order to access the constituent bytes of the 16-bit
input and output values, we use the \ref inline_asm_print_modifiers
"print modifiers" \c \%A and \c \%B.

The asm is placed in a small C test case so that we can inspect the
resulting assembly code as generated by the compiler with \c -save-temps.

\code
void callee (int, int);

void func (int param)
{
    int swapped;

    asm ("mov %A0, %B1" "\n\t"
         "mov %B0, %A1"
         : "=r" (swapped) : "r" (param));

    callee (param, swapped);
}
\endcode

The \c "\n\t" \ref special_sequences "sequence" adds a line feed that
is required between the
two instructions, and a TAB to align the two instructions in the generated
assembly. There is no \c "\n\t" after the last instruction because that would
just increase the \ref inline_asm_size "size of the asm".<br>
The generated assembly works as expected. The compiler wraps it in
\c \#APP / \c \#NOAPP annotations:
\code
func:
/* #APP */
    mov r22, r25     ;  swapped, param
    mov r23, r24     ;  swapped, param
/* #NOAPP */
    jmp callee
\endcode

Wrong!
<b>While the generated code above is correct, the inline asm itself is not!</b>
<br>
We see this with a slightly adjusted test case where the arguments of
\c callee have been swapped, but that uses the same inline asm:
\code
void func (int param)
{
    int swapped;

    asm ("mov %A0, %B1" "\n\t"
         "mov %B0, %A1"
         : "=r" (swapped) : "r" (param));

    callee (swapped, param);
}
\endcode

The result is the following assembly:

\code
func:
    movw r22,r24
/* #APP */
    mov r24, r25     ;  swapped, param
    mov r25, r24     ;  swapped, param
/* #NOAPP */
    jmp callee
\endcode

which is obviously wrong, because after the code from the inline asm,
the low byte of \c swapped and the high byte will always have the same
value of \c r25.

The reason is that the output operand overlaps the input,
<em>and</em> the output is changed before all of the input operands
are consumed.  This is a so-called <em>early-clobber</em> situation.
There are two possible solutions to this predicament:

- Mark the output operand with the early-clobber \ref constraint_modifiers
"constraint modifier":
\code
    asm ("mov %A0, %B1" "\n\t"
         "mov %B0, %A1"
         : "=&r" (swapped) : "r" (param));
\endcode

- Use constraints and a code sequence that expect input and output in the
same registers:
\code
    asm ("eor %A0, %B0" "\n\t"
         "eor %B0, %A0" "\n\t"
         "eor %A0, %B0"
         : "=r" (swapped) : "0" (param));
\endcode

\subsection inline_asm_access_memory Accessing Memory

Accessing memory requires that the AVR instructions that perform the memory
access are provided with the appropriate memory address.

-# The address can be provided directly, like \c __SREG__,
0x3f, as a symbol, or as a symbol plus a constant offset.
-# Provide the address by means of an inline asm operand.

Approach 1 is simpler as it does not require an asm operand,
while approach 2 is in many cases more powerful
because macros defined per, say, <code>\#include <avr/io.h></code> can be used
as operands, whereas such headers are not included in the assembly code as
generated by the compiler.

Reading a SFR like \c PORTB can be performed by
\code
asm volatile ("in %0, %1" : "=r" (result) : "I" _SFR_IO_ADDR (PORTB));
\endcode
Macro \c _SFR_IO_ADDR is provided by <code>avr/sfr_defs.h</code> which is
included by <code>avr/io.h</code>.

Since GCC v4.7, \ref print_modifiers "print modifier" \c \%i is supported,
which prints RAM addresses like <code>& PORTB</code> as an I/O address:

\code
asm volatile ("in %0, %i1" : "=r" (result) : "I" (& PORTB));
\endcode

When the address is not an I/O address, then \c LDS or \c LD must be used,
depending on whether the address is known at link-time or only at run-time.
For example, the following macro provides the functionality to clear an SFR.
The code discriminates between the possibilities that
- The SFR address is known at compile-time and is an I/O address.
- The SFR address is known at compile-time but is not in the I/O range.
- The SFR address is not known at compile-time.

<!-- "none" because Doxygen messes up syntax hilit -->
\code{none}
#include <avr/io.h>

#define CLEAR_REG(sfr)                          \
do {                                            \
  if (__builtin_constant_p (& (sfr))            \
      && _SFR_IO_REG_P (sfr))                   \
    asm volatile ("out %i0, __zero_reg__"       \
                  :: "I" (& (sfr)) : "memory"); \
  else if (__builtin_constant_p (& (sfr)))      \
    asm volatile ("sts %0, __zero_reg__"        \
                  :: "n" (& (sfr)) : "memory"); \
  else                                          \
    asm volatile ("st %a0, __zero_reg__"        \
                  :: "e" (& (sfr)) : "memory"); \
} while (0)
\endcode

The last case with constraint \c "e" works because \c \&sfr is a 16-bit
value, and 16-bit values (and larger) start in even registers.  Therefore,
the address will be located in R27:R26, R29:R28 or in R31:R30, which
print modifier \c \%a will print as X, Y or Z, respectively.
The address will never end up in, say, R30:R29.

The test case

\code
void clear_3_regs (uint8_t volatile *psfr)
{
    CLEAR_REG (PORTB);
    CLEAR_REG (UDR0);
    CLEAR_REG (*psfr);
}
\endcode

compiles for ATmega328 and with optimization turned on to

\code
clear_3_regs:
    movw r30,r24
/* #APP */
    out 0x5, __zero_reg__
    sts 198, __zero_reg__
    st Z,    __zero_reg__   ;  psfr
/* #NOAPP */
    ret
\endcode

\anchor builtin_constant_p_in_inline_functions
As \c __builtin_constant_p is used to infer whether the address of
the SFR is known at compile-time, extra care must be taken when the
functionality is implemented as an inline function:
\code
static inline __attribute__((__always_inline__))
void clear_reg (uint8_t volatile *psfr)
{
  // !!! The following cast is required to make __builtin_constant_p
  // !!! work as expected in the inline function.
  uintptr_t addr = (uintptr_t) psfr;

  if (__builtin_constant_p (addr)
      && _SFR_IO_REG_P (* psfr))
    asm volatile ("out %i0, __zero_reg__"
                  :: "I" (addr) : "memory");
  else if (__builtin_constant_p (addr))
    asm volatile ("sts %0, __zero_reg__"
                  :: "n" (addr) : "memory");
  else
    asm volatile ("st %a0, __zero_reg__"
                  :: "e" (addr) : "memory");
}

void clear_3_pregs (uint8_t volatile *psfr)
{
  clear_reg (& PORTB);
  clear_reg (& UDR0);
  clear_reg (psfr);
}
\endcode

<b>Casting the address \c psfr to an integer type in the inline function
  is required</b> so that the compiler will recognize constant addresses.<br>
Also notice that we have to pass the <em>address of the SFR</em> to the
inline function.  Passing the SFR directly like in the marco approach
won't work for obvious reasons.

\subsection inline_asm_bytes Accessing Bytes of wider Expressions

Finally, an example that atomically increments a 16-bit integer.
The code is wrapped in <tt>IN SREG</tt> / <tt>CLI</tt> / <tt>OUT SREG</tt>
to make it atomic. It reads the 16-bit value \c data from its absolute
address, increments it and then writes it back:

\code{c}
uint16_t volatile data;

void inc_data (void)
{
    uint16_t tmp;
    asm volatile ("in __tmp_reg__, __SREG__"   "\n\t"
                  "cli"                        "\n\t"
                  "lds %A[temp], %[addr]"      "\n\t"
                  "lds %B[temp], %[addr]+1"    "\n\t"
#ifdef __AVR_TINY__
                  // Reduced Tiny does not have ADIW.
                  "subi %A[temp], lo8(-1)"     "\n\t"
                  "sbci %B[temp], hi8(-1)"     "\n\t"
#else
                  "adiw %[temp], 1"            "\n\t"
#endif
                  "sts %[addr]+1, %B[temp]"    "\n\t"
                  "sts %[addr],   %A[temp]"    "\n\t"
                  "out __SREG__, __tmp_reg__"
#ifdef __AVR_TINY__
                  // No need to restrict tmp to a "w" register. And on
                  // avr-gcc v13.2 and older, "w" contains no regs.
                  : [temp] "=d" (tmp), "+m" (data)
#else
                  : [temp] "=w" (tmp), "+m" (data)
#endif
                  : [addr] "i" (& data));
}
\endcode

Notice there are three different ways required to access the different
bytes of the involved 16-bit entities:

- For the 16-bit general purpose register \c \%[temp], \ref print_modifiers
"print modifiers" \c \%A and \c \%B are used.

- For the 16-bit value \c data in static storage, <code>%[addr]+1</code>
is used to access the high byte. The resulting expression <code>data+1</code>
is computable at link-time and evaluated by the linker.

- In the compilation variant for Reduced Tiny, the bytes of the 16-bit
subtrahend \c &minus;1 are accessed with
the \ref operand_modifiers "operand modifiers" \c lo8 and \c hi8 that are
evaluated by the assembler because \c &minus;1 is known at assembler-time.

\c data is located in static storage, hence its address is known to the linker
and fits \ref constraints "constraint" \c "i".

The sole purpose of operand <code>"+m" (data)</code> is to describe the
effect of the asm on data memory: It changes \c data.
Notice that there is no \c "memory"
clobber, because that operand already describes all memory side effects,
and it does this in a less intrusive way than a catch-all \c "memory".
The operand is not used in the asm template; but in principle it would
be possible to use it as operand with \c LDS and \c STS instead of
operand <code>[addr] "i" (& data)</code>.  However, there are many
situations where a memory operand constrained by \c "m" takes a form that
cannot be used with AVR instructions because there are no matching print
modifiers, or because it is not known a priori what specific form the
memory operand takes.
In such cases, one would take the address of the operand and supply it
as address in a pointer register to the inline asm.  The compiler generates
the required instructions for address computation, and the inline asm knows
that it can use \c LD and \c ST.

\subsection inline_asm_jumping Jumping and Branching

When an inline asm contains jumps, then it also requires labels.
When the label is inside the asm, then care must be taken that the
label is unique in the compilation unit even when the inline asm is
used multiple times, e.g. when the code is located in an unrolled loop
or a function has multiple incarnations due to cloning, or simply because
a macro or inline function that contains an asm statement is used
more than once.
<br>
There are two kinds of labels that can be used:

- Local labels of the form <tt><em>n</em>:</tt> where <em>n</em> is
some (small, non-negative) number.  They can be targeted by means
of <tt><em>n</em>b</tt>
or <tt><em>n</em>f</tt>, depending on whether the jump direction is
<b>b</b>ackwards or <b>f</b>orwards. Such a numeric labels may be present
more than once.  The taken label is the first one with the specified number
in the respective direction:
\code
    // Loop until bit PORTB.7 is set.
    asm volatile ("1: sbrs %i[sfr], %[bitno]"  "\n\t"
                  "rjmp 1b"
                  :: [sfr] "I" (& PORTB), [bitno] "n" (PB7));
\endcode

- Local labels that contain the \ref special_sequences "sequence" <tt>\%=</tt>
which yields some number that's unique amongst all asm incarnations
in the respective compilation unit:
\code
    // Loop until bit PORTB.7 is set.
    asm volatile (".Loop.%=: sbrs %i[sfr], %[bitno]"  "\n\t"
                  "rjmp .Loop.%="
                  :: [sfr] "I" (& PORTB), [bitno] "n" (PB7));
\endcode

Which form is used is a matter of taste. In practice, the first variant is
often preferred in short sequences, whereas the second form is usually
seen in longer algorithms.

For labels that are defined in the surrounding C/C++ code, asm goto has to
be used.  The \ref print_modifiers "print modifier" <tt>\%x0</tt> prints
\c panic as a raw label, not as \c gs(panic) like it would be
the case with <tt>\%0</tt>.
\code
int main (void)
{
    asm goto ("tst __zero_reg__" "\n\t"
              "brne %x0"
              :::: panic);
    /* ...Application code here... */
    return 0;
panic:
    // __zero_reg__ is supposed to contain 0, but doesn't.
    return 1;
}
\endcode

This assumes that the jump offset can be encoded in the \c brne instruction in
all situations.  When static analysis cannot prove that the jump offset fits,
then a jumpity jump has to be used:
\code
    asm goto ("tst   __zero_reg__" "\n\t"
              "breq  1f"           "\n\t"
              "%~jmp %x0"          "\n"
              "1: ;; all fine"
              :::: panic);
\endcode

Sequence <tt>"%~jmp"</tt> yields <tt>"rjmp"</tt> or <tt>"jmp"</tt> depending
on the architecture.  Notice that a \c jmp can be relaxed to an \c rjmp
with option \c -mrelax provided the jump offset fits.

\section inline_asm_local_vars Binding local Variables to Registers

One use of GCC's \c asm keyword is to bind local register variables to
hardware registers.<br>
<b>Such bindings of local variables to registers are only guaranteed
during inline asm which has these variables as operands.</b>

\subsection inline_asm_abi_interface Interfacing non-ABI Functions

Suppose we want to interface a
non-<a href="https://gcc.gnu.org/wiki/avr-gcc#Calling_Convention"
       >ABI</a> assembly function \c mul_8_16 that
multiplies R24 with R27:R26, clobbers R0, R1 and R25, and returns the
24-bit result in R20:R19:R18.  One way to implement such an interface
would be to provide an assembly function that performs the required
copying and call to \c mul_8_16.  Such a function would destroy some of
the performance gain obtained by using assembly for \c mul_8_16:  Additional
copying back and forth and extra \c CALL and \c RET instructions.

The compiler comes to the rescue. We can bind local variables to the
required registers:
\code
extern void mul_8_16 (void); // Non-ABI function. Don't call in C/C++!

static inline __attribute__((__always_inline__))
__uint24 mul_8_16_gccabi (uint8_t val8, uint16_t val16)
{
    register uint8_t r24 __asm("r24") = val8;
    register __uint24 r18 __asm("r18");

    asm ("%~call %x[func]"  "\n\t"
         "clr    __zero_reg__"
         : "=r" (r18)
         : "r" (r24), "x" (val16), [func] "i" (mul_8_16)
         : "r25", "r0");

    return r18;
}
\endcode

- The 8-bit parameter is bound to R24, and the 24-bit return value is
bound to R18...R20.

- The \c register keyword is mandatory.

- The hard register is specified as a string literal for the lower case
register name or register number, like \c "18" or \c "r18".
Specifications like \c "R18", \c 18 or \c "Z" are not supported.

- The 16-bit parameter of \c mul_8_16 happens to be required in R27:R26,
which is the X register for which there is \ref constraints
"register constraint" <tt>"x"</tt>.
Therefore, no register binding is required for \c val16.

- As \c mul_8_16 clobbers the zero register R1, it has to be restored
by means of
\code
clr __zero_reg__
\endcode

- The asm is pure arithmetic and hence not volatile. (It might be
advisable to make it volatile anyway, so that it won't be reorderd across
\c sei() or \c cli() instructions.)

Let's have a look at how this performs in a test case:
\code
void use_mul_8_16_gccabi (uint8_t val, uint8_t a, uint8_t b)
{
    if (mul_8_16_gccabi (val, a * b) >= 0x2010)
        __builtin_abort();
}
\endcode
For ATmega8 we get the following assembly:
\code
use_mul_8_16_gccabi:
    mul  r22,r20
    movw r26,r0
    clr  __zero_reg__
/* #APP */
    rcall mul_8_16
    clr   __zero_reg__
/* #NOAPP */
    cpi  r18,16
    sbci r19,32
    cpc  r20,__zero_reg__
    brlo .L1
    rcall abort
.L1:
    ret
\endcode

No superfluous register moves. Great!

\section c_names_in_asm Specifying the Assembly Name of Static Objects

Sometimes, it is desirable to use a different name for an object or
function rather than the (mangled) name from the C/C++ implementation.
Just add an asm specifier with the desired name as a string literal at the
end of the declaration.

For example, this is how <code>avr/eeprom.h</code> implements the
\c eeprom_read_double() function:
\code
#if __SIZEOF_DOUBLE__ == 4
double eeprom_read_double (const double*) __asm("eeprom_read_dword");
#elif __SIZEOF_DOUBLE__ == 8
double eeprom_read_double (const double*) __asm("eeprom_read_qword");
#endif
\endcode

- It uses the implementation of \c eeprom_read_dword for \c eeprom_read_double,
provided \c double is a 32-bit type.

- It uses the implementation of \c eeprom_read_qword for 64-bit doubles.

\section inline_asm_fails What won't work

GCC inline asm has some limitations.

\subsection inline_asm_fails_split Setting a Register on one asm and using it in a different one

Sequences like the following are not supposed to work:
\code
char var;

void set_var (char c)
{
    __asm ("inc r24");
    __asm ("sts var, r24");
}
\endcode

- There is no guarantee whatsoever that the value in R24 will survive from
one asm to the next.  Such code might work in many situations, but it
is still wrong and the compiler may very well put instructions bewtween the
asm statements that change R24 prior to the first asm and also between the
asm statements.

- R24 is changed without noticing the compiler. When R24 contains other data,
then that data will be trashed.

A correct code would be
\code
    __asm ("inc %0"    "\n\t"
           "sts var, %0"
           :: "r" (c) : "memory");
\endcode
or
\code
    __asm ("inc %1"    "\n\t"
           "sts %0, %1"
           : "=m" (var) : "r" (c));
\endcode

\subsection inline_asm_fails_regvar Letting an Operand cross the Boundaries of the Y Register

It is not possible to bind a value to a local register variable that
crosses the boundaries of the Y register.  For example, trying to
bind a 32-bit value to R31:R28 by means of
\code
register uint32_t r28 __asm ("28");
\endcode
will result in an error message like
\code{none}
error: register specified for 'r28' isn't suitable for data type
\endcode

Similarly, an operand described by a constraint will be located either
completely below the Y register, as part of Y register, or above it.

\subsection asm_fails_output_match Using Matching Constraints "=0"..."=9" with Output Operands

Suppose we want an inline asm that returns the low byte of a 16-bit
value \c val16:
\code
asm ("" : "=1" (lo8) : "r" (val16));
\endcode
The diagnostic will be:
\code{none}
error: matching constraint not valid in output operand
\endcode

*/ */
