https://gcc.gnu.org/g:eaf619a0f552d73068a06d959ea6a4b8a19ff674

commit r17-892-geaf619a0f552d73068a06d959ea6a4b8a19ff674
Author: Georg-Johann Lay <[email protected]>
Date:   Thu May 28 11:44:21 2026 +0200

    AVR: Support [[len=<words]] notes in inline asm to specifty its size.
    
    This patch adds support for [[len=<words>]] in (the comments of) inline
    asm constructs.  It serves several purposes:
    
    - Cases where the expanded asm is longer than determined from the number
      of physical and logical line breaks.  Such cases can lead to errors
      when a jump that uses a too optimistic jump offset is crossing an asm.
    
    - Better code generation for jumps that are crossing an asm.  The default
      length of an asm is (1 + NL) * 2 words, where NL denotes the sum of
      physical and logical line breaks.  However, almost all AVR instructions
      occupy only one 16-bit word.
    
    The feature is implemented in ADJUST_INSN_LENGTH.  The length of
    an asm is the sum over all [[len=<words>]] notes, except when an
    unrecognized construct is found or an error occurred.  In the latter
    case, the default insn length is used.  These <words> are supported:
    
    <words> = [0-9]+
       Specifies a non-negative decimal integer.
    
    <words> = %[0-9]+
    <words> = %[<name>]   # Already resolved to %[0-9]+ by the middle-end.
       Refers to the respective asm operand, which must be CONST_INT.
    
    <words> = lds
    <words> = sts
       Specifies the length of a LDS or STS instruction, i.e.
       1 word if AVR_TINY, and 2 words otherwise.
    
    <words> = %~
    <words> = %~call
    <words> = %~jmp
       Specifies the length of a %~call resp. %~jmp instruction, i.e.
       2 words if AVR_HAVE_JMP_CALL, and 1 word otherwise.
    
    In order to observe the assigned lengths, see -fdump-rtl-shorten or the
    ";; ADDR = ..." insn addresses in the asm output with -mlog=insn_addresses.
    
    The benefits of using magic comments are:
    
    - The feature is backwards compatible, and the target code can use
      the same asm syntax since only asm comments have to be adjusted.
      No #ifdef feature test macros are needed.  The only case where the
      feature is not fully backwards compatible is when asm templates
      already contain invalid "[[len=" notes for some reason.  In that
      case, -mno-asm-len-notes restores the old behavior.
    
    - Since the asm size is the sum over all notes, the final size can
      be stitched together from multiple annotations / parts of an asm
      template, and there is no need to support operations like plus.
    
    gcc/
            * config/avr/avr.cc (avr_read_number, avr_length_of_asm)
            (avr_maybe_length_of_asm): New static functions.
            (avr_adjust_insn_length): Call avr_maybe_length_of_asm on
            unrecognized insns.
            * config/avr/avr.opt (-masm-len-notes, -Wasm-len-notes): New
            options.
            * doc/invoke.texi (AVR Options): Add -masm-len-notes,
            -Wasm-len-notes.
            * doc/extend.texi (Size of an asm): Add @subsubheading
            "Specifying the size of an asm on AVR".
    
    libgcc/config/avr/libf7/
            * libf7.h: Add "[len=...]]" notes to all non-empty inline asm's.
            * libf7.c: Dito.

Diff:
---
 gcc/config/avr/avr.cc           | 247 +++++++++++++++++++++++++++++++++++++++-
 gcc/config/avr/avr.opt          |   8 ++
 gcc/doc/extend.texi             |  68 +++++++++++
 gcc/doc/invoke.texi             |  24 +++-
 libgcc/config/avr/libf7/libf7.c |  13 ++-
 libgcc/config/avr/libf7/libf7.h |  14 +--
 6 files changed, 355 insertions(+), 19 deletions(-)

diff --git a/gcc/config/avr/avr.cc b/gcc/config/avr/avr.cc
index 25cb518b0f3e..c6443c03423a 100644
--- a/gcc/config/avr/avr.cc
+++ b/gcc/config/avr/avr.cc
@@ -11131,8 +11131,244 @@ avr_rotate_bytes (rtx operands[])
 }
 
 
