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.
This commit is contained in:
Jakub Jelinek 2023-09-06 17:33:05 +02:00
parent 7a610d44d8
commit 2ce182e258
33 changed files with 3339 additions and 13 deletions

View file

@ -446,7 +446,7 @@ lib2funcs = _muldi3 _negdi2 _lshrdi3 _ashldi3 _ashrdi3 _cmpdi2 _ucmpdi2 \
_paritysi2 _paritydi2 _powisf2 _powidf2 _powixf2 _powitf2 \
_mulhc3 _mulsc3 _muldc3 _mulxc3 _multc3 _divhc3 _divsc3 \
_divdc3 _divxc3 _divtc3 _bswapsi2 _bswapdi2 _clrsbsi2 \
_clrsbdi2
_clrsbdi2 _mulbitint3
# The floating-point conversion routines that involve a single-word integer.
# XX stands for the integer mode.
@ -466,7 +466,8 @@ endif
# These might cause a divide overflow trap and so are compiled with
# unwinder info.
LIB2_DIVMOD_FUNCS = _divdi3 _moddi3 _divmoddi4 \
_udivdi3 _umoddi3 _udivmoddi4 _udiv_w_sdiv
_udivdi3 _umoddi3 _udivmoddi4 _udiv_w_sdiv \
_divmodbitint4
# Remove any objects from lib2funcs and LIB2_DIVMOD_FUNCS that are
# defined as optimized assembly code in LIB1ASMFUNCS or as C code

View file

@ -3,7 +3,7 @@ softfp_int_modes := si di ti
softfp_extensions := sftf dftf hftf bfsf
softfp_truncations := tfsf tfdf tfhf tfbf dfbf sfbf hfbf
softfp_exclude_libgcc2 := n
softfp_extras := fixhfti fixunshfti floattihf floatuntihf \
softfp_extras += fixhfti fixunshfti floattihf floatuntihf \
floatdibf floatundibf floattibf floatuntibf
TARGET_LIBGCC2_CFLAGS += -Wno-missing-prototypes

View file

@ -1,4 +1,4 @@
softfp_extras := fixhfti fixunshfti floattihf floatuntihf \
softfp_extras += fixhfti fixunshfti floattihf floatuntihf \
floattibf floatuntibf
CFLAGS-fixhfti.c += -msse2

View file

@ -226,3 +226,13 @@ GCC_13.0.0 {
__truncxfbf2
__trunchfbf2
}
%inherit GCC_14.0.0 GCC_13.0.0
GCC_14.0.0 {
__PFX__fixxfbitint
__PFX__fixtfbitint
__PFX__floatbitintbf
__PFX__floatbitinthf
__PFX__floatbitintxf
__PFX__floatbitinttf
}

View file

@ -10,7 +10,7 @@ softfp_extensions := hfsf hfdf hftf hfxf sfdf sftf dftf xftf bfsf
softfp_truncations := tfhf xfhf dfhf sfhf tfsf dfsf tfdf tfxf \
tfbf xfbf dfbf sfbf hfbf
softfp_extras += eqhf2
softfp_extras += eqhf2 fixxfbitint $(foreach m,hf bf xf,floatbitint$(m))
CFLAGS-extendhfsf2.c += -msse2
CFLAGS-extendhfdf2.c += -msse2
@ -28,6 +28,9 @@ CFLAGS-truncxfbf2.c += -msse2
CFLAGS-trunctfbf2.c += -msse2
CFLAGS-trunchfbf2.c += -msse2
CFLAGS-floatbitintbf.c += -msse2
CFLAGS-floatbitinthf.c += -msse2
CFLAGS-eqhf2.c += -msse2
CFLAGS-_divhc3.c += -msse2
CFLAGS-_mulhc3.c += -msse2

View file

@ -13,7 +13,7 @@ softfp_extensions := sftf dftf
softfp_truncations := tfsf tfdf
# Enable divide routines to make -mno-fdiv work.
softfp_extras := divsf3 divdf3
softfp_extras += divsf3 divdf3
else
# !ABI_DOUBLE
@ -28,7 +28,7 @@ else
# ABI_SINGLE
# Enable divide routines to make -mno-fdiv work.
softfp_extras := divsf3
softfp_extras += divsf3
endif
@ -38,7 +38,7 @@ else
# ABI_QUAD
# Enable divide routines to make -mno-fdiv work.
softfp_extras := divsf3 divdf3 divtf3
softfp_extras += divsf3 divdf3 divtf3
endif

