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.
There are still many asm constructs in AVR-LibC for example, like
in avr/pgmspace.h which is still used in C++ because avr-g++
doesn not (yet) support named address-spaces like __flash.
The patch passes without new regressions.
Before going all in and adding test cases etc. my question is if
this feature is okay in principle, and if magic comments other
than [[len=...]] would be preferred for some reason.
The only thing that doesn't work as expected (though expected
by the LTO designers), is using warning_at in lto1. This means
that in order to get the warnings in LTO mode, one has to compile
with -ffat-lto-objects so cc1[plus] can do the diagnosing.
The patch is for trunk.
Johann
--
AVR: Support [[len=<words]] notes in inline asm to specify 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 --git a/gcc/config/avr/avr.cc b/gcc/config/avr/avr.cc
index 25cb518b0f3..e7662ff192a 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 8bc2f5f1739..97d207726ba 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 e14d033267d..e51f4f59ab6 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -13464,6 +13464,73 @@ 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, the annotation is ignored.
+@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 b605defb390..8ed1c851f59 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 a672e424dc8..d258f2b5ab2 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 fc9bcafe978..825cb68142b 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;