+/* Read a non-negative decimal number from a string starting at START.
+   Set *END to one position past the last digit of the number.  */
+
+static int
+avr_read_number (const char *start, const char **end)
+{
+  int num = 0;
+  for (*end = start; **end >= '0' && **end <= '9'; ++(*end))
+    num = 10 * num + **end - '0';
+
+  return num;
+}
+
+
+/* Return the sum over all [[len=<words>]] annotations in inline asm INSN.
+   TPL is the asm template, N_XOP the number of operands, or -1 when the
+   asm has no operands (not even zero operands).  XOP[] are these operands.
+   LOC is the location of the asm, and DEFAULT_LEN is the code length
+   in words as determined by the middle-end from the number of logical and
+   physical line breaks in TPL.
+
+   When an invalid %-reference or an unrecognized [[len=... is found,
+   then return -1.  Otherwise, return the sum over all [[len=<words>]]
+   annotations, where:
+
+   <words> = [0-9]+
+       Specifies a non-negative decimal integer.
+
+   <words> = %[0-9]+
+   <words> = %[<name>]   # Already resolved to %[0-9]+ by the middle-end.
+       Refers to the respective asm operand, which must be CONST_INT.
+
+   <words> = lds
+   <words> = sts
+       Specifies the length of a LDS or STS instruction, i.e.
+       1 word if AVR_TINY, and 2 words otherwise.
+
+   <words> = %~
+   <words> = %~call
+   <words> = %~jmp
+       Specifies the length of a %~call resp. %~jmp instruction, i.e.
+       2 words if AVR_HAVE_JMP_CALL, and 1 word otherwise.
+
+   In order to observe the assigned lengths, see -fdump-rtl-shorten or the
+   asm output with -mlog=insn_addresses.  */
+
+static int
+avr_length_of_asm (rtx_insn *insn, int default_len, const char *tpl,
+                  int n_xop, rtx *xop, location_t loc)
+{
+  const char *const len_begin = "[[len=";
+  const char *const len_end = "]]";
+  const char *pos = strstr (tpl, len_begin);
+  int len = 0;
+
+  if (! pos)
+    return -1;
+
+  avr_dump ("\n;;; Calculating length of asm insn (default=%d, warn=%d):\n"
+           "%r\n", default_len, avropt_warn_asmlen_notes, insn);
+
+  for (; pos; pos = strstr (pos, len_begin))
+    {
+      const char *const pos_begin = pos;
+      const char *const pos_end = strstr (pos, len_end);
+
+      pos += strlen (len_begin);
+      const bool percent_p = pos[0] == '%' && pos[1] != '~';
+      int inc = -1;
+
+      if (startswith (pos, "%~")
+         // %-resolution only applies to asm with operands.
+         && n_xop >= 0)
+       {
+         // "%~" specifies the length of %~jmp / %~call.
+         inc = AVR_HAVE_JMP_CALL ? 2 : 1;
+         pos += 2;
+
+         // Allow an optional suffix of "jmp" or "call".
+         if (startswith (pos, "jmp"))
+           pos += 3;
+         else if (startswith (pos, "call"))
+           pos += 4;
+       }
+      else if (startswith (pos, "lds")
+              || startswith (pos, "sts"))
+       {
+         // "lds" specifies the length of LDS or STS.
+         inc = AVR_TINY ? 1 : 2;
+         pos += 3;
+       }
+      else if (! percent_p
+              // %-resolution only applies to asm with operands.
+              || n_xop >= 0)
+       {
+         // A plain decimal number <num>, or %<num> to refer to the
+         // <num>-th asm operand.  Notice that the middle-end has already
+         // resolved named operand references like %[name] to the respective
+         // operand number (provided such a named operand exists).
+         pos += percent_p;
+         const char *end;
+         const int num = avr_read_number (pos, &end);
+         inc = end > pos ? num : -1;
+         pos = end;
+       }
+
+      /* Prepare a code quote so we have it handy in maybe diagnostics.  */
+
+      // Only show the gist of an unrecognized annotation.
+      // Recognized notes are short, so show only the relevant
+      // part and display the rest as ...'s.
+      const char *dots = "...";
+      const size_t l_pos_begin = strlen (pos_begin);
+      const size_t l_pos = pos_end ? pos_end - pos_begin : l_pos_begin;
+      const size_t l_show = pos - pos_begin + 5;
+      char *msg = XALLOCAVEC (char, 1 + strlen (tpl) + strlen (dots));
+      strcpy (msg, pos_begin);
+      if (l_pos > l_show + 2 * strlen (dots))
+       {
+         msg[l_show] = '\0';
+         strcat (msg, dots);
+         if (pos_end)
+           strncat (msg, pos_end - 4, 4);
+       }
+      if (pos_end)
+       strcat (msg, len_end);
+
+      /* Now use inc or diagnose a problem.  */
+
+      if (inc >= 0 && pos == pos_end)
+       {
+         pos += strlen (len_end);
+
+         avr_dump (";;; len = %s + %s%d",
+                   len ? "len" : "0", percent_p ? "%" : "", inc);
+         if (percent_p)
+           {
+             // Map inc to the value of the inc-th asm operand,
+             // which must be CONST_INT.
+
+             if (inc >= n_xop)
+               {
+                 // For asm with >= 0 operands, the middle-end will issue
+                 // an error message.
+                 avr_dump ("\n;;; Ignored: op %d does not exist\n\n", inc);
+                 return -1;
+               }
+             if (! CONST_INT_P (xop[inc]))
+               {
+                 avr_dump ("\n;;; Ignored: op %d is not CONST_INT\n\n", inc);
+                 warning_at (loc, OPT_Wasm_len_notes, "%<asm%> len annotation"
+                             " ignored: operand %d is not a compile-time"
+                             " integer constant: %qs", inc, msg);
+                 return -1;
+               }
+             inc = UINTVAL (xop[inc]) > 1000000 ? 1000000 : INTVAL (xop[inc]);
+             avr_dump (" = %s + %d", len ? "len" : "0", inc);
+           } // %
+
+         len += inc;
+         avr_dump (" = %d\n", len);
+       }
+      else // inc < 0 || pos != pos_end
+       {
+         // FIXME: Diagnosing is void in LTO mode, except when compiled
+         // with `-ffat-lto-objects' (in which case cc1[plus] is diagnosing,
+         // not lto1).
+         if (pos_end)
+           {
+             avr_dump (";;; Ignored: %s\n\n", msg);
+             warning_at (loc, OPT_Wasm_len_notes, "%<asm%> len annotation"
+                         " ignored: %qs", msg);
+           }
+         else
+           {
+             avr_dump (";;; Ignored (no %s): %s\n\n", len_end, msg);
+             warning_at (loc, OPT_Wasm_len_notes, "%<asm%> len annotation"
+                         " ignored: misses closing %qs: %qs", len_end, msg);
+           }
+         return -1;
+       }
+    }
+  avr_dump ("\n");
+
+  return len;
+}
+
+
+/* A helper for the function below.  Recognize [[len=<words>]] annotations
+   in the inline asm template of INSN, so the user can specify the length
+   of an asm.  This can solve two problems:
+
+   - Cases where the expanded asm is longer than determined from the number
+     of physical and logical line breaks.  Such cases can lead to errors
+     when a jump that uses a too optimistic jump offset is crossing an asm.
+
+   - Better code generation for jumps that are crossing an asm.  The default
+     length of an asm is (1 + NL) * 2 words, where NL denotes the sum of
+     physical and logical line breaks.  However, almost all AVR instructions
+     occupy only one 16-bit word.
+
+   LEN is the length in units of 16-bit words as determined by the middle-end.
+   When no annotation has been found or a diagnostic occurred, return -1.  */
+
+static int
+avr_maybe_length_of_asm (rtx_insn *insn, int len)
+{
+  if (avropt_asmlen_notes
+      && NONDEBUG_INSN_P (insn))
+    {
+      rtx body = PATTERN (insn);
+
+      if (asm_noperands (body) >= 0)
+       {
+         // An `asm' construct with operands.
+
+         location_t loc;
+         int n_ops = asm_noperands (body);
+         rtx *ops = XALLOCAVEC (rtx, n_ops);
+         const char *tpl = decode_asm_operands (body, ops, NULL, NULL, NULL,
+                                                &loc);
+         return avr_length_of_asm (insn, len, tpl, n_ops, ops, loc);
+       }
+      else if (GET_CODE (body) == ASM_INPUT)
+       {
+         // An `asm' construct without operands.
+
+         return avr_length_of_asm (insn, len, XSTR (body, 0), -1, nullptr,
+                                   ASM_INPUT_SOURCE_LOCATION (body));
+       }
+    }
+
+  return -1;
+}
+
+
 /* Worker function for `ADJUST_INSN_LENGTH'.  */
