On Mon, Sep 21, 2026 at 2:50 PM Matt Turner <[email protected]> wrote: > > Using a cast as an lvalue in an asm output operand is a GCC extension. > Clang accepts it only with -fheinous-gnu-extensions. By default > -Winvalid-gnu-asm-cast is an error, so these blocks fail to build with > clang.
Yes but this file should only be used for compiling target libraries
and always with GCC. Can you explain what is going on with how they
are compiling with clang here?
This is the 3rd (or 4th time) someone wants to change this due to clang usage.
Thanks,
Andrea
>
> The casts check something, though. GCC accepts a cast on an asm output
> only when it is a no-op, so they make the build fail if a caller passes
> an output of the wrong size. Keep that check with a new macro,
> __ll_check_output, which uses a negative array size to fail the build
> when sizeof the output differs from sizeof the type the cast named.
> The macros whose body was a bare asm statement are wrapped in
> do { } while (0) to make room for the checks.
>
> A check on the exact type, using _Generic or __builtin_types_compatible_p,
> is not possible in longlong.h. Neither is supported by g++, and
> gcc/wide-int.cc includes longlong.h in C++. It would also reject callers
> that the casts accept today: libgcc2.c passes a signed Wtype to
> count_leading_zeros, and the x86_64 soft-fp passes unsigned long long
> where UDItype is unsigned long.
>
> Taking the address of the output would let the check go inside the asm
> operand itself, but libquadmath passes register variables as outputs.
> The next two patches deal with that.
>
> Casts on input operands are left alone, since those are ordinary rvalue
> conversions. On x86 count_leading_zeros/count_trailing_zeros the
> "rm" ((USItype) (x)) cast is what selects the operand width.
>
> Verified with a test unit that instantiates every macro the header
> defines, compiled as C and C++ at -O2 for W_TYPE_SIZE 32 and 64 with the
> cross compilers I have: aarch64, alpha, arm (soft and hard float), hppa
> 32 and 64, loongarch64, m68k (68000, 68020, 68060, cpu32), mips and
> mipsel, mips64 n32 and n64, powerpc 32 and 64 (both endiannesses),
> riscv32, riscv64, s390 31-bit and s390x, sh4 and sh4eb, sparc (v7, v8,
> sparclite, v9 and 64-bit), and x86 (-m32, -mx32, -m64). All produce
> byte-identical assembly before and after. Outputs of the wrong size are
> still rejected in every configuration where they were rejected before,
> and same-size outputs of a different type are still accepted. I have no
> compiler for ARC, M32R, m88k, RT/ROMP or vax, so those are changed
> mechanically.
>
> With clang the same test unit fails to compile before this change and
> succeeds after it for x86_64, x32, i386, armv5, armv7 and sparcv9, and
> wrong-size outputs are now rejected there too.
>
> include/ChangeLog:
>
> * longlong.h (__ll_check_output): New macro.
> [__arc__, __arm__, __hppa, __i386__, __x86_64__, __M32R__,
> __mc68000__, __mc68020__, __m88000__, __ibm032__, __sh__,
> __sparc__, __sparc_v8__, __sparc_v9__, __sparclite__, __vax__]:
> Replace the casts on asm output operands with __ll_check_output.
> ---
> include/longlong.h | 528
> +++++++++++++++++++++++++++++++++++------------------
> 1 file changed, 353 insertions(+), 175 deletions(-)
>
> diff --git a/include/longlong.h b/include/longlong.h
> index d89b2f4e999..60b9aeeaf55 100644
> --- a/include/longlong.h
> +++ b/include/longlong.h
> @@ -122,6 +122,12 @@ extern const UQItype __clz_tab[256] attribute_hidden;
> #define __AND_CLOBBER_CC , "cc"
> #endif /* __GNUC__ < 2 */
>
> +/* Fail to compile unless the asm output operand X has the same size as
> + TYPE. This stands in for casting the output to TYPE, which clang
> + rejects. */
> +#define __ll_check_output(type, x) \
> + ((void) sizeof (char [sizeof (x) == sizeof (type) ? 1 : -1]))
> +
> #if defined (__aarch64__)
>
> #if W_TYPE_SIZE == 32
> @@ -193,23 +199,31 @@ extern UDItype __udiv_qrnnd (UDItype *, UDItype,
> UDItype, UDItype);
>
> #if defined (__arc__) && W_TYPE_SIZE == 32
> #define add_ssaaaa(sh, sl, ah, al, bh, bl) \
> - __asm__ ("add.f %1, %4, %5\n\tadc %0, %2, %3" \
> - : "=r" ((USItype) (sh)), \
> - "=&r" ((USItype) (sl)) \
> + do { \
> + __ll_check_output (USItype, sh); \
> + __ll_check_output (USItype, sl); \
> + __asm__ ("add.f %1, %4, %5\n\tadc %0, %2, %3" \
> + : "=r" (sh), \
> + "=&r" (sl) \
> : "%r" ((USItype) (ah)), \
> "rICal" ((USItype) (bh)), \
> "%r" ((USItype) (al)), \
> "rICal" ((USItype) (bl)) \
> - : "cc")
> + : "cc"); \
> + } while (0)
> #define sub_ddmmss(sh, sl, ah, al, bh, bl) \
> - __asm__ ("sub.f %1, %4, %5\n\tsbc %0, %2, %3" \
> - : "=r" ((USItype) (sh)), \
> - "=&r" ((USItype) (sl)) \
> + do { \
> + __ll_check_output (USItype, sh); \
> + __ll_check_output (USItype, sl); \
> + __asm__ ("sub.f %1, %4, %5\n\tsbc %0, %2, %3" \
> + : "=r" (sh), \
> + "=&r" (sl) \
> : "r" ((USItype) (ah)), \
> "rICal" ((USItype) (bh)), \
> "r" ((USItype) (al)), \
> "rICal" ((USItype) (bl)) \
> - : "cc")
> + : "cc"); \
> + } while (0)
>
> #define __umulsidi3(u,v) ((UDItype)(USItype)u*(USItype)v)
> #ifdef __ARC_NORM__
> @@ -229,26 +243,36 @@ extern UDItype __udiv_qrnnd (UDItype *, UDItype,
> UDItype, UDItype);
> #if defined (__arm__) && (defined (__thumb2__) || !defined (__thumb__)) \
> && W_TYPE_SIZE == 32
> #define add_ssaaaa(sh, sl, ah, al, bh, bl) \
> - __asm__ ("adds %1, %4, %5\n\tadc %0, %2, %3" \
> - : "=r" ((USItype) (sh)), \
> - "=&r" ((USItype) (sl)) \
> + do { \
> + __ll_check_output (USItype, sh); \
> + __ll_check_output (USItype, sl); \
> + __asm__ ("adds %1, %4, %5\n\tadc %0, %2, %3" \
> + : "=r" (sh), \
> + "=&r" (sl) \
> : "%r" ((USItype) (ah)), \
> "rI" ((USItype) (bh)), \
> "%r" ((USItype) (al)), \
> - "rI" ((USItype) (bl)) __CLOBBER_CC)
> + "rI" ((USItype) (bl)) __CLOBBER_CC); \
> + } while (0)
> #define sub_ddmmss(sh, sl, ah, al, bh, bl) \
> - __asm__ ("subs %1, %4, %5\n\tsbc %0, %2, %3" \
> - : "=r" ((USItype) (sh)), \
> - "=&r" ((USItype) (sl)) \
> + do { \
> + __ll_check_output (USItype, sh); \
> + __ll_check_output (USItype, sl); \
> + __asm__ ("subs %1, %4, %5\n\tsbc %0, %2, %3" \
> + : "=r" (sh), \
> + "=&r" (sl) \
> : "r" ((USItype) (ah)), \
> "rI" ((USItype) (bh)), \
> "r" ((USItype) (al)), \
> - "rI" ((USItype) (bl)) __CLOBBER_CC)
> + "rI" ((USItype) (bl)) __CLOBBER_CC); \
> + } while (0)
> # if defined(__ARM_ARCH_2__) || defined(__ARM_ARCH_2A__) \
> || defined(__ARM_ARCH_3__)
> # define umul_ppmm(xh, xl, a, b) \
> do { \
> register USItype __t0, __t1, __t2; \
> + __ll_check_output (USItype, xh); \
> + __ll_check_output (USItype, xl); \
> __asm__ ("%@ Inlined umul_ppmm\n" \
> " mov %2, %5, lsr #16\n" \
> " mov %0, %6, lsr #16\n" \
> @@ -262,8 +286,8 @@ extern UDItype __udiv_qrnnd (UDItype *, UDItype, UDItype,
> UDItype);
> " addcs %0, %0, #65536\n" \
> " adds %1, %1, %3, lsl #16\n" \
> " adc %0, %0, %3, lsr #16" \
> - : "=&r" ((USItype) (xh)), \
> - "=r" ((USItype) (xl)), \
> + : "=&r" (xh), \
> + "=r" (xl), \
> "=&r" (__t0), "=&r" (__t1), "=r" (__t2) \
> : "r" ((USItype) (a)), \
> "r" ((USItype) (b)) __CLOBBER_CC ); \
> @@ -347,21 +371,29 @@ extern UDItype __umulsidi3 (USItype, USItype);
>
> #if defined (__hppa) && W_TYPE_SIZE == 32
> #define add_ssaaaa(sh, sl, ah, al, bh, bl) \
> - __asm__ ("add %4,%5,%1\n\taddc %2,%3,%0" \
> - : "=r" ((USItype) (sh)), \
> - "=&r" ((USItype) (sl)) \
> + do { \
> + __ll_check_output (USItype, sh); \
> + __ll_check_output (USItype, sl); \
> + __asm__ ("add %4,%5,%1\n\taddc %2,%3,%0" \
> + : "=r" (sh), \
> + "=&r" (sl) \
> : "%rM" ((USItype) (ah)), \
> "rM" ((USItype) (bh)), \
> "%rM" ((USItype) (al)), \
> - "rM" ((USItype) (bl)))
> + "rM" ((USItype) (bl))); \
> + } while (0)
> #define sub_ddmmss(sh, sl, ah, al, bh, bl) \
> - __asm__ ("sub %4,%5,%1\n\tsubb %2,%3,%0" \
> - : "=r" ((USItype) (sh)), \
> - "=&r" ((USItype) (sl)) \
> + do { \
> + __ll_check_output (USItype, sh); \
> + __ll_check_output (USItype, sl); \
> + __asm__ ("sub %4,%5,%1\n\tsubb %2,%3,%0" \
> + : "=r" (sh), \
> + "=&r" (sl) \
> : "rM" ((USItype) (ah)), \
> "rM" ((USItype) (bh)), \
> "rM" ((USItype) (al)), \
> - "rM" ((USItype) (bl)))
> + "rM" ((USItype) (bl))); \
> + } while (0)
> #if defined (_PA_RISC1_1)
> #define umul_ppmm(w1, w0, u, v) \
> do { \
> @@ -455,34 +487,50 @@ extern UDItype __umulsidi3 (USItype, USItype);
>
> #if (defined (__i386__) || defined (__i486__)) && W_TYPE_SIZE == 32
> #define add_ssaaaa(sh, sl, ah, al, bh, bl) \
> - __asm__ ("add{l} {%5,%1|%1,%5}\n\tadc{l} {%3,%0|%0,%3}" \
> - : "=r" ((USItype) (sh)), \
> - "=&r" ((USItype) (sl)) \
> + do { \
> + __ll_check_output (USItype, sh); \
> + __ll_check_output (USItype, sl); \
> + __asm__ ("add{l} {%5,%1|%1,%5}\n\tadc{l} {%3,%0|%0,%3}" \
> + : "=r" (sh), \
> + "=&r" (sl) \
> : "%0" ((USItype) (ah)), \
> "g" ((USItype) (bh)), \
> "%1" ((USItype) (al)), \
> - "g" ((USItype) (bl)))
> + "g" ((USItype) (bl))); \
> + } while (0)
> #define sub_ddmmss(sh, sl, ah, al, bh, bl) \
> - __asm__ ("sub{l} {%5,%1|%1,%5}\n\tsbb{l} {%3,%0|%0,%3}" \
> - : "=r" ((USItype) (sh)), \
> - "=&r" ((USItype) (sl)) \
> + do { \
> + __ll_check_output (USItype, sh); \
> + __ll_check_output (USItype, sl); \
> + __asm__ ("sub{l} {%5,%1|%1,%5}\n\tsbb{l} {%3,%0|%0,%3}" \
> + : "=r" (sh), \
> + "=&r" (sl) \
> : "0" ((USItype) (ah)), \
> "g" ((USItype) (bh)), \
> "1" ((USItype) (al)), \
> - "g" ((USItype) (bl)))
> + "g" ((USItype) (bl))); \
> + } while (0)
> #define umul_ppmm(w1, w0, u, v) \
> - __asm__ ("mul{l} %3" \
> - : "=a" ((USItype) (w0)), \
> - "=d" ((USItype) (w1)) \
> + do { \
> + __ll_check_output (USItype, w0); \
> + __ll_check_output (USItype, w1); \
> + __asm__ ("mul{l} %3" \
> + : "=a" (w0), \
> + "=d" (w1) \
> : "%0" ((USItype) (u)), \
> - "rm" ((USItype) (v)))
> + "rm" ((USItype) (v))); \
> + } while (0)
> #define udiv_qrnnd(q, r, n1, n0, dv) \
> - __asm__ ("div{l} %4" \
> - : "=a" ((USItype) (q)), \
> - "=d" ((USItype) (r)) \
> + do { \
> + __ll_check_output (USItype, q); \
> + __ll_check_output (USItype, r); \
> + __asm__ ("div{l} %4" \
> + : "=a" (q), \
> + "=d" (r) \
> : "0" ((USItype) (n0)), \
> "1" ((USItype) (n1)), \
> - "rm" ((USItype) (dv)))
> + "rm" ((USItype) (dv))); \
> + } while (0)
> #define count_leading_zeros(count, x) ((count) = __builtin_clz (x))
> #define count_trailing_zeros(count, x) ((count) = __builtin_ctz (x))
> #define UMUL_TIME 40
> @@ -491,34 +539,50 @@ extern UDItype __umulsidi3 (USItype, USItype);
>
> #if defined (__x86_64__) && W_TYPE_SIZE == 64
> #define add_ssaaaa(sh, sl, ah, al, bh, bl) \
> - __asm__ ("add{q} {%5,%1|%1,%5}\n\tadc{q} {%3,%0|%0,%3}" \
> - : "=r" ((UDItype) (sh)), \
> - "=&r" ((UDItype) (sl)) \
> + do { \
> + __ll_check_output (UDItype, sh); \
> + __ll_check_output (UDItype, sl); \
> + __asm__ ("add{q} {%5,%1|%1,%5}\n\tadc{q} {%3,%0|%0,%3}" \
> + : "=r" (sh), \
> + "=&r" (sl) \
> : "%0" ((UDItype) (ah)), \
> "rme" ((UDItype) (bh)), \
> "%1" ((UDItype) (al)), \
> - "rme" ((UDItype) (bl)))
> + "rme" ((UDItype) (bl))); \
> + } while (0)
> #define sub_ddmmss(sh, sl, ah, al, bh, bl) \
> - __asm__ ("sub{q} {%5,%1|%1,%5}\n\tsbb{q} {%3,%0|%0,%3}" \
> - : "=r" ((UDItype) (sh)), \
> - "=&r" ((UDItype) (sl)) \
> + do { \
> + __ll_check_output (UDItype, sh); \
> + __ll_check_output (UDItype, sl); \
> + __asm__ ("sub{q} {%5,%1|%1,%5}\n\tsbb{q} {%3,%0|%0,%3}" \
> + : "=r" (sh), \
> + "=&r" (sl) \
> : "0" ((UDItype) (ah)), \
> "rme" ((UDItype) (bh)), \
> "1" ((UDItype) (al)), \
> - "rme" ((UDItype) (bl)))
> + "rme" ((UDItype) (bl))); \
> + } while (0)
> #define umul_ppmm(w1, w0, u, v) \
> - __asm__ ("mul{q} %3" \
> - : "=a" ((UDItype) (w0)), \
> - "=d" ((UDItype) (w1)) \
> + do { \
> + __ll_check_output (UDItype, w0); \
> + __ll_check_output (UDItype, w1); \
> + __asm__ ("mul{q} %3" \
> + : "=a" (w0), \
> + "=d" (w1) \
> : "%0" ((UDItype) (u)), \
> - "rm" ((UDItype) (v)))
> + "rm" ((UDItype) (v))); \
> + } while (0)
> #define udiv_qrnnd(q, r, n1, n0, dv) \
> - __asm__ ("div{q} %4" \
> - : "=a" ((UDItype) (q)), \
> - "=d" ((UDItype) (r)) \
> + do { \
> + __ll_check_output (UDItype, q); \
> + __ll_check_output (UDItype, r); \
> + __asm__ ("div{q} %4" \
> + : "=a" (q), \
> + "=d" (r) \
> : "0" ((UDItype) (n0)), \
> "1" ((UDItype) (n1)), \
> - "rm" ((UDItype) (dv)))
> + "rm" ((UDItype) (dv))); \
> + } while (0)
> #define count_leading_zeros(count, x) ((count) = __builtin_clzll (x))
> #define count_trailing_zeros(count, x) ((count) = __builtin_ctzll (x))
> #define UMUL_TIME 40
> @@ -603,74 +667,105 @@ extern UDItype __umulsidi3 (USItype, USItype);
>
> #if defined (__M32R__) && W_TYPE_SIZE == 32
> #define add_ssaaaa(sh, sl, ah, al, bh, bl) \
> - /* The cmp clears the condition bit. */ \
> - __asm__ ("cmp %0,%0\n\taddx %1,%5\n\taddx %0,%3" \
> - : "=r" ((USItype) (sh)), \
> - "=&r" ((USItype) (sl)) \
> + do { \
> + __ll_check_output (USItype, sh); \
> + __ll_check_output (USItype, sl); \
> + /* The cmp clears the condition bit. */ \
> + __asm__ ("cmp %0,%0\n\taddx %1,%5\n\taddx %0,%3" \
> + : "=r" (sh), \
> + "=&r" (sl) \
> : "0" ((USItype) (ah)), \
> "r" ((USItype) (bh)), \
> "1" ((USItype) (al)), \
> "r" ((USItype) (bl)) \
> - : "cbit")
> + : "cbit"); \
> + } while (0)
> #define sub_ddmmss(sh, sl, ah, al, bh, bl) \
> - /* The cmp clears the condition bit. */ \
> - __asm__ ("cmp %0,%0\n\tsubx %1,%5\n\tsubx %0,%3" \
> - : "=r" ((USItype) (sh)), \
> - "=&r" ((USItype) (sl)) \
> + do { \
> + __ll_check_output (USItype, sh); \
> + __ll_check_output (USItype, sl); \
> + /* The cmp clears the condition bit. */ \
> + __asm__ ("cmp %0,%0\n\tsubx %1,%5\n\tsubx %0,%3" \
> + : "=r" (sh), \
> + "=&r" (sl) \
> : "0" ((USItype) (ah)), \
> "r" ((USItype) (bh)), \
> "1" ((USItype) (al)), \
> "r" ((USItype) (bl)) \
> - : "cbit")
> + : "cbit"); \
> + } while (0)
> #endif /* __M32R__ */
>
> #if defined (__mc68000__) && W_TYPE_SIZE == 32
> #define add_ssaaaa(sh, sl, ah, al, bh, bl) \
> - __asm__ ("add%.l %5,%1\n\taddx%.l %3,%0" \
> - : "=d" ((USItype) (sh)), \
> - "=&d" ((USItype) (sl)) \
> + do { \
> + __ll_check_output (USItype, sh); \
> + __ll_check_output (USItype, sl); \
> + __asm__ ("add%.l %5,%1\n\taddx%.l %3,%0" \
> + : "=d" (sh), \
> + "=&d" (sl) \
> : "%0" ((USItype) (ah)), \
> "d" ((USItype) (bh)), \
> "%1" ((USItype) (al)), \
> - "g" ((USItype) (bl)))
> + "g" ((USItype) (bl))); \
> + } while (0)
> #define sub_ddmmss(sh, sl, ah, al, bh, bl) \
> - __asm__ ("sub%.l %5,%1\n\tsubx%.l %3,%0" \
> - : "=d" ((USItype) (sh)), \
> - "=&d" ((USItype) (sl)) \
> + do { \
> + __ll_check_output (USItype, sh); \
> + __ll_check_output (USItype, sl); \
> + __asm__ ("sub%.l %5,%1\n\tsubx%.l %3,%0" \
> + : "=d" (sh), \
> + "=&d" (sl) \
> : "0" ((USItype) (ah)), \
> "d" ((USItype) (bh)), \
> "1" ((USItype) (al)), \
> - "g" ((USItype) (bl)))
> + "g" ((USItype) (bl))); \
> + } while (0)
>
> /* The '020, '030, '040, '060 and CPU32 have 32x32->64 and 64/32->32q-32r.
> */
> #if (defined (__mc68020__) && !defined (__mc68060__))
> #define umul_ppmm(w1, w0, u, v) \
> - __asm__ ("mulu%.l %3,%1:%0" \
> - : "=d" ((USItype) (w0)), \
> - "=d" ((USItype) (w1)) \
> + do { \
> + __ll_check_output (USItype, w0); \
> + __ll_check_output (USItype, w1); \
> + __asm__ ("mulu%.l %3,%1:%0"
> \
> + : "=d" (w0), \
> + "=d" (w1) \
> : "%0" ((USItype) (u)), \
> - "dmi" ((USItype) (v)))
> + "dmi" ((USItype) (v))); \
> + } while (0)
> #define UMUL_TIME 45
> #define udiv_qrnnd(q, r, n1, n0, d) \
> - __asm__ ("divu%.l %4,%1:%0" \
> - : "=d" ((USItype) (q)), \
> - "=d" ((USItype) (r)) \
> + do { \
> + __ll_check_output (USItype, q); \
> + __ll_check_output (USItype, r); \
> + __asm__ ("divu%.l %4,%1:%0"
> \
> + : "=d" (q), \
> + "=d" (r) \
> : "0" ((USItype) (n0)), \
> "1" ((USItype) (n1)), \
> - "dmi" ((USItype) (d)))
> + "dmi" ((USItype) (d))); \
> + } while (0)
> #define UDIV_TIME 90
> #define sdiv_qrnnd(q, r, n1, n0, d) \
> - __asm__ ("divs%.l %4,%1:%0" \
> - : "=d" ((USItype) (q)), \
> - "=d" ((USItype) (r)) \
> + do { \
> + __ll_check_output (USItype, q); \
> + __ll_check_output (USItype, r); \
> + __asm__ ("divs%.l %4,%1:%0"
> \
> + : "=d" (q), \
> + "=d" (r) \
> : "0" ((USItype) (n0)), \
> "1" ((USItype) (n1)), \
> - "dmi" ((USItype) (d)))
> + "dmi" ((USItype) (d))); \
> + } while (0)
>
> #elif defined (__mcoldfire__) /* not mc68020 */
>
> #define umul_ppmm(xh, xl, a, b) \
> - __asm__ ("| Inlined umul_ppmm\n" \
> + do { \
> + __ll_check_output (USItype, xh); \
> + __ll_check_output (USItype, xl); \
> + __asm__ ("| Inlined umul_ppmm\n" \
> " move%.l %2,%/d0\n" \
> " move%.l %3,%/d1\n" \
> " move%.l %/d0,%/d2\n" \
> @@ -696,17 +791,21 @@ extern UDItype __umulsidi3 (USItype, USItype);
> " move%.l %/d2,%1\n" \
> " add%.l %/d1,%/d0\n" \
> " move%.l %/d0,%0" \
> - : "=g" ((USItype) (xh)), \
> - "=g" ((USItype) (xl)) \
> + : "=g" (xh), \
> + "=g" (xl) \
> : "g" ((USItype) (a)), \
> "g" ((USItype) (b)) \
> - : "d0", "d1", "d2", "d3", "d4")
> + : "d0", "d1", "d2", "d3", "d4"); \
> + } while (0)
> #define UMUL_TIME 100
> #define UDIV_TIME 400
> #else /* not ColdFire */
> /* %/ inserts REGISTER_PREFIX, %# inserts IMMEDIATE_PREFIX. */
> #define umul_ppmm(xh, xl, a, b) \
> - __asm__ ("| Inlined umul_ppmm\n" \
> + do { \
> + __ll_check_output (USItype, xh); \
> + __ll_check_output (USItype, xl); \
> + __asm__ ("| Inlined umul_ppmm\n" \
> " move%.l %2,%/d0\n" \
> " move%.l %3,%/d1\n" \
> " move%.l %/d0,%/d2\n" \
> @@ -732,11 +831,12 @@ extern UDItype __umulsidi3 (USItype, USItype);
> " move%.l %/d2,%1\n" \
> " add%.l %/d1,%/d0\n" \
> " move%.l %/d0,%0" \
> - : "=g" ((USItype) (xh)), \
> - "=g" ((USItype) (xl)) \
> + : "=g" (xh), \
> + "=g" (xl) \
> : "g" ((USItype) (a)), \
> "g" ((USItype) (b)) \
> - : "d0", "d1", "d2", "d3", "d4")
> + : "d0", "d1", "d2", "d3", "d4"); \
> + } while (0)
> #define UMUL_TIME 100
> #define UDIV_TIME 400
>
> @@ -746,9 +846,12 @@ extern UDItype __umulsidi3 (USItype, USItype);
> cpu32 disguises as a 68020, but lacks them. */
> #if defined (__mc68020__) && !defined (__mcpu32__)
> #define count_leading_zeros(count, x) \
> - __asm__ ("bfffo %1{%b2:%b2},%0" \
> - : "=d" ((USItype) (count)) \
> - : "od" ((USItype) (x)), "n" (0))
> + do { \
> + __ll_check_output (USItype, count);
> \
> + __asm__ ("bfffo %1{%b2:%b2},%0" \
> + : "=d" (count) \
> + : "od" ((USItype) (x)), "n" (0)); \
> + } while (0)
> /* Some ColdFire architectures have a ff1 instruction supported via
> __builtin_clz. */
> #elif defined (__mcfisaaplus__) || defined (__mcfisac__)
> @@ -759,21 +862,29 @@ extern UDItype __umulsidi3 (USItype, USItype);
>
> #if defined (__m88000__) && W_TYPE_SIZE == 32
> #define add_ssaaaa(sh, sl, ah, al, bh, bl) \
> - __asm__ ("addu.co %1,%r4,%r5\n\taddu.ci %0,%r2,%r3" \
> - : "=r" ((USItype) (sh)), \
> - "=&r" ((USItype) (sl)) \
> + do { \
> + __ll_check_output (USItype, sh); \
> + __ll_check_output (USItype, sl); \
> + __asm__ ("addu.co %1,%r4,%r5\n\taddu.ci %0,%r2,%r3"
> \
> + : "=r" (sh), \
> + "=&r" (sl) \
> : "%rJ" ((USItype) (ah)), \
> "rJ" ((USItype) (bh)), \
> "%rJ" ((USItype) (al)), \
> - "rJ" ((USItype) (bl)))
> + "rJ" ((USItype) (bl))); \
> + } while (0)
> #define sub_ddmmss(sh, sl, ah, al, bh, bl) \
> - __asm__ ("subu.co %1,%r4,%r5\n\tsubu.ci %0,%r2,%r3" \
> - : "=r" ((USItype) (sh)), \
> - "=&r" ((USItype) (sl)) \
> + do { \
> + __ll_check_output (USItype, sh); \
> + __ll_check_output (USItype, sl); \
> + __asm__ ("subu.co %1,%r4,%r5\n\tsubu.ci %0,%r2,%r3"
> \
> + : "=r" (sh), \
> + "=&r" (sl) \
> : "rJ" ((USItype) (ah)), \
> "rJ" ((USItype) (bh)), \
> "rJ" ((USItype) (al)), \
> - "rJ" ((USItype) (bl)))
> + "rJ" ((USItype) (bl))); \
> + } while (0)
> #define count_leading_zeros(count, x) \
> do { \
> USItype __cbtmp; \
> @@ -995,24 +1106,34 @@ extern UDItype __umulsidi3 (USItype, USItype);
>
> #if defined (__ibm032__) /* RT/ROMP */ && W_TYPE_SIZE == 32
> #define add_ssaaaa(sh, sl, ah, al, bh, bl) \
> - __asm__ ("a %1,%5\n\tae %0,%3" \
> - : "=r" ((USItype) (sh)), \
> - "=&r" ((USItype) (sl)) \
> + do { \
> + __ll_check_output (USItype, sh); \
> + __ll_check_output (USItype, sl); \
> + __asm__ ("a %1,%5\n\tae %0,%3" \
> + : "=r" (sh), \
> + "=&r" (sl) \
> : "%0" ((USItype) (ah)), \
> "r" ((USItype) (bh)), \
> "%1" ((USItype) (al)), \
> - "r" ((USItype) (bl)))
> + "r" ((USItype) (bl))); \
> + } while (0)
> #define sub_ddmmss(sh, sl, ah, al, bh, bl) \
> - __asm__ ("s %1,%5\n\tse %0,%3" \
> - : "=r" ((USItype) (sh)), \
> - "=&r" ((USItype) (sl)) \
> + do { \
> + __ll_check_output (USItype, sh); \
> + __ll_check_output (USItype, sl); \
> + __asm__ ("s %1,%5\n\tse %0,%3" \
> + : "=r" (sh), \
> + "=&r" (sl) \
> : "0" ((USItype) (ah)), \
> "r" ((USItype) (bh)), \
> "1" ((USItype) (al)), \
> - "r" ((USItype) (bl)))
> + "r" ((USItype) (bl))); \
> + } while (0)
> #define umul_ppmm(ph, pl, m0, m1) \
> do { \
> USItype __m0 = (m0), __m1 = (m1); \
> + __ll_check_output (USItype, ph); \
> + __ll_check_output (USItype, pl); \
> __asm__ ( \
> "s r2,r2\n" \
> " mts r10,%2\n" \
> @@ -1034,8 +1155,8 @@ extern UDItype __umulsidi3 (USItype, USItype);
> " m r2,%3\n" \
> " cas %0,r2,r0\n" \
> " mfs r10,%1" \
> - : "=r" ((USItype) (ph)), \
> - "=r" ((USItype) (pl)) \
> + : "=r" (ph), \
> + "=r" (pl) \
> : "%r" (__m0), \
> "r" (__m1) \
> : "r2"); \
> @@ -1046,14 +1167,15 @@ extern UDItype __umulsidi3 (USItype, USItype);
> #define UDIV_TIME 200
> #define count_leading_zeros(count, x) \
> do { \
> + __ll_check_output (USItype, count);
> \
> if ((x) >= 0x10000)
> \
> __asm__ ("clz %0,%1" \
> - : "=r" ((USItype) (count)) \
> + : "=r" (count) \
> : "r" ((USItype) (x) >> 16)); \
> else \
> {
> \
> __asm__ ("clz %0,%1" \
> - : "=r" ((USItype) (count)) \
> + : "=r" (count) \
> : "r" ((USItype) (x)));
> \
> (count) += 16; \
> }
> \
> @@ -1127,13 +1249,17 @@ extern UDItype __umulsidi3 (USItype, USItype);
> #if defined(__sh__) && W_TYPE_SIZE == 32
> #ifndef __sh1__
> #define umul_ppmm(w1, w0, u, v) \
> - __asm__ ( \
> + do { \
> + __ll_check_output (USItype, w1); \
> + __ll_check_output (USItype, w0); \
> + __asm__ ( \
> "dmulu.l %2,%3\n\tsts%M1 macl,%1\n\tsts%M0 mach,%0"
> \
> - : "=r<" ((USItype)(w1)), \
> - "=r<" ((USItype)(w0)) \
> + : "=r<" (w1), \
> + "=r<" (w0) \
> : "r" ((USItype)(u)), \
> "r" ((USItype)(v)) \
> - : "macl", "mach")
> + : "macl", "mach"); \
> + } while (0)
> #define UMUL_TIME 5
> #endif
>
> @@ -1200,72 +1326,100 @@ extern UDItype __umulsidi3 (USItype, USItype);
> #if defined (__sparc__) && !defined (__arch64__) && !defined (__sparcv9) \
> && W_TYPE_SIZE == 32
> #define add_ssaaaa(sh, sl, ah, al, bh, bl) \
> - __asm__ ("addcc %r4,%5,%1\n\taddx %r2,%3,%0" \
> - : "=r" ((USItype) (sh)), \
> - "=&r" ((USItype) (sl)) \
> + do { \
> + __ll_check_output (USItype, sh); \
> + __ll_check_output (USItype, sl); \
> + __asm__ ("addcc %r4,%5,%1\n\taddx %r2,%3,%0" \
> + : "=r" (sh), \
> + "=&r" (sl) \
> : "%rJ" ((USItype) (ah)), \
> "rI" ((USItype) (bh)), \
> "%rJ" ((USItype) (al)), \
> "rI" ((USItype) (bl)) \
> - __CLOBBER_CC)
> + __CLOBBER_CC); \
> + } while (0)
> #define sub_ddmmss(sh, sl, ah, al, bh, bl) \
> - __asm__ ("subcc %r4,%5,%1\n\tsubx %r2,%3,%0" \
> - : "=r" ((USItype) (sh)), \
> - "=&r" ((USItype) (sl)) \
> + do { \
> + __ll_check_output (USItype, sh); \
> + __ll_check_output (USItype, sl); \
> + __asm__ ("subcc %r4,%5,%1\n\tsubx %r2,%3,%0" \
> + : "=r" (sh), \
> + "=&r" (sl) \
> : "rJ" ((USItype) (ah)), \
> "rI" ((USItype) (bh)), \
> "rJ" ((USItype) (al)), \
> "rI" ((USItype) (bl)) \
> - __CLOBBER_CC)
> + __CLOBBER_CC); \
> + } while (0)
> #if defined (__sparc_v9__)
> #define umul_ppmm(w1, w0, u, v) \
> do { \
> register USItype __g1 asm ("g1"); \
> + __ll_check_output (USItype, w1); \
> __asm__ ("umul\t%2,%3,%1\n\t" \
> "srlx\t%1, 32, %0" \
> - : "=r" ((USItype) (w1)), \
> + : "=r" (w1), \
> "=r" (__g1) \
> : "r" ((USItype) (u)), \
> "r" ((USItype) (v))); \
> (w0) = __g1; \
> } while (0)
> #define udiv_qrnnd(__q, __r, __n1, __n0, __d) \
> - __asm__ ("mov\t%2,%%y\n\t" \
> + do { \
> + __ll_check_output (USItype, __q); \
> + __ll_check_output (USItype, __r); \
> + __asm__ ("mov\t%2,%%y\n\t" \
> "udiv\t%3,%4,%0\n\t" \
> "umul\t%0,%4,%1\n\t" \
> "sub\t%3,%1,%1" \
> - : "=&r" ((USItype) (__q)), \
> - "=&r" ((USItype) (__r)) \
> + : "=&r" (__q), \
> + "=&r" (__r) \
> : "r" ((USItype) (__n1)), \
> "r" ((USItype) (__n0)), \
> - "r" ((USItype) (__d)))
> + "r" ((USItype) (__d))); \
> + } while (0)
> #else
> #if defined (__sparc_v8__)
> #define umul_ppmm(w1, w0, u, v) \
> - __asm__ ("umul %2,%3,%1;rd %%y,%0" \
> - : "=r" ((USItype) (w1)), \
> - "=r" ((USItype) (w0)) \
> + do { \
> + __ll_check_output (USItype, w1); \
> + __ll_check_output (USItype, w0); \
> + __asm__ ("umul %2,%3,%1;rd %%y,%0" \
> + : "=r" (w1), \
> + "=r" (w0) \
> : "r" ((USItype) (u)), \
> - "r" ((USItype) (v)))
> + "r" ((USItype) (v))); \
> + } while (0)
> #define udiv_qrnnd(__q, __r, __n1, __n0, __d) \
> - __asm__ ("mov %2,%%y;nop;nop;nop;udiv %3,%4,%0;umul %0,%4,%1;sub %3,%1,%1"\
> - : "=&r" ((USItype) (__q)), \
> - "=&r" ((USItype) (__r)) \
> + do { \
> + __ll_check_output (USItype, __q); \
> + __ll_check_output (USItype, __r); \
> + __asm__ ("mov %2,%%y;nop;nop;nop;udiv %3,%4,%0;umul %0,%4,%1;sub
> %3,%1,%1" \
> + : "=&r" (__q), \
> + "=&r" (__r) \
> : "r" ((USItype) (__n1)), \
> "r" ((USItype) (__n0)), \
> - "r" ((USItype) (__d)))
> + "r" ((USItype) (__d))); \
> + } while (0)
> #else
> #if defined (__sparclite__)
> /* This has hardware multiply but not divide. It also has two additional
> instructions scan (ffs from high bit) and divscc. */
> #define umul_ppmm(w1, w0, u, v) \
> - __asm__ ("umul %2,%3,%1;rd %%y,%0" \
> - : "=r" ((USItype) (w1)), \
> - "=r" ((USItype) (w0)) \
> + do { \
> + __ll_check_output (USItype, w1); \
> + __ll_check_output (USItype, w0); \
> + __asm__ ("umul %2,%3,%1;rd %%y,%0" \
> + : "=r" (w1), \
> + "=r" (w0) \
> : "r" ((USItype) (u)), \
> - "r" ((USItype) (v)))
> + "r" ((USItype) (v))); \
> + } while (0)
> #define udiv_qrnnd(q, r, n1, n0, d) \
> - __asm__ ("! Inlined udiv_qrnnd\n" \
> + do { \
> + __ll_check_output (USItype, q); \
> + __ll_check_output (USItype, r); \
> + __asm__ ("! Inlined udiv_qrnnd\n" \
> " wr %%g0,%2,%%y ! Not a delayed write for sparclite\n" \
> " tst %%g0\n" \
> " divscc %3,%4,%%g1\n" \
> @@ -1304,17 +1458,19 @@ extern UDItype __umulsidi3 (USItype, USItype);
> " bl,a 1f\n" \
> " add %1,%4,%1\n" \
> "1: ! End of inline udiv_qrnnd" \
> - : "=r" ((USItype) (q)), \
> - "=r" ((USItype) (r)) \
> + : "=r" (q), \
> + "=r" (r) \
> : "r" ((USItype) (n1)), \
> "r" ((USItype) (n0)), \
> "rI" ((USItype) (d)) \
> - : "g1" __AND_CLOBBER_CC)
> + : "g1" __AND_CLOBBER_CC); \
> + } while (0)
> #define UDIV_TIME 37
> #define count_leading_zeros(count, x) \
> do { \
> + __ll_check_output (USItype, count); \
> __asm__ ("scan %1,1,%0" \
> - : "=r" ((USItype) (count)) \
> + : "=r" (count) \
> : "r" ((USItype) (x))); \
> } while (0)
> /* Early sparclites return 63 for an argument of 0, but they warn that future
> @@ -1324,7 +1480,10 @@ extern UDItype __umulsidi3 (USItype, USItype);
> /* SPARC without integer multiplication and divide instructions.
> (i.e. at least Sun4/20,40,60,65,75,110,260,280,330,360,380,470,490) */
> #define umul_ppmm(w1, w0, u, v) \
> - __asm__ ("! Inlined umul_ppmm\n" \
> + do { \
> + __ll_check_output (USItype, w1); \
> + __ll_check_output (USItype, w0); \
> + __asm__ ("! Inlined umul_ppmm\n" \
> " wr %%g0,%2,%%y ! SPARC has 0-3 delay insn after a wr\n"\
> " sra %3,31,%%o5 ! Don't move this insn\n" \
> " and %2,%%o5,%%o5 ! Don't move this insn\n" \
> @@ -1364,16 +1523,20 @@ extern UDItype __umulsidi3 (USItype, USItype);
> " mulscc %%g1,0,%%g1\n" \
> " add %%g1,%%o5,%0\n" \
> " rd %%y,%1" \
> - : "=r" ((USItype) (w1)), \
> - "=r" ((USItype) (w0)) \
> + : "=r" (w1), \
> + "=r" (w0) \
> : "%rI" ((USItype) (u)), \
> "r" ((USItype) (v))
> \
> - : "g1", "o5" __AND_CLOBBER_CC)
> + : "g1", "o5" __AND_CLOBBER_CC); \
> + } while (0)
> #define UMUL_TIME 39 /* 39 instructions */
> /* It's quite necessary to add this much assembler for the sparc.
> The default udiv_qrnnd (in C) is more than 10 times slower! */
> #define udiv_qrnnd(__q, __r, __n1, __n0, __d) \
> - __asm__ ("! Inlined udiv_qrnnd\n" \
> + do { \
> + __ll_check_output (USItype, __q); \
> + __ll_check_output (USItype, __r); \
> + __asm__ ("! Inlined udiv_qrnnd\n" \
> " mov 32,%%g1\n" \
> " subcc %1,%2,%%g0\n" \
> "1: bcs 5f\n" \
> @@ -1397,11 +1560,12 @@ extern UDItype __umulsidi3 (USItype, USItype);
> " sub %1,%2,%1\n" \
> "3: xnor %0,0,%0\n" \
> " ! End of inline udiv_qrnnd" \
> - : "=&r" ((USItype) (__q)), \
> - "=&r" ((USItype) (__r)) \
> + : "=&r" (__q), \
> + "=&r" (__r) \
> : "r" ((USItype) (__d)), \
> "1" ((USItype) (__n1)), \
> - "0" ((USItype) (__n0)) : "g1" __AND_CLOBBER_CC)
> + "0" ((USItype) (__n0)) : "g1" __AND_CLOBBER_CC); \
> + } while (0)
> #define UDIV_TIME (3+7*32) /* 7 instructions/iteration. 32 iterations.
> */
> #endif /* __sparclite__ */
> #endif /* __sparc_v8__ */
> @@ -1413,12 +1577,14 @@ extern UDItype __umulsidi3 (USItype, USItype);
> #define add_ssaaaa(sh, sl, ah, al, bh, bl) \
> do { \
> UDItype __carry = 0; \
> + __ll_check_output (UDItype, sh); \
> + __ll_check_output (UDItype, sl); \
> __asm__ ("addcc\t%r5,%6,%1\n\t" \
> "add\t%r3,%4,%0\n\t" \
> "movcs\t%%xcc, 1, %2\n\t" \
> "add\t%0, %2, %0" \
> - : "=r" ((UDItype)(sh)), \
> - "=&r" ((UDItype)(sl)), \
> + : "=r" (sh), \
> + "=&r" (sl), \
> "+r" (__carry) \
> : "%rJ" ((UDItype)(ah)), \
> "rI" ((UDItype)(bh)), \
> @@ -1430,12 +1596,14 @@ extern UDItype __umulsidi3 (USItype, USItype);
> #define sub_ddmmss(sh, sl, ah, al, bh, bl) \
> do { \
> UDItype __carry = 0; \
> + __ll_check_output (UDItype, sh); \
> + __ll_check_output (UDItype, sl); \
> __asm__ ("subcc\t%r5,%6,%1\n\t" \
> "sub\t%r3,%4,%0\n\t" \
> "movcs\t%%xcc, 1, %2\n\t" \
> "sub\t%0, %2, %0" \
> - : "=r" ((UDItype)(sh)), \
> - "=&r" ((UDItype)(sl)), \
> + : "=r" (sh), \
> + "=&r" (sl), \
> "+r" (__carry) \
> : "%rJ" ((UDItype)(ah)), \
> "rI" ((UDItype)(bh)), \
> @@ -1447,6 +1615,8 @@ extern UDItype __umulsidi3 (USItype, USItype);
> #define umul_ppmm(wh, wl, u, v)
> \
> do { \
> UDItype tmp1, tmp2, tmp3, tmp4; \
> + __ll_check_output (UDItype, wh); \
> + __ll_check_output (UDItype, wl); \
> __asm__ __volatile__ ( \
> "srl %7,0,%3\n\t" \
> "mulx %3,%6,%1\n\t" \
> @@ -1469,8 +1639,8 @@ extern UDItype __umulsidi3 (USItype, USItype);
> "sllx %3,32,%3\n\t" \
> "add %1,%3,%1\n\t" \
> "add %5,%2,%0" \
> - : "=r" ((UDItype)(wh)), \
> - "=&r" ((UDItype)(wl)), \
> + : "=r" (wh), \
> + "=&r" (wl), \
> "=&r" (tmp1), "=&r" (tmp2), "=&r" (tmp3), "=&r" (tmp4) \
> : "r" ((UDItype)(u)), \
> "r" ((UDItype)(v)) \
> @@ -1482,21 +1652,29 @@ extern UDItype __umulsidi3 (USItype, USItype);
>
> #if defined (__vax__) && W_TYPE_SIZE == 32
> #define add_ssaaaa(sh, sl, ah, al, bh, bl) \
> - __asm__ ("addl2 %5,%1\n\tadwc %3,%0" \
> - : "=g" ((USItype) (sh)), \
> - "=&g" ((USItype) (sl)) \
> + do { \
> + __ll_check_output (USItype, sh); \
> + __ll_check_output (USItype, sl); \
> + __asm__ ("addl2 %5,%1\n\tadwc %3,%0" \
> + : "=g" (sh), \
> + "=&g" (sl) \
> : "%0" ((USItype) (ah)), \
> "g" ((USItype) (bh)), \
> "%1" ((USItype) (al)), \
> - "g" ((USItype) (bl)))
> + "g" ((USItype) (bl))); \
> + } while (0)
> #define sub_ddmmss(sh, sl, ah, al, bh, bl) \
> - __asm__ ("subl2 %5,%1\n\tsbwc %3,%0" \
> - : "=g" ((USItype) (sh)), \
> - "=&g" ((USItype) (sl)) \
> + do { \
> + __ll_check_output (USItype, sh); \
> + __ll_check_output (USItype, sl); \
> + __asm__ ("subl2 %5,%1\n\tsbwc %3,%0" \
> + : "=g" (sh), \
> + "=&g" (sl) \
> : "0" ((USItype) (ah)), \
> "g" ((USItype) (bh)), \
> "1" ((USItype) (al)), \
> - "g" ((USItype) (bl)))
> + "g" ((USItype) (bl))); \
> + } while (0)
> #define umul_ppmm(xh, xl, m0, m1) \
> do { \
> union { \
>
> --
> 2.54.0
>