View file

@ -29,4 +29,4 @@ softfp_int_modes := si di
softfp_extensions := sfdf
softfp_truncations := dfsf
softfp_exclude_libgcc2 := n
softfp_extras := unordsf2
softfp_extras += unordsf2

View file

@ -23,4 +23,4 @@ softfp_int_modes :=
softfp_extensions :=
softfp_truncations :=
softfp_exclude_libgcc2 := n
softfp_extras := unordsf2 unorddf2
softfp_extras += unordsf2 unorddf2

View file

@ -64,12 +64,21 @@ softfp_float_funcs = add$(m)3 div$(m)3 eq$(m)2 ge$(m)2 le$(m)2 mul$(m)3 \
neg$(m)2 sub$(m)3 unord$(m)2
softfp_floatint_funcs = fix$(m)$(i) fixuns$(m)$(i) \
float$(i)$(m) floatun$(i)$(m)
softfp_floatbitint_funcs = fix$(m)bitint floatbitint$(m)
softfp_bid_list :=
ifeq ($(decimal_float),yes)
ifeq ($(enable_decimal_float),bid)
softfp_bid_list += bitintpow10 \
$(foreach m,sd dd td,fix$(m)bitint floatbitint$(m))
endif
endif
softfp_func_list := \
$(foreach m,$(softfp_float_modes), \
$(softfp_float_funcs) \
$(foreach i,$(softfp_int_modes), \
$(softfp_floatint_funcs))) \
$(foreach m,sf df,$(softfp_floatbitint_funcs)) \
$(foreach e,$(softfp_extensions),extend$(e)2) \
$(foreach t,$(softfp_truncations),trunc$(t)2) \
$(softfp_extras)
@ -116,6 +125,8 @@ softfp_file_list := \
$(addsuffix .c,$(addprefix $(srcdir)/soft-fp/,$(softfp_func_list)))
endif
endif
softfp_bid_file_list := \
$(addsuffix .c,$(addprefix $(srcdir)/soft-fp/,$(softfp_bid_list)))
# Disable missing prototype and type limit warnings. The prototypes
# for the functions in the soft-fp files have not been brought across
@ -129,6 +140,7 @@ soft-fp-objects = $(addsuffix $(objext), $(soft-fp-objects-base)) \
$(soft-fp-objects) : INTERNAL_CFLAGS += -Wno-missing-prototypes -Wno-type-limits
LIB2ADD += $(softfp_file_list)
LIB2ADD_ST += $(softfp_bid_file_list)
ifneq ($(softfp_exclude_libgcc2),y)
# Functions in libgcc2.c are excluded for each soft-float mode (a

View file

@ -2,4 +2,5 @@ softfp_float_modes := sf df tf
softfp_int_modes := si di
softfp_extensions := sfdf sftf dftf xftf
softfp_truncations := dfsf tfsf tfdf tfxf
softfp_extras += fixtfbitint floatbitinttf
softfp_exclude_libgcc2 := n

View file

@ -2,4 +2,5 @@ softfp_float_modes := tf
softfp_int_modes := si di ti
softfp_extensions := sftf dftf xftf
softfp_truncations := tfsf tfdf tfxf
softfp_extras += fixtfbitint floatbitinttf
softfp_exclude_libgcc2 := n

View file

@ -1944,3 +1944,13 @@ GCC_7.0.0 {
__PFX__divmoddi4
__PFX__divmodti4
}
%inherit GCC_14.0.0 GCC_7.0.0
GCC_14.0.0 {
__PFX__mulbitint3
__PFX__divmodbitint4
__PFX__fixsfbitint
__PFX__fixdfbitint
__PFX__floatbitintsf
__PFX__floatbitintdf
}

View file

