
I've tried last night to enable _BitInt support for i?86-linux, and a few spots in libgcc emitted -Wshift-count-overflow warnings and clearly didn't do what it was supposed to do. Fixed thusly. 2024-02-10 Jakub Jelinek <jakub@redhat.com> * soft-fp/fixddbitint.c (__bid_fixddbitint): Fix up BIL_TYPE_SIZE == 32 shifts. * soft-fp/fixsdbitint.c (__bid_fixsdbitint): Likewise. * soft-fp/fixtdbitint.c (__bid_fixtdbitint): Likewise. * soft-fp/floatbitintdd.c (__bid_floatbitintdd): Likewise. * soft-fp/floatbitinttd.c (__bid_floatbitinttd): Likewise.
242 lines
7.6 KiB
C
242 lines
7.6 KiB
C
/* 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 = (UDItype) limbs[BITINT_END (8, 11)] << 32;
|
|
mantissahi |= limbs[BITINT_END (9, 10)];
|
|
mantissalo = (UDItype) 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
|