blob: 50b9e77a83573481f38d5668876183f37f896e58 [file] [log] [blame]
/* Software floating-point emulation.
Convert a _BitInt to _Decimal128.
Copyright (C) 2023-2025 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__
#ifndef ENABLE_DECIMAL_BID_FORMAT
#define __bid_floatbitinttd __dpd_floatbitinttd
#endif
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;
if (msb == ~(UBILtype) 0)
n = 1;
else
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 + j];
}
else
{
__builtin_memcpy (buf + BITINT_END (q_limbs - in + 1, 0),
i + BITINT_END (1, 0),
(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
= ((UDItype)
buf[q_limbs + pow10_limbs * 2 + 1 + BITINT_END (0, 3)] << 32
| buf[q_limbs + pow10_limbs * 2 + 1 + BITINT_END (1, 2)]);
mantissalo
= ((UDItype)
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 = ((UDItype) buf[BITINT_END (0, 3)] << 32
| buf[BITINT_END (1, 2)]);
mantissalo = ((UDItype) 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 = (UDItype) msb << 32 | i[BITINT_END (1, 0)];
}
else
{
if (in == 3)
mantissahi = iprec < 0 ? (UDItype) (BILtype) msb : (UDItype) msb;
else
mantissahi = (UDItype) msb << 32 | i[BITINT_END (1, 2)];
mantissalo = ((UDItype) 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;
#ifdef ENABLE_DECIMAL_BID_FORMAT
u.u[__FLOAT_WORD_ORDER__ != __ORDER_BIG_ENDIAN__]
= ((((UDItype) (iprec < 0)) << 63)
| (((UDItype) exponent) << 49)
| mantissahi);
#else
#ifdef __SIZEOF_INT128__
unsigned __int128 m = mantissahi;
#else
unsigned _BitInt(128) m = mantissahi;
#endif
m = (m << 64) | mantissalo;
u.u[0] = m / 1000000000000000ULL;
u.u[1] = m % 1000000000000000ULL;
mantissalo = __dpd_b2dbitint[u.u[1] % 1000];
u.u[1] /= 1000;
mantissalo |= ((UDItype) __dpd_b2dbitint[u.u[1] % 1000]) << 10;
u.u[1] /= 1000;
mantissalo |= ((UDItype) __dpd_b2dbitint[u.u[1] % 1000]) << 20;
u.u[1] /= 1000;
mantissalo |= ((UDItype) __dpd_b2dbitint[u.u[1] % 1000]) << 30;
u.u[1] /= 1000;
mantissalo |= ((UDItype) __dpd_b2dbitint[u.u[1] % 1000]) << 40;
mantissalo |= ((UDItype) __dpd_b2dbitint[u.u[0] % 1000]) << 50;
u.u[0] /= 1000;
mantissahi = __dpd_b2dbitint[u.u[0] % 1000];
u.u[0] /= 1000;
mantissalo |= mantissahi << 60;
mantissahi >>= 4;
mantissahi |= ((UDItype) __dpd_b2dbitint[u.u[0] % 1000]) << 6;
u.u[0] /= 1000;
mantissahi |= ((UDItype) __dpd_b2dbitint[u.u[0] % 1000]) << 16;
u.u[0] /= 1000;
mantissahi |= ((UDItype) __dpd_b2dbitint[u.u[0] % 1000]) << 26;
u.u[0] /= 1000;
mantissahi |= ((UDItype) __dpd_b2dbitint[u.u[0] % 1000]) << 36;
u.u[0] /= 1000;
if (u.u[0] >= 8)
u.u[__FLOAT_WORD_ORDER__ != __ORDER_BIG_ENDIAN__]
= (((((iprec < 0) << 2) | (UDItype) 3) << 61)
| (((UDItype) exponent & (3 << 12)) << 47)
| ((u.u[0] & 1) << 58)
| (((UDItype) exponent & 4095) << 46)
| mantissahi);
else
u.u[__FLOAT_WORD_ORDER__ != __ORDER_BIG_ENDIAN__]
= ((((UDItype) (iprec < 0)) << 63)
| (((UDItype) exponent & (3 << 12)) << 49)
| (u.u[0] << 58)
| (((UDItype) exponent & 4095) << 46)
| mantissahi);
#endif
u.u[__FLOAT_WORD_ORDER__ == __ORDER_BIG_ENDIAN__] = mantissalo;
if (inexact)
{
ui.u[__FLOAT_WORD_ORDER__ != __ORDER_BIG_ENDIAN__]
#ifdef ENABLE_DECIMAL_BID_FORMAT
= (((UDItype) (iprec < 0)) << 63) | (((UDItype) exponent - 1) << 49);
#else
= ((((UDItype) (iprec < 0)) << 63)
| ((((UDItype) exponent - 1) & (3 << 12)) << 49)
| ((((UDItype) exponent - 1) & 4095) << 46));
#endif
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