-/* Modifies the length assigned to instruction INSN
+/* Modifies the length assigned to instruction INSN.
    LEN is the initially computed length of the insn.  */
 
 int
@@ -11151,9 +11387,14 @@ avr_adjust_insn_length (rtx_insn *insn, int len)
      It is easier to state this in an insn attribute "adjust_len" than
      to clutter up code here...  */
 
-  if (!NONDEBUG_INSN_P (insn) || recog_memoized (insn) == -1)
+  if (!NONDEBUG_INSN_P (insn))
+    return len;
+
+  if (recog_memoized (insn) == -1)
     {
-      return len;
+      // Let the user specify the length of the asm with [[len=<words>]]'s.
+      const int len_asm = avr_maybe_length_of_asm (insn, len);
+      return len_asm < 0 ? len : len_asm;
     }
 
   /* Read from insn attribute "adjust_len" if/how length is to be adjusted.  */
diff --git a/gcc/config/avr/avr.opt b/gcc/config/avr/avr.opt
index 8bc2f5f1739a..97d207726ba9 100644
--- a/gcc/config/avr/avr.opt
+++ b/gcc/config/avr/avr.opt
@@ -140,6 +140,14 @@ mfuse-add=
 Target Joined RejectNegative UInteger Var(avropt_fuse_add) Init(0) 
