From nobody Tue Oct 7 06:01:51 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1543846329894434.98223706730937; Mon, 3 Dec 2018 06:12:09 -0800 (PST) Received: from localhost ([::1]:49580 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gToxE-0006an-5D for importer@patchew.org; Mon, 03 Dec 2018 09:12:08 -0500 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 Received: from smtp.corp.redhat.com (int-mx07.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id CC10630C318F; Mon, 3 Dec 2018 14:05:44 +0000 (UTC) Received: from thuth.com (ovpn-116-54.ams2.redhat.com [10.36.116.54]) by smtp.corp.redhat.com (Postfix) with ESMTP id 99BDC1001F57; Mon, 3 Dec 2018 14:05:43 +0000 (UTC) From: Thomas Huth To: qemu-devel@nongnu.org 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> X-Scanned-By: MIMEDefang 2.84 on 10.5.11.22 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.45]); Mon, 03 Dec 2018 14:05:44 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH for-4.0 2/7] Remove support for compilers that can not do 128-bit arithmetics X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: peter.maydell@linaro.org, pbonzini@redhat.com, Richard Henderson Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" 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 =20 -######################################## -# check if __[u]int128_t is usable. - -int128=3Dno -cat > $TMPC << EOF -#if defined(__clang_major__) && defined(__clang_minor__) -# if ((__clang_major__ < 3) || (__clang_major__ =3D=3D 3) && (__clang_mino= r__ < 2)) -# error __int128_t does not work in CLANG before 3.2 -# endif -#endif -__int128_t a; -__uint128_t b; -int main (void) { - a =3D a + b; - b =3D a * b; - a =3D a * a; - return 0; -} -EOF -if compile_prog "" "" ; then - int128=3Dyes -fi - ######################################### # See if 128-bit atomic operations are supported. =20 atomic128=3Dno -if test "$int128" =3D "yes"; then - cat > $TMPC << EOF +cat > $TMPC << EOF int main(void) { unsigned __int128 x =3D 0, y =3D 0; @@ -5175,13 +5151,12 @@ int main(void) return 0; } EOF - if compile_prog "" "" ; then - atomic128=3Dyes - fi +if compile_prog "" "" ; then + atomic128=3Dyes fi =20 cmpxchg128=3Dno -if test "$int128" =3D yes -a "$atomic128" =3D no; then +if test "$atomic128" =3D no; then cat > $TMPC << EOF int main(void) { @@ -6708,10 +6683,6 @@ if test "$cpuid_h" =3D "yes" ; then echo "CONFIG_CPUID_H=3Dy" >> $config_host_mak fi =20 -if test "$int128" =3D "yes" ; then - echo "CONFIG_INT128=3Dy" >> $config_host_mak -fi - if test "$atomic128" =3D "yes" ; then echo "CONFIG_ATOMIC128=3Dy" >> $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 @@ =20 #include "qemu/bswap.h" =20 -#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 !=3D *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 =3D a; - rl =3D (uint64_t)u.l.low * (uint64_t)b; - rh =3D (uint64_t)u.l.high * (uint64_t)b; - rh +=3D (rl >> 32); - res.l.high =3D rh / c; - res.l.low =3D (((rh % c) << 32) + (rl & 0xffffffff)) / c; - return res.ll; -} -#endif =20 /** * 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 =20 -#ifdef CONFIG_INT128 #include "qemu/bswap.h" =20 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= ))); } =20 -#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 =3D a, .hi =3D (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 =3D a.hi >> (n & 63); - if (n >=3D 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 =3D a.lo + b.lo; - - /* a.lo <=3D a.lo + b.lo < a.lo + k (k is the base, 2^64). Hence, - * a.lo + b.lo >=3D k implies 0 <=3D lo =3D a.lo + b.lo - k < a.lo. - * Similarly, a.lo + b.lo < k implies a.lo <=3D lo =3D 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 =3D -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.l= o)); -} - -static inline bool int128_nonneg(Int128 a) -{ - return a.hi >=3D 0; -} - -static inline bool int128_eq(Int128 a, Int128 b) -{ - return a.lo =3D=3D b.lo && a.hi =3D=3D 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 =3D=3D b.hi && a.lo >=3D 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 =3D int128_add(*a, b); -} - -static inline void int128_subfrom(Int128 *a, Int128 b) -{ - *a =3D 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; }; =20 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) =20 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]; =20 @@ -1565,32 +1563,6 @@ void helper_vpmsumd(ppc_avr_t *r, ppc_avr_t *a, ppc_= avr_t *b) } =20 r->u128 =3D prod[0] ^ prod[1]; - -#else - int i, j; - ppc_avr_t prod[2]; - - VECTOR_FOR_INORDER_I(i, u64) { - prod[i].u64[LO_IDX] =3D prod[i].u64[HI_IDX] =3D 0; - for (j =3D 0; j < 64; j++) { - if (a->u64[i] & (1ull<u64[i]; - } else { - bshift.u64[HI_IDX] =3D b->u64[i] >> (64-j); - bshift.u64[LO_IDX] =3D b->u64[i] << j; - } - prod[i].u64[LO_IDX] ^=3D bshift.u64[LO_IDX]; - prod[i].u64[HI_IDX] ^=3D bshift.u64[HI_IDX]; - } - } - } - - r->u64[LO_IDX] =3D prod[0].u64[LO_IDX] ^ prod[1].u64[LO_IDX]; - r->u64[HI_IDX] =3D prod[0].u64[HI_IDX] ^ prod[1].u64[HI_IDX]; -#endif } =20 =20 @@ -2354,183 +2326,52 @@ VGENERIC_DO(popcntd, u64) #define QW_ONE { .u64 =3D { 1, 0 } } #endif =20 -#ifndef CONFIG_INT128 - -static inline void avr_qw_not(ppc_avr_t *t, ppc_avr_t a) -{ - t->u64[0] =3D ~a.u64[0]; - t->u64[1] =3D ~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] =3D a.u64[LO_IDX] + b.u64[LO_IDX]; - t->u64[HI_IDX] =3D 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] =3D a.u64[LO_IDX] + b.u64[LO_IDX]; - t->u64[HI_IDX] =3D 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 =3D a->u128 + b->u128; -#else - avr_qw_add(r, *a, *b); -#endif } =20 void helper_vaddeuqm(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *= c) { -#ifdef CONFIG_INT128 r->u128 =3D a->u128 + b->u128 + (c->u128 & 1); -#else - - if (c->u64[LO_IDX] & 1) { - ppc_avr_t tmp; - - tmp.u64[HI_IDX] =3D 0; - tmp.u64[LO_IDX] =3D 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 } =20 void helper_vaddcuq(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) { -#ifdef CONFIG_INT128 r->u128 =3D (~a->u128 < b->u128); -#else - ppc_avr_t not_a; - - avr_qw_not(¬_a, *a); - - r->u64[HI_IDX] =3D 0; - r->u64[LO_IDX] =3D (avr_qw_cmpu(not_a, *b) < 0); -#endif } =20 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 =3D (~a->u128 < b->u128); if (!carry_out && (c->u128 & 1)) { carry_out =3D ((a->u128 + b->u128 + 1) =3D=3D 0) && ((a->u128 !=3D 0) || (b->u128 !=3D 0)); } r->u128 =3D carry_out; -#else - - int carry_in =3D c->u64[LO_IDX] & 1; - int carry_out =3D 0; - ppc_avr_t tmp; - - carry_out =3D avr_qw_addc(&tmp, *a, *b); - - if (!carry_out && carry_in) { - ppc_avr_t one =3D QW_ONE; - carry_out =3D avr_qw_addc(&tmp, tmp, one); - } - r->u64[HI_IDX] =3D 0; - r->u64[LO_IDX] =3D carry_out; -#endif } =20 void helper_vsubuqm(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) { -#ifdef CONFIG_INT128 r->u128 =3D a->u128 - b->u128; -#else - ppc_avr_t tmp; - ppc_avr_t one =3D QW_ONE; - - avr_qw_not(&tmp, *b); - avr_qw_add(&tmp, *a, tmp); - avr_qw_add(r, tmp, one); -#endif } =20 void helper_vsubeuqm(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *= c) { -#ifdef CONFIG_INT128 r->u128 =3D 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] =3D 0; - tmp.u64[LO_IDX] =3D c->u64[LO_IDX] & 1; - avr_qw_add(r, sum, tmp); -#endif } =20 void helper_vsubcuq(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) { -#ifdef CONFIG_INT128 r->u128 =3D (~a->u128 < ~b->u128) || (a->u128 + ~b->u128 =3D=3D (__uint128_t)-1); -#else - int carry =3D (avr_qw_cmpu(*a, *b) > 0); - if (!carry) { - ppc_avr_t tmp; - avr_qw_not(&tmp, *b); - avr_qw_add(&tmp, *a, tmp); - carry =3D ((tmp.s64[HI_IDX] =3D=3D -1ull) && (tmp.s64[LO_IDX] =3D= =3D -1ull)); - } - r->u64[HI_IDX] =3D 0; - r->u64[LO_IDX] =3D carry; -#endif } =20 void helper_vsubecuq(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *= c) { -#ifdef CONFIG_INT128 r->u128 =3D (~a->u128 < ~b->u128) || ((c->u128 & 1) && (a->u128 + ~b->u128 =3D=3D (__uint128_t)-1)); -#else - int carry_in =3D c->u64[LO_IDX] & 1; - int carry_out =3D (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 =3D ((tmp.u64[HI_IDX] =3D=3D -1ull) && (tmp.u64[LO_IDX] = =3D=3D -1ull)); - } - - r->u64[HI_IDX] =3D 0; - r->u64[LO_IDX] =3D carry_out; -#endif } =20 #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 =3D al / b; } else { /* ??? Move i386 idivq helper to host-utils. */ -#ifdef CONFIG_INT128 __uint128_t a =3D ((__uint128_t)ah << 64) | al; __uint128_t q =3D a / b; env->retxl =3D a % b; @@ -108,12 +107,6 @@ uint64_t HELPER(divu64)(CPUS390XState *env, uint64_t a= h, uint64_t al, if (ret !=3D q) { s390_program_interrupt(env, PGM_FIXPT_DIVIDE, ILEN_AUTO, GETPC= ()); } -#else - S390CPU *cpu =3D s390_env_get_cpu(env); - /* 32-bit hosts would need special wrapper functionality - just ab= ort 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" =20 -#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 =3D a; - b0.ll =3D b; - - rl.ll =3D (uint64_t)a0.l.low * b0.l.low; - rm.ll =3D (uint64_t)a0.l.low * b0.l.high; - rn.ll =3D (uint64_t)a0.l.high * b0.l.low; - rh.ll =3D (uint64_t)a0.l.high * b0.l.high; - - c =3D (uint64_t)rl.l.high + rm.l.low + rn.l.low; - rl.l.high =3D c; - c >>=3D 32; - c =3D c + rm.l.high + rn.l.high + rh.l.low; - rh.l.low =3D c; - rh.l.high +=3D (uint32_t)(c >> 32); - - *plow =3D rl.ll; - *phigh =3D 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 -=3D a; - } - if (a < 0) { - rh -=3D b; - } - *phigh =3D 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 =3D *phigh; - uint64_t dlo =3D *plow; - unsigned i; - uint64_t carry =3D 0; - - if (divisor =3D=3D 0) { - return 1; - } else if (dhi =3D=3D 0) { - *plow =3D dlo / divisor; - *phigh =3D dlo % divisor; - return 0; - } else if (dhi > divisor) { - return 1; - } else { - - for (i =3D 0; i < 64; i++) { - carry =3D dhi >> 63; - dhi =3D (dhi << 1) | (dlo >> 63); - if (carry || (dhi >=3D divisor)) { - dhi -=3D divisor; - carry =3D 1; - } else { - carry =3D 0; - } - dlo =3D (dlo << 1) | carry; - } - - *plow =3D dlo; - *phigh =3D dhi; - return 0; - } -} - -int divs128(int64_t *plow, int64_t *phigh, int64_t divisor) -{ - int sgn_dvdnd =3D *phigh < 0; - int sgn_divsr =3D divisor < 0; - int overflow =3D 0; - - if (sgn_dvdnd) { - *plow =3D ~(*plow); - *phigh =3D ~(*phigh); - if (*plow =3D=3D (int64_t)-1) { - *plow =3D 0; - (*phigh)++; - } else { - (*plow)++; - } - } - - if (sgn_divsr) { - divisor =3D 0 - divisor; - } - - overflow =3D divu128((uint64_t *)plow, (uint64_t *)phigh, (uint64_t)di= visor); - - if (sgn_dvdnd ^ sgn_divsr) { - *plow =3D 0 - *plow; - } - - if (!overflow) { - if ((*plow < 0) ^ (sgn_dvdnd ^ sgn_divsr)) { - overflow =3D 1; - } - } - - return overflow; -} -#endif - /** * urshift - 128-bit Unsigned Right Shift. * @plow: in/out - lower 64-bit integer. --=20 1.8.3.1