From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:44966) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gTos5-0002EO-EE for qemu-devel@nongnu.org; Mon, 03 Dec 2018 09:08:24 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1gTore-0002UK-3J for qemu-devel@nongnu.org; Mon, 03 Dec 2018 09:06:49 -0500 Received: from mx1.redhat.com ([209.132.183.28]:56674) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1gTord-0001ib-Mu for qemu-devel@nongnu.org; Mon, 03 Dec 2018 09:06:21 -0500 From: Thomas Huth Date: Mon, 3 Dec 2018 15:05:32 +0100 Message-Id: <1543845937-300-3-git-send-email-thuth@redhat.com> In-Reply-To: <1543845937-300-1-git-send-email-thuth@redhat.com> References: <1543845937-300-1-git-send-email-thuth@redhat.com> Subject: [Qemu-devel] [PATCH for-4.0 2/7] Remove support for compilers that can not do 128-bit arithmetics List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: Richard Henderson , =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= , pbonzini@redhat.com, peter.maydell@linaro.org Now that we require at least GCC v4.8 and Clang v3.4, we can be sure that we always have a compiler that has support for 128-bit arithmetics. Thus we can remove the !CONFIG_INT128 code now. Signed-off-by: Thomas Huth --- Note: We could even remove int128.h and the helper functions now ... but that's also topic for a separate patch, I think. configure | 37 ++--------- include/qemu/host-utils.h | 30 --------- include/qemu/int128.h | 160 ---------------------------------------------- target/ppc/cpu.h | 2 - target/ppc/int_helper.c | 159 --------------------------------------------- target/s390x/int_helper.c | 7 -- util/host-utils.c | 135 -------------------------------------- 7 files changed, 4 insertions(+), 526 deletions(-) diff --git a/configure b/configure index f1e305e..14e9722 100755 --- a/configure +++ b/configure @@ -5137,35 +5137,11 @@ EOF fi fi -######################################## -# check if __[u]int128_t is usable. - -int128=no -cat > $TMPC << EOF -#if defined(__clang_major__) && defined(__clang_minor__) -# if ((__clang_major__ < 3) || (__clang_major__ == 3) && (__clang_minor__ < 2)) -# error __int128_t does not work in CLANG before 3.2 -# endif -#endif -__int128_t a; -__uint128_t b; -int main (void) { - a = a + b; - b = a * b; - a = a * a; - return 0; -} -EOF -if compile_prog "" "" ; then - int128=yes -fi - ######################################### # See if 128-bit atomic operations are supported. atomic128=no -if test "$int128" = "yes"; then - cat > $TMPC << EOF +cat > $TMPC << EOF int main(void) { unsigned __int128 x = 0, y = 0; @@ -5175,13 +5151,12 @@ int main(void) return 0; } EOF - if compile_prog "" "" ; then - atomic128=yes - fi +if compile_prog "" "" ; then + atomic128=yes fi cmpxchg128=no -if test "$int128" = yes -a "$atomic128" = no; then +if test "$atomic128" = no; then cat > $TMPC << EOF int main(void) { @@ -6708,10 +6683,6 @@ if test "$cpuid_h" = "yes" ; then echo "CONFIG_CPUID_H=y" >> $config_host_mak fi -if test "$int128" = "yes" ; then - echo "CONFIG_INT128=y" >> $config_host_mak -fi - if test "$atomic128" = "yes" ; then echo "CONFIG_ATOMIC128=y" >> $config_host_mak fi diff --git a/include/qemu/host-utils.h b/include/qemu/host-utils.h index 38da849..25ba3e8 100644 --- a/include/qemu/host-utils.h +++ b/include/qemu/host-utils.h @@ -28,7 +28,6 @@ #include "qemu/bswap.h" -#ifdef CONFIG_INT128 static inline void mulu64(uint64_t *plow, uint64_t *phigh, uint64_t a, uint64_t b) { @@ -76,35 +75,6 @@ static inline int divs128(int64_t *plow, int64_t *phigh, int64_t divisor) return result != *plow; } } -#else -void muls64(uint64_t *phigh, uint64_t *plow, int64_t a, int64_t b); -void mulu64(uint64_t *phigh, uint64_t *plow, uint64_t a, uint64_t b); -int divu128(uint64_t *plow, uint64_t *phigh, uint64_t divisor); -int divs128(int64_t *plow, int64_t *phigh, int64_t divisor); - -static inline uint64_t muldiv64(uint64_t a, uint32_t b, uint32_t c) -{ - union { - uint64_t ll; - struct { -#ifdef HOST_WORDS_BIGENDIAN - uint32_t high, low; -#else - uint32_t low, high; -#endif - } l; - } u, res; - uint64_t rl, rh; - - u.ll = a; - rl = (uint64_t)u.l.low * (uint64_t)b; - rh = (uint64_t)u.l.high * (uint64_t)b; - rh += (rl >> 32); - res.l.high = rh / c; - res.l.low = (((rh % c) << 32) + (rl & 0xffffffff)) / c; - return res.ll; -} -#endif /** * clz32 - count leading zeros in a 32-bit value. diff --git a/include/qemu/int128.h b/include/qemu/int128.h index 5c9890d..8eac3f8 100644 --- a/include/qemu/int128.h +++ b/include/qemu/int128.h @@ -1,7 +1,6 @@ #ifndef INT128_H #define INT128_H -#ifdef CONFIG_INT128 #include "qemu/bswap.h" typedef __int128_t Int128; @@ -143,163 +142,4 @@ static inline Int128 bswap128(Int128 a) return int128_make128(bswap64(int128_gethi(a)), bswap64(int128_getlo(a))); } -#else /* !CONFIG_INT128 */ - -typedef struct Int128 Int128; - -struct Int128 { - uint64_t lo; - int64_t hi; -}; - -static inline Int128 int128_make64(uint64_t a) -{ - return (Int128) { a, 0 }; -} - -static inline Int128 int128_make128(uint64_t lo, uint64_t hi) -{ - return (Int128) { lo, hi }; -} - -static inline uint64_t int128_get64(Int128 a) -{ - assert(!a.hi); - return a.lo; -} - -static inline uint64_t int128_getlo(Int128 a) -{ - return a.lo; -} - -static inline int64_t int128_gethi(Int128 a) -{ - return a.hi; -} - -static inline Int128 int128_zero(void) -{ - return int128_make64(0); -} - -static inline Int128 int128_one(void) -{ - return int128_make64(1); -} - -static inline Int128 int128_2_64(void) -{ - return (Int128) { 0, 1 }; -} - -static inline Int128 int128_exts64(int64_t a) -{ - return (Int128) { .lo = a, .hi = (a < 0) ? -1 : 0 }; -} - -static inline Int128 int128_and(Int128 a, Int128 b) -{ - return (Int128) { a.lo & b.lo, a.hi & b.hi }; -} - -static inline Int128 int128_rshift(Int128 a, int n) -{ - int64_t h; - if (!n) { - return a; - } - h = a.hi >> (n & 63); - if (n >= 64) { - return int128_make128(h, h >> 63); - } else { - return int128_make128((a.lo >> n) | ((uint64_t)a.hi << (64 - n)), h); - } -} - -static inline Int128 int128_add(Int128 a, Int128 b) -{ - uint64_t lo = a.lo + b.lo; - - /* a.lo <= a.lo + b.lo < a.lo + k (k is the base, 2^64). Hence, - * a.lo + b.lo >= k implies 0 <= lo = a.lo + b.lo - k < a.lo. - * Similarly, a.lo + b.lo < k implies a.lo <= lo = a.lo + b.lo < k. - * - * So the carry is lo < a.lo. - */ - return int128_make128(lo, (uint64_t)a.hi + b.hi + (lo < a.lo)); -} - -static inline Int128 int128_neg(Int128 a) -{ - uint64_t lo = -a.lo; - return int128_make128(lo, ~(uint64_t)a.hi + !lo); -} - -static inline Int128 int128_sub(Int128 a, Int128 b) -{ - return int128_make128(a.lo - b.lo, (uint64_t)a.hi - b.hi - (a.lo < b.lo)); -} - -static inline bool int128_nonneg(Int128 a) -{ - return a.hi >= 0; -} - -static inline bool int128_eq(Int128 a, Int128 b) -{ - return a.lo == b.lo && a.hi == b.hi; -} - -static inline bool int128_ne(Int128 a, Int128 b) -{ - return !int128_eq(a, b); -} - -static inline bool int128_ge(Int128 a, Int128 b) -{ - return a.hi > b.hi || (a.hi == b.hi && a.lo >= b.lo); -} - -static inline bool int128_lt(Int128 a, Int128 b) -{ - return !int128_ge(a, b); -} - -static inline bool int128_le(Int128 a, Int128 b) -{ - return int128_ge(b, a); -} - -static inline bool int128_gt(Int128 a, Int128 b) -{ - return !int128_le(a, b); -} - -static inline bool int128_nz(Int128 a) -{ - return a.lo || a.hi; -} - -static inline Int128 int128_min(Int128 a, Int128 b) -{ - return int128_le(a, b) ? a : b; -} - -static inline Int128 int128_max(Int128 a, Int128 b) -{ - return int128_ge(a, b) ? a : b; -} - -static inline void int128_addto(Int128 *a, Int128 b) -{ - *a = int128_add(*a, b); -} - -static inline void int128_subfrom(Int128 *a, Int128 b) -{ - *a = int128_sub(*a, b); -} - -#endif /* CONFIG_INT128 */ #endif /* INT128_H */ diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h index ab68abe..858f121 100644 --- a/target/ppc/cpu.h +++ b/target/ppc/cpu.h @@ -265,9 +265,7 @@ union ppc_avr_t { int32_t s32[4]; uint64_t u64[2]; int64_t s64[2]; -#ifdef CONFIG_INT128 __uint128_t u128; -#endif Int128 s128; }; diff --git a/target/ppc/int_helper.c b/target/ppc/int_helper.c index fcac90a..00c65bd 100644 --- a/target/ppc/int_helper.c +++ b/target/ppc/int_helper.c @@ -1550,8 +1550,6 @@ PMSUM(vpmsumw, u32, u64, uint64_t) void helper_vpmsumd(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) { - -#ifdef CONFIG_INT128 int i, j; __uint128_t prod[2]; @@ -1565,32 +1563,6 @@ void helper_vpmsumd(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) } r->u128 = prod[0] ^ prod[1]; - -#else - int i, j; - ppc_avr_t prod[2]; - - VECTOR_FOR_INORDER_I(i, u64) { - prod[i].u64[LO_IDX] = prod[i].u64[HI_IDX] = 0; - for (j = 0; j < 64; j++) { - if (a->u64[i] & (1ull<u64[i]; - } else { - bshift.u64[HI_IDX] = b->u64[i] >> (64-j); - bshift.u64[LO_IDX] = b->u64[i] << j; - } - prod[i].u64[LO_IDX] ^= bshift.u64[LO_IDX]; - prod[i].u64[HI_IDX] ^= bshift.u64[HI_IDX]; - } - } - } - - r->u64[LO_IDX] = prod[0].u64[LO_IDX] ^ prod[1].u64[LO_IDX]; - r->u64[HI_IDX] = prod[0].u64[HI_IDX] ^ prod[1].u64[HI_IDX]; -#endif } @@ -2354,183 +2326,52 @@ VGENERIC_DO(popcntd, u64) #define QW_ONE { .u64 = { 1, 0 } } #endif -#ifndef CONFIG_INT128 - -static inline void avr_qw_not(ppc_avr_t *t, ppc_avr_t a) -{ - t->u64[0] = ~a.u64[0]; - t->u64[1] = ~a.u64[1]; -} - -static int avr_qw_cmpu(ppc_avr_t a, ppc_avr_t b) -{ - if (a.u64[HI_IDX] < b.u64[HI_IDX]) { - return -1; - } else if (a.u64[HI_IDX] > b.u64[HI_IDX]) { - return 1; - } else if (a.u64[LO_IDX] < b.u64[LO_IDX]) { - return -1; - } else if (a.u64[LO_IDX] > b.u64[LO_IDX]) { - return 1; - } else { - return 0; - } -} - -static void avr_qw_add(ppc_avr_t *t, ppc_avr_t a, ppc_avr_t b) -{ - t->u64[LO_IDX] = a.u64[LO_IDX] + b.u64[LO_IDX]; - t->u64[HI_IDX] = a.u64[HI_IDX] + b.u64[HI_IDX] + - (~a.u64[LO_IDX] < b.u64[LO_IDX]); -} - -static int avr_qw_addc(ppc_avr_t *t, ppc_avr_t a, ppc_avr_t b) -{ - ppc_avr_t not_a; - t->u64[LO_IDX] = a.u64[LO_IDX] + b.u64[LO_IDX]; - t->u64[HI_IDX] = a.u64[HI_IDX] + b.u64[HI_IDX] + - (~a.u64[LO_IDX] < b.u64[LO_IDX]); - avr_qw_not(¬_a, a); - return avr_qw_cmpu(not_a, b) < 0; -} - -#endif - void helper_vadduqm(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) { -#ifdef CONFIG_INT128 r->u128 = a->u128 + b->u128; -#else - avr_qw_add(r, *a, *b); -#endif } void helper_vaddeuqm(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c) { -#ifdef CONFIG_INT128 r->u128 = a->u128 + b->u128 + (c->u128 & 1); -#else - - if (c->u64[LO_IDX] & 1) { - ppc_avr_t tmp; - - tmp.u64[HI_IDX] = 0; - tmp.u64[LO_IDX] = c->u64[LO_IDX] & 1; - avr_qw_add(&tmp, *a, tmp); - avr_qw_add(r, tmp, *b); - } else { - avr_qw_add(r, *a, *b); - } -#endif } void helper_vaddcuq(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) { -#ifdef CONFIG_INT128 r->u128 = (~a->u128 < b->u128); -#else - ppc_avr_t not_a; - - avr_qw_not(¬_a, *a); - - r->u64[HI_IDX] = 0; - r->u64[LO_IDX] = (avr_qw_cmpu(not_a, *b) < 0); -#endif } void helper_vaddecuq(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c) { -#ifdef CONFIG_INT128 int carry_out = (~a->u128 < b->u128); if (!carry_out && (c->u128 & 1)) { carry_out = ((a->u128 + b->u128 + 1) == 0) && ((a->u128 != 0) || (b->u128 != 0)); } r->u128 = carry_out; -#else - - int carry_in = c->u64[LO_IDX] & 1; - int carry_out = 0; - ppc_avr_t tmp; - - carry_out = avr_qw_addc(&tmp, *a, *b); - - if (!carry_out && carry_in) { - ppc_avr_t one = QW_ONE; - carry_out = avr_qw_addc(&tmp, tmp, one); - } - r->u64[HI_IDX] = 0; - r->u64[LO_IDX] = carry_out; -#endif } void helper_vsubuqm(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) { -#ifdef CONFIG_INT128 r->u128 = a->u128 - b->u128; -#else - ppc_avr_t tmp; - ppc_avr_t one = QW_ONE; - - avr_qw_not(&tmp, *b); - avr_qw_add(&tmp, *a, tmp); - avr_qw_add(r, tmp, one); -#endif } void helper_vsubeuqm(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c) { -#ifdef CONFIG_INT128 r->u128 = a->u128 + ~b->u128 + (c->u128 & 1); -#else - ppc_avr_t tmp, sum; - - avr_qw_not(&tmp, *b); - avr_qw_add(&sum, *a, tmp); - - tmp.u64[HI_IDX] = 0; - tmp.u64[LO_IDX] = c->u64[LO_IDX] & 1; - avr_qw_add(r, sum, tmp); -#endif } void helper_vsubcuq(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) { -#ifdef CONFIG_INT128 r->u128 = (~a->u128 < ~b->u128) || (a->u128 + ~b->u128 == (__uint128_t)-1); -#else - int carry = (avr_qw_cmpu(*a, *b) > 0); - if (!carry) { - ppc_avr_t tmp; - avr_qw_not(&tmp, *b); - avr_qw_add(&tmp, *a, tmp); - carry = ((tmp.s64[HI_IDX] == -1ull) && (tmp.s64[LO_IDX] == -1ull)); - } - r->u64[HI_IDX] = 0; - r->u64[LO_IDX] = carry; -#endif } void helper_vsubecuq(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c) { -#ifdef CONFIG_INT128 r->u128 = (~a->u128 < ~b->u128) || ((c->u128 & 1) && (a->u128 + ~b->u128 == (__uint128_t)-1)); -#else - int carry_in = c->u64[LO_IDX] & 1; - int carry_out = (avr_qw_cmpu(*a, *b) > 0); - if (!carry_out && carry_in) { - ppc_avr_t tmp; - avr_qw_not(&tmp, *b); - avr_qw_add(&tmp, *a, tmp); - carry_out = ((tmp.u64[HI_IDX] == -1ull) && (tmp.u64[LO_IDX] == -1ull)); - } - - r->u64[HI_IDX] = 0; - r->u64[LO_IDX] = carry_out; -#endif } #define BCD_PLUS_PREF_1 0xC diff --git a/target/s390x/int_helper.c b/target/s390x/int_helper.c index abf77a9..c8cfb93 100644 --- a/target/s390x/int_helper.c +++ b/target/s390x/int_helper.c @@ -100,7 +100,6 @@ uint64_t HELPER(divu64)(CPUS390XState *env, uint64_t ah, uint64_t al, ret = al / b; } else { /* ??? Move i386 idivq helper to host-utils. */ -#ifdef CONFIG_INT128 __uint128_t a = ((__uint128_t)ah << 64) | al; __uint128_t q = a / b; env->retxl = a % b; @@ -108,12 +107,6 @@ uint64_t HELPER(divu64)(CPUS390XState *env, uint64_t ah, uint64_t al, if (ret != q) { s390_program_interrupt(env, PGM_FIXPT_DIVIDE, ILEN_AUTO, GETPC()); } -#else - S390CPU *cpu = s390_env_get_cpu(env); - /* 32-bit hosts would need special wrapper functionality - just abort if - we encounter such a case; it's very unlikely anyways. */ - cpu_abort(CPU(cpu), "128 -> 64/64 division not implemented\n"); -#endif } return ret; } diff --git a/util/host-utils.c b/util/host-utils.c index 7b93220..18fa1d0 100644 --- a/util/host-utils.c +++ b/util/host-utils.c @@ -26,141 +26,6 @@ #include "qemu/osdep.h" #include "qemu/host-utils.h" -#ifndef CONFIG_INT128 -/* Long integer helpers */ -static inline void mul64(uint64_t *plow, uint64_t *phigh, - uint64_t a, uint64_t b) -{ - typedef union { - uint64_t ll; - struct { -#ifdef HOST_WORDS_BIGENDIAN - uint32_t high, low; -#else - uint32_t low, high; -#endif - } l; - } LL; - LL rl, rm, rn, rh, a0, b0; - uint64_t c; - - a0.ll = a; - b0.ll = b; - - rl.ll = (uint64_t)a0.l.low * b0.l.low; - rm.ll = (uint64_t)a0.l.low * b0.l.high; - rn.ll = (uint64_t)a0.l.high * b0.l.low; - rh.ll = (uint64_t)a0.l.high * b0.l.high; - - c = (uint64_t)rl.l.high + rm.l.low + rn.l.low; - rl.l.high = c; - c >>= 32; - c = c + rm.l.high + rn.l.high + rh.l.low; - rh.l.low = c; - rh.l.high += (uint32_t)(c >> 32); - - *plow = rl.ll; - *phigh = rh.ll; -} - -/* Unsigned 64x64 -> 128 multiplication */ -void mulu64 (uint64_t *plow, uint64_t *phigh, uint64_t a, uint64_t b) -{ - mul64(plow, phigh, a, b); -} - -/* Signed 64x64 -> 128 multiplication */ -void muls64 (uint64_t *plow, uint64_t *phigh, int64_t a, int64_t b) -{ - uint64_t rh; - - mul64(plow, &rh, a, b); - - /* Adjust for signs. */ - if (b < 0) { - rh -= a; - } - if (a < 0) { - rh -= b; - } - *phigh = rh; -} - -/* Unsigned 128x64 division. Returns 1 if overflow (divide by zero or */ -/* quotient exceeds 64 bits). Otherwise returns quotient via plow and */ -/* remainder via phigh. */ -int divu128(uint64_t *plow, uint64_t *phigh, uint64_t divisor) -{ - uint64_t dhi = *phigh; - uint64_t dlo = *plow; - unsigned i; - uint64_t carry = 0; - - if (divisor == 0) { - return 1; - } else if (dhi == 0) { - *plow = dlo / divisor; - *phigh = dlo % divisor; - return 0; - } else if (dhi > divisor) { - return 1; - } else { - - for (i = 0; i < 64; i++) { - carry = dhi >> 63; - dhi = (dhi << 1) | (dlo >> 63); - if (carry || (dhi >= divisor)) { - dhi -= divisor; - carry = 1; - } else { - carry = 0; - } - dlo = (dlo << 1) | carry; - } - - *plow = dlo; - *phigh = dhi; - return 0; - } -} - -int divs128(int64_t *plow, int64_t *phigh, int64_t divisor) -{ - int sgn_dvdnd = *phigh < 0; - int sgn_divsr = divisor < 0; - int overflow = 0; - - if (sgn_dvdnd) { - *plow = ~(*plow); - *phigh = ~(*phigh); - if (*plow == (int64_t)-1) { - *plow = 0; - (*phigh)++; - } else { - (*plow)++; - } - } - - if (sgn_divsr) { - divisor = 0 - divisor; - } - - overflow = divu128((uint64_t *)plow, (uint64_t *)phigh, (uint64_t)divisor); - - if (sgn_dvdnd ^ sgn_divsr) { - *plow = 0 - *plow; - } - - if (!overflow) { - if ((*plow < 0) ^ (sgn_dvdnd ^ sgn_divsr)) { - overflow = 1; - } - } - - return overflow; -} -#endif - /** * urshift - 128-bit Unsigned Right Shift. * @plow: in/out - lower 64-bit integer. -- 1.8.3.1