public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
From: Jakub Jelinek <jakub@redhat.com>
To: Joseph Myers <joseph@codesourcery.com>
Cc: Ian Lance Taylor <ian@airs.com>, gcc-patches@gcc.gnu.org
Subject: Re: [PATCH 9/12] libgcc _BitInt support [PR102989]
Date: Sat, 2 Sep 2023 13:42:46 +0200	[thread overview]
Message-ID: <ZPMftiNAbxvN/l+y@tucnak> (raw)
In-Reply-To: <18ed8557-5c75-4f3-e9a9-3cba6ab0a5b1@codesourcery.com>

On Fri, Sep 01, 2023 at 09:48:22PM +0000, Joseph Myers wrote:
> This patch is OK with these fixes.

Thanks, here is an updated patch, thanks for catching the _Decimal128
bug.  Will post testsuite additions/adjustment patch as follow-up on Monday.

2023-09-02  Jakub Jelinek  <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.

--- libgcc/config/aarch64/t-softfp.jj	2023-08-08 15:54:35.737595343 +0200
+++ libgcc/config/aarch64/t-softfp	2023-08-08 16:12:02.346939560 +0200
@@ -3,7 +3,7 @@ softfp_int_modes := si di ti
 softfp_extensions := sftf dftf hftf bfsf
 softfp_truncations := tfsf tfdf tfhf tfbf dfbf sfbf hfbf
 softfp_exclude_libgcc2 := n
-softfp_extras := fixhfti fixunshfti floattihf floatuntihf \
+softfp_extras += fixhfti fixunshfti floattihf floatuntihf \
 		 floatdibf floatundibf floattibf floatuntibf
 
 TARGET_LIBGCC2_CFLAGS += -Wno-missing-prototypes
--- libgcc/config/i386/64/t-softfp.jj	2023-08-08 15:54:35.766594936 +0200
+++ libgcc/config/i386/64/t-softfp	2023-08-08 16:12:02.346939560 +0200
@@ -1,4 +1,4 @@
-softfp_extras := fixhfti fixunshfti floattihf floatuntihf \
+softfp_extras += fixhfti fixunshfti floattihf floatuntihf \
 		 floattibf floatuntibf
 
 CFLAGS-fixhfti.c += -msse2
--- libgcc/config/i386/libgcc-glibc.ver.jj	2023-08-08 15:54:35.831594026 +0200
+++ libgcc/config/i386/libgcc-glibc.ver	2023-08-08 16:12:02.347939546 +0200
@@ -226,3 +226,13 @@ GCC_13.0.0 {
   __truncxfbf2
   __trunchfbf2
 }
+
+%inherit GCC_14.0.0 GCC_13.0.0
+GCC_14.0.0 {
+  __PFX__fixxfbitint
+  __PFX__fixtfbitint
+  __PFX__floatbitintbf
+  __PFX__floatbitinthf
+  __PFX__floatbitintxf
+  __PFX__floatbitinttf
+}
--- libgcc/config/i386/t-softfp.jj	2023-08-08 15:55:09.819118062 +0200
+++ libgcc/config/i386/t-softfp	2023-08-08 16:12:02.347939546 +0200
@@ -10,7 +10,7 @@ softfp_extensions := hfsf hfdf hftf hfxf
 softfp_truncations := tfhf xfhf dfhf sfhf tfsf dfsf tfdf tfxf \
 		      tfbf xfbf dfbf sfbf hfbf
 
-softfp_extras += eqhf2
+softfp_extras += eqhf2 fixxfbitint $(foreach m,hf bf xf,floatbitint$(m))
 
 CFLAGS-extendhfsf2.c += -msse2
 CFLAGS-extendhfdf2.c += -msse2
@@ -28,6 +28,9 @@ CFLAGS-truncxfbf2.c += -msse2
 CFLAGS-trunctfbf2.c += -msse2
 CFLAGS-trunchfbf2.c += -msse2
 
+CFLAGS-floatbitintbf.c += -msse2
+CFLAGS-floatbitinthf.c += -msse2
+
 CFLAGS-eqhf2.c += -msse2
 CFLAGS-_divhc3.c += -msse2
 CFLAGS-_mulhc3.c += -msse2