@ -1301,6 +1301,687 @@ __udivdi3 (UDWtype n, UDWtype d)
}
#endif
#if (defined(__BITINT_MAXWIDTH__) \
&& (defined(L_mulbitint3) || defined(L_divmodbitint4)))
/* _BitInt support. */
/* If *P is zero or sign extended (the latter only for PREC < 0) from
some narrower _BitInt value, reduce precision. */
static inline __attribute__((__always_inline__)) SItype
bitint_reduce_prec (const UWtype **p, SItype prec)
{
UWtype mslimb;
SItype i;
if (prec < 0)
{
#if __LIBGCC_BITINT_ORDER__ == __ORDER_BIG_ENDIAN__
i = 0;
#else
i = ((USItype) -1 - prec) / W_TYPE_SIZE;
#endif
mslimb = (*p)[i];
if (mslimb & ((UWtype) 1 << (((USItype) -1 - prec) % W_TYPE_SIZE)))
{
SItype n = ((USItype) -prec) % W_TYPE_SIZE;
if (n)
{
mslimb |= ((UWtype) -1 << (((USItype) -1 - prec) % W_TYPE_SIZE));
if (mslimb == (UWtype) -1)
{
prec += n;
if (prec >= -1)
return -2;
#if __LIBGCC_BITINT_ORDER__ == __ORDER_BIG_ENDIAN__
++p;
#else
--i;
#endif
mslimb = (*p)[i];
n = 0;
}
}
while (mslimb == (UWtype) -1)
{
prec += W_TYPE_SIZE;
if (prec >= -1)
return -2;
#if __LIBGCC_BITINT_ORDER__ == __ORDER_BIG_ENDIAN__
++p;
#else
--i;
#endif
mslimb = (*p)[i];
}
if (n == 0)
{
if ((Wtype) mslimb >= 0)
{
#if __LIBGCC_BITINT_ORDER__ == __ORDER_BIG_ENDIAN__
--p;
#endif
return prec - 1;
}
}
return prec;
}
else
prec = -prec;
}
else
{
#if __LIBGCC_BITINT_ORDER__ == __ORDER_BIG_ENDIAN__
i = 0;
#else
i = ((USItype) prec - 1) / W_TYPE_SIZE;
#endif
mslimb = (*p)[i];
}
SItype n = ((USItype) prec) % W_TYPE_SIZE;
if (n)
{
mslimb &= ((UWtype) 1 << (((USItype) prec) % W_TYPE_SIZE)) - 1;
if (mslimb == 0)
{
prec -= n;
if (prec == 0)
return 1;
#if __LIBGCC_BITINT_ORDER__ == __ORDER_BIG_ENDIAN__
++p;
#else
--i;
#endif
mslimb = (*p)[i];
}
}
while (mslimb == 0)
{
prec -= W_TYPE_SIZE;
if (prec == 0)
return 1;
#if __LIBGCC_BITINT_ORDER__ == __ORDER_BIG_ENDIAN__
++p;
#else
--i;
#endif
mslimb = (*p)[i];
}
return prec;
}
#if __LIBGCC_BITINT_ORDER__ == __ORDER_BIG_ENDIAN__
# define BITINT_INC -1
# define BITINT_END(be, le) (be)
#else
# define BITINT_INC 1
# define BITINT_END(be, le) (le)
#endif
#ifdef L_mulbitint3
/* D = S * L. */
static UWtype
bitint_mul_1 (UWtype *d, const UWtype *s, UWtype l, SItype n)
{
UWtype sv, hi, lo, c = 0;
do
{
sv = *s;
s += BITINT_INC;
umul_ppmm (hi, lo, sv, l);
c = __builtin_add_overflow (lo, c, &lo) + hi;
*d = lo;
d += BITINT_INC;
}
while (--n);
return c;
}
/* D += S * L. */
static UWtype
bitint_addmul_1 (UWtype *d, const UWtype *s, UWtype l, SItype n)
{
UWtype sv, hi, lo, c = 0;
do
{
sv = *s;
s += BITINT_INC;
umul_ppmm (hi, lo, sv, l);
hi += __builtin_add_overflow (lo, *d, &lo);
c = __builtin_add_overflow (lo, c, &lo) + hi;
*d = lo;
d += BITINT_INC;
}
while (--n);
return c;
}
/* If XPREC is positive, it is precision in bits
of an unsigned _BitInt operand (which has XPREC/W_TYPE_SIZE
full limbs and if Xprec%W_TYPE_SIZE one partial limb.
If Xprec is negative, -XPREC is precision in bits
of a signed _BitInt operand. RETPREC should be always
positive. */
void
__mulbitint3 (UWtype *ret, SItype retprec,
const UWtype *u, SItype uprec,
const UWtype *v, SItype vprec)
{
uprec = bitint_reduce_prec (&u, uprec);
vprec = bitint_reduce_prec (&v, vprec);
USItype auprec = uprec < 0 ? -uprec : uprec;
USItype avprec = vprec < 0 ? -vprec : vprec;
/* Prefer non-negative U.
Otherwise make sure V doesn't have higher precision than U. */
if ((uprec < 0 && vprec >= 0)
|| (avprec > auprec && !(uprec >= 0 && vprec < 0)))
{
SItype p;
const UWtype *t;
p = uprec; uprec = vprec; vprec = p;
p = auprec; auprec = avprec; avprec = p;
t = u; u = v; v = t;
}
USItype un = auprec / W_TYPE_SIZE;
USItype un2 = (auprec + W_TYPE_SIZE - 1) / W_TYPE_SIZE;
USItype vn = avprec / W_TYPE_SIZE;
USItype vn2 = (avprec + W_TYPE_SIZE - 1) / W_TYPE_SIZE;
USItype retn = ((USItype) retprec + W_TYPE_SIZE - 1) / W_TYPE_SIZE;
USItype retidx, uidx, vidx;
UWtype vv;
/* Indexes of least significant limb. */
#if __LIBGCC_BITINT_ORDER__ == __ORDER_BIG_ENDIAN__
retidx = retn - 1;
uidx = un2 - 1;
vidx = vn2 - 1;
#else
retidx = 0;
uidx = 0;
vidx = 0;
#endif
if (__builtin_expect (auprec <= W_TYPE_SIZE, 0) && vprec < 0)
{
UWtype uu = u[uidx];
if (__builtin_expect (auprec < W_TYPE_SIZE, 0))
uu &= ((UWtype) 1 << (auprec % W_TYPE_SIZE)) - 1;
if (uu == 0)
{
/* 0 * negative would be otherwise mishandled below, so
handle it specially. */
__builtin_memset (ret, 0, retn * sizeof (UWtype));
return;
}
}
vv = v[vidx];
if (__builtin_expect (avprec < W_TYPE_SIZE, 0))
{
if (vprec > 0)
vv &= ((UWtype) 1 << (avprec % W_TYPE_SIZE)) - 1;
else
vv |= (UWtype) -1 << (avprec % W_TYPE_SIZE);
}
USItype n = un > retn ? retn : un;
USItype n2 = n;
USItype retidx2 = retidx + n * BITINT_INC;
UWtype c = 0, uv = 0;
if (n)
c = bitint_mul_1 (ret + retidx, u + uidx, vv, n);
if (retn > un && un2 != un)
{
UWtype hi, lo;
uv = u[uidx + n * BITINT_INC];
if (uprec > 0)
uv &= ((UWtype) 1 << (auprec % W_TYPE_SIZE)) - 1;
else
uv |= (UWtype) -1 << (auprec % W_TYPE_SIZE);
umul_ppmm (hi, lo, uv, vv);
c = __builtin_add_overflow (lo, c, &lo) + hi;
ret[retidx2] = lo;
retidx2 += BITINT_INC;
++n2;
}
if (retn > un2)
{
if (uprec < 0)
{
while (n2 < retn)
{
if (n2 >= un2 + vn2)
break;
UWtype hi, lo;
umul_ppmm (hi, lo, (UWtype) -1, vv);
c = __builtin_add_overflow (lo, c, &lo) + hi;
ret[retidx2] = lo;
retidx2 += BITINT_INC;
++n2;
}
}
else
{
ret[retidx2] = c;
retidx2 += BITINT_INC;
++n2;
}
/* If RET has more limbs than U after precision reduction,
fill in the remaining limbs. */
while (n2 < retn)
{
if (n2 < un2 + vn2 || (uprec ^ vprec) >= 0)
c = 0;
else
c = (UWtype) -1;
ret[retidx2] = c;
retidx2 += BITINT_INC;
++n2;
}
}
/* N is now number of possibly non-zero limbs in RET (ignoring
limbs above UN2 + VN2 which if any have been finalized already). */
USItype end = vprec < 0 ? un2 + vn2 : vn2;
if (retn > un2 + vn2) retn = un2 + vn2;
if (end > retn) end = retn;
for (USItype m = 1; m < end; ++m)
{
retidx += BITINT_INC;
vidx += BITINT_INC;
if (m < vn2)
{
vv = v[vidx];
if (__builtin_expect (m == vn, 0))
{
if (vprec > 0)
vv &= ((UWtype) 1 << (avprec % W_TYPE_SIZE)) - 1;
else
vv |= (UWtype) -1 << (avprec % W_TYPE_SIZE);
}
}
else
vv = (UWtype) -1;
if (m + n > retn)
n = retn - m;
c = 0;
if (n)
c = bitint_addmul_1 (ret + retidx, u + uidx, vv, n);
n2 = m + n;
retidx2 = retidx + n * BITINT_INC;
if (n2 < retn && un2 != un)
{
UWtype hi, lo;
umul_ppmm (hi, lo, uv, vv);
hi += __builtin_add_overflow (lo, ret[retidx2], &lo);
c = __builtin_add_overflow (lo, c, &lo) + hi;
ret[retidx2] = lo;
retidx2 += BITINT_INC;
++n2;
}
if (uprec < 0)
while (n2 < retn)
{
UWtype hi, lo;
umul_ppmm (hi, lo, (UWtype) -1, vv);
hi += __builtin_add_overflow (lo, ret[retidx2], &lo);
c = __builtin_add_overflow (lo, c, &lo) + hi;
ret[retidx2] = lo;
retidx2 += BITINT_INC;
++n2;
}
else if (n2 < retn)
{
ret[retidx2] = c;
retidx2 += BITINT_INC;
}
}
}
#endif
#ifdef L_divmodbitint4
static void
bitint_negate (UWtype *d, const UWtype *s, SItype n)
{
UWtype c = 1;
do
{
UWtype sv = *s, lo;
s += BITINT_INC;
c = __builtin_add_overflow (~sv, c, &lo);
*d = lo;
d += BITINT_INC;
}
while (--n);
}
/* D -= S * L. */
static UWtype
bitint_submul_1 (UWtype *d, const UWtype *s, UWtype l, SItype n)
{
UWtype sv, hi, lo, c = 0;
do
{
sv = *s;
s += BITINT_INC;
umul_ppmm (hi, lo, sv, l);
hi += __builtin_sub_overflow (*d, lo, &lo);
c = __builtin_sub_overflow (lo, c, &lo) + hi;
*d = lo;
d += BITINT_INC;
}
while (--n);
return c;
}
/* If XPREC is positive, it is precision in bits
of an unsigned _BitInt operand (which has XPREC/W_TYPE_SIZE
full limbs and if Xprec%W_TYPE_SIZE one partial limb.
If Xprec is negative, -XPREC is precision in bits
of a signed _BitInt operand. QPREC and RPREC should be
always non-negative. If either Q or R is NULL (at least
one should be non-NULL), then corresponding QPREC or RPREC
should be 0. */
void
__divmodbitint4 (UWtype *q, SItype qprec,
UWtype *r, SItype rprec,
const UWtype *u, SItype uprec,
const UWtype *v, SItype vprec)
{
uprec = bitint_reduce_prec (&u, uprec);
vprec = bitint_reduce_prec (&v, vprec);
USItype auprec = uprec < 0 ? -uprec : uprec;
USItype avprec = vprec < 0 ? -vprec : vprec;
USItype un = (auprec + W_TYPE_SIZE - 1) / W_TYPE_SIZE;
USItype vn = (avprec + W_TYPE_SIZE - 1) / W_TYPE_SIZE;
USItype qn = ((USItype) qprec + W_TYPE_SIZE - 1) / W_TYPE_SIZE;
USItype rn = ((USItype) rprec + W_TYPE_SIZE - 1) / W_TYPE_SIZE;
USItype up = auprec % W_TYPE_SIZE;
USItype vp = avprec % W_TYPE_SIZE;
if (__builtin_expect (un < vn, 0))
{
/* If abs(v) > abs(u), then q is 0 and r is u. */
if (q)
__builtin_memset (q, 0, qn * sizeof (UWtype));
if (r == NULL)
return;
#if __LIBGCC_BITINT_ORDER__ == __ORDER_BIG_ENDIAN__
r += rn - 1;
u += un - 1;
#endif
if (up)
--un;
if (rn < un)
un = rn;
for (rn -= un; un; --un)
{
*r = *u;
r += BITINT_INC;
u += BITINT_INC;
}
if (!rn)
return;
if (up)
{
if (uprec > 0)
*r = *u & (((UWtype) 1 << up) - 1);
else
*r = *u | ((UWtype) -1 << up);
r += BITINT_INC;
if (!--rn)
return;
}
UWtype c = uprec < 0 ? (UWtype) -1 : (UWtype) 0;
for (; rn; --rn)
{
*r = c;
r += BITINT_INC;
}
return;
}
USItype qn2 = un - vn + 1;
if (qn >= qn2)
qn2 = 0;
USItype sz = un + 1 + vn + qn2;
UWtype *buf = __builtin_alloca (sz * sizeof (UWtype));
USItype uidx, vidx;
#if __LIBGCC_BITINT_ORDER__ == __ORDER_BIG_ENDIAN__
uidx = un - 1;
vidx = vn - 1;
#else
uidx = 0;
vidx = 0;
#endif
if (uprec < 0)
bitint_negate (buf + BITINT_END (uidx + 1, 0), u + uidx, un);
else
__builtin_memcpy (buf + BITINT_END (1, 0), u, un * sizeof (UWtype));
if (up)
buf[BITINT_END (1, un - 1)] &= (((UWtype) 1 << up) - 1);
if (vprec < 0)
bitint_negate (buf + un + 1 + vidx, v + vidx, vn);
else
__builtin_memcpy (buf + un + 1, v, vn * sizeof (UWtype));
if (vp)
buf[un + 1 + BITINT_END (0, vn - 1)] &= (((UWtype) 1 << vp) - 1);
UWtype *u2 = buf;
UWtype *v2 = u2 + un + 1;
UWtype *q2 = v2 + vn;
if (!qn2)
q2 = q + BITINT_END (qn - (un - vn + 1), 0);
/* Knuth's algorithm. See also ../gcc/wide-int.cc (divmod_internal_2). */
#ifndef UDIV_NEEDS_NORMALIZATION
/* Handle single limb divisor first. */
if (vn == 1)
{
UWtype vv = v2[0];
if (vv == 0)
vv = 1 / vv; /* Divide intentionally by zero. */
UWtype k = 0;
#if __LIBGCC_BITINT_ORDER__ == __ORDER_BIG_ENDIAN__
for (SItype i = 0; i <= un - 1; ++i)
#else
for (SItype i = un - 1; i >= 0; --i)
#endif
udiv_qrnnd (q2[i], k, k, u2[BITINT_END (i + 1, i)], vv);
if (r != NULL)
r[BITINT_END (rn - 1, 0)] = k;
}
else
#endif
{
SItype s;
#ifdef UDIV_NEEDS_NORMALIZATION
if (vn == 1 && v2[0] == 0)
s = 0;
else
#endif
if (sizeof (0U) == sizeof (UWtype))
s = __builtin_clz (v2[BITINT_END (0, vn - 1)]);
else if (sizeof (0UL) == sizeof (UWtype))
s = __builtin_clzl (v2[BITINT_END (0, vn - 1)]);
else
s = __builtin_clzll (v2[BITINT_END (0, vn - 1)]);
if (s)
{
/* Normalize by shifting v2 left so that it has msb set. */
const SItype n = sizeof (UWtype) * __CHAR_BIT__;
#if __LIBGCC_BITINT_ORDER__ == __ORDER_BIG_ENDIAN__
for (SItype i = 0; i < vn - 1; ++i)
#else
for (SItype i = vn - 1; i > 0; --i)
#endif
v2[i] = (v2[i] << s) | (v2[i - BITINT_INC] >> (n - s));
v2[vidx] = v2[vidx] << s;
/* And shift u2 left by the same amount. */
u2[BITINT_END (0, un)] = u2[BITINT_END (1, un - 1)] >> (n - s);
#if __LIBGCC_BITINT_ORDER__ == __ORDER_BIG_ENDIAN__
for (SItype i = 1; i < un; ++i)
#else
for (SItype i = un - 1; i > 0; --i)
#endif
u2[i] = (u2[i] << s) | (u2[i - BITINT_INC] >> (n - s));
u2[BITINT_END (un, 0)] = u2[BITINT_END (un, 0)] << s;
}
else
u2[BITINT_END (0, un)] = 0;
#ifdef UDIV_NEEDS_NORMALIZATION
/* Handle single limb divisor first. */
if (vn == 1)
{
UWtype vv = v2[0];
if (vv == 0)
vv = 1 / vv; /* Divide intentionally by zero. */
UWtype k = u2[BITINT_END (0, un)];
#if __LIBGCC_BITINT_ORDER__ == __ORDER_BIG_ENDIAN__
for (SItype i = 0; i <= un - 1; ++i)
#else
for (SItype i = un - 1; i >= 0; --i)
#endif
udiv_qrnnd (q2[i], k, k, u2[BITINT_END (i + 1, i)], vv);
if (r != NULL)
r[BITINT_END (rn - 1, 0)] = k >> s;
}
else
#endif
{
UWtype vv1 = v2[BITINT_END (0, vn - 1)];
UWtype vv0 = v2[BITINT_END (1, vn - 2)];
/* Main loop. */
for (SItype j = un - vn; j >= 0; --j)
{
/* Compute estimate in qhat. */
UWtype uv1 = u2[BITINT_END (un - j - vn, j + vn)];
UWtype uv0 = u2[BITINT_END (un - j - vn + 1, j + vn - 1)];
UWtype qhat, rhat, hi, lo, c;
if (uv1 >= vv1)
{
/* udiv_qrnnd doesn't support quotients which don't
fit into UWtype, so subtract from uv1:uv0 vv1
first. */
uv1 -= vv1 + __builtin_sub_overflow (uv0, vv1, &uv0);
udiv_qrnnd (qhat, rhat, uv1, uv0, vv1);
if (!__builtin_add_overflow (rhat, vv1, &rhat))
goto again;
}
else
{
udiv_qrnnd (qhat, rhat, uv1, uv0, vv1);
again:
umul_ppmm (hi, lo, qhat, vv0);
if (hi > rhat
|| (hi == rhat
&& lo > u2[BITINT_END (un - j - vn + 2,
j + vn - 2)]))
{
--qhat;
if (!__builtin_add_overflow (rhat, vv1, &rhat))
goto again;
}
}
c = bitint_submul_1 (u2 + BITINT_END (un - j, j),
v2 + BITINT_END (vn - 1, 0), qhat, vn);
u2[BITINT_END (un - j - vn, j + vn)] -= c;
/* If we've subtracted too much, decrease qhat and
and add back. */
if ((Wtype) u2[BITINT_END (un - j - vn, j + vn)] < 0)
{
--qhat;
c = 0;
for (USItype i = 0; i < vn; ++i)
{
UWtype s = v2[BITINT_END (vn - 1 - i, i)];
UWtype d = u2[BITINT_END (un - i - j, i + j)];
UWtype c1 = __builtin_add_overflow (d, s, &d);
UWtype c2 = __builtin_add_overflow (d, c, &d);
c = c1 + c2;
u2[BITINT_END (un - i - j, i + j)] = d;
}
u2[BITINT_END (un - j - vn, j + vn)] += c;
}
q2[BITINT_END (un - vn - j, j)] = qhat;
}
if (r != NULL)
{
if (s)
{
const SItype n = sizeof (UWtype) * __CHAR_BIT__;
/* Unnormalize remainder. */
USItype i;
for (i = 0; i < vn && i < rn; ++i)
r[BITINT_END (rn - 1 - i, i)]
= ((u2[BITINT_END (un - i, i)] >> s)
| (u2[BITINT_END (un - i - 1, i + 1)] << (n - s)));
if (i < rn)
r[BITINT_END (rn - vn, vn - 1)]
= u2[BITINT_END (un - vn + 1, vn - 1)] >> s;
}
else if (rn > vn)
__builtin_memcpy (&r[BITINT_END (rn - vn, 0)],
&u2[BITINT_END (un + 1 - vn, 0)],
vn * sizeof (UWtype));
else
__builtin_memcpy (&r[0], &u2[BITINT_END (un + 1 - rn, 0)],
rn * sizeof (UWtype));
}
}
}
if (q != NULL)
{
if ((uprec < 0) ^ (vprec < 0))
{
/* Negative quotient. */
USItype n;
if (un - vn + 1 > qn)
n = qn;
else
n = un - vn + 1;
bitint_negate (q + BITINT_END (qn - 1, 0),
q2 + BITINT_END (un - vn, 0), n);
if (qn > n)
__builtin_memset (q + BITINT_END (0, n), -1,
(qn - n) * sizeof (UWtype));
}
else
{
/* Positive quotient. */
if (qn2)
__builtin_memcpy (q, q2 + BITINT_END (un - vn + 1 - qn, 0),
qn * sizeof (UWtype));
else if (qn > un - vn + 1)
__builtin_memset (q + BITINT_END (0, un - vn + 1), 0,
(qn - (un - vn + 1)) * sizeof (UWtype));
}
}
if (r != NULL)
{
if (uprec < 0)
{
/* Negative remainder. */
bitint_negate (r + BITINT_END (rn - 1, 0),
r + BITINT_END (rn - 1, 0),
rn > vn ? vn : rn);
if (rn > vn)
__builtin_memset (r + BITINT_END (0, vn), -1,
(rn - vn) * sizeof (UWtype));
}
else
{
/* Positive remainder. */
if (rn > vn)
__builtin_memset (r + BITINT_END (0, vn), 0,
(rn - vn) * sizeof (UWtype));
}
}
}
#endif
#endif
#ifdef L_cmpdi2
cmp_return_type
__cmpdi2 (DWtype a, DWtype b)

