From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by sourceware.org (Postfix) with ESMTPS id 5C8163858D39 for ; Sat, 2 Sep 2023 11:42:55 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 5C8163858D39 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=redhat.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=redhat.com DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1693654975; h=from:from:reply-to:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-type:in-reply-to:in-reply-to: references:references; bh=Fqgrm+WVwdXcKF7jNJDwIKZkNrHsZb6FOtBFXrnGHZ0=; b=CAKnMuVb1LII58ZzEAgVFJRwA8W5KYY3dA/p8BCzAOuJ/ghE88/Lz5zqYO1w+PNz1F+JoR eiBl943IhZICEKEqxSHkXnp+e8y09C/tyP3uJ2V68WYnUDJapRA1axuLF1jN18xXPSLGdS SGgb2Gqys6+9TR+hvc8HTyOvf08V8Ho= Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-609-wunT1joNMXeuH0wtI80N7w-1; Sat, 02 Sep 2023 07:42:51 -0400 X-MC-Unique: wunT1joNMXeuH0wtI80N7w-1 Received: from smtp.corp.redhat.com (int-mx10.intmail.prod.int.rdu2.redhat.com [10.11.54.10]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id E2BB110264C1; Sat, 2 Sep 2023 11:42:50 +0000 (UTC) Received: from tucnak.zalov.cz (unknown [10.45.224.16]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 6E8B449310F; Sat, 2 Sep 2023 11:42:49 +0000 (UTC) Received: from tucnak.zalov.cz (localhost [127.0.0.1]) by tucnak.zalov.cz (8.17.1/8.17.1) with ESMTPS id 382BglbJ2781690 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384 bits=256 verify=NOT); Sat, 2 Sep 2023 13:42:47 +0200 Received: (from jakub@localhost) by tucnak.zalov.cz (8.17.1/8.17.1/Submit) id 382BgkRN2781689; Sat, 2 Sep 2023 13:42:46 +0200 Date: Sat, 2 Sep 2023 13:42:46 +0200 From: Jakub Jelinek To: Joseph Myers Cc: Ian Lance Taylor , gcc-patches@gcc.gnu.org Subject: Re: [PATCH 9/12] libgcc _BitInt support [PR102989] Message-ID: Reply-To: Jakub Jelinek References: <18ed8557-5c75-4f3-e9a9-3cba6ab0a5b1@codesourcery.com> MIME-Version: 1.0 In-Reply-To: <18ed8557-5c75-4f3-e9a9-3cba6ab0a5b1@codesourcery.com> X-Scanned-By: MIMEDefang 3.1 on 10.11.54.10 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Type: text/plain; charset=us-ascii Content-Disposition: inline X-Spam-Status: No, score=-14.7 required=5.0 tests=BAYES_00,DKIM_INVALID,DKIM_SIGNED,KAM_DMARC_NONE,KAM_DMARC_STATUS,KAM_SHORT,RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H4,RCVD_IN_MSPIKE_WL,SPF_HELO_NONE,SPF_NONE,TXREP autolearn=no autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org List-Id: On Fri, Sep 01, 2023 at 09:48:22PM +0000, Joseph Myers wrote: > This patch is OK with these fixes. Thanks, here is an updated patch, thanks for catching the _Decimal128 bug. Will post testsuite additions/adjustment patch as follow-up on Monday. 2023-09-02 Jakub Jelinek PR c/102989 libgcc/ * config/aarch64/t-softfp (softfp_extras): Use += rather than :=. * config/i386/64/t-softfp (softfp_extras): Likewise. * config/i386/libgcc-glibc.ver (GCC_14.0.0): Export _BitInt support routines. * config/i386/t-softfp (softfp_extras): Add fixxfbitint and bf, hf and xf mode floatbitint. (CFLAGS-floatbitintbf.c, CFLAGS-floatbitinthf.c): Add -msse2. * config/riscv/t-softfp32 (softfp_extras): Use += rather than :=. * config/rs6000/t-e500v1-fp (softfp_extras): Likewise. * config/rs6000/t-e500v2-fp (softfp_extras): Likewise. * config/t-softfp (softfp_floatbitint_funcs): New. (softfp_bid_list): New. (softfp_func_list): Add sf and df mode from and to _BitInt libcalls. (softfp_bid_file_list): New. (LIB2ADD_ST): Add $(softfp_bid_file_list). * config/t-softfp-sfdftf (softfp_extras): Add fixtfbitint and floatbitinttf. * config/t-softfp-tf (softfp_extras): Likewise. * libgcc2.c (bitint_reduce_prec): New inline function. (BITINT_INC, BITINT_END): Define. (bitint_mul_1, bitint_addmul_1): New helper functions. (__mulbitint3): New function. (bitint_negate, bitint_submul_1): New helper functions. (__divmodbitint4): New function. * libgcc2.h (LIBGCC2_UNITS_PER_WORD): When building _BitInt support libcalls, redefine depending on __LIBGCC_BITINT_LIMB_WIDTH__. (__mulbitint3, __divmodbitint4): Declare. * libgcc-std.ver.in (GCC_14.0.0): Export _BitInt support routines. * Makefile.in (lib2funcs): Add _mulbitint3. (LIB2_DIVMOD_FUNCS): Add _divmodbitint4. * soft-fp/bitint.h: New file. * soft-fp/fixdfbitint.c: New file. * soft-fp/fixsfbitint.c: New file. * soft-fp/fixtfbitint.c: New file. * soft-fp/fixxfbitint.c: New file. * soft-fp/floatbitintbf.c: New file. * soft-fp/floatbitintdf.c: New file. * soft-fp/floatbitinthf.c: New file. * soft-fp/floatbitintsf.c: New file. * soft-fp/floatbitinttf.c: New file. * soft-fp/floatbitintxf.c: New file. * soft-fp/op-common.h (_FP_FROM_INT): Add support for rsize up to 4 * _FP_W_TYPE_SIZE rather than just 2 * _FP_W_TYPE_SIZE. * soft-fp/bitintpow10.c: New file. * soft-fp/fixsdbitint.c: New file. * soft-fp/fixddbitint.c: New file. * soft-fp/fixtdbitint.c: New file. * soft-fp/floatbitintsd.c: New file. * soft-fp/floatbitintdd.c: New file. * soft-fp/floatbitinttd.c: New file. --- libgcc/config/aarch64/t-softfp.jj 2023-08-08 15:54:35.737595343 +0200 +++ libgcc/config/aarch64/t-softfp 2023-08-08 16:12:02.346939560 +0200 @@ -3,7 +3,7 @@ softfp_int_modes := si di ti softfp_extensions := sftf dftf hftf bfsf softfp_truncations := tfsf tfdf tfhf tfbf dfbf sfbf hfbf softfp_exclude_libgcc2 := n -softfp_extras := fixhfti fixunshfti floattihf floatuntihf \ +softfp_extras += fixhfti fixunshfti floattihf floatuntihf \ floatdibf floatundibf floattibf floatuntibf TARGET_LIBGCC2_CFLAGS += -Wno-missing-prototypes --- libgcc/config/i386/64/t-softfp.jj 2023-08-08 15:54:35.766594936 +0200 +++ libgcc/config/i386/64/t-softfp 2023-08-08 16:12:02.346939560 +0200 @@ -1,4 +1,4 @@ -softfp_extras := fixhfti fixunshfti floattihf floatuntihf \ +softfp_extras += fixhfti fixunshfti floattihf floatuntihf \ floattibf floatuntibf CFLAGS-fixhfti.c += -msse2 --- libgcc/config/i386/libgcc-glibc.ver.jj 2023-08-08 15:54:35.831594026 +0200 +++ libgcc/config/i386/libgcc-glibc.ver 2023-08-08 16:12:02.347939546 +0200 @@ -226,3 +226,13 @@ GCC_13.0.0 { __truncxfbf2 __trunchfbf2 } + +%inherit GCC_14.0.0 GCC_13.0.0 +GCC_14.0.0 { + __PFX__fixxfbitint + __PFX__fixtfbitint + __PFX__floatbitintbf + __PFX__floatbitinthf + __PFX__floatbitintxf + __PFX__floatbitinttf +} --- libgcc/config/i386/t-softfp.jj 2023-08-08 15:55:09.819118062 +0200 +++ libgcc/config/i386/t-softfp 2023-08-08 16:12:02.347939546 +0200 @@ -10,7 +10,7 @@ softfp_extensions := hfsf hfdf hftf hfxf softfp_truncations := tfhf xfhf dfhf sfhf tfsf dfsf tfdf tfxf \ tfbf xfbf dfbf sfbf hfbf -softfp_extras += eqhf2 +softfp_extras += eqhf2 fixxfbitint $(foreach m,hf bf xf,floatbitint$(m)) CFLAGS-extendhfsf2.c += -msse2 CFLAGS-extendhfdf2.c += -msse2 @@ -28,6 +28,9 @@ CFLAGS-truncxfbf2.c += -msse2 CFLAGS-trunctfbf2.c += -msse2 CFLAGS-trunchfbf2.c += -msse2 +CFLAGS-floatbitintbf.c += -msse2 +CFLAGS-floatbitinthf.c += -msse2 + CFLAGS-eqhf2.c += -msse2 CFLAGS-_divhc3.c += -msse2 CFLAGS-_mulhc3.c += -msse2 --- libgcc/config/riscv/t-softfp32.jj 2023-08-08 15:54:35.920592780 +0200 +++ libgcc/config/riscv/t-softfp32 2023-08-08 16:12:02.347939546 +0200 @@ -13,7 +13,7 @@ softfp_extensions := sftf dftf softfp_truncations := tfsf tfdf # Enable divide routines to make -mno-fdiv work. -softfp_extras := divsf3 divdf3 +softfp_extras += divsf3 divdf3 else # !ABI_DOUBLE @@ -28,7 +28,7 @@ else # ABI_SINGLE # Enable divide routines to make -mno-fdiv work. -softfp_extras := divsf3 +softfp_extras += divsf3 endif @@ -38,7 +38,7 @@ else # ABI_QUAD # Enable divide routines to make -mno-fdiv work. -softfp_extras := divsf3 divdf3 divtf3 +softfp_extras += divsf3 divdf3 divtf3 endif --- libgcc/config/rs6000/t-e500v1-fp.jj 2023-08-08 15:54:35.965592150 +0200 +++ libgcc/config/rs6000/t-e500v1-fp 2023-08-08 16:12:02.347939546 +0200 @@ -29,4 +29,4 @@ softfp_int_modes := si di softfp_extensions := sfdf softfp_truncations := dfsf softfp_exclude_libgcc2 := n -softfp_extras := unordsf2 +softfp_extras += unordsf2 --- libgcc/config/rs6000/t-e500v2-fp.jj 2023-08-08 15:54:35.965592150 +0200 +++ libgcc/config/rs6000/t-e500v2-fp 2023-08-08 16:12:02.347939546 +0200 @@ -23,4 +23,4 @@ softfp_int_modes := softfp_extensions := softfp_truncations := softfp_exclude_libgcc2 := n -softfp_extras := unordsf2 unorddf2 +softfp_extras += unordsf2 unorddf2 --- libgcc/config/t-softfp.jj 2023-08-08 15:54:35.992591772 +0200 +++ libgcc/config/t-softfp 2023-08-08 16:22:09.404440148 +0200 @@ -64,12 +64,21 @@ softfp_float_funcs = add$(m)3 div$(m)3 e neg$(m)2 sub$(m)3 unord$(m)2 softfp_floatint_funcs = fix$(m)$(i) fixuns$(m)$(i) \ float$(i)$(m) floatun$(i)$(m) +softfp_floatbitint_funcs = fix$(m)bitint floatbitint$(m) +softfp_bid_list := +ifeq ($(decimal_float),yes) +ifeq ($(enable_decimal_float),bid) +softfp_bid_list += bitintpow10 \ + $(foreach m,sd dd td,fix$(m)bitint floatbitint$(m)) +endif +endif softfp_func_list := \ $(foreach m,$(softfp_float_modes), \ $(softfp_float_funcs) \ $(foreach i,$(softfp_int_modes), \ $(softfp_floatint_funcs))) \ + $(foreach m,sf df,$(softfp_floatbitint_funcs)) \ $(foreach e,$(softfp_extensions),extend$(e)2) \ $(foreach t,$(softfp_truncations),trunc$(t)2) \ $(softfp_extras) @@ -116,6 +125,8 @@ softfp_file_list := \ $(addsuffix .c,$(addprefix $(srcdir)/soft-fp/,$(softfp_func_list))) endif endif +softfp_bid_file_list := \ + $(addsuffix .c,$(addprefix $(srcdir)/soft-fp/,$(softfp_bid_list))) # Disable missing prototype and type limit warnings. The prototypes # for the functions in the soft-fp files have not been brought across @@ -129,6 +140,7 @@ soft-fp-objects = $(addsuffix $(objext), $(soft-fp-objects) : INTERNAL_CFLAGS += -Wno-missing-prototypes -Wno-type-limits LIB2ADD += $(softfp_file_list) +LIB2ADD_ST += $(softfp_bid_file_list) ifneq ($(softfp_exclude_libgcc2),y) # Functions in libgcc2.c are excluded for each soft-float mode (a --- libgcc/config/t-softfp-sfdftf.jj 2023-08-08 15:54:35.992591772 +0200 +++ libgcc/config/t-softfp-sfdftf 2023-08-08 16:12:02.347939546 +0200 @@ -2,4 +2,5 @@ softfp_float_modes := sf df tf softfp_int_modes := si di softfp_extensions := sfdf sftf dftf xftf softfp_truncations := dfsf tfsf tfdf tfxf +softfp_extras += fixtfbitint floatbitinttf softfp_exclude_libgcc2 := n --- libgcc/config/t-softfp-tf.jj 2023-08-08 15:54:36.011591506 +0200 +++ libgcc/config/t-softfp-tf 2023-08-08 16:12:02.347939546 +0200 @@ -2,4 +2,5 @@ softfp_float_modes := tf softfp_int_modes := si di ti softfp_extensions := sftf dftf xftf softfp_truncations := tfsf tfdf tfxf +softfp_extras += fixtfbitint floatbitinttf softfp_exclude_libgcc2 := n --- libgcc/libgcc2.c.jj 2023-08-08 15:54:36.059590834 +0200 +++ libgcc/libgcc2.c 2023-08-08 16:12:02.348939532 +0200 @@ -1301,6 +1301,687 @@ __udivdi3 (UDWtype n, UDWtype d) } #endif +#if (defined(__BITINT_MAXWIDTH__) \ + && (defined(L_mulbitint3) || defined(L_divmodbitint4))) +/* _BitInt support. */ + +/* If *P is zero or sign extended (the latter only for PREC < 0) from + some narrower _BitInt value, reduce precision. */ + +static inline __attribute__((__always_inline__)) SItype +bitint_reduce_prec (const UWtype **p, SItype prec) +{ + UWtype mslimb; + SItype i; + if (prec < 0) + { +#if __LIBGCC_BITINT_ORDER__ == __ORDER_BIG_ENDIAN__ + i = 0; +#else + i = ((USItype) -1 - prec) / W_TYPE_SIZE; +#endif + mslimb = (*p)[i]; + if (mslimb & ((UWtype) 1 << (((USItype) -1 - prec) % W_TYPE_SIZE))) + { + SItype n = ((USItype) -prec) % W_TYPE_SIZE; + if (n) + { + mslimb |= ((UWtype) -1 << (((USItype) -1 - prec) % W_TYPE_SIZE)); + if (mslimb == (UWtype) -1) + { + prec += n; + if (prec >= -1) + return -2; +#if __LIBGCC_BITINT_ORDER__ == __ORDER_BIG_ENDIAN__ + ++p; +#else + --i; +#endif + mslimb = (*p)[i]; + n = 0; + } + } + while (mslimb == (UWtype) -1) + { + prec += W_TYPE_SIZE; + if (prec >= -1) + return -2; +#if __LIBGCC_BITINT_ORDER__ == __ORDER_BIG_ENDIAN__ + ++p; +#else + --i; +#endif + mslimb = (*p)[i]; + } + if (n == 0) + { + if ((Wtype) mslimb >= 0) + { +#if __LIBGCC_BITINT_ORDER__ == __ORDER_BIG_ENDIAN__ + --p; +#endif + return prec - 1; + } + } + return prec; + } + else + prec = -prec; + } + else + { +#if __LIBGCC_BITINT_ORDER__ == __ORDER_BIG_ENDIAN__ + i = 0; +#else + i = ((USItype) prec - 1) / W_TYPE_SIZE; +#endif + mslimb = (*p)[i]; + } + SItype n = ((USItype) prec) % W_TYPE_SIZE; + if (n) + { + mslimb &= ((UWtype) 1 << (((USItype) prec) % W_TYPE_SIZE)) - 1; + if (mslimb == 0) + { + prec -= n; + if (prec == 0) + return 1; +#if __LIBGCC_BITINT_ORDER__ == __ORDER_BIG_ENDIAN__ + ++p; +#else + --i; +#endif + mslimb = (*p)[i]; + } + } + while (mslimb == 0) + { + prec -= W_TYPE_SIZE; + if (prec == 0) + return 1; +#if __LIBGCC_BITINT_ORDER__ == __ORDER_BIG_ENDIAN__ + ++p; +#else + --i; +#endif + mslimb = (*p)[i]; + } + return prec; +} + +#if __LIBGCC_BITINT_ORDER__ == __ORDER_BIG_ENDIAN__ +# define BITINT_INC -1 +# define BITINT_END(be, le) (be) +#else +# define BITINT_INC 1 +# define BITINT_END(be, le) (le) +#endif + +#ifdef L_mulbitint3 +/* D = S * L. */ + +static UWtype +bitint_mul_1 (UWtype *d, const UWtype *s, UWtype l, SItype n) +{ + UWtype sv, hi, lo, c = 0; + do + { + sv = *s; + s += BITINT_INC; + umul_ppmm (hi, lo, sv, l); + c = __builtin_add_overflow (lo, c, &lo) + hi; + *d = lo; + d += BITINT_INC; + } + while (--n); + return c; +} + +/* D += S * L. */ + +static UWtype +bitint_addmul_1 (UWtype *d, const UWtype *s, UWtype l, SItype n) +{ + UWtype sv, hi, lo, c = 0; + do + { + sv = *s; + s += BITINT_INC; + umul_ppmm (hi, lo, sv, l); + hi += __builtin_add_overflow (lo, *d, &lo); + c = __builtin_add_overflow (lo, c, &lo) + hi; + *d = lo; + d += BITINT_INC; + } + while (--n); + return c; +} + +/* If XPREC is positive, it is precision in bits + of an unsigned _BitInt operand (which has XPREC/W_TYPE_SIZE + full limbs and if Xprec%W_TYPE_SIZE one partial limb. + If Xprec is negative, -XPREC is precision in bits + of a signed _BitInt operand. RETPREC should be always + positive. */ + +void +__mulbitint3 (UWtype *ret, SItype retprec, + const UWtype *u, SItype uprec, + const UWtype *v, SItype vprec) +{ + uprec = bitint_reduce_prec (&u, uprec); + vprec = bitint_reduce_prec (&v, vprec); + USItype auprec = uprec < 0 ? -uprec : uprec; + USItype avprec = vprec < 0 ? -vprec : vprec; + + /* Prefer non-negative U. + Otherwise make sure V doesn't have higher precision than U. */ + if ((uprec < 0 && vprec >= 0) + || (avprec > auprec && !(uprec >= 0 && vprec < 0))) + { + SItype p; + const UWtype *t; + p = uprec; uprec = vprec; vprec = p; + p = auprec; auprec = avprec; avprec = p; + t = u; u = v; v = t; + } + + USItype un = auprec / W_TYPE_SIZE; + USItype un2 = (auprec + W_TYPE_SIZE - 1) / W_TYPE_SIZE; + USItype vn = avprec / W_TYPE_SIZE; + USItype vn2 = (avprec + W_TYPE_SIZE - 1) / W_TYPE_SIZE; + USItype retn = ((USItype) retprec + W_TYPE_SIZE - 1) / W_TYPE_SIZE; + USItype retidx, uidx, vidx; + UWtype vv; + /* Indexes of least significant limb. */ +#if __LIBGCC_BITINT_ORDER__ == __ORDER_BIG_ENDIAN__ + retidx = retn - 1; + uidx = un2 - 1; + vidx = vn2 - 1; +#else + retidx = 0; + uidx = 0; + vidx = 0; +#endif + if (__builtin_expect (auprec <= W_TYPE_SIZE, 0) && vprec < 0) + { + UWtype uu = u[uidx]; + if (__builtin_expect (auprec < W_TYPE_SIZE, 0)) + uu &= ((UWtype) 1 << (auprec % W_TYPE_SIZE)) - 1; + if (uu == 0) + { + /* 0 * negative would be otherwise mishandled below, so + handle it specially. */ + __builtin_memset (ret, 0, retn * sizeof (UWtype)); + return; + } + } + vv = v[vidx]; + if (__builtin_expect (avprec < W_TYPE_SIZE, 0)) + { + if (vprec > 0) + vv &= ((UWtype) 1 << (avprec % W_TYPE_SIZE)) - 1; + else + vv |= (UWtype) -1 << (avprec % W_TYPE_SIZE); + } + + USItype n = un > retn ? retn : un; + USItype n2 = n; + USItype retidx2 = retidx + n * BITINT_INC; + UWtype c = 0, uv = 0; + if (n) + c = bitint_mul_1 (ret + retidx, u + uidx, vv, n); + if (retn > un && un2 != un) + { + UWtype hi, lo; + uv = u[uidx + n * BITINT_INC]; + if (uprec > 0) + uv &= ((UWtype) 1 << (auprec % W_TYPE_SIZE)) - 1; + else + uv |= (UWtype) -1 << (auprec % W_TYPE_SIZE); + umul_ppmm (hi, lo, uv, vv); + c = __builtin_add_overflow (lo, c, &lo) + hi; + ret[retidx2] = lo; + retidx2 += BITINT_INC; + ++n2; + } + if (retn > un2) + { + if (uprec < 0) + { + while (n2 < retn) + { + if (n2 >= un2 + vn2) + break; + UWtype hi, lo; + umul_ppmm (hi, lo, (UWtype) -1, vv); + c = __builtin_add_overflow (lo, c, &lo) + hi; + ret[retidx2] = lo; + retidx2 += BITINT_INC; + ++n2; + } + } + else + { + ret[retidx2] = c; + retidx2 += BITINT_INC; + ++n2; + } + /* If RET has more limbs than U after precision reduction, + fill in the remaining limbs. */ + while (n2 < retn) + { + if (n2 < un2 + vn2 || (uprec ^ vprec) >= 0) + c = 0; + else + c = (UWtype) -1; + ret[retidx2] = c; + retidx2 += BITINT_INC; + ++n2; + } + } + /* N is now number of possibly non-zero limbs in RET (ignoring + limbs above UN2 + VN2 which if any have been finalized already). */ + USItype end = vprec < 0 ? un2 + vn2 : vn2; + if (retn > un2 + vn2) retn = un2 + vn2; + if (end > retn) end = retn; + for (USItype m = 1; m < end; ++m) + { + retidx += BITINT_INC; + vidx += BITINT_INC; + if (m < vn2) + { + vv = v[vidx]; + if (__builtin_expect (m == vn, 0)) + { + if (vprec > 0) + vv &= ((UWtype) 1 << (avprec % W_TYPE_SIZE)) - 1; + else + vv |= (UWtype) -1 << (avprec % W_TYPE_SIZE); + } + } + else + vv = (UWtype) -1; + if (m + n > retn) + n = retn - m; + c = 0; + if (n) + c = bitint_addmul_1 (ret + retidx, u + uidx, vv, n); + n2 = m + n; + retidx2 = retidx + n * BITINT_INC; + if (n2 < retn && un2 != un) + { + UWtype hi, lo; + umul_ppmm (hi, lo, uv, vv); + hi += __builtin_add_overflow (lo, ret[retidx2], &lo); + c = __builtin_add_overflow (lo, c, &lo) + hi; + ret[retidx2] = lo; + retidx2 += BITINT_INC; + ++n2; + } + if (uprec < 0) + while (n2 < retn) + { + UWtype hi, lo; + umul_ppmm (hi, lo, (UWtype) -1, vv); + hi += __builtin_add_overflow (lo, ret[retidx2], &lo); + c = __builtin_add_overflow (lo, c, &lo) + hi; + ret[retidx2] = lo; + retidx2 += BITINT_INC; + ++n2; + } + else if (n2 < retn) + { + ret[retidx2] = c; + retidx2 += BITINT_INC; + } + } +} +#endif + +#ifdef L_divmodbitint4 +static void +bitint_negate (UWtype *d, const UWtype *s, SItype n) +{ + UWtype c = 1; + do + { + UWtype sv = *s, lo; + s += BITINT_INC; + c = __builtin_add_overflow (~sv, c, &lo); + *d = lo; + d += BITINT_INC; + } + while (--n); +} + +/* D -= S * L. */ + +static UWtype +bitint_submul_1 (UWtype *d, const UWtype *s, UWtype l, SItype n) +{ + UWtype sv, hi, lo, c = 0; + do + { + sv = *s; + s += BITINT_INC; + umul_ppmm (hi, lo, sv, l); + hi += __builtin_sub_overflow (*d, lo, &lo); + c = __builtin_sub_overflow (lo, c, &lo) + hi; + *d = lo; + d += BITINT_INC; + } + while (--n); + return c; +} + +/* If XPREC is positive, it is precision in bits + of an unsigned _BitInt operand (which has XPREC/W_TYPE_SIZE + full limbs and if Xprec%W_TYPE_SIZE one partial limb. + If Xprec is negative, -XPREC is precision in bits + of a signed _BitInt operand. QPREC and RPREC should be + always non-negative. If either Q or R is NULL (at least + one should be non-NULL), then corresponding QPREC or RPREC + should be 0. */ + +void +__divmodbitint4 (UWtype *q, SItype qprec, + UWtype *r, SItype rprec, + const UWtype *u, SItype uprec, + const UWtype *v, SItype vprec) +{ + uprec = bitint_reduce_prec (&u, uprec); + vprec = bitint_reduce_prec (&v, vprec); + USItype auprec = uprec < 0 ? -uprec : uprec; + USItype avprec = vprec < 0 ? -vprec : vprec; + USItype un = (auprec + W_TYPE_SIZE - 1) / W_TYPE_SIZE; + USItype vn = (avprec + W_TYPE_SIZE - 1) / W_TYPE_SIZE; + USItype qn = ((USItype) qprec + W_TYPE_SIZE - 1) / W_TYPE_SIZE; + USItype rn = ((USItype) rprec + W_TYPE_SIZE - 1) / W_TYPE_SIZE; + USItype up = auprec % W_TYPE_SIZE; + USItype vp = avprec % W_TYPE_SIZE; + if (__builtin_expect (un < vn, 0)) + { + /* If abs(v) > abs(u), then q is 0 and r is u. */ + if (q) + __builtin_memset (q, 0, qn * sizeof (UWtype)); + if (r == NULL) + return; +#if __LIBGCC_BITINT_ORDER__ == __ORDER_BIG_ENDIAN__ + r += rn - 1; + u += un - 1; +#endif + if (up) + --un; + if (rn < un) + un = rn; + for (rn -= un; un; --un) + { + *r = *u; + r += BITINT_INC; + u += BITINT_INC; + } + if (!rn) + return; + if (up) + { + if (uprec > 0) + *r = *u & (((UWtype) 1 << up) - 1); + else + *r = *u | ((UWtype) -1 << up); + r += BITINT_INC; + if (!--rn) + return; + } + UWtype c = uprec < 0 ? (UWtype) -1 : (UWtype) 0; + for (; rn; --rn) + { + *r = c; + r += BITINT_INC; + } + return; + } + USItype qn2 = un - vn + 1; + if (qn >= qn2) + qn2 = 0; + USItype sz = un + 1 + vn + qn2; + UWtype *buf = __builtin_alloca (sz * sizeof (UWtype)); + USItype uidx, vidx; +#if __LIBGCC_BITINT_ORDER__ == __ORDER_BIG_ENDIAN__ + uidx = un - 1; + vidx = vn - 1; +#else + uidx = 0; + vidx = 0; +#endif + if (uprec < 0) + bitint_negate (buf + BITINT_END (uidx + 1, 0), u + uidx, un); + else + __builtin_memcpy (buf + BITINT_END (1, 0), u, un * sizeof (UWtype)); + if (up) + buf[BITINT_END (1, un - 1)] &= (((UWtype) 1 << up) - 1); + if (vprec < 0) + bitint_negate (buf + un + 1 + vidx, v + vidx, vn); + else + __builtin_memcpy (buf + un + 1, v, vn * sizeof (UWtype)); + if (vp) + buf[un + 1 + BITINT_END (0, vn - 1)] &= (((UWtype) 1 << vp) - 1); + UWtype *u2 = buf; + UWtype *v2 = u2 + un + 1; + UWtype *q2 = v2 + vn; + if (!qn2) + q2 = q + BITINT_END (qn - (un - vn + 1), 0); + + /* Knuth's algorithm. See also ../gcc/wide-int.cc (divmod_internal_2). */ + +#ifndef UDIV_NEEDS_NORMALIZATION + /* Handle single limb divisor first. */ + if (vn == 1) + { + UWtype vv = v2[0]; + if (vv == 0) + vv = 1 / vv; /* Divide intentionally by zero. */ + UWtype k = 0; +#if __LIBGCC_BITINT_ORDER__ == __ORDER_BIG_ENDIAN__ + for (SItype i = 0; i <= un - 1; ++i) +#else + for (SItype i = un - 1; i >= 0; --i) +#endif + udiv_qrnnd (q2[i], k, k, u2[BITINT_END (i + 1, i)], vv); + if (r != NULL) + r[BITINT_END (rn - 1, 0)] = k; + } + else +#endif + { + SItype s; +#ifdef UDIV_NEEDS_NORMALIZATION + if (vn == 1 && v2[0] == 0) + s = 0; + else +#endif + if (sizeof (0U) == sizeof (UWtype)) + s = __builtin_clz (v2[BITINT_END (0, vn - 1)]); + else if (sizeof (0UL) == sizeof (UWtype)) + s = __builtin_clzl (v2[BITINT_END (0, vn - 1)]); + else + s = __builtin_clzll (v2[BITINT_END (0, vn - 1)]); + if (s) + { + /* Normalize by shifting v2 left so that it has msb set. */ + const SItype n = sizeof (UWtype) * __CHAR_BIT__; +#if __LIBGCC_BITINT_ORDER__ == __ORDER_BIG_ENDIAN__ + for (SItype i = 0; i < vn - 1; ++i) +#else + for (SItype i = vn - 1; i > 0; --i) +#endif + v2[i] = (v2[i] << s) | (v2[i - BITINT_INC] >> (n - s)); + v2[vidx] = v2[vidx] << s; + /* And shift u2 left by the same amount. */ + u2[BITINT_END (0, un)] = u2[BITINT_END (1, un - 1)] >> (n - s); +#if __LIBGCC_BITINT_ORDER__ == __ORDER_BIG_ENDIAN__ + for (SItype i = 1; i < un; ++i) +#else + for (SItype i = un - 1; i > 0; --i) +#endif + u2[i] = (u2[i] << s) | (u2[i - BITINT_INC] >> (n - s)); + u2[BITINT_END (un, 0)] = u2[BITINT_END (un, 0)] << s; + } + else + u2[BITINT_END (0, un)] = 0; +#ifdef UDIV_NEEDS_NORMALIZATION + /* Handle single limb divisor first. */ + if (vn == 1) + { + UWtype vv = v2[0]; + if (vv == 0) + vv = 1 / vv; /* Divide intentionally by zero. */ + UWtype k = u2[BITINT_END (0, un)]; +#if __LIBGCC_BITINT_ORDER__ == __ORDER_BIG_ENDIAN__ + for (SItype i = 0; i <= un - 1; ++i) +#else + for (SItype i = un - 1; i >= 0; --i) +#endif + udiv_qrnnd (q2[i], k, k, u2[BITINT_END (i + 1, i)], vv); + if (r != NULL) + r[BITINT_END (rn - 1, 0)] = k >> s; + } + else +#endif + { + UWtype vv1 = v2[BITINT_END (0, vn - 1)]; + UWtype vv0 = v2[BITINT_END (1, vn - 2)]; + /* Main loop. */ + for (SItype j = un - vn; j >= 0; --j) + { + /* Compute estimate in qhat. */ + UWtype uv1 = u2[BITINT_END (un - j - vn, j + vn)]; + UWtype uv0 = u2[BITINT_END (un - j - vn + 1, j + vn - 1)]; + UWtype qhat, rhat, hi, lo, c; + if (uv1 >= vv1) + { + /* udiv_qrnnd doesn't support quotients which don't + fit into UWtype, so subtract from uv1:uv0 vv1 + first. */ + uv1 -= vv1 + __builtin_sub_overflow (uv0, vv1, &uv0); + udiv_qrnnd (qhat, rhat, uv1, uv0, vv1); + if (!__builtin_add_overflow (rhat, vv1, &rhat)) + goto again; + } + else + { + udiv_qrnnd (qhat, rhat, uv1, uv0, vv1); + again: + umul_ppmm (hi, lo, qhat, vv0); + if (hi > rhat + || (hi == rhat + && lo > u2[BITINT_END (un - j - vn + 2, + j + vn - 2)])) + { + --qhat; + if (!__builtin_add_overflow (rhat, vv1, &rhat)) + goto again; + } + } + + c = bitint_submul_1 (u2 + BITINT_END (un - j, j), + v2 + BITINT_END (vn - 1, 0), qhat, vn); + u2[BITINT_END (un - j - vn, j + vn)] -= c; + /* If we've subtracted too much, decrease qhat and + and add back. */ + if ((Wtype) u2[BITINT_END (un - j - vn, j + vn)] < 0) + { + --qhat; + c = 0; + for (USItype i = 0; i < vn; ++i) + { + UWtype s = v2[BITINT_END (vn - 1 - i, i)]; + UWtype d = u2[BITINT_END (un - i - j, i + j)]; + UWtype c1 = __builtin_add_overflow (d, s, &d); + UWtype c2 = __builtin_add_overflow (d, c, &d); + c = c1 + c2; + u2[BITINT_END (un - i - j, i + j)] = d; + } + u2[BITINT_END (un - j - vn, j + vn)] += c; + } + q2[BITINT_END (un - vn - j, j)] = qhat; + } + if (r != NULL) + { + if (s) + { + const SItype n = sizeof (UWtype) * __CHAR_BIT__; + /* Unnormalize remainder. */ + USItype i; + for (i = 0; i < vn && i < rn; ++i) + r[BITINT_END (rn - 1 - i, i)] + = ((u2[BITINT_END (un - i, i)] >> s) + | (u2[BITINT_END (un - i - 1, i + 1)] << (n - s))); + if (i < rn) + r[BITINT_END (rn - vn, vn - 1)] + = u2[BITINT_END (un - vn + 1, vn - 1)] >> s; + } + else if (rn > vn) + __builtin_memcpy (&r[BITINT_END (rn - vn, 0)], + &u2[BITINT_END (un + 1 - vn, 0)], + vn * sizeof (UWtype)); + else + __builtin_memcpy (&r[0], &u2[BITINT_END (un + 1 - rn, 0)], + rn * sizeof (UWtype)); + } + } + } + if (q != NULL) + { + if ((uprec < 0) ^ (vprec < 0)) + { + /* Negative quotient. */ + USItype n; + if (un - vn + 1 > qn) + n = qn; + else + n = un - vn + 1; + bitint_negate (q + BITINT_END (qn - 1, 0), + q2 + BITINT_END (un - vn, 0), n); + if (qn > n) + __builtin_memset (q + BITINT_END (0, n), -1, + (qn - n) * sizeof (UWtype)); + } + else + { + /* Positive quotient. */ + if (qn2) + __builtin_memcpy (q, q2 + BITINT_END (un - vn + 1 - qn, 0), + qn * sizeof (UWtype)); + else if (qn > un - vn + 1) + __builtin_memset (q + BITINT_END (0, un - vn + 1), 0, + (qn - (un - vn + 1)) * sizeof (UWtype)); + } + } + if (r != NULL) + { + if (uprec < 0) + { + /* Negative remainder. */ + bitint_negate (r + BITINT_END (rn - 1, 0), + r + BITINT_END (rn - 1, 0), + rn > vn ? vn : rn); + if (rn > vn) + __builtin_memset (r + BITINT_END (0, vn), -1, + (rn - vn) * sizeof (UWtype)); + } + else + { + /* Positive remainder. */ + if (rn > vn) + __builtin_memset (r + BITINT_END (0, vn), 0, + (rn - vn) * sizeof (UWtype)); + } + } +} +#endif +#endif + #ifdef L_cmpdi2 cmp_return_type __cmpdi2 (DWtype a, DWtype b) --- libgcc/libgcc2.h.jj 2023-08-08 15:54:36.075590609 +0200 +++ libgcc/libgcc2.h 2023-08-08 16:12:02.348939532 +0200 @@ -181,6 +181,12 @@ typedef int shift_count_type __attribute #define float bogus_type #define double bogus_type +#if (defined(__BITINT_MAXWIDTH__) \ + && (defined(L_mulbitint3) || defined(L_divmodbitint4))) +#undef LIBGCC2_UNITS_PER_WORD +#define LIBGCC2_UNITS_PER_WORD (__LIBGCC_BITINT_LIMB_WIDTH__ / __CHAR_BIT__) +#endif + /* Versions prior to 3.4.4 were not taking into account the word size for the 5 trapping arithmetic functions absv, addv, subv, mulv and negv. As a consequence, the si and di variants were always and the only ones emitted. @@ -390,6 +396,15 @@ extern DWtype __divmoddi4 (DWtype, DWtyp extern UDWtype __udivmoddi4 (UDWtype, UDWtype, UDWtype *); #endif +#if (defined(__BITINT_MAXWIDTH__) \ + && (defined(L_mulbitint3) || defined(L_divmodbitint4))) +/* _BitInt support. */ +extern void __mulbitint3 (UWtype *, SItype, const UWtype *, SItype, + const UWtype *, SItype); +extern void __divmodbitint4 (UWtype *, SItype, UWtype *, SItype, + const UWtype *, SItype, const UWtype *, SItype); +#endif + /* __negdi2 is static inline when building other libgcc2 portions. */ #if !defined(L_divdi3) && !defined(L_moddi3) extern DWtype __negdi2 (DWtype); --- libgcc/libgcc-std.ver.in.jj 2023-08-08 15:54:36.029591253 +0200 +++ libgcc/libgcc-std.ver.in 2023-08-08 16:12:02.348939532 +0200 @@ -1944,3 +1944,13 @@ GCC_7.0.0 { __PFX__divmoddi4 __PFX__divmodti4 } + +%inherit GCC_14.0.0 GCC_7.0.0 +GCC_14.0.0 { + __PFX__mulbitint3 + __PFX__divmodbitint4 + __PFX__fixsfbitint + __PFX__fixdfbitint + __PFX__floatbitintsf + __PFX__floatbitintdf +} --- libgcc/Makefile.in.jj 2023-08-08 15:54:35.711595707 +0200 +++ libgcc/Makefile.in 2023-08-08 16:12:02.348939532 +0200 @@ -446,7 +446,7 @@ lib2funcs = _muldi3 _negdi2 _lshrdi3 _as _paritysi2 _paritydi2 _powisf2 _powidf2 _powixf2 _powitf2 \ _mulhc3 _mulsc3 _muldc3 _mulxc3 _multc3 _divhc3 _divsc3 \ _divdc3 _divxc3 _divtc3 _bswapsi2 _bswapdi2 _clrsbsi2 \ - _clrsbdi2 + _clrsbdi2 _mulbitint3 # The floating-point conversion routines that involve a single-word integer. # XX stands for the integer mode. @@ -466,7 +466,8 @@ endif # These might cause a divide overflow trap and so are compiled with # unwinder info. LIB2_DIVMOD_FUNCS = _divdi3 _moddi3 _divmoddi4 \ - _udivdi3 _umoddi3 _udivmoddi4 _udiv_w_sdiv + _udivdi3 _umoddi3 _udivmoddi4 _udiv_w_sdiv \ + _divmodbitint4 # Remove any objects from lib2funcs and LIB2_DIVMOD_FUNCS that are # defined as optimized assembly code in LIB1ASMFUNCS or as C code --- libgcc/soft-fp/bitint.h.jj 2023-08-08 16:12:02.348939532 +0200 +++ libgcc/soft-fp/bitint.h 2023-08-08 16:21:45.953768373 +0200 @@ -0,0 +1,329 @@ +/* Software floating-point emulation. + Definitions for _BitInt implementation details. + + Copyright (C) 2023 Free Software Foundation, Inc. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 3, or (at your option) any later +version. + +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +Under Section 7 of GPL version 3, you are granted additional +permissions described in the GCC Runtime Library Exception, version +3.1, as published by the Free Software Foundation. + +You should have received a copy of the GNU General Public License and +a copy of the GCC Runtime Library Exception along with this program; +see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +. */ + +#ifndef GCC_SOFT_FP_BITINT_H +#define GCC_SOFT_FP_BITINT_H + +#ifdef __BITINT_MAXWIDTH__ +#define BIL_UNITS_PER_WORD (__LIBGCC_BITINT_LIMB_WIDTH__ / __CHAR_BIT__) + +#if BIL_UNITS_PER_WORD == 8 +#define BIL_TYPE_SIZE (8 * __CHAR_BIT__) +#define BILtype DItype +#define UBILtype UDItype +#elif BIL_UNITS_PER_WORD == 4 +#define BIL_TYPE_SIZE (4 * __CHAR_BIT__) +#define BILtype SItype +#define UBILtype USItype +#elif BIL_UNITS_PER_WORD == 2 +#define BIL_TYPE_SIZE (2 * __CHAR_BIT__) +#define BILtype HItype +#define UBILtype UHItype +#else +#define BIL_TYPE_SIZE __CHAR_BIT__ +#define BILtype QItype +#define UBILtype UQItype +#endif + +/* If *P is zero or sign extended (the latter only for PREC < 0) from + some narrower _BitInt value, reduce precision. */ + +static inline __attribute__((__always_inline__)) SItype +bitint_reduce_prec (const UBILtype **p, SItype prec) +{ + UBILtype mslimb; + SItype i; + if (prec < 0) + { +#if __LIBGCC_BITINT_ORDER__ == __ORDER_BIG_ENDIAN__ + i = 0; +#else + i = ((USItype) -1 - prec) / BIL_TYPE_SIZE; +#endif + mslimb = (*p)[i]; + if (mslimb & ((UBILtype) 1 << (((USItype) -1 - prec) % BIL_TYPE_SIZE))) + { + SItype n = ((USItype) -prec) % BIL_TYPE_SIZE; + if (n) + { + mslimb |= ((UBILtype) -1 << (((USItype) -1 - prec) % BIL_TYPE_SIZE)); + if (mslimb == (UBILtype) -1) + { + prec += n; + if (prec >= -1) + return -2; +#if __LIBGCC_BITINT_ORDER__ == __ORDER_BIG_ENDIAN__ + ++p; +#else + --i; +#endif + mslimb = (*p)[i]; + n = 0; + } + } + while (mslimb == (UBILtype) -1) + { + prec += BIL_TYPE_SIZE; + if (prec >= -1) + return -2; +#if __LIBGCC_BITINT_ORDER__ == __ORDER_BIG_ENDIAN__ + ++p; +#else + --i; +#endif + mslimb = (*p)[i]; + } + if (n == 0) + { + if ((BILtype) mslimb >= 0) + { +#if __LIBGCC_BITINT_ORDER__ == __ORDER_BIG_ENDIAN__ + --p; +#endif + return prec - 1; + } + } + return prec; + } + else + prec = -prec; + } + else + { +#if __LIBGCC_BITINT_ORDER__ == __ORDER_BIG_ENDIAN__ + i = 0; +#else + i = ((USItype) prec - 1) / BIL_TYPE_SIZE; +#endif + mslimb = (*p)[i]; + } + SItype n = ((USItype) prec) % BIL_TYPE_SIZE; + if (n) + { + mslimb &= ((UBILtype) 1 << (((USItype) prec) % BIL_TYPE_SIZE)) - 1; + if (mslimb == 0) + { + prec -= n; + if (prec == 0) + return 1; +#if __LIBGCC_BITINT_ORDER__ == __ORDER_BIG_ENDIAN__ + ++p; +#else + --i; +#endif + mslimb = (*p)[i]; + } + } + while (mslimb == 0) + { + prec -= BIL_TYPE_SIZE; + if (prec == 0) + return 1; +#if __LIBGCC_BITINT_ORDER__ == __ORDER_BIG_ENDIAN__ + ++p; +#else + --i; +#endif + mslimb = (*p)[i]; + } + return prec; +} + +#if __LIBGCC_BITINT_ORDER__ == __ORDER_BIG_ENDIAN__ +# define BITINT_INC -1 +# define BITINT_END(be, le) (be) +#else +# define BITINT_INC 1 +# define BITINT_END(be, le) (le) +#endif + +static inline __attribute__((__always_inline__)) void +bitint_negate (UBILtype *d, const UBILtype *s, SItype n) +{ + UBILtype c = 1; + do + { + UBILtype sv = *s, lo; + s += BITINT_INC; + c = __builtin_add_overflow (~sv, c, &lo); + *d = lo; + d += BITINT_INC; + } + while (--n); +} + +#define FP_TO_BITINT(r, rn, arprec, shift, rv, rsize, rsigned, ovf, DI) \ + if (ovf) \ + { \ + if ((rv & 1) != 0) \ + __builtin_memset (r, -1, rn * sizeof (UBILtype)); \ + else \ + __builtin_memset (r, 0, rn * sizeof (UBILtype)); \ + if (rv & (((U##DI##type) 1) << (rsize - 1))) \ + r[BITINT_END (0, rn - 1)] \ + |= (UBILtype) -1 << ((arprec - 1) % BIL_TYPE_SIZE); \ + else \ + r[BITINT_END (0, rn - 1)] \ + &= ~((UBILtype) -1 << ((arprec - 1) % BIL_TYPE_SIZE)); \ + } \ + else \ + { \ + USItype shiftl = shift / BIL_TYPE_SIZE; \ + rsize = DI##_BITS; \ + if (rsigned && (DI##type) rv >= 0) \ + rsigned = 0; \ + if (shift + DI##_BITS > arprec) \ + rsize = arprec - shift; \ + USItype shiftr = shift % BIL_TYPE_SIZE; \ + if (shiftl) \ + __builtin_memset (r + BITINT_END (rn - shiftl, 0), 0, \ + shiftl * sizeof (UBILtype)); \ + USItype idx = BITINT_END (rn - shiftl - 1, shiftl); \ + DI##type rvs = rv; \ + if (shiftr) \ + { \ + r[idx] = (rsigned ? (UBILtype) rvs : (UBILtype) rv) << shiftr;\ + idx += BITINT_INC; \ + if (rsize > BIL_TYPE_SIZE - shiftr) \ + { \ + rv >>= BIL_TYPE_SIZE - shiftr; \ + rvs >>= BIL_TYPE_SIZE - shiftr; \ + rsize -= BIL_TYPE_SIZE - shiftr; \ + } \ + else \ + rsize = 0; \ + } \ + while (rsize) \ + { \ + r[idx] = rsigned ? (UBILtype) rvs : (UBILtype) rv; \ + idx += BITINT_INC; \ + if (rsize <= BIL_TYPE_SIZE) \ + break; \ + rv >>= (DI##_BITS > BIL_TYPE_SIZE ? BIL_TYPE_SIZE : 0); \ + rvs >>= (DI##_BITS > BIL_TYPE_SIZE ? BIL_TYPE_SIZE : 0); \ + rsize -= BIL_TYPE_SIZE; \ + } \ + if (idx < rn) \ + __builtin_memset (r + BITINT_END (0, idx), rsigned ? -1 : 0, \ + BITINT_END (idx + 1, rn - idx) \ + * sizeof (UBILtype)); \ + } + +#define FP_FROM_BITINT(i, iprec, iv, shift, DI) \ + do \ + { \ + iprec = bitint_reduce_prec (&i, iprec); \ + USItype aiprec = iprec < 0 ? -iprec : iprec; \ + USItype in = (aiprec + BIL_TYPE_SIZE - 1) / BIL_TYPE_SIZE; \ + USItype idx = BITINT_END (0, in - 1); \ + UBILtype msb = i[idx]; \ + SItype n = 0; \ + if (aiprec % BIL_TYPE_SIZE) \ + { \ + if (iprec > 0) \ + msb &= ((UBILtype) 1 << (aiprec % BIL_TYPE_SIZE)) - 1; \ + else \ + msb |= (UBILtype) -1 << (aiprec % BIL_TYPE_SIZE); \ + } \ + if (iprec < 0) \ + { \ + n = sizeof (0ULL) * __CHAR_BIT__ + 1 - __builtin_clzll (~msb);\ + if (BIL_TYPE_SIZE > DI##_BITS && n > DI##_BITS) \ + { \ + iv = msb >> (n - DI##_BITS); \ + shift = n - DI##_BITS; \ + n = 0; \ + } \ + else \ + { \ + iv = (BILtype) msb; \ + n = DI##_BITS - n; \ + } \ + } \ + /* bitint_reduce_prec guarantees that if msb is 0, then whole \ + i must be zero, otherwise it would have reduced the \ + precision. */ \ + else if (msb == 0) \ + iv = 0; \ + else \ + { \ + n = sizeof (0ULL) * __CHAR_BIT__ - __builtin_clzll (msb); \ + if (BIL_TYPE_SIZE >= DI##_BITS && n >= DI##_BITS) \ + { \ + iv = msb >> (n - DI##_BITS + 1); \ + shift = n - DI##_BITS + 1; \ + n = 0; \ + } \ + else \ + { \ + iv = msb; \ + n = DI##_BITS - 1 - n; \ + } \ + } \ + while (n && BITINT_END (idx < in - 1, idx)) \ + { \ + idx -= BITINT_INC; \ + msb = i[idx]; \ + if (BIL_TYPE_SIZE < DI##_BITS && n >= BIL_TYPE_SIZE) \ + { \ + iv = (U##DI##type) iv << (BIL_TYPE_SIZE < DI##_BITS \ + ? BIL_TYPE_SIZE : 0); \ + iv |= msb; \ + n -= BIL_TYPE_SIZE; \ + } \ + else \ + { \ + iv = (U##DI##type) iv << n; \ + iv |= msb >> (BIL_TYPE_SIZE - n); \ + shift = BIL_TYPE_SIZE - n; \ + break; \ + } \ + } \ + \ + UBILtype low_bits = 0; \ + if (shift) \ + low_bits = msb & (((UBILtype) 1 << shift) - 1); \ + shift += BITINT_END (in - 1 - idx, idx) * BIL_TYPE_SIZE; \ + while (!low_bits && BITINT_END (idx < in - 1, idx)) \ + { \ + idx -= BITINT_INC; \ + low_bits |= i[idx]; \ + } \ + iv |= (low_bits != 0); \ + } \ + while (0) + +extern void __mulbitint3 (UBILtype *, SItype, const UBILtype *, SItype, + const UBILtype *, SItype); +extern void __divmodbitint4 (UBILtype *, SItype, UBILtype *, SItype, + const UBILtype *, SItype, + const UBILtype *, SItype); + +extern USItype __bid_pow10bitint (UBILtype *, SItype, USItype); + +#endif /* __BITINT_MAXWIDTH__ */ + +#endif /* GCC_SOFT_FP_BITINT_H */ --- libgcc/soft-fp/fixdfbitint.c.jj 2023-08-08 16:12:02.348939532 +0200 +++ libgcc/soft-fp/fixdfbitint.c 2023-08-08 16:12:02.348939532 +0200 @@ -0,0 +1,71 @@ +/* Software floating-point emulation. + Convert IEEE double to signed or unsigned _BitInt. + + Copyright (C) 2023 Free Software Foundation, Inc. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 3, or (at your option) any later +version. + +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +Under Section 7 of GPL version 3, you are granted additional +permissions described in the GCC Runtime Library Exception, version +3.1, as published by the Free Software Foundation. + +You should have received a copy of the GNU General Public License and +a copy of the GCC Runtime Library Exception along with this program; +see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +. */ + +#include "soft-fp.h" +#include "double.h" +#include "bitint.h" + +#ifdef __BITINT_MAXWIDTH__ +void +__fixdfbitint (UBILtype *r, SItype rprec, DFtype a) +{ + FP_DECL_EX; + FP_DECL_D (A); + USItype arprec = rprec < 0 ? -rprec : rprec; + USItype rn = ((USItype) arprec + BIL_TYPE_SIZE - 1) / BIL_TYPE_SIZE; + UDItype rv; + USItype rsize = arprec > DI_BITS ? DI_BITS : arprec; + USItype rsigned = rprec < 0; + USItype ovf = 0; + USItype shift = 0; + + FP_INIT_EXCEPTIONS; + FP_UNPACK_RAW_D (A, a); + if (arprec > DI_BITS) + { + if (A_e < _FP_EXPBIAS_D || (A_s && !rsigned)) + ovf = 1; + else if (A_e >= (_FP_EXPMAX_D < _FP_EXPBIAS_D + arprec + ? _FP_EXPMAX_D + : _FP_EXPBIAS_D + arprec - rsigned)) + { + ovf = 1; + if (A_s + && A_e == _FP_EXPBIAS_D + arprec - 1 + && A_e < _FP_EXPMAX_D) + A_e -= arprec - DI_BITS; + } + else if (A_e >= _FP_EXPBIAS_D + DI_BITS - rsigned) + { + shift = A_e - (_FP_EXPBIAS_D + DI_BITS - rsigned - 1); + A_e -= shift; + } + } + FP_TO_INT_D (rv, A, rsize, rsigned); + FP_HANDLE_EXCEPTIONS; + FP_TO_BITINT (r, rn, arprec, shift, rv, rsize, rsigned, ovf, DI); +} +#endif --- libgcc/soft-fp/fixsfbitint.c.jj 2023-08-08 16:12:02.348939532 +0200 +++ libgcc/soft-fp/fixsfbitint.c 2023-08-08 16:12:02.348939532 +0200 @@ -0,0 +1,71 @@ +/* Software floating-point emulation. + Convert IEEE single to signed or unsigned _BitInt. + + Copyright (C) 2023 Free Software Foundation, Inc. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 3, or (at your option) any later +version. + +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +Under Section 7 of GPL version 3, you are granted additional +permissions described in the GCC Runtime Library Exception, version +3.1, as published by the Free Software Foundation. + +You should have received a copy of the GNU General Public License and +a copy of the GCC Runtime Library Exception along with this program; +see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +. */ + +#include "soft-fp.h" +#include "single.h" +#include "bitint.h" + +#ifdef __BITINT_MAXWIDTH__ +void +__fixsfbitint (UBILtype *r, SItype rprec, SFtype a) +{ + FP_DECL_EX; + FP_DECL_S (A); + USItype arprec = rprec < 0 ? -rprec : rprec; + USItype rn = ((USItype) arprec + BIL_TYPE_SIZE - 1) / BIL_TYPE_SIZE; + USItype rv; + USItype rsize = arprec > SI_BITS ? SI_BITS : arprec; + USItype rsigned = rprec < 0; + USItype ovf = 0; + USItype shift = 0; + + FP_INIT_EXCEPTIONS; + FP_UNPACK_RAW_S (A, a); + if (arprec > SI_BITS) + { + if (A_e < _FP_EXPBIAS_S || (A_s && !rsigned)) + ovf = 1; + else if (A_e >= (_FP_EXPMAX_S < _FP_EXPBIAS_S + arprec + ? _FP_EXPMAX_S + : _FP_EXPBIAS_S + arprec - rsigned)) + { + ovf = 1; + if (A_s + && A_e == _FP_EXPBIAS_S + arprec - 1 + && A_e < _FP_EXPMAX_S) + A_e -= arprec - SI_BITS; + } + else if (A_e >= _FP_EXPBIAS_S + SI_BITS - rsigned) + { + shift = A_e - (_FP_EXPBIAS_S + SI_BITS - rsigned - 1); + A_e -= shift; + } + } + FP_TO_INT_S (rv, A, rsize, rsigned); + FP_HANDLE_EXCEPTIONS; + FP_TO_BITINT (r, rn, arprec, shift, rv, rsize, rsigned, ovf, SI); +} +#endif --- libgcc/soft-fp/fixtfbitint.c.jj 2023-08-08 16:12:02.349939518 +0200 +++ libgcc/soft-fp/fixtfbitint.c 2023-08-08 16:12:02.349939518 +0200 @@ -0,0 +1,81 @@ +/* Software floating-point emulation. + Convert IEEE quad to signed or unsigned _BitInt. + + Copyright (C) 2023 Free Software Foundation, Inc. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 3, or (at your option) any later +version. + +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +Under Section 7 of GPL version 3, you are granted additional +permissions described in the GCC Runtime Library Exception, version +3.1, as published by the Free Software Foundation. + +You should have received a copy of the GNU General Public License and +a copy of the GCC Runtime Library Exception along with this program; +see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +. */ + +#include "soft-fp.h" +#include "quad.h" +#include "bitint.h" + +#ifdef __BITINT_MAXWIDTH__ + +#ifndef TI_BITS +/* As mantissa is 112 bits + 1 implicit bit, we need 128-bit + type, but on most 32-bit architectures TImode isn't supported. + Use _BitInt(128) instead. */ +typedef _BitInt(128) TItype; +typedef unsigned _BitInt(128) UTItype; +#define TI_BITS 128 +#endif + +void +__fixtfbitint (UBILtype *r, SItype rprec, TFtype a) +{ + FP_DECL_EX; + FP_DECL_Q (A); + USItype arprec = rprec < 0 ? -rprec : rprec; + USItype rn = ((USItype) arprec + BIL_TYPE_SIZE - 1) / BIL_TYPE_SIZE; + UTItype rv; + USItype rsize = arprec > TI_BITS ? TI_BITS : arprec; + USItype rsigned = rprec < 0; + USItype ovf = 0; + USItype shift = 0; + + FP_INIT_EXCEPTIONS; + FP_UNPACK_RAW_Q (A, a); + if (arprec > TI_BITS) + { + if (A_e < _FP_EXPBIAS_Q || (A_s && !rsigned)) + ovf = 1; + else if (A_e >= (_FP_EXPMAX_Q < _FP_EXPBIAS_Q + arprec + ? _FP_EXPMAX_Q + : _FP_EXPBIAS_Q + arprec - rsigned)) + { + ovf = 1; + if (A_s + && A_e == _FP_EXPBIAS_Q + arprec - 1 + && A_e < _FP_EXPMAX_Q) + A_e -= arprec - TI_BITS; + } + else if (A_e >= _FP_EXPBIAS_Q + TI_BITS - rsigned) + { + shift = A_e - (_FP_EXPBIAS_Q + TI_BITS - rsigned - 1); + A_e -= shift; + } + } + FP_TO_INT_Q (rv, A, rsize, rsigned); + FP_HANDLE_EXCEPTIONS; + FP_TO_BITINT (r, rn, arprec, shift, rv, rsize, rsigned, ovf, TI); +} +#endif --- libgcc/soft-fp/fixxfbitint.c.jj 2023-08-08 16:12:02.349939518 +0200 +++ libgcc/soft-fp/fixxfbitint.c 2023-08-08 16:12:02.349939518 +0200 @@ -0,0 +1,82 @@ +/* Software floating-point emulation. + Convert IEEE extended to signed or unsigned _BitInt. + + Copyright (C) 2023 Free Software Foundation, Inc. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 3, or (at your option) any later +version. + +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +Under Section 7 of GPL version 3, you are granted additional +permissions described in the GCC Runtime Library Exception, version +3.1, as published by the Free Software Foundation. + +You should have received a copy of the GNU General Public License and +a copy of the GCC Runtime Library Exception along with this program; +see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +. */ + +#include "soft-fp.h" +#include "extended.h" +#include "bitint.h" + +#ifdef __BITINT_MAXWIDTH__ + +#ifndef TI_BITS +/* While mantissa is 64 bits including 1 explicit bit, extended.h uses + op-2.h for W_TYPE_SIZE 64 and op-4.h for W_TYPE_SIZE 32, so we have + to use 128-bit type here. On most 32-bit architectures TImode isn't + supported, so use _BitInt(128) instead. */ +typedef _BitInt(128) TItype; +typedef unsigned _BitInt(128) UTItype; +#define TI_BITS 128 +#endif + +void +__fixxfbitint (UBILtype *r, SItype rprec, XFtype a) +{ + FP_DECL_EX; + FP_DECL_E (A); + USItype arprec = rprec < 0 ? -rprec : rprec; + USItype rn = ((USItype) arprec + BIL_TYPE_SIZE - 1) / BIL_TYPE_SIZE; + UTItype rv; + USItype rsize = arprec > TI_BITS ? TI_BITS : arprec; + USItype rsigned = rprec < 0; + USItype ovf = 0; + USItype shift = 0; + + FP_INIT_EXCEPTIONS; + FP_UNPACK_RAW_E (A, a); + if (arprec > TI_BITS) + { + if (A_e < _FP_EXPBIAS_E || (A_s && !rsigned)) + ovf = 1; + else if (A_e >= (_FP_EXPMAX_E < _FP_EXPBIAS_E + arprec + ? _FP_EXPMAX_E + : _FP_EXPBIAS_E + arprec - rsigned)) + { + ovf = 1; + if (A_s + && A_e == _FP_EXPBIAS_E + arprec - 1 + && A_e < _FP_EXPMAX_E) + A_e -= arprec - TI_BITS; + } + else if (A_e >= _FP_EXPBIAS_E + TI_BITS - rsigned) + { + shift = A_e - (_FP_EXPBIAS_E + TI_BITS - rsigned - 1); + A_e -= shift; + } + } + FP_TO_INT_E (rv, A, rsize, rsigned); + FP_HANDLE_EXCEPTIONS; + FP_TO_BITINT (r, rn, arprec, shift, rv, rsize, rsigned, ovf, TI); +} +#endif --- libgcc/soft-fp/floatbitintbf.c.jj 2023-08-08 16:12:02.349939518 +0200 +++ libgcc/soft-fp/floatbitintbf.c 2023-08-08 16:12:02.349939518 +0200 @@ -0,0 +1,59 @@ +/* Software floating-point emulation. + Convert a _BitInt to bfloat16. + + Copyright (C) 2023 Free Software Foundation, Inc. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 3, or (at your option) any later +version. + +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +Under Section 7 of GPL version 3, you are granted additional +permissions described in the GCC Runtime Library Exception, version +3.1, as published by the Free Software Foundation. + +You should have received a copy of the GNU General Public License and +a copy of the GCC Runtime Library Exception along with this program; +see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +. */ + +#include "soft-fp.h" +#include "brain.h" +#include "bitint.h" + +#ifdef __BITINT_MAXWIDTH__ +BFtype +__floatbitintbf (const UBILtype *i, SItype iprec) +{ + SItype iv; + USItype shift = 0; + FP_DECL_EX; + FP_DECL_B (A); + BFtype a; + + FP_FROM_BITINT (i, iprec, iv, shift, SI); + FP_INIT_ROUNDMODE; + FP_FROM_INT_B (A, iv, SI_BITS, USItype); + if (shift) + { + A_e += shift; + if (A_e >= _FP_EXPMAX_B) + { + /* Exponent too big; overflow to infinity. */ + _FP_OVERFLOW_SEMIRAW (B, 1, A); + _FP_PACK_SEMIRAW (B, 1, A); + } + } + FP_PACK_RAW_B (a, A); + FP_HANDLE_EXCEPTIONS; + + return a; +} +#endif --- libgcc/soft-fp/floatbitintdf.c.jj 2023-08-08 16:12:02.349939518 +0200 +++ libgcc/soft-fp/floatbitintdf.c 2023-08-08 16:12:02.349939518 +0200 @@ -0,0 +1,64 @@ +/* Software floating-point emulation. + Convert a _BitInt to IEEE double. + + Copyright (C) 2023 Free Software Foundation, Inc. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 3, or (at your option) any later +version. + +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +Under Section 7 of GPL version 3, you are granted additional +permissions described in the GCC Runtime Library Exception, version +3.1, as published by the Free Software Foundation. + +You should have received a copy of the GNU General Public License and +a copy of the GCC Runtime Library Exception along with this program; +see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +. */ + +#include "soft-fp.h" +#include "double.h" +#include "bitint.h" + +#ifdef __BITINT_MAXWIDTH__ +DFtype +__floatbitintdf (const UBILtype *i, SItype iprec) +{ + DItype iv; + USItype shift = 0; + FP_DECL_EX; + FP_DECL_D (A); + DFtype a; + + FP_FROM_BITINT (i, iprec, iv, shift, DI); + FP_INIT_ROUNDMODE; + FP_FROM_INT_D (A, iv, DI_BITS, UDItype); + if (shift) + { + A_e += shift; + if (A_e >= _FP_EXPMAX_D) + { + /* Exponent too big; overflow to infinity. */ +#if _FP_W_TYPE_SIZE < 64 + _FP_OVERFLOW_SEMIRAW (D, 2, A); + _FP_PACK_SEMIRAW (D, 2, A); +#else + _FP_OVERFLOW_SEMIRAW (D, 1, A); + _FP_PACK_SEMIRAW (D, 1, A); +#endif + } + } + FP_PACK_RAW_D (a, A); + FP_HANDLE_EXCEPTIONS; + + return a; +} +#endif --- libgcc/soft-fp/floatbitinthf.c.jj 2023-08-08 16:12:02.349939518 +0200 +++ libgcc/soft-fp/floatbitinthf.c 2023-08-08 16:12:02.349939518 +0200 @@ -0,0 +1,59 @@ +/* Software floating-point emulation. + Convert a _BitInt to IEEE half. + + Copyright (C) 2023 Free Software Foundation, Inc. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 3, or (at your option) any later +version. + +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +Under Section 7 of GPL version 3, you are granted additional +permissions described in the GCC Runtime Library Exception, version +3.1, as published by the Free Software Foundation. + +You should have received a copy of the GNU General Public License and +a copy of the GCC Runtime Library Exception along with this program; +see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +. */ + +#include "soft-fp.h" +#include "half.h" +#include "bitint.h" + +#ifdef __BITINT_MAXWIDTH__ +HFtype +__floatbitinthf (const UBILtype *i, SItype iprec) +{ + SItype iv; + USItype shift = 0; + FP_DECL_EX; + FP_DECL_H (A); + HFtype a; + + FP_FROM_BITINT (i, iprec, iv, shift, SI); + FP_INIT_ROUNDMODE; + FP_FROM_INT_H (A, iv, SI_BITS, USItype); + if (shift) + { + A_e += shift; + if (A_e >= _FP_EXPMAX_H) + { + /* Exponent too big; overflow to infinity. */ + _FP_OVERFLOW_SEMIRAW (H, 1, A); + _FP_PACK_SEMIRAW (H, 1, A); + } + } + FP_PACK_RAW_H (a, A); + FP_HANDLE_EXCEPTIONS; + + return a; +} +#endif --- libgcc/soft-fp/floatbitintsf.c.jj 2023-08-08 16:12:02.349939518 +0200 +++ libgcc/soft-fp/floatbitintsf.c 2023-08-08 16:12:02.349939518 +0200 @@ -0,0 +1,59 @@ +/* Software floating-point emulation. + Convert a _BitInt to IEEE single. + + Copyright (C) 2023 Free Software Foundation, Inc. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 3, or (at your option) any later +version. + +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +Under Section 7 of GPL version 3, you are granted additional +permissions described in the GCC Runtime Library Exception, version +3.1, as published by the Free Software Foundation. + +You should have received a copy of the GNU General Public License and +a copy of the GCC Runtime Library Exception along with this program; +see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +. */ + +#include "soft-fp.h" +#include "single.h" +#include "bitint.h" + +#ifdef __BITINT_MAXWIDTH__ +SFtype +__floatbitintsf (const UBILtype *i, SItype iprec) +{ + SItype iv; + USItype shift = 0; + FP_DECL_EX; + FP_DECL_S (A); + SFtype a; + + FP_FROM_BITINT (i, iprec, iv, shift, SI); + FP_INIT_ROUNDMODE; + FP_FROM_INT_S (A, iv, SI_BITS, USItype); + if (shift) + { + A_e += shift; + if (A_e >= _FP_EXPMAX_S) + { + /* Exponent too big; overflow to infinity. */ + _FP_OVERFLOW_SEMIRAW (S, 1, A); + _FP_PACK_SEMIRAW (S, 1, A); + } + } + FP_PACK_RAW_S (a, A); + FP_HANDLE_EXCEPTIONS; + + return a; +} +#endif --- libgcc/soft-fp/floatbitinttf.c.jj 2023-08-08 16:12:02.349939518 +0200 +++ libgcc/soft-fp/floatbitinttf.c 2023-08-08 16:12:02.349939518 +0200 @@ -0,0 +1,73 @@ +/* Software floating-point emulation. + Convert a _BitInt to IEEE quad. + + Copyright (C) 2023 Free Software Foundation, Inc. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 3, or (at your option) any later +version. + +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +Under Section 7 of GPL version 3, you are granted additional +permissions described in the GCC Runtime Library Exception, version +3.1, as published by the Free Software Foundation. + +You should have received a copy of the GNU General Public License and +a copy of the GCC Runtime Library Exception along with this program; +see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +. */ + +#include "soft-fp.h" +#include "quad.h" +#include "bitint.h" + +#ifdef __BITINT_MAXWIDTH__ +#ifndef TI_BITS +/* As mantissa is 112 bits + 1 implicit bit, we need 128-bit + type, but on most 32-bit architectures TImode isn't supported. + Use _BitInt(128) instead. */ +typedef _BitInt(128) TItype; +typedef unsigned _BitInt(128) UTItype; +#define TI_BITS 128 +#endif + +TFtype +__floatbitinttf (const UBILtype *i, SItype iprec) +{ + TItype iv; + USItype shift = 0; + FP_DECL_EX; + FP_DECL_Q (A); + TFtype a; + + FP_FROM_BITINT (i, iprec, iv, shift, TI); + FP_INIT_ROUNDMODE; + FP_FROM_INT_Q (A, iv, TI_BITS, UTItype); + if (shift) + { + A_e += shift; + if (A_e >= _FP_EXPMAX_Q) + { + /* Exponent too big; overflow to infinity. */ +#if _FP_W_TYPE_SIZE < 64 + _FP_OVERFLOW_SEMIRAW (Q, 4, A); + _FP_PACK_SEMIRAW (Q, 4, A); +#else + _FP_OVERFLOW_SEMIRAW (Q, 2, A); + _FP_PACK_SEMIRAW (Q, 2, A); +#endif + } + } + FP_PACK_RAW_Q (a, A); + FP_HANDLE_EXCEPTIONS; + + return a; +} +#endif --- libgcc/soft-fp/floatbitintxf.c.jj 2023-08-08 16:12:02.349939518 +0200 +++ libgcc/soft-fp/floatbitintxf.c 2023-08-08 16:12:02.349939518 +0200 @@ -0,0 +1,74 @@ +/* Software floating-point emulation. + Convert a _BitInt to IEEE extended. + + Copyright (C) 2023 Free Software Foundation, Inc. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 3, or (at your option) any later +version. + +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +Under Section 7 of GPL version 3, you are granted additional +permissions described in the GCC Runtime Library Exception, version +3.1, as published by the Free Software Foundation. + +You should have received a copy of the GNU General Public License and +a copy of the GCC Runtime Library Exception along with this program; +see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +. */ + +#include "soft-fp.h" +#include "extended.h" +#include "bitint.h" + +#ifdef __BITINT_MAXWIDTH__ +#ifndef TI_BITS +/* While mantissa is 64 bits including 1 explicit bit, extended.h uses + op-2.h for W_TYPE_SIZE 64 and op-4.h for W_TYPE_SIZE 32, so we have + to use 128-bit type here. On most 32-bit architectures TImode isn't + supported, so use _BitInt(128) instead. */ +typedef _BitInt(128) TItype; +typedef unsigned _BitInt(128) UTItype; +#define TI_BITS 128 +#endif + +XFtype +__floatbitintxf (const UBILtype *i, SItype iprec) +{ + TItype iv; + USItype shift = 0; + FP_DECL_EX; + FP_DECL_E (A); + XFtype a; + + FP_FROM_BITINT (i, iprec, iv, shift, TI); + FP_INIT_ROUNDMODE; + FP_FROM_INT_E (A, iv, TI_BITS, UTItype); + if (shift) + { + A_e += shift; + if (A_e >= _FP_EXPMAX_E) + { + /* Exponent too big; overflow to infinity. */ +#if _FP_W_TYPE_SIZE < 64 + _FP_OVERFLOW_SEMIRAW (E, 4, A); + _FP_PACK_SEMIRAW (E, 4, A); +#else + _FP_OVERFLOW_SEMIRAW (E, 2, A); + _FP_PACK_SEMIRAW (E, 2, A); +#endif + } + } + FP_PACK_RAW_E (a, A); + FP_HANDLE_EXCEPTIONS; + + return a; +} +#endif --- libgcc/soft-fp/op-common.h.jj 2023-08-08 15:54:36.110590119 +0200 +++ libgcc/soft-fp/op-common.h 2023-08-08 16:12:02.349939518 +0200 @@ -1800,7 +1800,7 @@ if ((X##_s = ((r) < 0))) \ _FP_FROM_INT_ur = -_FP_FROM_INT_ur; \ \ - _FP_STATIC_ASSERT ((rsize) <= 2 * _FP_W_TYPE_SIZE, \ + _FP_STATIC_ASSERT ((rsize) <= 4 * _FP_W_TYPE_SIZE, \ "rsize too large"); \ (void) (((rsize) <= _FP_W_TYPE_SIZE) \ ? ({ \ @@ -1810,13 +1810,38 @@ X##_e = (_FP_EXPBIAS_##fs + _FP_W_TYPE_SIZE - 1 \ - _FP_FROM_INT_lz); \ }) \ - : ({ \ + : ((rsize) <= 2 * _FP_W_TYPE_SIZE) \ + ? ({ \ int _FP_FROM_INT_lz; \ __FP_CLZ_2 (_FP_FROM_INT_lz, \ (_FP_W_TYPE) (_FP_FROM_INT_ur \ >> _FP_W_TYPE_SIZE), \ (_FP_W_TYPE) _FP_FROM_INT_ur); \ - X##_e = (_FP_EXPBIAS_##fs + 2 * _FP_W_TYPE_SIZE - 1 \ + X##_e = (_FP_EXPBIAS_##fs \ + + 2 * _FP_W_TYPE_SIZE - 1 \ + - _FP_FROM_INT_lz); \ + }) \ + : ({ \ + int _FP_FROM_INT_lz; \ + if (_FP_FROM_INT_ur >> (2 * _FP_W_TYPE_SIZE)) \ + { \ + rtype _FP_FROM_INT_uru \ + = _FP_FROM_INT_ur >> (2 * _FP_W_TYPE_SIZE); \ + __FP_CLZ_2 (_FP_FROM_INT_lz, \ + (_FP_W_TYPE) (_FP_FROM_INT_uru \ + >> _FP_W_TYPE_SIZE),\ + (_FP_W_TYPE) _FP_FROM_INT_uru); \ + } \ + else \ + { \ + __FP_CLZ_2 (_FP_FROM_INT_lz, \ + (_FP_W_TYPE) (_FP_FROM_INT_ur \ + >> _FP_W_TYPE_SIZE),\ + (_FP_W_TYPE) _FP_FROM_INT_ur); \ + _FP_FROM_INT_lz += 2 * _FP_W_TYPE_SIZE; \ + } \ + X##_e = (_FP_EXPBIAS_##fs \ + + 4 * _FP_W_TYPE_SIZE - 1 \ - _FP_FROM_INT_lz); \ })); \ \ --- libgcc/soft-fp/bitintpow10.c.jj 2023-08-08 16:21:45.956768331 +0200 +++ libgcc/soft-fp/bitintpow10.c 2023-08-09 15:22:45.519805895 +0200 @@ -0,0 +1,132 @@ +/* Software floating-point emulation. + Compute powers of 10 into _BitInt. + + Copyright (C) 2023 Free Software Foundation, Inc. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 3, or (at your option) any later +version. + +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +Under Section 7 of GPL version 3, you are granted additional +permissions described in the GCC Runtime Library Exception, version +3.1, as published by the Free Software Foundation. + +You should have received a copy of the GNU General Public License and +a copy of the GCC Runtime Library Exception along with this program; +see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +. */ + +#include "soft-fp.h" +#include "bitint.h" + +#ifdef __BITINT_MAXWIDTH__ +# define BIL_VAL(x) ((UBILtype) (x)) +# if BIL_TYPE_SIZE == 64 +# define BIL_PAIR(x, y) ((BIL_VAL (x) << 32) | BIL_VAL (y)) +# define BIL_OFF(x, y) (x) +# elif BIL_TYPE_SIZE == 32 +# if __LIBGCC_BITINT_ORDER__ == __ORDER_BIG_ENDIAN__ +# define BIL_PAIR(x, y) BIL_VAL (x), BIL_VAL (y) +# else +# define BIL_PAIR(x, y) BIL_VAL (y), BIL_VAL (x) +# endif +# define BIL_OFF(x, y) (y) +# else +# error Unsupported _BitInt limb size +# endif +#if __LIBGCC_BITINT_ORDER__ == __ORDER_BIG_ENDIAN__ +# define BIL_SET2(a, b) a, b +# define BIL_SET3(a, b, c) a, b, c +# define BIL_SET4(a, b, c, d) a, b, c, d +# define BIL_SET5(a, b, c, d, e) a, b, c, d, e +# define BIL_SET6(a, b, c, d, e, f) a, b, c, d, e, f +# define BIL_SET7(a, b, c, d, e, f, g) a, b, c, d, e, f, g +# define BIL_SET8(a, b, c, d, e, f, g, h) a, b, c, d, e, f, g, h +# define BIL_SET9(a, b, c, d, e, f, g, h, i) a, b, c, d, e, f, g, h, i +# define BIL_SET10(a, b, c, d, e, f, g, h, i, j) a, b, c, d, e, f, g, h, i, j +# define BIL_SET11(a, b, c, d, e, f, g, h, i, j, k) \ + a, b, c, d, e, f, g, h, i, j, k +# define BIL_SET12(a, b, c, d, e, f, g, h, i, j, k, l) \ + a, b, c, d, e, f, g, h, i, j, k, l +# define BIL_SET13(a, b, c, d, e, f, g, h, i, j, k, l, m) \ + a, b, c, d, e, f, g, h, i, j, k, l, m +# define BIL_SET14(a, b, c, d, e, f, g, h, i, j, k, l, m, n) \ + a, b, c, d, e, f, g, h, i, j, k, l, m, n +# define BIL_SET15(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o) \ + a, b, c, d, e, f, g, h, i, j, k, l, m, n, o +#else +# define BIL_SET2(a, b) b, a +# define BIL_SET3(a, b, c) c, b, a +# define BIL_SET4(a, b, c, d) d, c, b, a +# define BIL_SET5(a, b, c, d, e) e, d, c, b, a +# define BIL_SET6(a, b, c, d, e, f) f, e, d, c, b, a +# define BIL_SET7(a, b, c, d, e, f, g) g, f, e, d, c, b, a +# define BIL_SET8(a, b, c, d, e, f, g, h) h, g, f, e, d, c, b, a +# define BIL_SET9(a, b, c, d, e, f, g, h, i) i, h, g, f, e, d, c, b, a +# define BIL_SET10(a, b, c, d, e, f, g, h, i, j) j, i, h, g, f, e, d, c, b, a +# define BIL_SET11(a, b, c, d, e, f, g, h, i, j, k) \ + k, j, i, h, g, f, e, d, c, b, a +# define BIL_SET12(a, b, c, d, e, f, g, h, i, j, k, l) \ + l, k, j, i, h, g, f, e, d, c, b, a +# define BIL_SET13(a, b, c, d, e, f, g, h, i, j, k, l, m) \ + m, l, k, j, i, h, g, f, e, d, c, b, a +# define BIL_SET14(a, b, c, d, e, f, g, h, i, j, k, l, m, n) \ + n, m, l, k, j, i, h, g, f, e, d, c, b, a +# define BIL_SET15(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o) \ + o, n, m, l, k, j, i, h, g, f, e, d, c, b, a +#endif + +#include "bitintpow10.h" + +/* Set r (_BitInt limbs with rprec bits) to pow10 (n), + where n is in [0, 6111]. Returns number of least significant + limbs with just 0s in it. */ + +USItype +__bid_pow10bitint (UBILtype *r, SItype rprec, USItype n) +{ + USItype rn = ((USItype) rprec + BIL_TYPE_SIZE - 1) / BIL_TYPE_SIZE; + if (n <= 256) + { + /* No need to multiply anything, just copy it from pow10_limbs + array. */ + USItype low_zeros = (n / 64) * (64 / BIL_TYPE_SIZE); + UBILtype *p = &pow10_limbs[pow10_offs[n]]; + USItype cnt = pow10_offs[n + 1] - pow10_offs[n]; + if (low_zeros) + __builtin_memset (r + BITINT_END (rn - low_zeros, 0), '\0', + low_zeros * sizeof (UBILtype)); + __builtin_memcpy (r + BITINT_END (rn - low_zeros - cnt, low_zeros), + p, cnt * sizeof (UBILtype)); + if (rn > low_zeros + cnt) + __builtin_memset (r + BITINT_END (0, low_zeros + cnt), '\0', + (rn - low_zeros - cnt) * sizeof (UBILtype)); + return low_zeros; + } + else + { + USItype m = n / 256; + n &= 255; + USItype low_zeros = ((n / 64) + (m * 4)) * (64 / BIL_TYPE_SIZE); + UBILtype *pm = &pow10_limbs[pow10_offs[m + 255]]; + USItype cntm = pow10_offs[m + 256] - pow10_offs[m + 255]; + UBILtype *pn = &pow10_limbs[pow10_offs[n]]; + USItype cntn = pow10_offs[n + 1] - pow10_offs[n]; + if (low_zeros) + __builtin_memset (r + BITINT_END (rn - low_zeros, 0), '\0', + low_zeros * sizeof (UBILtype)); + __mulbitint3 (r + BITINT_END (0, low_zeros), + rprec - low_zeros * BIL_TYPE_SIZE, + pm, cntm * BIL_TYPE_SIZE, pn, cntn * BIL_TYPE_SIZE); + return low_zeros; + } +} +#endif --- libgcc/soft-fp/fixsdbitint.c.jj 2023-08-08 16:21:45.953768373 +0200 +++ libgcc/soft-fp/fixsdbitint.c 2023-08-08 16:21:45.953768373 +0200 @@ -0,0 +1,196 @@ +/* Software floating-point emulation. + Convert _Decimal32 to signed or unsigned _BitInt. + + Copyright (C) 2023 Free Software Foundation, Inc. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 3, or (at your option) any later +version. + +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +Under Section 7 of GPL version 3, you are granted additional +permissions described in the GCC Runtime Library Exception, version +3.1, as published by the Free Software Foundation. + +You should have received a copy of the GNU General Public License and +a copy of the GCC Runtime Library Exception along with this program; +see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +. */ + +#include "soft-fp.h" +#include "bitint.h" + +#ifdef __BITINT_MAXWIDTH__ +extern void __bid_fixsdbitint (UBILtype *, SItype, _Decimal32); + +void +__bid_fixsdbitint (UBILtype *r, SItype rprec, _Decimal32 a) +{ + FP_DECL_EX; + USItype arprec = rprec < 0 ? -rprec : rprec; + USItype rn = (arprec + BIL_TYPE_SIZE - 1) / BIL_TYPE_SIZE; + union { _Decimal32 d; USItype u; } u; + USItype mantissa, t; + SItype sgn; + SItype exponent; + USItype exp_bits, mant_bits; + UBILtype *pow10v, *resv; + USItype pow10_limbs, res_limbs, min_limbs, mant_limbs, low_zeros; + + FP_INIT_EXCEPTIONS; + u.d = a; + t = u.u >> 21; + sgn = (SItype) u.u < 0; + if ((t & (3 << 8)) != (3 << 8)) + { + mantissa = u.u & ((((USItype) 1) << 23) - 1); + exponent = (t >> 2) & 0xff; + } + else if ((t & (3 << 6)) != (3 << 6)) + { + mantissa = u.u & ((((USItype) 1) << 21) - 1); + mantissa |= ((USItype) 1) << 23; + exponent = t & 0xff; + if (mantissa > (USItype) 9999999) + mantissa = 0; + } + else + { + FP_SET_EXCEPTION (FP_EX_INVALID + | FP_EX_INVALID_CVI + | ((FP_EX_INVALID_SNAN + && ((t & 0x20)) != 0) + ? FP_EX_INVALID_SNAN : 0)); + ovf: + if (!sgn) + __builtin_memset (r, -1, rn * sizeof (UBILtype)); + else + __builtin_memset (r, 0, rn * sizeof (UBILtype)); + if (sgn ^ (rprec >= 0)) + r[BITINT_END (0, rn - 1)] + |= (UBILtype) -1 << ((arprec - 1) % BIL_TYPE_SIZE); + else + r[BITINT_END (0, rn - 1)] + &= ~((UBILtype) -1 << ((arprec - 1) % BIL_TYPE_SIZE)); + goto done; + } + exponent -= 101; + + if (mantissa == 0) + { + /* Zero (with any exponent). */ + zero: + __builtin_memset (r, 0, rn * sizeof (UBILtype)); + goto done; + } + if (exponent <= -7) + { + FP_SET_EXCEPTION (FP_EX_INEXACT); + goto zero; + } + else if (exponent < 0) + { + UBILtype limbs[64 / BIL_TYPE_SIZE]; + USItype rem; + UDItype d; + __bid_pow10bitint (limbs, 64, -exponent); +#if BIL_TYPE_SIZE == 64 + d = limbs[0]; +#elif BIL_TYPE_SIZE == 32 + d = (limbs[BITINT_END (0, 1)] << 32) | limbs[BITINT_END (1, 0)]; +#else +# error Unsupported BIL_TYPE_SIZE +#endif + rem = mantissa % (USItype) d; + mantissa /= (USItype) d; + if (rem) + FP_SET_EXCEPTION (FP_EX_INEXACT); + if (mantissa == 0) + goto zero; + exponent = 0; + } + + if (rprec >= 0 && sgn) + { + ovf_ex: + FP_SET_EXCEPTION (FP_EX_INVALID | FP_EX_INVALID_CVI); + goto ovf; + } + + /* Lower estimate for number of bits needed for pow10 (exponent). */ + exp_bits = exponent / 3; + exp_bits = exp_bits * 10 - exp_bits / 29; + mant_bits = sizeof (0ULL) * __CHAR_BIT__ - __builtin_clzll (mantissa); + if (exp_bits + mant_bits > arprec + 1) + goto ovf_ex; + /* Upper estimate for number of bits needed for pow10 (exponent). */ + exp_bits = (exponent + 2) / 3; + exp_bits = exp_bits * 10 - exp_bits / 30; + if (exp_bits == 0) + exp_bits = 1; + pow10_limbs = (exp_bits + BIL_TYPE_SIZE - 1) / BIL_TYPE_SIZE; + pow10v = __builtin_alloca (pow10_limbs * sizeof (UBILtype)); + low_zeros = __bid_pow10bitint (pow10v, exp_bits, exponent); + + res_limbs = ((exp_bits + mant_bits + BIL_TYPE_SIZE - 1) + / BIL_TYPE_SIZE) - low_zeros; + mant_limbs = 1; + resv = __builtin_alloca ((res_limbs + mant_limbs) * sizeof (UBILtype)); + resv[res_limbs] = mantissa; + __mulbitint3 (resv, exp_bits + mant_bits - low_zeros * BIL_TYPE_SIZE, + resv + res_limbs, mant_bits, + pow10v + BITINT_END (0, low_zeros), + exp_bits - low_zeros * BIL_TYPE_SIZE); + if (res_limbs + low_zeros >= rn) + { + if (res_limbs + low_zeros > rn && resv[BITINT_END (0, res_limbs - 1)]) + goto ovf_ex; + if ((arprec % BIL_TYPE_SIZE) != 0 + && (resv[BITINT_END (rn - res_limbs, rn - 1) - low_zeros] + & ((UBILtype) -1 << (arprec % BIL_TYPE_SIZE))) != 0) + goto ovf_ex; + min_limbs = rn - low_zeros; + } + else + min_limbs = res_limbs; + if (low_zeros) + __builtin_memset (r + BITINT_END (rn - low_zeros, 0), '\0', + low_zeros * sizeof (UBILtype)); + if (sgn) + bitint_negate (r + BITINT_END (rn - low_zeros - 1, low_zeros), + resv + BITINT_END (res_limbs - 1, 0), min_limbs); + else + __builtin_memcpy (r + BITINT_END (rn - low_zeros - min_limbs, low_zeros), + resv + BITINT_END (res_limbs - min_limbs, 0), + min_limbs * sizeof (UBILtype)); + if (res_limbs + low_zeros < rn) + { + if (sgn) + __builtin_memset (r + BITINT_END (0, res_limbs + low_zeros), -1, + (rn - res_limbs - low_zeros) * sizeof (UBILtype)); + else + __builtin_memset (r + BITINT_END (0, res_limbs + low_zeros), '\0', + (rn - res_limbs - low_zeros) * sizeof (UBILtype)); + } + else if (sgn) + { + if ((r[BITINT_END (0, rn - 1)] + & ((UBILtype) 1 << ((arprec - 1) % BIL_TYPE_SIZE))) == 0) + goto ovf_ex; + } + else if (rprec < 0 + && (r[BITINT_END (0, rn - 1)] + & ((UBILtype) 1 << ((arprec - 1) % BIL_TYPE_SIZE))) != 0) + goto ovf_ex; + +done: + FP_HANDLE_EXCEPTIONS; +} +#endif --- libgcc/soft-fp/fixddbitint.c.jj 2023-08-08 16:21:45.953768373 +0200 +++ libgcc/soft-fp/fixddbitint.c 2023-08-08 16:21:45.953768373 +0200 @@ -0,0 +1,205 @@ +/* Software floating-point emulation. + Convert _Decimal64 to signed or unsigned _BitInt. + + Copyright (C) 2023 Free Software Foundation, Inc. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 3, or (at your option) any later +version. + +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +Under Section 7 of GPL version 3, you are granted additional +permissions described in the GCC Runtime Library Exception, version +3.1, as published by the Free Software Foundation. + +You should have received a copy of the GNU General Public License and +a copy of the GCC Runtime Library Exception along with this program; +see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +. */ + +#include "soft-fp.h" +#include "bitint.h" + +#ifdef __BITINT_MAXWIDTH__ +extern void __bid_fixddbitint (UBILtype *, SItype, _Decimal64); + +void +__bid_fixddbitint (UBILtype *r, SItype rprec, _Decimal64 a) +{ + FP_DECL_EX; + USItype arprec = rprec < 0 ? -rprec : rprec; + USItype rn = (arprec + BIL_TYPE_SIZE - 1) / BIL_TYPE_SIZE; + union { _Decimal64 d; UDItype u; } u; + UDItype mantissa, t; + SItype sgn; + SItype exponent; + USItype exp_bits, mant_bits; + UBILtype *pow10v, *resv; + USItype pow10_limbs, res_limbs, min_limbs, mant_limbs, low_zeros; + + FP_INIT_EXCEPTIONS; + u.d = a; + t = u.u >> 51; + sgn = (DItype) u.u < 0; + if ((t & (3 << 10)) != (3 << 10)) + { + mantissa = u.u & ((((UDItype) 1) << 53) - 1); + exponent = (t >> 2) & 0x3ff; + } + else if ((t & (3 << 8)) != (3 << 8)) + { + mantissa = u.u & ((((UDItype) 1) << 51) - 1); + mantissa |= ((UDItype) 1) << 53; + exponent = t & 0x3ff; + if (mantissa > (UDItype) 9999999999999999) + mantissa = 0; + } + else + { + FP_SET_EXCEPTION (FP_EX_INVALID + | FP_EX_INVALID_CVI + | ((FP_EX_INVALID_SNAN + && ((t & 0x80)) != 0) + ? FP_EX_INVALID_SNAN : 0)); + ovf: + if (!sgn) + __builtin_memset (r, -1, rn * sizeof (UBILtype)); + else + __builtin_memset (r, 0, rn * sizeof (UBILtype)); + if (sgn ^ (rprec >= 0)) + r[BITINT_END (0, rn - 1)] + |= (UBILtype) -1 << ((arprec - 1) % BIL_TYPE_SIZE); + else + r[BITINT_END (0, rn - 1)] + &= ~((UBILtype) -1 << ((arprec - 1) % BIL_TYPE_SIZE)); + goto done; + } + exponent -= 398; + + if (mantissa == 0) + { + /* Zero (with any exponent). */ + zero: + __builtin_memset (r, 0, rn * sizeof (UBILtype)); + goto done; + } + if (exponent <= -16) + { + FP_SET_EXCEPTION (FP_EX_INEXACT); + goto zero; + } + else if (exponent < 0) + { + UBILtype limbs[64 / BIL_TYPE_SIZE]; + UDItype d, rem; + __bid_pow10bitint (limbs, 64, -exponent); +#if BIL_TYPE_SIZE == 64 + d = limbs[0]; +#elif BIL_TYPE_SIZE == 32 + d = (limbs[BITINT_END (0, 1)] << 32) | limbs[BITINT_END (1, 0)]; +#else +# error Unsupported BIL_TYPE_SIZE +#endif + rem = mantissa % d; + mantissa /= d; + if (rem) + FP_SET_EXCEPTION (FP_EX_INEXACT); + if (mantissa == 0) + goto zero; + exponent = 0; + } + + if (rprec >= 0 && sgn) + { + ovf_ex: + FP_SET_EXCEPTION (FP_EX_INVALID | FP_EX_INVALID_CVI); + goto ovf; + } + + /* Lower estimate for number of bits needed for pow10 (exponent). */ + exp_bits = exponent / 3; + exp_bits = exp_bits * 10 - exp_bits / 29; + mant_bits = sizeof (0ULL) * __CHAR_BIT__ - __builtin_clzll (mantissa); + if (exp_bits + mant_bits > arprec + 1) + goto ovf_ex; + /* Upper estimate for number of bits needed for pow10 (exponent). */ + exp_bits = (exponent + 2) / 3; + exp_bits = exp_bits * 10 - exp_bits / 30; + if (exp_bits == 0) + exp_bits = 1; + pow10_limbs = (exp_bits + BIL_TYPE_SIZE - 1) / BIL_TYPE_SIZE; + pow10v = __builtin_alloca (pow10_limbs * sizeof (UBILtype)); + low_zeros = __bid_pow10bitint (pow10v, exp_bits, exponent); + + res_limbs = ((exp_bits + mant_bits + BIL_TYPE_SIZE - 1) + / BIL_TYPE_SIZE) - low_zeros; + mant_limbs = (mant_bits + BIL_TYPE_SIZE - 1) / BIL_TYPE_SIZE; + resv = __builtin_alloca ((res_limbs + mant_limbs) * sizeof (UBILtype)); +#if BIL_TYPE_SIZE >= 64 + resv[res_limbs] = mantissa; +#else + if (mant_limbs == 1) + resv[res_limbs] = mantissa; + else + { + resv[res_limbs + BITINT_END (1, 0)] = mantissa; + resv[res_limbs + BITINT_END (0, 1)] = mantissa >> 32; + } +#endif + __mulbitint3 (resv, exp_bits + mant_bits - low_zeros * BIL_TYPE_SIZE, + resv + res_limbs, mant_bits, + pow10v + BITINT_END (0, low_zeros), + exp_bits - low_zeros * BIL_TYPE_SIZE); + if (res_limbs + low_zeros >= rn) + { + if (res_limbs + low_zeros > rn && resv[BITINT_END (0, res_limbs - 1)]) + goto ovf_ex; + if ((arprec % BIL_TYPE_SIZE) != 0 + && (resv[BITINT_END (rn - res_limbs, rn - 1) - low_zeros] + & ((UBILtype) -1 << (arprec % BIL_TYPE_SIZE))) != 0) + goto ovf_ex; + min_limbs = rn - low_zeros; + } + else + min_limbs = res_limbs; + if (low_zeros) + __builtin_memset (r + BITINT_END (rn - low_zeros, 0), '\0', + low_zeros * sizeof (UBILtype)); + if (sgn) + bitint_negate (r + BITINT_END (rn - low_zeros - 1, low_zeros), + resv + BITINT_END (res_limbs - 1, 0), min_limbs); + else + __builtin_memcpy (r + BITINT_END (rn - low_zeros - min_limbs, low_zeros), + resv + BITINT_END (res_limbs - min_limbs, 0), + min_limbs * sizeof (UBILtype)); + if (res_limbs + low_zeros < rn) + { + if (sgn) + __builtin_memset (r + BITINT_END (0, res_limbs + low_zeros), -1, + (rn - res_limbs - low_zeros) * sizeof (UBILtype)); + else + __builtin_memset (r + BITINT_END (0, res_limbs + low_zeros), '\0', + (rn - res_limbs - low_zeros) * sizeof (UBILtype)); + } + else if (sgn) + { + if ((r[BITINT_END (0, rn - 1)] + & ((UBILtype) 1 << ((arprec - 1) % BIL_TYPE_SIZE))) == 0) + goto ovf_ex; + } + else if (rprec < 0 + && (r[BITINT_END (0, rn - 1)] + & ((UBILtype) 1 << ((arprec - 1) % BIL_TYPE_SIZE))) != 0) + goto ovf_ex; + +done: + FP_HANDLE_EXCEPTIONS; +} +#endif --- libgcc/soft-fp/fixtdbitint.c.jj 2023-08-08 16:21:45.953768373 +0200 +++ libgcc/soft-fp/fixtdbitint.c 2023-08-08 16:21:45.953768373 +0200 @@ -0,0 +1,242 @@ +/* Software floating-point emulation. + Convert _Decimal128 to signed or unsigned _BitInt. + + Copyright (C) 2023 Free Software Foundation, Inc. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 3, or (at your option) any later +version. + +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +Under Section 7 of GPL version 3, you are granted additional +permissions described in the GCC Runtime Library Exception, version +3.1, as published by the Free Software Foundation. + +You should have received a copy of the GNU General Public License and +a copy of the GCC Runtime Library Exception along with this program; +see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +. */ + +#include "soft-fp.h" +#include "bitint.h" + +#ifdef __BITINT_MAXWIDTH__ +extern void __bid_fixtdbitint (UBILtype *, SItype, _Decimal128); + +void +__bid_fixtdbitint (UBILtype *r, SItype rprec, _Decimal128 a) +{ + FP_DECL_EX; + USItype arprec = rprec < 0 ? -rprec : rprec; + USItype rn = (arprec + BIL_TYPE_SIZE - 1) / BIL_TYPE_SIZE; + union { _Decimal128 d; UDItype u[2]; } u; + UDItype mantissahi, mantissalo, t; + SItype sgn; + SItype exponent; + USItype exp_bits, mant_bits; + UBILtype *pow10v, *resv; + USItype pow10_limbs, res_limbs, min_limbs, mant_limbs, low_zeros; + + FP_INIT_EXCEPTIONS; + u.d = a; + mantissahi = u.u[__FLOAT_WORD_ORDER__ != __ORDER_BIG_ENDIAN__]; + mantissalo = u.u[__FLOAT_WORD_ORDER__ == __ORDER_BIG_ENDIAN__]; + t = mantissahi >> 47; + sgn = (DItype) mantissahi < 0; + if ((t & (3 << 14)) != (3 << 14)) + { + mantissahi &= ((((UDItype) 1) << 49) - 1); + exponent = (t >> 2) & 0x3fff; + if (mantissahi > (UDItype) 0x1ed09bead87c0 + || (mantissahi == (UDItype) 0x1ed09bead87c0 + && mantissalo > 0x378d8e63ffffffff)) + { + mantissahi = 0; + mantissalo = 0; + } + } + else if ((t & (3 << 12)) != (3 << 12)) + { + mantissahi = 0; + mantissalo = 0; + exponent = t & 0x3fff; + } + else + { + FP_SET_EXCEPTION (FP_EX_INVALID + | FP_EX_INVALID_CVI + | ((FP_EX_INVALID_SNAN + && ((t & 0x800)) != 0) + ? FP_EX_INVALID_SNAN : 0)); + ovf: + if (!sgn) + __builtin_memset (r, -1, rn * sizeof (UBILtype)); + else + __builtin_memset (r, 0, rn * sizeof (UBILtype)); + if (sgn ^ (rprec >= 0)) + r[BITINT_END (0, rn - 1)] + |= (UBILtype) -1 << ((arprec - 1) % BIL_TYPE_SIZE); + else + r[BITINT_END (0, rn - 1)] + &= ~((UBILtype) -1 << ((arprec - 1) % BIL_TYPE_SIZE)); + goto done; + } + exponent -= 6176; + + if (mantissahi == 0 && mantissalo == 0) + { + /* Zero (with any exponent). */ + zero: + __builtin_memset (r, 0, rn * sizeof (UBILtype)); + goto done; + } + if (exponent <= -34) + { + FP_SET_EXCEPTION (FP_EX_INEXACT); + goto zero; + } + if (exponent < 0) + { + UBILtype limbs[4 * 128 / BIL_TYPE_SIZE]; +#if BIL_TYPE_SIZE == 64 + limbs[BITINT_END (0, 1)] = mantissahi; + limbs[BITINT_END (1, 0)] = mantissalo; +#elif BIL_TYPE_SIZE == 32 + limbs[BITINT_END (0, 3)] = mantissahi >> 32; + limbs[BITINT_END (1, 2)] = mantissahi; + limbs[BITINT_END (2, 1)] = mantissalo >> 32; + limbs[BITINT_END (3, 0)] = mantissalo; +#elif +# error Unhandled BIL_TYPE_SIZE +#endif + __bid_pow10bitint (&limbs[128 / BIL_TYPE_SIZE], 128, -exponent); + __divmodbitint4 (&limbs[2 * 128 / BIL_TYPE_SIZE], 128, + &limbs[3 * 128 / BIL_TYPE_SIZE], 128, + &limbs[0], 128, &limbs[128 / BIL_TYPE_SIZE], 128); + UDItype rem; +#if BIL_TYPE_SIZE == 64 + mantissahi = limbs[BITINT_END (4, 5)]; + mantissalo = limbs[BITINT_END (5, 4)]; + rem = limbs[6] | limbs[7]; +#elif BIL_TYPE_SIZE == 32 + mantissahi = limbs[BITINT_END (8, 11)] << 32; + mantissahi |= limbs[BITINT_END (9, 10)]; + mantissalo = limbs[BITINT_END (10, 9)] << 32; + mantissalo |= limbs[BITINT_END (11, 8)]; + rem = limbs[12] | limbs[13] | limbs[14] | limbs[15]; +#endif + if (rem) + FP_SET_EXCEPTION (FP_EX_INEXACT); + if (mantissahi == 0 && mantissalo == 0) + goto zero; + exponent = 0; + } + + if (rprec >= 0 && sgn) + { + ovf_ex: + FP_SET_EXCEPTION (FP_EX_INVALID | FP_EX_INVALID_CVI); + goto ovf; + } + + /* Lower estimate for number of bits needed for pow10 (exponent). */ + exp_bits = exponent / 3; + exp_bits = exp_bits * 10 - exp_bits / 29; + if (mantissahi) + mant_bits = sizeof (0ULL) * __CHAR_BIT__ - __builtin_clzll (mantissahi) + + 64; + else + mant_bits = sizeof (0ULL) * __CHAR_BIT__ - __builtin_clzll (mantissalo); + if (exp_bits + mant_bits > arprec + 1) + goto ovf_ex; + /* Upper estimate for number of bits needed for pow10 (exponent). */ + exp_bits = (exponent + 2) / 3; + exp_bits = exp_bits * 10 - exp_bits / 30; + if (exp_bits == 0) + exp_bits = 1; + pow10_limbs = (exp_bits + BIL_TYPE_SIZE - 1) / BIL_TYPE_SIZE; + pow10v = __builtin_alloca (pow10_limbs * sizeof (UBILtype)); + low_zeros = __bid_pow10bitint (pow10v, exp_bits, exponent); + + res_limbs = ((exp_bits + mant_bits + BIL_TYPE_SIZE - 1) + / BIL_TYPE_SIZE) - low_zeros; + mant_limbs = (mant_bits + BIL_TYPE_SIZE - 1) / BIL_TYPE_SIZE; + resv = __builtin_alloca ((res_limbs + mant_limbs) * sizeof (UBILtype)); +#if BIL_TYPE_SIZE >= 64 + if (mant_limbs == 1) + resv[res_limbs] = mantissalo; + else + { + resv[res_limbs + BITINT_END (1, 0)] = mantissalo; + resv[res_limbs + BITINT_END (0, 1)] = mantissahi; + } +#else + resv[res_limbs + BITINT_END (mant_limbs - 1, 0)] = mantissalo; + if (mant_limbs >= 2) + { + resv[res_limbs + BITINT_END (mant_limbs - 2, 1)] = mantissalo >> 32; + if (mant_limbs >= 3) + { + resv[res_limbs + BITINT_END (mant_limbs - 3, 2)] = mantissahi; + if (mant_limbs == 4) + resv[res_limbs + BITINT_END (0, 3)] = mantissahi >> 32; + } + } +#endif + __mulbitint3 (resv, exp_bits + mant_bits - low_zeros * BIL_TYPE_SIZE, + resv + res_limbs, mant_bits, + pow10v + BITINT_END (0, low_zeros), + exp_bits - low_zeros * BIL_TYPE_SIZE); + if (res_limbs + low_zeros >= rn) + { + if (res_limbs + low_zeros > rn && resv[BITINT_END (0, res_limbs - 1)]) + goto ovf_ex; + if ((arprec % BIL_TYPE_SIZE) != 0 + && (resv[BITINT_END (rn - res_limbs, rn - 1) - low_zeros] + & ((UBILtype) -1 << (arprec % BIL_TYPE_SIZE))) != 0) + goto ovf_ex; + min_limbs = rn - low_zeros; + } + else + min_limbs = res_limbs; + if (low_zeros) + __builtin_memset (r + BITINT_END (rn - low_zeros, 0), '\0', + low_zeros * sizeof (UBILtype)); + if (sgn) + bitint_negate (r + BITINT_END (rn - low_zeros - 1, low_zeros), + resv + BITINT_END (res_limbs - 1, 0), min_limbs); + else + __builtin_memcpy (r + BITINT_END (rn - low_zeros - min_limbs, low_zeros), + resv + BITINT_END (res_limbs - min_limbs, 0), + min_limbs * sizeof (UBILtype)); + if (res_limbs + low_zeros < rn) + { + if (sgn) + __builtin_memset (r + BITINT_END (0, res_limbs + low_zeros), -1, + (rn - res_limbs - low_zeros) * sizeof (UBILtype)); + else + __builtin_memset (r + BITINT_END (0, res_limbs + low_zeros), '\0', + (rn - res_limbs - low_zeros) * sizeof (UBILtype)); + } + else if (sgn) + { + if ((r[BITINT_END (0, rn - 1)] + & ((UBILtype) 1 << ((arprec - 1) % BIL_TYPE_SIZE))) == 0) + goto ovf_ex; + } + else if (rprec < 0 + && (r[BITINT_END (0, rn - 1)] + & ((UBILtype) 1 << ((arprec - 1) % BIL_TYPE_SIZE))) != 0) + goto ovf_ex; + +done: + FP_HANDLE_EXCEPTIONS; +} +#endif --- libgcc/soft-fp/floatbitintsd.c.jj 2023-08-08 16:22:09.405440134 +0200 +++ libgcc/soft-fp/floatbitintsd.c 2023-08-08 16:22:09.405440134 +0200 @@ -0,0 +1,235 @@ +/* Software floating-point emulation. + Convert a _BitInt to _Decimal32. + + Copyright (C) 2023 Free Software Foundation, Inc. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 3, or (at your option) any later +version. + +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +Under Section 7 of GPL version 3, you are granted additional +permissions described in the GCC Runtime Library Exception, version +3.1, as published by the Free Software Foundation. + +You should have received a copy of the GNU General Public License and +a copy of the GCC Runtime Library Exception along with this program; +see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +. */ + +#include "soft-fp.h" +#include "bitint.h" + +#ifdef __BITINT_MAXWIDTH__ +extern _Decimal32 __bid_floatbitintsd (const UBILtype *, SItype); + +_Decimal32 +__bid_floatbitintsd (const UBILtype *i, SItype iprec) +{ + iprec = bitint_reduce_prec (&i, iprec); + USItype aiprec = iprec < 0 ? -iprec : iprec; + USItype in = (aiprec + BIL_TYPE_SIZE - 1) / BIL_TYPE_SIZE; + USItype idx = BITINT_END (0, in - 1); + UBILtype msb = i[idx]; + USItype mantissa; + SItype exponent = 0; + UBILtype inexact = 0; + union { _Decimal32 d; USItype u; } u, ui; + if (aiprec % BIL_TYPE_SIZE) + { + if (iprec > 0) + msb &= ((UBILtype) 1 << (aiprec % BIL_TYPE_SIZE)) - 1; + else + msb |= (UBILtype) -1 << (aiprec % BIL_TYPE_SIZE); + } + if (iprec < 0) + { + SItype n = sizeof (0ULL) * __CHAR_BIT__ + 1 - __builtin_clzll (~msb); + aiprec = (in - 1) * BIL_TYPE_SIZE + n; + } + else if (msb == 0) + aiprec = 1; + else + { + SItype n = sizeof (0ULL) * __CHAR_BIT__ - __builtin_clzll (msb); + aiprec = (in - 1) * BIL_TYPE_SIZE + n; + } + /* Number of bits in (_BitInt(2048)) 9999999e+90DF. */ + if (aiprec > 323 + (iprec < 0)) + { + ovf: + if (iprec < 0) + u.d = -9000000e+90DF; + else + u.d = 9000000e+90DF; + __asm ("" : "+g" (u.d)); + u.d += u.d; + __asm ("" : "+g" (u.d)); + goto done; + } + /* Bit precision of 9999999uwb. */ + if (aiprec >= 24) + { + USItype pow10_limbs, q_limbs, q2_limbs, j; + USItype exp_bits = 0, e; + UDItype m; + UBILtype *buf; + /* First do a possibly large divide smaller enough such that + we only need to check remainder for 0 or non-0 and then + we'll do further division. */ + if (aiprec >= 24 + 4 + 10) + { + exp_bits = (aiprec - 24 - 4) / 10; + exponent = exp_bits * 3; + /* Upper estimate for pow10 (exponent) bits. */ + exp_bits = exp_bits * 10 - exp_bits / 30; + } + pow10_limbs = (exp_bits + BIL_TYPE_SIZE - 1) / BIL_TYPE_SIZE; + /* 38 is the highest number of quotient bits needed on + aiprec range of [38, 323]. E.g. if aiprec is 317, + exponent will be 84 and exp_bits 280. 317 - 280 + 1 + is 38. */ + q_limbs = (38 + BIL_TYPE_SIZE - 1) / BIL_TYPE_SIZE; + q2_limbs = (32 + BIL_TYPE_SIZE - 1) / BIL_TYPE_SIZE; + buf = __builtin_alloca ((q_limbs + pow10_limbs * 2 + q2_limbs + 2) + * sizeof (UBILtype)); + if (exponent) + { + __bid_pow10bitint (buf + q_limbs, exp_bits, exponent); + __divmodbitint4 (buf, q_limbs * BIL_TYPE_SIZE, + buf + q_limbs + pow10_limbs, + pow10_limbs * BIL_TYPE_SIZE, + i, iprec < 0 ? -aiprec : aiprec, + buf + q_limbs, exp_bits); + if (iprec < 0) + bitint_negate (buf + BITINT_END (q_limbs - 1, 0), + buf + BITINT_END (q_limbs - 1, 0), q_limbs); + inexact = buf[q_limbs + pow10_limbs]; + for (j = 1; j < pow10_limbs; ++j) + inexact |= buf[q_limbs + pow10_limbs + 1]; + } + else + { + __builtin_memcpy (buf + BITINT_END (q_limbs - in + 1, 0), i, + (in - 1) * sizeof (UBILtype)); + buf[BITINT_END (q_limbs - in, in - 1)] = msb; + if (iprec < 0) + bitint_negate (buf + BITINT_END (q_limbs - 1, 0), + buf + BITINT_END (q_limbs - 1, 0), in); + if (q_limbs > in) + __builtin_memset (buf + BITINT_END (0, in), '\0', + (q_limbs - in) * sizeof (UBILtype)); + } + e = 0; +#if BIL_TYPE_SIZE == 64 + m = buf[0]; +#elif BIL_TYPE_SIZE == 32 + m = ((UDItype) buf[BITINT_END (0, 1)] << 32) | buf[BITINT_END (1, 0)]; +#else +# error Unsupported BIL_TYPE_SIZE +#endif + if (m >= (UDItype) 10000000000) + { + if (m >= (UDItype) 100000000000) + e = 5; + else + e = 4; + } + else if (m >= (UDItype) 100000000) + { + if (m >= (UDItype) 1000000000) + e = 3; + else + e = 2; + } + else if (m >= (UDItype) 10000000) + e = 1; + exponent += e; + if (exponent > 90) + goto ovf; + if (e) + { + UBILtype rem, half; + __bid_pow10bitint (buf + q_limbs + pow10_limbs * 2, + BIL_TYPE_SIZE, e); + __divmodbitint4 (buf + q_limbs + pow10_limbs * 2 + 1, + q2_limbs * BIL_TYPE_SIZE, + buf + q_limbs + pow10_limbs * 2 + 1 + q2_limbs, + BIL_TYPE_SIZE, + buf, q_limbs * BIL_TYPE_SIZE, + buf + q_limbs + pow10_limbs * 2, BIL_TYPE_SIZE); + half = buf[q_limbs + pow10_limbs * 2] / 2; + rem = buf[q_limbs + pow10_limbs * 2 + 1 + q2_limbs]; + if (inexact) + { + /* If first division discovered some non-0 digits + and this second division is by 10, e.g. + for XXXXXX5499999999999 or XXXXXX5000000000001 + if first division is by 10^12 and second by 10^1, + doing rem |= 1 wouldn't change the 5. Similarly + for rem 4 doing rem |= 1 would change it to 5, + but we don't want to change it in that case. */ + if (e == 1) + { + if (rem == 5) + rem = 6; + else if (rem != 4) + rem |= 1; + } + else + rem |= 1; + } + /* Set inexact to 0, 1, 2, 3 depending on if remainder + of the divisions is exact 0, smaller than 10^exponent / 2, + exactly 10^exponent / 2 or greater than that. */ + if (rem >= half) + inexact = 2 + (rem > half); + else + inexact = (rem != 0); + mantissa = buf[q_limbs + pow10_limbs * 2 + 1]; + } + else +#if BIL_TYPE_SIZE == 64 + mantissa = buf[0]; +#else + mantissa = buf[BITINT_END (1, 0)]; +#endif + } + else + { + mantissa = msb; + if (iprec < 0) + mantissa = -mantissa; + } + + exponent += 101; + if (mantissa >= (USItype) 0x800000) + u.u = (((((iprec < 0) << 2) | (USItype) 3) << 29) + | (((USItype) exponent) << 21) + | (mantissa ^ (USItype) 0x800000)); + else + u.u = ((((USItype) (iprec < 0)) << 31) + | (((USItype) exponent) << 23) + | mantissa); + if (inexact) + { + ui.u = ((((USItype) (iprec < 0)) << 31) + | (((USItype) (exponent - 1)) << 23) + | (inexact + 3)); + __asm ("" : "+g" (u.d)); + __asm ("" : "+g" (ui.d)); + u.d += ui.d; + __asm ("" : "+g" (u.d)); + } + +done: + return u.d; +} +#endif --- libgcc/soft-fp/floatbitintdd.c.jj 2023-08-08 16:22:09.405440134 +0200 +++ libgcc/soft-fp/floatbitintdd.c 2023-08-08 16:22:09.405440134 +0200 @@ -0,0 +1,264 @@ +/* Software floating-point emulation. + Convert a _BitInt to _Decimal64. + + Copyright (C) 2023 Free Software Foundation, Inc. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 3, or (at your option) any later +version. + +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +Under Section 7 of GPL version 3, you are granted additional +permissions described in the GCC Runtime Library Exception, version +3.1, as published by the Free Software Foundation. + +You should have received a copy of the GNU General Public License and +a copy of the GCC Runtime Library Exception along with this program; +see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +. */ + +#include "soft-fp.h" +#include "bitint.h" + +#ifdef __BITINT_MAXWIDTH__ +extern _Decimal64 __bid_floatbitintdd (const UBILtype *, SItype); + +_Decimal64 +__bid_floatbitintdd (const UBILtype *i, SItype iprec) +{ + iprec = bitint_reduce_prec (&i, iprec); + USItype aiprec = iprec < 0 ? -iprec : iprec; + USItype in = (aiprec + BIL_TYPE_SIZE - 1) / BIL_TYPE_SIZE; + USItype idx = BITINT_END (0, in - 1); + UBILtype msb = i[idx]; + UDItype mantissa; + SItype exponent = 0; + UBILtype inexact = 0; + union { _Decimal64 d; UDItype u; } u, ui; + if (aiprec % BIL_TYPE_SIZE) + { + if (iprec > 0) + msb &= ((UBILtype) 1 << (aiprec % BIL_TYPE_SIZE)) - 1; + else + msb |= (UBILtype) -1 << (aiprec % BIL_TYPE_SIZE); + } + if (iprec < 0) + { + SItype n = sizeof (0ULL) * __CHAR_BIT__ + 1 - __builtin_clzll (~msb); + aiprec = (in - 1) * BIL_TYPE_SIZE + n; + } + else if (msb == 0) + aiprec = 1; + else + { + SItype n = sizeof (0ULL) * __CHAR_BIT__ - __builtin_clzll (msb); + aiprec = (in - 1) * BIL_TYPE_SIZE + n; + } + /* Number of bits in (_BitInt(2048)) 9999999999999999e+369DD. */ + if (aiprec > 1279 + (iprec < 0)) + { + ovf: + if (iprec < 0) + u.d = -9000000000000000e+369DD; + else + u.d = 9000000000000000e+369DD; + __asm ("" : "+g" (u.d)); + u.d += u.d; + __asm ("" : "+g" (u.d)); + goto done; + } + /* Bit precision of 9999999999999999uwb. */ + if (aiprec >= 54) + { + USItype pow10_limbs, q_limbs, q2_limbs, j; + USItype exp_bits = 0, e; + UDItype m; + UBILtype *buf; + /* First do a possibly large divide smaller enough such that + we only need to check remainder for 0 or non-0 and then + we'll do further division. */ + if (aiprec >= 54 + 4 + 10) + { + exp_bits = (aiprec - 54 - 4) / 10; + exponent = exp_bits * 3; + /* Upper estimate for pow10 (exponent) bits. */ + exp_bits = exp_bits * 10 - exp_bits / 30; + } + pow10_limbs = (exp_bits + BIL_TYPE_SIZE - 1) / BIL_TYPE_SIZE; + /* 72 is the highest number of quotient bits needed on + aiprec range of [68, 1279]. E.g. if aiprec is 1277, + exponent will be 363 and exp_bits 1206. 1277 - 1206 + 1 + is 72. Unfortunately that means the result doesn't fit into + UDItype... */ + q_limbs = (72 + BIL_TYPE_SIZE - 1) / BIL_TYPE_SIZE; + q2_limbs = 64 / BIL_TYPE_SIZE; + buf = __builtin_alloca ((q_limbs + pow10_limbs * 2 + q2_limbs + 2) + * sizeof (UBILtype)); + if (exponent) + { + __bid_pow10bitint (buf + q_limbs, exp_bits, exponent); + __divmodbitint4 (buf, q_limbs * BIL_TYPE_SIZE, + buf + q_limbs + pow10_limbs, + pow10_limbs * BIL_TYPE_SIZE, + i, iprec < 0 ? -aiprec : aiprec, + buf + q_limbs, exp_bits); + if (iprec < 0) + bitint_negate (buf + BITINT_END (q_limbs - 1, 0), + buf + BITINT_END (q_limbs - 1, 0), q_limbs); + inexact = buf[q_limbs + pow10_limbs]; + for (j = 1; j < pow10_limbs; ++j) + inexact |= buf[q_limbs + pow10_limbs + 1]; + } + else + { + __builtin_memcpy (buf + BITINT_END (q_limbs - in + 1, 0), i, + (in - 1) * sizeof (UBILtype)); + buf[BITINT_END (q_limbs - in, in - 1)] = msb; + if (iprec < 0) + bitint_negate (buf + BITINT_END (q_limbs - 1, 0), + buf + BITINT_END (q_limbs - 1, 0), in); + if (q_limbs > in) + __builtin_memset (buf + BITINT_END (0, in), '\0', + (q_limbs - in) * sizeof (UBILtype)); + } + e = 0; +#if BIL_TYPE_SIZE == 64 + m = buf[BITINT_END (1, 0)]; +#elif BIL_TYPE_SIZE == 32 + m = ((UDItype) buf[1] << 32) | buf[BITINT_END (2, 0)]; +#else +# error Unsupported BIL_TYPE_SIZE +#endif + if (buf[BITINT_END (0, q_limbs - 1)]) + { + if (buf[BITINT_END (0, q_limbs - 1)] > 0x5) + { + /* 1000000000000000000000wb */ + if (buf[BITINT_END (0, q_limbs - 1)] > 0x36 + || (buf[BITINT_END (0, q_limbs - 1)] == 0x36 + && m >= (UDItype) 0x35c9adc5dea00000)) + e = 6; + else + e = 5; + } + /* 100000000000000000000wb */ + else if (buf[BITINT_END (0, q_limbs - 1)] == 0x5 + && m >= (UDItype) 0x6bc75e2d63100000) + e = 5; + else + e = 4; + } + else if (m >= (UDItype) 1000000000000000000) + { + if (m >= (UDItype) 10000000000000000000ULL) + e = 4; + else + e = 3; + } + else if (m >= (UDItype) 100000000000000000) + e = 2; + else if (m >= (UDItype) 10000000000000000) + e = 1; + exponent += e; + if (exponent > 369) + goto ovf; + if (e) + { + UBILtype rem, half; + __bid_pow10bitint (buf + q_limbs + pow10_limbs * 2, + BIL_TYPE_SIZE, e); + __divmodbitint4 (buf + q_limbs + pow10_limbs * 2 + 1, + q2_limbs * BIL_TYPE_SIZE, + buf + q_limbs + pow10_limbs * 2 + 1 + q2_limbs, + BIL_TYPE_SIZE, + buf, q_limbs * BIL_TYPE_SIZE, + buf + q_limbs + pow10_limbs * 2, BIL_TYPE_SIZE); + half = buf[q_limbs + pow10_limbs * 2] / 2; + rem = buf[q_limbs + pow10_limbs * 2 + 1 + q2_limbs]; + if (inexact) + { + /* If first division discovered some non-0 digits + and this second division is by 10, e.g. + for XXXXXX5499999999999 or XXXXXX5000000000001 + if first division is by 10^12 and second by 10^1, + doing rem |= 1 wouldn't change the 5. Similarly + for rem 4 doing rem |= 1 would change it to 5, + but we don't want to change it in that case. */ + if (e == 1) + { + if (rem == 5) + rem = 6; + else if (rem != 4) + rem |= 1; + } + else + rem |= 1; + } + /* Set inexact to 0, 1, 2, 3 depending on if remainder + of the divisions is exact 0, smaller than 10^exponent / 2, + exactly 10^exponent / 2 or greater than that. */ + if (rem >= half) + inexact = 2 + (rem > half); + else + inexact = (rem != 0); +#if BIL_TYPE_SIZE == 64 + mantissa = buf[q_limbs + pow10_limbs * 2 + 1]; +#else + mantissa + = ((buf[q_limbs + pow10_limbs * 2 + 1 + BITINT_END (0, 1)] << 32) + | buf[q_limbs + pow10_limbs * 2 + 1 + BITINT_END (1, 0)]); +#endif + } + else +#if BIL_TYPE_SIZE == 64 + mantissa = buf[BITINT_END (1, 0)]; +#else + mantissa + = ((buf[1] << 32) | buf[BITINT_END (2, 0)]); +#endif + } + else + { +#if BIL_TYPE_SIZE == 64 + mantissa = msb; +#else + if (in == 1) + mantissa = iprec < 0 ? (UDItype) (BILtype) msb : (UDItype) msb; + else + mantissa = ((msb << 32) | i[BITINT_END (1, 0)]); +#endif + if (iprec < 0) + mantissa = -mantissa; + } + + exponent += 398; + if (mantissa >= (UDItype) 0x20000000000000) + u.u = (((((iprec < 0) << 2) | (UDItype) 3) << 61) + | (((UDItype) exponent) << 51) + | (mantissa ^ (UDItype) 0x20000000000000)); + else + u.u = ((((UDItype) (iprec < 0)) << 63) + | (((UDItype) exponent) << 53) + | mantissa); + if (inexact) + { + ui.u = ((((UDItype) (iprec < 0)) << 63) + | (((UDItype) (exponent - 1)) << 53) + | (inexact + 3)); + __asm ("" : "+g" (u.d)); + __asm ("" : "+g" (ui.d)); + u.d += ui.d; + __asm ("" : "+g" (u.d)); + } + +done: + return u.d; +} +#endif --- libgcc/soft-fp/floatbitinttd.c.jj 2023-08-08 16:22:09.405440134 +0200 +++ libgcc/soft-fp/floatbitinttd.c 2023-08-08 16:22:09.405440134 +0200 @@ -0,0 +1,271 @@ +/* Software floating-point emulation. + Convert a _BitInt to _Decimal128. + + Copyright (C) 2023 Free Software Foundation, Inc. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 3, or (at your option) any later +version. + +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +Under Section 7 of GPL version 3, you are granted additional +permissions described in the GCC Runtime Library Exception, version +3.1, as published by the Free Software Foundation. + +You should have received a copy of the GNU General Public License and +a copy of the GCC Runtime Library Exception along with this program; +see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +. */ + +#include "soft-fp.h" +#include "bitint.h" + +#ifdef __BITINT_MAXWIDTH__ +extern _Decimal128 __bid_floatbitinttd (const UBILtype *, SItype); + +_Decimal128 +__bid_floatbitinttd (const UBILtype *i, SItype iprec) +{ + iprec = bitint_reduce_prec (&i, iprec); + USItype aiprec = iprec < 0 ? -iprec : iprec; + USItype in = (aiprec + BIL_TYPE_SIZE - 1) / BIL_TYPE_SIZE; + USItype idx = BITINT_END (0, in - 1); + UBILtype msb = i[idx]; + UDItype mantissahi, mantissalo; + SItype exponent = 0; + UBILtype inexact = 0; + union { _Decimal128 d; UDItype u[2]; } u, ui; + if (aiprec % BIL_TYPE_SIZE) + { + if (iprec > 0) + msb &= ((UBILtype) 1 << (aiprec % BIL_TYPE_SIZE)) - 1; + else + msb |= (UBILtype) -1 << (aiprec % BIL_TYPE_SIZE); + } + if (iprec < 0) + { + SItype n = sizeof (0ULL) * __CHAR_BIT__ + 1 - __builtin_clzll (~msb); + aiprec = (in - 1) * BIL_TYPE_SIZE + n; + } + else if (msb == 0) + aiprec = 1; + else + { + SItype n = sizeof (0ULL) * __CHAR_BIT__ - __builtin_clzll (msb); + aiprec = (in - 1) * BIL_TYPE_SIZE + n; + } + /* Number of bits in + (_BitInt(32768)) 9999999999999999999999999999999999e+6111DL. */ + if (aiprec > 20414 + (iprec < 0)) + { + ovf: + if (iprec < 0) + u.d = -9000000000000000000000000000000000e+6111DL; + else + u.d = 9000000000000000000000000000000000e+6111DL; + __asm ("" : "+g" (u.d)); + u.d += u.d; + __asm ("" : "+g" (u.d)); + goto done; + } + /* Bit precision of 9999999999999999999999999999999999uwb. */ + if (aiprec >= 113) + { + USItype pow10_limbs, q_limbs, q2_limbs, j, k; + USItype exp_bits = 0, e; + UBILtype *buf; + /* First do a possibly large divide smaller enough such that + we only need to check remainder for 0 or non-0 and then + we'll do further division. */ + if (aiprec >= 113 + 4 + 10) + { + exp_bits = ((aiprec - 113 - 4) * (UDItype) 30) / 299; + exponent = exp_bits * 3; + /* Upper estimate for pow10 (exponent) bits. */ + exp_bits = exp_bits * 10 - exp_bits / 30; + } + pow10_limbs = (exp_bits + BIL_TYPE_SIZE - 1) / BIL_TYPE_SIZE; + /* 127 is the highest number of quotient bits needed on + aiprec range of [127, 20414]. E.g. if aiprec is 20409, + exponent will be 6105 and exp_bits 20283. 20409 - 20283 + 1 + is 127. */ + q_limbs = (127 + BIL_TYPE_SIZE - 1) / BIL_TYPE_SIZE; + q2_limbs = 128 / BIL_TYPE_SIZE; + buf = __builtin_alloca ((q_limbs + pow10_limbs * 2 + q2_limbs + 2) + * sizeof (UBILtype)); + if (exponent) + { + __bid_pow10bitint (buf + q_limbs, exp_bits, exponent); + __divmodbitint4 (buf, q_limbs * BIL_TYPE_SIZE, + buf + q_limbs + pow10_limbs, + pow10_limbs * BIL_TYPE_SIZE, + i, iprec < 0 ? -aiprec : aiprec, + buf + q_limbs, exp_bits); + if (iprec < 0) + bitint_negate (buf + BITINT_END (q_limbs - 1, 0), + buf + BITINT_END (q_limbs - 1, 0), q_limbs); + inexact = buf[q_limbs + pow10_limbs]; + for (j = 1; j < pow10_limbs; ++j) + inexact |= buf[q_limbs + pow10_limbs + 1]; + } + else + { + __builtin_memcpy (buf + BITINT_END (q_limbs - in + 1, 0), i, + (in - 1) * sizeof (UBILtype)); + buf[BITINT_END (q_limbs - in, in - 1)] = msb; + if (iprec < 0) + bitint_negate (buf + BITINT_END (q_limbs - 1, 0), + buf + BITINT_END (q_limbs - 1, 0), in); + if (q_limbs > in) + __builtin_memset (buf + BITINT_END (0, in), '\0', + (q_limbs - in) * sizeof (UBILtype)); + } + e = 0; + for (j = 3; j; ) + { + USItype eprev = e; + __bid_pow10bitint (buf + q_limbs + pow10_limbs * 2 + 1, + 128, 33 + e + j); + for (k = BITINT_END (0, q_limbs - 1); + k != BITINT_END (q_limbs, (USItype) -1); k -= BITINT_INC) + if (buf[k] > buf[q_limbs + pow10_limbs * 2 + 1 + k]) + { + e += j; + break; + } + else if (buf[k] < buf[q_limbs + pow10_limbs * 2 + 1 + k]) + break; + if (k == BITINT_END (q_limbs, (USItype) -1)) + e += j; + if (j == 2 && e != eprev) + break; + else + --j; + } + exponent += e; + if (exponent > 6111) + goto ovf; + if (e) + { + UBILtype rem, half; + __bid_pow10bitint (buf + q_limbs + pow10_limbs * 2, + BIL_TYPE_SIZE, e); + __divmodbitint4 (buf + q_limbs + pow10_limbs * 2 + 1, + q2_limbs * BIL_TYPE_SIZE, + buf + q_limbs + pow10_limbs * 2 + 1 + q2_limbs, + BIL_TYPE_SIZE, + buf, q_limbs * BIL_TYPE_SIZE, + buf + q_limbs + pow10_limbs * 2, BIL_TYPE_SIZE); + half = buf[q_limbs + pow10_limbs * 2] / 2; + rem = buf[q_limbs + pow10_limbs * 2 + 1 + q2_limbs]; + if (inexact) + { + /* If first division discovered some non-0 digits + and this second division is by 10, e.g. + for XXXXXX5499999999999 or XXXXXX5000000000001 + if first division is by 10^12 and second by 10^1, + doing rem |= 1 wouldn't change the 5. Similarly + for rem 4 doing rem |= 1 would change it to 5, + but we don't want to change it in that case. */ + if (e == 1) + { + if (rem == 5) + rem = 6; + else if (rem != 4) + rem |= 1; + } + else + rem |= 1; + } + /* Set inexact to 0, 1, 2, 3 depending on if remainder + of the divisions is exact 0, smaller than 10^exponent / 2, + exactly 10^exponent / 2 or greater than that. */ + if (rem >= half) + inexact = 2 + (rem > half); + else + inexact = (rem != 0); +#if BIL_TYPE_SIZE == 64 + mantissahi = buf[q_limbs + pow10_limbs * 2 + 1 + BITINT_END (0, 1)]; + mantissalo = buf[q_limbs + pow10_limbs * 2 + 1 + BITINT_END (1, 0)]; +#else + mantissahi + = ((buf[q_limbs + pow10_limbs * 2 + 1 + BITINT_END (0, 3)] << 32) + | buf[q_limbs + pow10_limbs * 2 + 1 + BITINT_END (1, 2)]); + mantissalo + = ((buf[q_limbs + pow10_limbs * 2 + 1 + BITINT_END (2, 1)] << 32) + | buf[q_limbs + pow10_limbs * 2 + 1 + BITINT_END (3, 0)]); +#endif + } + else + { +#if BIL_TYPE_SIZE == 64 + mantissahi = buf[BITINT_END (0, 1)]; + mantissalo = buf[BITINT_END (1, 0)]; +#else + mantissahi = (buf[BITINT_END (0, 3)] << 32) | buf[BITINT_END (1, 2)]; + mantissalo = (buf[BITINT_END (2, 1)] << 32) | buf[BITINT_END (3, 0)]; +#endif + } + } + else + { + mantissahi = iprec < 0 ? -1 : 0; +#if BIL_TYPE_SIZE == 64 + if (in == 1) + mantissalo = msb; + else + { + mantissahi = msb; + mantissalo = i[BITINT_END (1, 0)]; + } +#else + if (in <= 2) + { + if (in == 1) + mantissalo = iprec < 0 ? (UDItype) (BILtype) msb : (UDItype) msb; + else + mantissalo = (msb << 32) | i[BITINT_END (1, 0)]; + } + else + { + if (in == 3) + mantissahi = iprec < 0 ? (UDItype) (BILtype) msb : (UDItype) msb; + else + mantissahi = (msb << 32) | i[BITINT_END (1, 2)]; + mantissalo = ((i[BITINT_END (in - 2, 1)] << 32) + | i[BITINT_END (in - 1, 0)]); + } +#endif + if (iprec < 0) + mantissahi + = ~mantissahi + __builtin_add_overflow (~mantissalo, 1, &mantissalo); + } + + exponent += 6176; + u.u[__FLOAT_WORD_ORDER__ != __ORDER_BIG_ENDIAN__] + = ((((UDItype) (iprec < 0)) << 63) + | (((UDItype) exponent) << 49) + | mantissahi); + u.u[__FLOAT_WORD_ORDER__ == __ORDER_BIG_ENDIAN__] = mantissalo; + if (inexact) + { + ui.u[__FLOAT_WORD_ORDER__ != __ORDER_BIG_ENDIAN__] + = (((UDItype) (iprec < 0)) << 63) | (((UDItype) exponent - 1) << 49); + ui.u[__FLOAT_WORD_ORDER__ == __ORDER_BIG_ENDIAN__] = inexact + 3; + __asm ("" : "+g" (u.d)); + __asm ("" : "+g" (ui.d)); + u.d += ui.d; + __asm ("" : "+g" (u.d)); + } + +done: + return u.d; +} +#endif Jakub