--- libgcc/config/riscv/t-softfp32.jj	2023-08-08 15:54:35.920592780 +0200
+++ libgcc/config/riscv/t-softfp32	2023-08-08 16:12:02.347939546 +0200
@@ -13,7 +13,7 @@ softfp_extensions := sftf dftf
 softfp_truncations := tfsf tfdf
 
 # Enable divide routines to make -mno-fdiv work.
-softfp_extras := divsf3 divdf3
+softfp_extras += divsf3 divdf3
 
 else
 # !ABI_DOUBLE
@@ -28,7 +28,7 @@ else
 # ABI_SINGLE
 
 # Enable divide routines to make -mno-fdiv work.
-softfp_extras := divsf3
+softfp_extras += divsf3
 
 endif
 
@@ -38,7 +38,7 @@ else
 # ABI_QUAD
 
 # Enable divide routines to make -mno-fdiv work.
-softfp_extras := divsf3 divdf3 divtf3
+softfp_extras += divsf3 divdf3 divtf3
 
 endif
 
--- libgcc/config/rs6000/t-e500v1-fp.jj	2023-08-08 15:54:35.965592150 +0200
+++ libgcc/config/rs6000/t-e500v1-fp	2023-08-08 16:12:02.347939546 +0200
@@ -29,4 +29,4 @@ softfp_int_modes := si di
 softfp_extensions := sfdf
 softfp_truncations := dfsf
 softfp_exclude_libgcc2 := n
-softfp_extras := unordsf2
+softfp_extras += unordsf2
--- libgcc/config/rs6000/t-e500v2-fp.jj	2023-08-08 15:54:35.965592150 +0200
+++ libgcc/config/rs6000/t-e500v2-fp	2023-08-08 16:12:02.347939546 +0200
@@ -23,4 +23,4 @@ softfp_int_modes :=
 softfp_extensions :=
 softfp_truncations :=
 softfp_exclude_libgcc2 := n
-softfp_extras := unordsf2 unorddf2
+softfp_extras += unordsf2 unorddf2
--- libgcc/config/t-softfp.jj	2023-08-08 15:54:35.992591772 +0200
+++ libgcc/config/t-softfp	2023-08-08 16:22:09.404440148 +0200
@@ -64,12 +64,21 @@ softfp_float_funcs = add$(m)3 div$(m)3 e
   neg$(m)2 sub$(m)3 unord$(m)2
 softfp_floatint_funcs = fix$(m)$(i) fixuns$(m)$(i) \
   float$(i)$(m) floatun$(i)$(m)
+softfp_floatbitint_funcs = fix$(m)bitint floatbitint$(m)
+softfp_bid_list := 
+ifeq ($(decimal_float),yes)
+ifeq ($(enable_decimal_float),bid)
+softfp_bid_list += bitintpow10 \
+		   $(foreach m,sd dd td,fix$(m)bitint floatbitint$(m))
+endif
+endif
 
 softfp_func_list := \
   $(foreach m,$(softfp_float_modes), \
               $(softfp_float_funcs) \
               $(foreach i,$(softfp_int_modes), \
                           $(softfp_floatint_funcs))) \
+  $(foreach m,sf df,$(softfp_floatbitint_funcs)) \
   $(foreach e,$(softfp_extensions),extend$(e)2) \
   $(foreach t,$(softfp_truncations),trunc$(t)2) \
   $(softfp_extras)
@@ -116,6 +125,8 @@ softfp_file_list := \
   $(addsuffix .c,$(addprefix $(srcdir)/soft-fp/,$(softfp_func_list)))
 endif
 endif
+softfp_bid_file_list := \
+  $(addsuffix .c,$(addprefix $(srcdir)/soft-fp/,$(softfp_bid_list)))
 
 # Disable missing prototype and type limit warnings.  The prototypes
 # for the functions in the soft-fp files have not been brought across
