diff options
author | Jakub Jelinek <jakub@redhat.com> | 2023-09-06 17:33:05 +0200 |
---|---|---|
committer | Jakub Jelinek <jakub@redhat.com> | 2023-09-06 17:33:05 +0200 |
commit | 2ce182e258d3ab11310442d5f4dd1d063018aca9 (patch) | |
tree | c0a3975f2567a96ba48cc4ab930bfb15ff32f3c8 /libgcc/soft-fp | |
parent | 7a610d44d855424518ecb4429ea5226ed2c32543 (diff) | |
download | gcc-2ce182e258d3ab11310442d5f4dd1d063018aca9.zip gcc-2ce182e258d3ab11310442d5f4dd1d063018aca9.tar.gz gcc-2ce182e258d3ab11310442d5f4dd1d063018aca9.tar.bz2 |
libgcc _BitInt support [PR102989]
This patch adds the library helpers for multiplication, division + modulo
and casts from and to floating point (both binary and decimal).
As described in the intro, the first step is try to reduce further the
passed in precision by skipping over most significant limbs with just zeros
or sign bit copies. For multiplication and division I've implemented
a simple algorithm, using something smarter like Karatsuba or Toom N-Way
might be faster for very large _BitInts (which we don't support right now
anyway), but could mean more code in libgcc, which maybe isn't what people
are willing to accept.
For the to/from floating point conversions the patch uses soft-fp, because
it already has tons of handy macros which can be used for that. In theory
it could be implemented using {,unsigned} long long or {,unsigned} __int128
to/from floating point conversions with some frexp before/after, but at that
point we already need to force it into integer registers and analyze it
anyway. Plus, for 32-bit arches there is no __int128 that could be used
for XF/TF mode stuff.
I know that soft-fp is owned by glibc and I think the op-common.h change
should be propagated there, but the bitint stuff is really GCC specific
and IMHO doesn't belong into the glibc copy.
2023-09-06 Jakub Jelinek <jakub@redhat.com>
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.
Diffstat (limited to 'libgcc/soft-fp')
-rw-r--r-- | libgcc/soft-fp/bitint.h | 329 | ||||
-rw-r--r-- | libgcc/soft-fp/bitintpow10.c | 132 | ||||
-rw-r--r-- | libgcc/soft-fp/fixddbitint.c | 205 | ||||
-rw-r--r-- | libgcc/soft-fp/fixdfbitint.c | 71 | ||||
-rw-r--r-- | libgcc/soft-fp/fixsdbitint.c | 196 | ||||
-rw-r--r-- | libgcc/soft-fp/fixsfbitint.c | 71 | ||||
-rw-r--r-- | libgcc/soft-fp/fixtdbitint.c | 242 | ||||
-rw-r--r-- | libgcc/soft-fp/fixtfbitint.c | 81 | ||||
-rw-r--r-- | libgcc/soft-fp/fixxfbitint.c | 82 | ||||
-rw-r--r-- | libgcc/soft-fp/floatbitintbf.c | 59 | ||||
-rw-r--r-- | libgcc/soft-fp/floatbitintdd.c | 264 | ||||
-rw-r--r-- | libgcc/soft-fp/floatbitintdf.c | 64 | ||||
-rw-r--r-- | libgcc/soft-fp/floatbitinthf.c | 59 | ||||
-rw-r--r-- | libgcc/soft-fp/floatbitintsd.c | 235 | ||||
-rw-r--r-- | libgcc/soft-fp/floatbitintsf.c | 59 | ||||
-rw-r--r-- | libgcc/soft-fp/floatbitinttd.c | 271 | ||||
-rw-r--r-- | libgcc/soft-fp/floatbitinttf.c | 73 | ||||
-rw-r--r-- | libgcc/soft-fp/floatbitintxf.c | 74 | ||||
-rw-r--r-- | libgcc/soft-fp/op-common.h | 31 |
19 files changed, 2595 insertions, 3 deletions
diff --git a/libgcc/soft-fp/bitint.h b/libgcc/soft-fp/bitint.h new file mode 100644 index 0000000..5e8b764 --- /dev/null +++ b/libgcc/soft-fp/bitint.h @@ -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 +<http://www.gnu.org/licenses/>. */ + +#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 */ diff --git a/libgcc/soft-fp/bitintpow10.c b/libgcc/soft-fp/bitintpow10.c new file mode 100644 index 0000000..06a470f0 --- /dev/null +++ b/libgcc/soft-fp/bitintpow10.c @@ -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 +<http://www.gnu.org/licenses/>. */ + +#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 diff --git a/libgcc/soft-fp/fixddbitint.c b/libgcc/soft-fp/fixddbitint.c new file mode 100644 index 0000000..bd212ae --- /dev/null +++ b/libgcc/soft-fp/fixddbitint.c @@ -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 +<http://www.gnu.org/licenses/>. */ + +#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 diff --git a/libgcc/soft-fp/fixdfbitint.c b/libgcc/soft-fp/fixdfbitint.c new file mode 100644 index 0000000..3f4a46c --- /dev/null +++ b/libgcc/soft-fp/fixdfbitint.c @@ -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 +<http://www.gnu.org/licenses/>. */ + +#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 diff --git a/libgcc/soft-fp/fixsdbitint.c b/libgcc/soft-fp/fixsdbitint.c new file mode 100644 index 0000000..98e3ab9 --- /dev/null +++ b/libgcc/soft-fp/fixsdbitint.c @@ -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 +<http://www.gnu.org/licenses/>. */ + +#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 diff --git a/libgcc/soft-fp/fixsfbitint.c b/libgcc/soft-fp/fixsfbitint.c new file mode 100644 index 0000000..f691722 --- /dev/null +++ b/libgcc/soft-fp/fixsfbitint.c @@ -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 +<http://www.gnu.org/licenses/>. */ + +#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 diff --git a/libgcc/soft-fp/fixtdbitint.c b/libgcc/soft-fp/fixtdbitint.c new file mode 100644 index 0000000..6d33ec2 --- /dev/null +++ b/libgcc/soft-fp/fixtdbitint.c @@ -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 +<http://www.gnu.org/licenses/>. */ + +#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 > (UDItype) 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 diff --git a/libgcc/soft-fp/fixtfbitint.c b/libgcc/soft-fp/fixtfbitint.c new file mode 100644 index 0000000..f126deb --- /dev/null +++ b/libgcc/soft-fp/fixtfbitint.c @@ -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 +<http://www.gnu.org/licenses/>. */ + +#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 diff --git a/libgcc/soft-fp/fixxfbitint.c b/libgcc/soft-fp/fixxfbitint.c new file mode 100644 index 0000000..de79721 --- /dev/null +++ b/libgcc/soft-fp/fixxfbitint.c @@ -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 +<http://www.gnu.org/licenses/>. */ + +#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 diff --git a/libgcc/soft-fp/floatbitintbf.c b/libgcc/soft-fp/floatbitintbf.c new file mode 100644 index 0000000..6600b72 --- /dev/null +++ b/libgcc/soft-fp/floatbitintbf.c @@ -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 +<http://www.gnu.org/licenses/>. */ + +#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 diff --git a/libgcc/soft-fp/floatbitintdd.c b/libgcc/soft-fp/floatbitintdd.c new file mode 100644 index 0000000..0fcc845 --- /dev/null +++ b/libgcc/soft-fp/floatbitintdd.c @@ -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 +<http://www.gnu.org/licenses/>. */ + +#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 diff --git a/libgcc/soft-fp/floatbitintdf.c b/libgcc/soft-fp/floatbitintdf.c new file mode 100644 index 0000000..18cdc65 --- /dev/null +++ b/libgcc/soft-fp/floatbitintdf.c @@ -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 +<http://www.gnu.org/licenses/>. */ + +#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 diff --git a/libgcc/soft-fp/floatbitinthf.c b/libgcc/soft-fp/floatbitinthf.c new file mode 100644 index 0000000..a28d03a --- /dev/null +++ b/libgcc/soft-fp/floatbitinthf.c @@ -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 +<http://www.gnu.org/licenses/>. */ + +#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 diff --git a/libgcc/soft-fp/floatbitintsd.c b/libgcc/soft-fp/floatbitintsd.c new file mode 100644 index 0000000..5c5ed6c --- /dev/null +++ b/libgcc/soft-fp/floatbitintsd.c @@ -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 +<http://www.gnu.org/licenses/>. */ + +#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 diff --git a/libgcc/soft-fp/floatbitintsf.c b/libgcc/soft-fp/floatbitintsf.c new file mode 100644 index 0000000..6a40a43 --- /dev/null +++ b/libgcc/soft-fp/floatbitintsf.c @@ -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 +<http://www.gnu.org/licenses/>. */ + +#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 diff --git a/libgcc/soft-fp/floatbitinttd.c b/libgcc/soft-fp/floatbitinttd.c new file mode 100644 index 0000000..329ce1b --- /dev/null +++ b/libgcc/soft-fp/floatbitinttd.c @@ -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 +<http://www.gnu.org/licenses/>. */ + +#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 diff --git a/libgcc/soft-fp/floatbitinttf.c b/libgcc/soft-fp/floatbitinttf.c new file mode 100644 index 0000000..f9f76eb --- /dev/null +++ b/libgcc/soft-fp/floatbitinttf.c @@ -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 +<http://www.gnu.org/licenses/>. */ + +#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 diff --git a/libgcc/soft-fp/floatbitintxf.c b/libgcc/soft-fp/floatbitintxf.c new file mode 100644 index 0000000..4731eb3 --- /dev/null +++ b/libgcc/soft-fp/floatbitintxf.c @@ -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 +<http://www.gnu.org/licenses/>. */ + +#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 diff --git a/libgcc/soft-fp/op-common.h b/libgcc/soft-fp/op-common.h index fde4489..090028f 100644 --- a/libgcc/soft-fp/op-common.h +++ b/libgcc/soft-fp/op-common.h @@ -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); \ })); \ \ |