Optimization IntegerRange(0, 3)
 -mfuse-add=<0,2>       Optimization. Split register additions from load/store 
instructions. Most useful on Reduced Tiny.
 
+masm-len-notes
+Target Var(avropt_asmlen_notes) Init(1) Save
+Recognize [[len=<spec>]] notes to specify the size of inline asm constructs. 
Enabled by default.
+
+Wasm-len-notes
+Warning C C++ Var(avropt_warn_asmlen_notes) Init(1) Save
+Warn about unrecognized [[len=<spec>]] notes in inline asm constructs. Enabled 
by default.
+
 Waddr-space-convert
 Warning C Var(avropt_warn_addr_space_convert) Init(0)
 Warn if the address space of an address is changed.
diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
index e14d033267dd..d9a6594d72a1 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -13464,6 +13464,74 @@ This size is also used for inlining decisions.  If you 
use @code{asm inline}
 instead of just @code{asm}, then for inlining purposes the size of the asm
 is taken as the minimum size, ignoring how many instructions GCC thinks it is.
 
+@subsubheading Specifying the size of an @code{asm} on AVR
+
+Apart from the default size calculation explained above, since GCC@tie{}17
+there is a way to specify the exact size of an @code{asm} by means of
+@code{[[len=@var{spec}]]} annotations.  The annotations must be placed
+in assembly comments in the @code{asm} template:
+In a @code{/* ... */} block comment, or after a @samp{;} that starts
+a single-line comment.
+
+The following @code{@var{spec}}'s are supported.  They specify the
+size of the @code{asm} --- or parts of it --- in units of 16-bit words:
+
+@table @code
+@item [0-9]+
+The decimal representation of a non-negative integer.
+
+@item %[0-9]+
+@itemx %[@var{name}]
+The value of the referred operand, which must evaluate to a
+compile-time integer constant.
+
+@item %~
+@itemx %~jmp
+@itemx %~call
+The length of a @code{%~call} or @code{%~jmp} instruction before relaxing.
+
+@item lds
+@itemx sts
+The length of a @code{lds} resp.@: @code{sts} instruction.
+@end table
+
+The following rules apply:
+
+@itemize
+@item All such annotations will be ignored with option
+@ref{avr_masm_len_notes,@option{-mno-asm-len-notes}}.  Diagnosing can be
+adjusted with option @ref{avr_Wasm_len_notes,@option{-Wasm-len-notes}}.
+
+@item The length of the @code{asm} is the sum over all
+@code{[[len=@var{spec}]]} notes in the @code{asm} template.  When an invalid
+or unrecognizable note is found, then the default length (as calculated from
+the number of physical and logical line breaks) applies.
+
+@item No white-spaces are recognized inside @code{[[...]]} notes, and all
+letters must be lower case.  Otherwise, all notes in that asm are ignored,
+and the default length of the @code{asm} is used.
+@end itemize
+
+The actual instruction lengths can be inferred from @samp{;; ADDR = ...}
+assembly comments as generated with, say
+@option{-save-temps -mlog=insn_addresses}.
+Length calculations are also shown in the RTL dump file(s) as generated with
+@option{-fdump-rtl-shorten}.
+
+Lengths annotations can solve two issues:
+
+@itemize
+@item Cases where the expanded assembly code is longer than determined from the
+number of physical and logical line breaks.  Such cases can lead to errors when
+a jump that uses a too optimistic jump offset is crossing such assembly code.
+
+@item Better code generation for jumps that are crossing an @code{asm}.
+The default length of an asm is (1 + @var{NL}) * 2 words, where @var{NL}
+denotes the sum of physical and logical line breaks.  However, almost
+all AVR instructions occupy only a single 16-bit word.
+@end itemize
+
+
 @node Syntax Extensions
 @section Other Extensions to C Syntax
 
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index b605defb3907..8ed1c851f598 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -984,8 +984,8 @@ Objective-C and Objective-C++ Dialects}.
 -mvectorize-with-neon-quad  -mvectorize-with-neon-double}
 
 @emph{AVR Options} (@ref{AVR Options})
