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.
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