View file

@ -181,6 +181,12 @@ typedef int shift_count_type __attribute__((mode (__libgcc_shift_count__)));
#define float bogus_type
#define double bogus_type
#if (defined(__BITINT_MAXWIDTH__) \
&& (defined(L_mulbitint3) || defined(L_divmodbitint4)))
#undef LIBGCC2_UNITS_PER_WORD
#define LIBGCC2_UNITS_PER_WORD (__LIBGCC_BITINT_LIMB_WIDTH__ / __CHAR_BIT__)
#endif
/* Versions prior to 3.4.4 were not taking into account the word size for
the 5 trapping arithmetic functions absv, addv, subv, mulv and negv. As
a consequence, the si and di variants were always and the only ones emitted.
@ -390,6 +396,15 @@ extern DWtype __divmoddi4 (DWtype, DWtype, DWtype *);
extern UDWtype __udivmoddi4 (UDWtype, UDWtype, UDWtype *);
#endif
#if (defined(__BITINT_MAXWIDTH__) \
&& (defined(L_mulbitint3) || defined(L_divmodbitint4)))
/* _BitInt support. */
extern void __mulbitint3 (UWtype *, SItype, const UWtype *, SItype,
const UWtype *, SItype);
extern void __divmodbitint4 (UWtype *, SItype, UWtype *, SItype,
const UWtype *, SItype, const UWtype *, SItype);
#endif
/* __negdi2 is static inline when building other libgcc2 portions. */
#if !defined(L_divdi3) && !defined(L_moddi3)
extern DWtype __negdi2 (DWtype);

329
libgcc/soft-fp/bitint.h Normal file
View file

@ -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 */

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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); \
})); \
\