-@gccoptlist{-mmcu=@var{mcu}  -mabsdata  -maccumulate-args  -mcvt
--mbranch-cost=@var{cost}  -mfuse-add=@var{level}  -mfuse-move=@var{level}
+@gccoptlist{-mmcu=@var{mcu}  -mabsdata  -maccumulate-args -masm-len-notes
+-mcvt  -mbranch-cost=@var{cost}  -mfuse-add=@var{level}  
-mfuse-move=@var{level}
 -mfuse-move2  -mcall-prologues  -mgas-isr-prologues  -mint8  -mflmap
 -mdouble=@var{bits}  -mlong-double=@var{bits}  -mno-call-main
 -mn_flash=@var{size}  -mfract-convert-truncate  -mno-interrupts
@@ -993,7 +993,7 @@ Objective-C and Objective-C++ Dialects}.
 -mrmw  -mstrict-X  -mtiny-stack
 -mrodata-in-ram  -msplit-bit-shift  -msplit-ldst  -mshort-calls
 -mskip-bug  -muse-nonzero-bits  -nodevicelib  -nodevicespecs
--Waddr-space-convert  -Wmisspelled-isr}
+-Wasm-len-notes  -Waddr-space-convert  -Wmisspelled-isr}
 
 @emph{Blackfin Options} (@ref{Blackfin Options})
 @gccoptlist{-mcpu=@var{cpu}@r{[}-@var{sirevision}@r{]}
@@ -24314,6 +24314,15 @@ instructions.  This option has only an effect on 
reduced Tiny devices like
 ATtiny40.  See also the @code{absdata}
 @ref{AVR Attributes,variable attribute}.
 
+@anchor{avr_masm_len_notes}
+@opindex masm-len-notes
+@item -masm-len-notes
+@itemx -mno-asm-len-notes
+Recognize resp.@: ignore @code{[[len=@var{spec}]]} notes that are placed in
+(comments in) inline assembly code templates.  They allow to specify
+the exact @ref{Size of an asm,size of @code{asm} constructs}.
+This option is on per default.
+
 @opindex mcvt
 @item -mcvt
 Use a @emph{compact vector table}.  Some devices support a CVT
@@ -24468,6 +24477,15 @@ which contains a folder named @code{device-specs} 
which contains a specs file na
 Warn about conversions between address spaces in the case where the
 resulting address space is not contained in the incoming address space.
 
+@anchor{avr_Wasm_len_notes}
+@opindex Wasm-len-notes
+@item -Wasm-len-notes
+Warn about unrecognized @code{[[len=@var{spec}]]}
+@ref{Size of an asm,length} annotations in inline assembly code templates.
+This @ref{Warning Options,warning} is on per default.
+Notice that in LTO mode, the code must be compiled with option
+@option{-ffat-lto-objects} in order for these diagnoses to appear.
+
 @opindex Wmisspelled-isr
 @opindex Wno-misspelled-isr
 @item -Wmisspelled-isr
diff --git a/libgcc/config/avr/libf7/libf7.c b/libgcc/config/avr/libf7/libf7.c
index a672e424dc8c..d258f2b5ab25 100644
--- a/libgcc/config/avr/libf7/libf7.c
+++ b/libgcc/config/avr/libf7/libf7.c
@@ -344,7 +344,7 @@ float f7_get_float (const f7_t *aa)
 
   __asm ("cbr %T0%t2, 1 << (7 & %2)"  "\n\t"
         "or  %C0, %A1"               "\n\t"
-        "or  %D0, %B1"
+        "or  %D0, %B1 ; [[len=3]]"
         : "+d" (mant)
         : "r" (expo16), "n" (FLT_DIG_MANT));
 
@@ -410,7 +410,8 @@ uint64_t clr_r18 (void)
 {
   extern void __clr_8 (void);
   register uint64_t r18 __asm ("r18");
-  __asm ("%~call %x[f]" : "=r" (r18) : [f] "i" (__clr_8));
+  __asm ("%~call %x[f] ; [[len=%~call]]"
+        : "=r" (r18) : [f] "i" (__clr_8));
   return r18;
 }
 
@@ -459,7 +460,7 @@ f7_double_t f7_get_double (const f7_t *aa)
   // dex = Overflow ? 1 : 0.
   __asm ("bst %T[mant]%T[bitno]"  "\n\t"
         "clr %0"                 "\n\t"
-        "bld %0,0"
+        "bld %0,0 ; [[len=3]]"
         : "=r" (dex), [mant] "+r" (r18)
         : [bitno] "n" (64 - 8));
 
@@ -504,7 +505,7 @@ f7_double_t f7_get_double (const f7_t *aa)
   r18 = mant;
   __asm ("cbr %T0%t2, 1 << (7 & %2)"  "\n\t"
         "or  %r0+6, %A1"             "\n\t"
-        "or  %r0+7, %B1"
+        "or  %r0+7, %B1 ; [[len=3]]"
         : "+r" (r18)
         : "r" (expo16), "n" (DBL_DIG_MANT));
 
@@ -672,7 +673,7 @@ int8_t cmp_u8 (uint8_t a_class, uint8_t b_class, bool 
sign_a)
         "sbci %[c], -1"      "\n\t"
         "sbrc %[s], 0"       "\n\t"
         "neg  %[c]"          "\n\t"
-        "1:"
+        "1: ; [[len=6]]"
         : [c] "=d" (c)
         : [a] "0" (a_class), [b] "r" (b_class), [s] "r" (sign_a));
   return c;