@@ -129,6 +140,7 @@ soft-fp-objects = $(addsuffix $(objext),
 $(soft-fp-objects) : INTERNAL_CFLAGS += -Wno-missing-prototypes -Wno-type-limits
 
 LIB2ADD += $(softfp_file_list)
+LIB2ADD_ST += $(softfp_bid_file_list)
 
 ifneq ($(softfp_exclude_libgcc2),y)
 # Functions in libgcc2.c are excluded for each soft-float mode (a
--- libgcc/config/t-softfp-sfdftf.jj	2023-08-08 15:54:35.992591772 +0200
+++ libgcc/config/t-softfp-sfdftf	2023-08-08 16:12:02.347939546 +0200
@@ -2,4 +2,5 @@ softfp_float_modes := sf df tf
 softfp_int_modes := si di
 softfp_extensions := sfdf sftf dftf xftf
 softfp_truncations := dfsf tfsf tfdf tfxf
+softfp_extras += fixtfbitint floatbitinttf
 softfp_exclude_libgcc2 := n
--- libgcc/config/t-softfp-tf.jj	2023-08-08 15:54:36.011591506 +0200
+++ libgcc/config/t-softfp-tf	2023-08-08 16:12:02.347939546 +0200
@@ -2,4 +2,5 @@ softfp_float_modes := tf
 softfp_int_modes := si di ti
 softfp_extensions := sftf dftf xftf
 softfp_truncations := tfsf tfdf tfxf
+softfp_extras += fixtfbitint floatbitinttf
 softfp_exclude_libgcc2 := n
--- libgcc/libgcc2.c.jj	2023-08-08 15:54:36.059590834 +0200
+++ libgcc/libgcc2.c	2023-08-08 16:12:02.348939532 +0200
@@ -1301,6 +1301,687 @@ __udivdi3 (UDWtype n, UDWtype d)
 }
 #endif
 \f
+#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
+\f
 #ifdef L_cmpdi2
 cmp_return_type
 __cmpdi2 (DWtype a, DWtype b)
--- libgcc/libgcc2.h.jj	2023-08-08 15:54:36.075590609 +0200
+++ libgcc/libgcc2.h	2023-08-08 16:12:02.348939532 +0200
@@ -181,6 +181,12 @@ typedef int shift_count_type __attribute
 #define float bogus_type
 #define double bogus_type
 
+#if (defined(__BITINT_MAXWIDTH__) \
+     && (defined(L_mulbitint3) || defined(L_divmodbitint4)))
+#undef LIBGCC2_UNITS_PER_WORD
+#define LIBGCC2_UNITS_PER_WORD (__LIBGCC_BITINT_LIMB_WIDTH__ / __CHAR_BIT__)
+#endif
+
 /* Versions prior to 3.4.4 were not taking into account the word size for
    the 5 trapping arithmetic functions absv, addv, subv, mulv and negv.  As
    a consequence, the si and di variants were always and the only ones emitted.
@@ -390,6 +396,15 @@ extern DWtype __divmoddi4 (DWtype, DWtyp
 extern UDWtype __udivmoddi4 (UDWtype, UDWtype, UDWtype *);
 #endif
 
+#if (defined(__BITINT_MAXWIDTH__) \
+     && (defined(L_mulbitint3) || defined(L_divmodbitint4)))
+/* _BitInt support.  */
+extern void __mulbitint3 (UWtype *, SItype, const UWtype *, SItype,
+			  const UWtype *, SItype);
+extern void __divmodbitint4 (UWtype *, SItype, UWtype *, SItype,
+			     const UWtype *, SItype, const UWtype *, SItype);
+#endif
+
 /* __negdi2 is static inline when building other libgcc2 portions.  */
 #if !defined(L_divdi3) && !defined(L_moddi3)
 extern DWtype __negdi2 (DWtype);
--- libgcc/libgcc-std.ver.in.jj	2023-08-08 15:54:36.029591253 +0200
+++ libgcc/libgcc-std.ver.in	2023-08-08 16:12:02.348939532 +0200
@@ -1944,3 +1944,13 @@ GCC_7.0.0 {
   __PFX__divmoddi4
   __PFX__divmodti4
 }
+
+%inherit GCC_14.0.0 GCC_7.0.0
+GCC_14.0.0 {
+  __PFX__mulbitint3
+  __PFX__divmodbitint4
+  __PFX__fixsfbitint
+  __PFX__fixdfbitint
+  __PFX__floatbitintsf
+  __PFX__floatbitintdf
+}
--- libgcc/Makefile.in.jj	2023-08-08 15:54:35.711595707 +0200
+++ libgcc/Makefile.in	2023-08-08 16:12:02.348939532 +0200
@@ -446,7 +446,7 @@ lib2funcs = _muldi3 _negdi2 _lshrdi3 _as
 	    _paritysi2 _paritydi2 _powisf2 _powidf2 _powixf2 _powitf2	   \
 	    _mulhc3 _mulsc3 _muldc3 _mulxc3 _multc3 _divhc3 _divsc3	   \
 	    _divdc3 _divxc3 _divtc3 _bswapsi2 _bswapdi2 _clrsbsi2	   \