@@ -944,7 +945,7 @@ void f7_fdim (f7_t *cc, const f7_t *aa, const f7_t *bb)
 #ifdef F7MOD_addsub_
 static void return_with_sign (f7_t *cc, const f7_t *aa, int8_t c_sign)
 {
-  __asm (";;; return with sign");
+  __asm (";;; return with sign ; [[len=0]]");
   f7_copy (cc, aa);
   if (c_sign != -1)
     f7_set_sign (cc, c_sign);
diff --git a/libgcc/config/avr/libf7/libf7.h b/libgcc/config/avr/libf7/libf7.h
index fc9bcafe978c..825cb68142b9 100644
--- a/libgcc/config/avr/libf7/libf7.h
+++ b/libgcc/config/avr/libf7/libf7.h
@@ -159,7 +159,7 @@ uint8_t f7_classify (const f7_t *aa)
 {
   extern void f7_classify_asm (void);
   register uint8_t rclass __asm ("r24");
-  __asm ("%~call %x[f]"
+  __asm ("%~call %x[f] ; [[len=%~call]]"
         : "=r" (rclass)
         : [f] "i" (f7_classify_asm), "z" (aa));
   return rclass;
@@ -268,7 +268,7 @@ static F7_INLINE
 void f7_clr (f7_t *cc)
 {
   extern void f7_clr_asm (void);
-  __asm ("%~call %x[f]"
+  __asm ("%~call %x[f] ; [[len=%~call]]"
         :
         : [f] "i" (f7_clr_asm), "z" (cc)
         : "memory");
@@ -278,7 +278,7 @@ static F7_INLINE
 f7_t* f7_copy (f7_t *cc, const f7_t *aa)
 {
   extern void f7_copy_asm (void);
-  __asm ("%~call %x[f]"
+  __asm ("%~call %x[f] ; [[len=%~call]]"
         :
         : [f] "i" (f7_copy_asm), "z" (cc), "x" (aa)
         : "memory");
@@ -289,7 +289,7 @@ static F7_INLINE
 f7_t* f7_copy_P (f7_t *cc, const f7_t *aa)
 {
   extern void f7_copy_P_asm (void);
-  __asm ("%~call %x[f]"
+  __asm ("%~call %x[f] ; [[len=%~call]]"
         :
         : [f] "i" (f7_copy_P_asm), "x" (cc), "z" (aa)
         : "memory");
@@ -300,7 +300,7 @@ static F7_INLINE
 void f7_copy_mant (f7_t *cc, const f7_t *aa)
 {
   extern void f7_copy_mant_asm (void);
-  __asm ("%~call %x[f]"
+  __asm ("%~call %x[f] ; [[len=%~call]]"
         :
         : [f] "i" (f7_copy_mant_asm), "z" (cc), "x" (aa)
         : "memory");
@@ -337,7 +337,7 @@ int8_t f7_cmp_mant (const f7_t *aa, const f7_t *bb)
 {
   extern void f7_cmp_mant_asm (void);
   register int8_t r24 __asm ("r24");
-  __asm ("%~call %x[f] ;; %1 %3"
+  __asm ("%~call %x[f] ;; %1 %3 ; [[len=%~call]]"
         : "=r" (r24)
         : [f] "i" (f7_cmp_mant_asm), "x" (aa), "z" (bb));
   return r24;
@@ -349,7 +349,7 @@ bool f7_store_expo (f7_t *cc, int16_t expo)
   extern void f7_store_expo_asm (void);
   register bool r24 __asm ("r24");
   register int16_t rexpo __asm ("r24") = expo;
-  __asm ("%~call %x[f] ;; %0 %2 %3"
+  __asm ("%~call %x[f] ;; %0 %2 %3 ; [[len=%~call]]"
         : "=r" (r24)
         : [f] "i" (f7_store_expo_asm), "z" (cc), "r" (rexpo));
   return r24;

Reply via email to