-	    _clrsbdi2
+	    _clrsbdi2 _mulbitint3
 
 # The floating-point conversion routines that involve a single-word integer.
 # XX stands for the integer mode.
@@ -466,7 +466,8 @@ endif
 # These might cause a divide overflow trap and so are compiled with
 # unwinder info.
 LIB2_DIVMOD_FUNCS = _divdi3 _moddi3 _divmoddi4 \
-		    _udivdi3 _umoddi3 _udivmoddi4 _udiv_w_sdiv
+		    _udivdi3 _umoddi3 _udivmoddi4 _udiv_w_sdiv \
+		    _divmodbitint4
 
 # Remove any objects from lib2funcs and LIB2_DIVMOD_FUNCS that are
 # defined as optimized assembly code in LIB1ASMFUNCS or as C code
--- libgcc/soft-fp/bitint.h.jj	2023-08-08 16:12:02.348939532 +0200
+++ libgcc/soft-fp/bitint.h	2023-08-08 16:21:45.953768373 +0200
@@ -0,0 +1,329 @@
+/* Software floating-point emulation.
+   Definitions for _BitInt implementation details.
+
+   Copyright (C) 2023 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<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 */
--- libgcc/soft-fp/fixdfbitint.c.jj	2023-08-08 16:12:02.348939532 +0200
+++ libgcc/soft-fp/fixdfbitint.c	2023-08-08 16:12:02.348939532 +0200
@@ -0,0 +1,71 @@
+/* Software floating-point emulation.
+   Convert IEEE double to signed or unsigned _BitInt.
+
+   Copyright (C) 2023 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<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
--- libgcc/soft-fp/fixsfbitint.c.jj	2023-08-08 16:12:02.348939532 +0200
+++ libgcc/soft-fp/fixsfbitint.c	2023-08-08 16:12:02.348939532 +0200
@@ -0,0 +1,71 @@
+/* Software floating-point emulation.
+   Convert IEEE single to signed or unsigned _BitInt.
+
+   Copyright (C) 2023 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<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
--- libgcc/soft-fp/fixtfbitint.c.jj	2023-08-08 16:12:02.349939518 +0200
+++ libgcc/soft-fp/fixtfbitint.c	2023-08-08 16:12:02.349939518 +0200
@@ -0,0 +1,81 @@
+/* Software floating-point emulation.
+   Convert IEEE quad to signed or unsigned _BitInt.
+
+   Copyright (C) 2023 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<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
--- libgcc/soft-fp/fixxfbitint.c.jj	2023-08-08 16:12:02.349939518 +0200
+++ libgcc/soft-fp/fixxfbitint.c	2023-08-08 16:12:02.349939518 +0200
@@ -0,0 +1,82 @@
+/* Software floating-point emulation.
+   Convert IEEE extended to signed or unsigned _BitInt.
+
+   Copyright (C) 2023 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<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
--- libgcc/soft-fp/floatbitintbf.c.jj	2023-08-08 16:12:02.349939518 +0200
+++ libgcc/soft-fp/floatbitintbf.c	2023-08-08 16:12:02.349939518 +0200
@@ -0,0 +1,59 @@
+/* Software floating-point emulation.
+   Convert a _BitInt to bfloat16.
+
+   Copyright (C) 2023 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<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
--- libgcc/soft-fp/floatbitintdf.c.jj	2023-08-08 16:12:02.349939518 +0200
+++ libgcc/soft-fp/floatbitintdf.c	2023-08-08 16:12:02.349939518 +0200
@@ -0,0 +1,64 @@
+/* Software floating-point emulation.
+   Convert a _BitInt to IEEE double.
+
+   Copyright (C) 2023 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<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
--- libgcc/soft-fp/floatbitinthf.c.jj	2023-08-08 16:12:02.349939518 +0200
+++ libgcc/soft-fp/floatbitinthf.c	2023-08-08 16:12:02.349939518 +0200
@@ -0,0 +1,59 @@
+/* Software floating-point emulation.
+   Convert a _BitInt to IEEE half.
+
+   Copyright (C) 2023 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<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
--- libgcc/soft-fp/floatbitintsf.c.jj	2023-08-08 16:12:02.349939518 +0200
+++ libgcc/soft-fp/floatbitintsf.c	2023-08-08 16:12:02.349939518 +0200
@@ -0,0 +1,59 @@
+/* Software floating-point emulation.
+   Convert a _BitInt to IEEE single.
+
+   Copyright (C) 2023 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<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
--- libgcc/soft-fp/floatbitinttf.c.jj	2023-08-08 16:12:02.349939518 +0200
+++ libgcc/soft-fp/floatbitinttf.c	2023-08-08 16:12:02.349939518 +0200
@@ -0,0 +1,73 @@
+/* Software floating-point emulation.
+   Convert a _BitInt to IEEE quad.
+
+   Copyright (C) 2023 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<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
--- libgcc/soft-fp/floatbitintxf.c.jj	2023-08-08 16:12:02.349939518 +0200
+++ libgcc/soft-fp/floatbitintxf.c	2023-08-08 16:12:02.349939518 +0200
@@ -0,0 +1,74 @@
+/* Software floating-point emulation.
+   Convert a _BitInt to IEEE extended.
+
+   Copyright (C) 2023 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<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
--- libgcc/soft-fp/op-common.h.jj	2023-08-08 15:54:36.110590119 +0200
+++ libgcc/soft-fp/op-common.h	2023-08-08 16:12:02.349939518 +0200
@@ -1800,7 +1800,7 @@
 	  if ((X##_s = ((r) < 0)))					\
 	    _FP_FROM_INT_ur = -_FP_FROM_INT_ur;				\
 									\
-	  _FP_STATIC_ASSERT ((rsize) <= 2 * _FP_W_TYPE_SIZE,		\
+	  _FP_STATIC_ASSERT ((rsize) <= 4 * _FP_W_TYPE_SIZE,		\
 			     "rsize too large");			\
 	  (void) (((rsize) <= _FP_W_TYPE_SIZE)				\
 		  ? ({							\
@@ -1810,13 +1810,38 @@
 		      X##_e = (_FP_EXPBIAS_##fs + _FP_W_TYPE_SIZE - 1	\
 			       - _FP_FROM_INT_lz);			\
 		    })							\
-		  : ({						\
+		  : ((rsize) <= 2 * _FP_W_TYPE_SIZE)			\
+		  ? ({							\
 		      int _FP_FROM_INT_lz;				\
 		      __FP_CLZ_2 (_FP_FROM_INT_lz,			\
 				  (_FP_W_TYPE) (_FP_FROM_INT_ur		\
 						>> _FP_W_TYPE_SIZE),	\
 				  (_FP_W_TYPE) _FP_FROM_INT_ur);	\
-		      X##_e = (_FP_EXPBIAS_##fs + 2 * _FP_W_TYPE_SIZE - 1 \
+		      X##_e = (_FP_EXPBIAS_##fs				\
+			       + 2 * _FP_W_TYPE_SIZE - 1		\
+			       - _FP_FROM_INT_lz);			\
+		    })							\
+		  : ({							\
+		      int _FP_FROM_INT_lz;				\
+		      if (_FP_FROM_INT_ur >> (2 * _FP_W_TYPE_SIZE))	\
+			{						\
+			  rtype _FP_FROM_INT_uru			\
+			    = _FP_FROM_INT_ur >> (2 * _FP_W_TYPE_SIZE);	\
+			  __FP_CLZ_2 (_FP_FROM_INT_lz,			\
+				      (_FP_W_TYPE) (_FP_FROM_INT_uru	\
+						    >> _FP_W_TYPE_SIZE),\
+				      (_FP_W_TYPE) _FP_FROM_INT_uru);	\
+			}						\
+		      else						\
+			{						\
+			  __FP_CLZ_2 (_FP_FROM_INT_lz,			\
+				      (_FP_W_TYPE) (_FP_FROM_INT_ur	\
+						    >> _FP_W_TYPE_SIZE),\
+				      (_FP_W_TYPE) _FP_FROM_INT_ur);	\
+			  _FP_FROM_INT_lz += 2 * _FP_W_TYPE_SIZE;	\
+			}						\
+		      X##_e = (_FP_EXPBIAS_##fs				\
+			       + 4 * _FP_W_TYPE_SIZE - 1		\
 			       - _FP_FROM_INT_lz);			\
 		    }));						\
 									\
--- libgcc/soft-fp/bitintpow10.c.jj	2023-08-08 16:21:45.956768331 +0200
+++ libgcc/soft-fp/bitintpow10.c	2023-08-09 15:22:45.519805895 +0200
@@ -0,0 +1,132 @@
+/* Software floating-point emulation.
+   Compute powers of 10 into _BitInt.
+
+   Copyright (C) 2023 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<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
--- libgcc/soft-fp/fixsdbitint.c.jj	2023-08-08 16:21:45.953768373 +0200
+++ libgcc/soft-fp/fixsdbitint.c	2023-08-08 16:21:45.953768373 +0200
@@ -0,0 +1,196 @@
+/* Software floating-point emulation.
+   Convert _Decimal32 to signed or unsigned _BitInt.
+
+   Copyright (C) 2023 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<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
--- libgcc/soft-fp/fixddbitint.c.jj	2023-08-08 16:21:45.953768373 +0200
+++ libgcc/soft-fp/fixddbitint.c	2023-08-08 16:21:45.953768373 +0200
@@ -0,0 +1,205 @@
+/* Software floating-point emulation.
+   Convert _Decimal64 to signed or unsigned _BitInt.
+
+   Copyright (C) 2023 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<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
--- libgcc/soft-fp/fixtdbitint.c.jj	2023-08-08 16:21:45.953768373 +0200
+++ libgcc/soft-fp/fixtdbitint.c	2023-08-08 16:21:45.953768373 +0200
@@ -0,0 +1,242 @@
+/* Software floating-point emulation.
+   Convert _Decimal128 to signed or unsigned _BitInt.
+
+   Copyright (C) 2023 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<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 > 0x378d8e63ffffffff))
+	{
+	  mantissahi = 0;
+	  mantissalo = 0;
+	}
+    }
+  else if ((t & (3 << 12)) != (3 << 12))
+    {
+      mantissahi = 0;
+      mantissalo = 0;
+      exponent = t & 0x3fff;
+    }
+  else
+    {
+      FP_SET_EXCEPTION (FP_EX_INVALID
+			| FP_EX_INVALID_CVI
+			| ((FP_EX_INVALID_SNAN
+			    && ((t & 0x800)) != 0)
+			   ? FP_EX_INVALID_SNAN : 0));
+    ovf:
+      if (!sgn)
+	__builtin_memset (r, -1, rn * sizeof (UBILtype));
+      else
+	__builtin_memset (r, 0, rn * sizeof (UBILtype));
+      if (sgn ^ (rprec >= 0))
+	r[BITINT_END (0, rn - 1)]
+	  |= (UBILtype) -1 << ((arprec - 1) % BIL_TYPE_SIZE);
+      else
+	r[BITINT_END (0, rn - 1)]
+	  &= ~((UBILtype) -1 << ((arprec - 1) % BIL_TYPE_SIZE));
+      goto done;
+    }
+  exponent -= 6176;
+
+  if (mantissahi == 0 && mantissalo == 0)
+    {
+      /* Zero (with any exponent).  */
+    zero:
+      __builtin_memset (r, 0, rn * sizeof (UBILtype));
+      goto done;
+    }
+  if (exponent <= -34)
+    {
+      FP_SET_EXCEPTION (FP_EX_INEXACT);
+      goto zero;
+    }
+  if (exponent < 0)
+    {
+      UBILtype limbs[4 * 128 / BIL_TYPE_SIZE];
+#if BIL_TYPE_SIZE == 64
+      limbs[BITINT_END (0, 1)] = mantissahi;
+      limbs[BITINT_END (1, 0)] = mantissalo;
+#elif BIL_TYPE_SIZE == 32
+      limbs[BITINT_END (0, 3)] = mantissahi >> 32;
+      limbs[BITINT_END (1, 2)] = mantissahi;
+      limbs[BITINT_END (2, 1)] = mantissalo >> 32;
+      limbs[BITINT_END (3, 0)] = mantissalo;
+#elif
+# error Unhandled BIL_TYPE_SIZE
+#endif
+      __bid_pow10bitint (&limbs[128 / BIL_TYPE_SIZE], 128, -exponent);
+      __divmodbitint4 (&limbs[2 * 128 / BIL_TYPE_SIZE], 128,
+		       &limbs[3 * 128 / BIL_TYPE_SIZE], 128,
+		       &limbs[0], 128, &limbs[128 / BIL_TYPE_SIZE], 128);
+      UDItype rem;
+#if BIL_TYPE_SIZE == 64
+      mantissahi = limbs[BITINT_END (4, 5)];
+      mantissalo = limbs[BITINT_END (5, 4)];
+      rem = limbs[6] | limbs[7];
+#elif BIL_TYPE_SIZE == 32
+      mantissahi = limbs[BITINT_END (8, 11)] << 32;
+      mantissahi |= limbs[BITINT_END (9, 10)];
+      mantissalo = limbs[BITINT_END (10, 9)] << 32;
+      mantissalo |= limbs[BITINT_END (11, 8)];
+      rem = limbs[12] | limbs[13] | limbs[14] | limbs[15];
+#endif
+      if (rem)
+	FP_SET_EXCEPTION (FP_EX_INEXACT);
+      if (mantissahi == 0 && mantissalo == 0)
+	goto zero;
+      exponent = 0;
+    }
+
+  if (rprec >= 0 && sgn)
+    {
+    ovf_ex:
+      FP_SET_EXCEPTION (FP_EX_INVALID | FP_EX_INVALID_CVI);
+      goto ovf;
+    }
+
+  /* Lower estimate for number of bits needed for pow10 (exponent).  */
+  exp_bits = exponent / 3;
+  exp_bits = exp_bits * 10 - exp_bits / 29;
+  if (mantissahi)
+    mant_bits = sizeof (0ULL) * __CHAR_BIT__ - __builtin_clzll (mantissahi)
+		+ 64;
+  else
+    mant_bits = sizeof (0ULL) * __CHAR_BIT__ - __builtin_clzll (mantissalo);
+  if (exp_bits + mant_bits > arprec + 1)
+    goto ovf_ex;
+  /* Upper estimate for number of bits needed for pow10 (exponent).  */
+  exp_bits = (exponent + 2) / 3;
+  exp_bits = exp_bits * 10 - exp_bits / 30;
+  if (exp_bits == 0)
+    exp_bits = 1;
+  pow10_limbs = (exp_bits + BIL_TYPE_SIZE - 1) / BIL_TYPE_SIZE;
+  pow10v = __builtin_alloca (pow10_limbs * sizeof (UBILtype));
+  low_zeros = __bid_pow10bitint (pow10v, exp_bits, exponent);
+
+  res_limbs = ((exp_bits + mant_bits + BIL_TYPE_SIZE - 1)
+	       / BIL_TYPE_SIZE) - low_zeros;
+  mant_limbs = (mant_bits + BIL_TYPE_SIZE - 1) / BIL_TYPE_SIZE;
+  resv = __builtin_alloca ((res_limbs + mant_limbs) * sizeof (UBILtype));
+#if BIL_TYPE_SIZE >= 64
+  if (mant_limbs == 1)
+    resv[res_limbs] = mantissalo;
+  else
+    {
+      resv[res_limbs + BITINT_END (1, 0)] = mantissalo;
+      resv[res_limbs + BITINT_END (0, 1)] = mantissahi;
+    }
+#else
+  resv[res_limbs + BITINT_END (mant_limbs - 1, 0)] = mantissalo;
+  if (mant_limbs >= 2)
+    {
+      resv[res_limbs + BITINT_END (mant_limbs - 2, 1)] = mantissalo >> 32;
+      if (mant_limbs >= 3)
+	{
+	  resv[res_limbs + BITINT_END (mant_limbs - 3, 2)] = mantissahi;
+	  if (mant_limbs == 4)
+	    resv[res_limbs + BITINT_END (0, 3)] = mantissahi >> 32;
+	}
+    }
+#endif
+  __mulbitint3 (resv, exp_bits + mant_bits - low_zeros * BIL_TYPE_SIZE,
+		resv + res_limbs, mant_bits,
+		pow10v + BITINT_END (0, low_zeros),
+		exp_bits - low_zeros * BIL_TYPE_SIZE);
+  if (res_limbs + low_zeros >= rn)
+    {
+      if (res_limbs + low_zeros > rn && resv[BITINT_END (0, res_limbs - 1)])
+	goto ovf_ex;
+      if ((arprec % BIL_TYPE_SIZE) != 0
+	  && (resv[BITINT_END (rn - res_limbs, rn - 1) - low_zeros]
+	      & ((UBILtype) -1 << (arprec % BIL_TYPE_SIZE))) != 0)
+	goto ovf_ex;
+      min_limbs = rn - low_zeros;
+    }
+  else
+    min_limbs = res_limbs;
+  if (low_zeros)
+    __builtin_memset (r + BITINT_END (rn - low_zeros, 0), '\0',
+		      low_zeros * sizeof (UBILtype));
+  if (sgn)
+    bitint_negate (r + BITINT_END (rn - low_zeros - 1, low_zeros),
+		   resv + BITINT_END (res_limbs - 1, 0), min_limbs);
+  else
+    __builtin_memcpy (r + BITINT_END (rn - low_zeros - min_limbs, low_zeros),
+		      resv + BITINT_END (res_limbs - min_limbs, 0),
+		      min_limbs * sizeof (UBILtype));
+  if (res_limbs + low_zeros < rn)
+    {
+      if (sgn)
+	__builtin_memset (r + BITINT_END (0, res_limbs + low_zeros), -1,
+			  (rn - res_limbs - low_zeros) * sizeof (UBILtype));
+      else
+	__builtin_memset (r + BITINT_END (0, res_limbs + low_zeros), '\0',
+			  (rn - res_limbs - low_zeros) * sizeof (UBILtype));
+    }
+  else if (sgn)
+    {
+      if ((r[BITINT_END (0, rn - 1)]
+	   & ((UBILtype) 1 << ((arprec - 1) % BIL_TYPE_SIZE))) == 0)
+	goto ovf_ex;
+    }
+  else if (rprec < 0
+	   && (r[BITINT_END (0, rn - 1)]
+	       & ((UBILtype) 1 << ((arprec - 1) % BIL_TYPE_SIZE))) != 0)
+    goto ovf_ex;
+
+done:
+  FP_HANDLE_EXCEPTIONS;
+}
+#endif
--- libgcc/soft-fp/floatbitintsd.c.jj	2023-08-08 16:22:09.405440134 +0200
+++ libgcc/soft-fp/floatbitintsd.c	2023-08-08 16:22:09.405440134 +0200
@@ -0,0 +1,235 @@
+/* Software floating-point emulation.
+   Convert a _BitInt to _Decimal32.
+
+   Copyright (C) 2023 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<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
--- libgcc/soft-fp/floatbitintdd.c.jj	2023-08-08 16:22:09.405440134 +0200
+++ libgcc/soft-fp/floatbitintdd.c	2023-08-08 16:22:09.405440134 +0200
@@ -0,0 +1,264 @@
+/* Software floating-point emulation.
+   Convert a _BitInt to _Decimal64.
+
+   Copyright (C) 2023 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<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
--- libgcc/soft-fp/floatbitinttd.c.jj	2023-08-08 16:22:09.405440134 +0200
+++ libgcc/soft-fp/floatbitinttd.c	2023-08-08 16:22:09.405440134 +0200
@@ -0,0 +1,271 @@
+/* Software floating-point emulation.
+   Convert a _BitInt to _Decimal128.
+
+   Copyright (C) 2023 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<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


	Jakub


  reply	other threads:[~2023-09-02 11:42 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-08-09 18:23 Jakub Jelinek
2023-09-01 21:48 ` Joseph Myers
2023-09-02 11:42   ` Jakub Jelinek [this message]
2023-09-04 19:42   ` [PATCH 15/12] Add further _BitInt <-> floating point tests [PR102989] Jakub Jelinek

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=ZPMftiNAbxvN/l+y@tucnak \
    --to=jakub@redhat.com \
    --cc=gcc-patches@gcc.gnu.org \
    --cc=ian@airs.com \
    --cc=joseph@codesourcery.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).