_BitInt to _Decimal* conversion support [PR102989]

Message ID ZNE8SVeUupRLUJ1u@tucnak
State New
Headers
Series _BitInt to _Decimal* conversion support [PR102989] |

Checks

Context Check Description
linaro-tcwg-bot/tcwg_gcc_check--master-aarch64 warning Patch failed to apply
linaro-tcwg-bot/tcwg_gcc_build--master-arm warning Patch failed to apply
linaro-tcwg-bot/tcwg_gcc_build--master-aarch64 warning Patch failed to apply
linaro-tcwg-bot/tcwg_gcc_check--master-arm warning Patch failed to apply

Commit Message

Jakub Jelinek Aug. 7, 2023, 6:47 p.m. UTC
  Hi!

The following patch on top of the _Decimal* to _BitInt conversion support
patch (and obviously the _BitInt patch series) implements the _BitInt to
_Decimal{32,64,128} conversions.  These functions do at most two divisions,
one possibly by very large power of 10 for which the code just checks if the
remainder is 0 or non-zero and where the exponent is just guessed from the
input actual minumum bit precision (with a guarantee that if we do the first
large division, there will be second one), and then one final on by 10^1
to 10^6 (perhaps smaller for _Decimal{32,128}) which ensures the result is
in between 10^{6,15,33} and (10^{7,16,34})-1.  For this division we then
incorporate the inexact flag from the first division if any and check if
with that the remainder is 0, half of the second divisor, smaller than that
or larger than that.
To make the code independent between libbid in libgcc and the __bid_*
support in libdfp and not having to figure out how to get at the rounding
mode, the code actually if the result isn't exact performs an addition of
the non-rounded value, XXXXXXXXXe+expD{F,D,L} + {4,5,6}e+(exp-1)D{F,D,L}.
Similarly, for overflow to infinity it performs addition of two very large
(same) numbers (but with single non-0 digit in mantissa such that inexact
isn't the case).

Will work tomorrow on the runtime gcc.dg/atomic/ testcase and then try to
rework the series based on Richi's review.

2023-08-07  Jakub Jelinek  <jakub@redhat.com>

	PR c/102989
gcc/
	* gimple-lower-bitint.cc (bitint_large_huge::lower_float_conv_stmt):
	Handle _BitInt to _Decimal* conversions.
	* internal-fn.cc (expand_BITINTTOFLOAT): Likewise.
gcc/testsuite/
	* gcc.dg/dfp/bitint-4.c: New test.
	* gcc.dg/dfp/bitint-5.c: New test.
	* gcc.dg/dfp/bitint-6.c: New test.
libgcc/
	* config/t-softfp (softfp_bid_list): Add floatbitint{s,d,t}d.
	* soft-fp/floatbitintsd.c: New file.
	* soft-fp/floatbitintdd.c: New file.
	* soft-fp/floatbitinttd.c: New file.


	Jakub
  

Patch

--- gcc/gimple-lower-bitint.cc.jj	2023-08-04 09:40:14.271005211 +0200
+++ gcc/gimple-lower-bitint.cc	2023-08-05 19:14:04.125034849 +0200
@@ -3363,23 +3363,6 @@  bitint_large_huge::lower_float_conv_stmt
   tree rhs1 = gimple_assign_rhs1 (stmt);
   tree lhs = gimple_assign_lhs (stmt);
   tree_code rhs_code = gimple_assign_rhs_code (stmt);
-  if (DECIMAL_FLOAT_MODE_P (TYPE_MODE (TREE_TYPE (lhs))))
-    {
-      sorry_at (gimple_location (stmt),
-		"unsupported conversion between %<_BitInt(%d)%> and %qT",
-		rhs_code == FIX_TRUNC_EXPR
-		? TYPE_PRECISION (TREE_TYPE (lhs))
-		: TYPE_PRECISION (TREE_TYPE (rhs1)),
-		rhs_code == FIX_TRUNC_EXPR
-		? TREE_TYPE (rhs1) : TREE_TYPE (lhs));
-      if (rhs_code == FLOAT_EXPR)
-	{
-	  gimple *g
-	    = gimple_build_assign (lhs, build_zero_cst (TREE_TYPE (lhs)));
-	  gsi_replace (&m_gsi, g, true);
-	}
-      return;
-    }
   tree sitype = lang_hooks.types.type_for_mode (SImode, 0);
   gimple *g;
   if (rhs_code == FIX_TRUNC_EXPR)
--- gcc/internal-fn.cc.jj	2023-08-04 09:47:58.368480546 +0200
+++ gcc/internal-fn.cc	2023-08-05 19:15:24.477915179 +0200
@@ -4885,11 +4885,25 @@  expand_BITINTTOFLOAT (internal_fn, gcall
   const char *mname = GET_MODE_NAME (mode);
   unsigned mname_len = strlen (mname);
   int len = 14 + mname_len;
+  if (DECIMAL_FLOAT_MODE_P (mode))
+    len += 4;
   char *libfunc_name = XALLOCAVEC (char, len);
   char *p = libfunc_name;
   const char *q;
-  memcpy (p, "__floatbitint", 13);
-  p += 13;
+  if (DECIMAL_FLOAT_MODE_P (mode))
+    {
+#if ENABLE_DECIMAL_BID_FORMAT
+      memcpy (p, "__bid_floatbitint", 17);
+#else
+      memcpy (p, "__dpd_floatbitint", 17);
+#endif
+      p += 17;
+    }
+  else
+    {
+      memcpy (p, "__floatbitint", 13);
+      p += 13;
+    }
   for (q = mname; *q; q++)
     *p++ = TOLOWER (*q);
   *p = '\0';
--- gcc/testsuite/gcc.dg/dfp/bitint-4.c.jj	2023-08-05 20:08:13.819721742 +0200
+++ gcc/testsuite/gcc.dg/dfp/bitint-4.c	2023-08-07 12:02:12.530386424 +0200
@@ -0,0 +1,156 @@ 
+/* PR c/102989 */
+/* { dg-do run { target bitint } } */
+/* { dg-options "-O2 -std=c2x -pedantic-errors" } */
+
+#if __BITINT_MAXWIDTH__ >= 192
+__attribute__((noipa)) _Decimal64
+tests192 (_BitInt(192) b)
+{
+  return b;
+}
+
+__attribute__((noipa)) _Decimal64
+testu192 (unsigned _BitInt(192) b)
+{
+  return b;
+}
+#endif
+
+#if __BITINT_MAXWIDTH__ >= 575
+__attribute__((noipa)) _Decimal64
+tests575 (_BitInt(575) b)
+{
+  return b;
+}
+
+__attribute__((noipa)) _Decimal64
+testu575 (unsigned _BitInt(575) b)
+{
+  return b;
+}
+#endif
+
+int
+main ()
+{
+  _Decimal64 a, b;
+#define CHECK(x, y) (a = (x), b = (y), a != (y) || __builtin_memcmp (&a, &b, sizeof (a)))
+#if __BITINT_MAXWIDTH__ >= 192
+  if (CHECK (tests192 (0wb), 0.DD)
+      || CHECK (tests192 (7wb), 7.DD)
+      || CHECK (tests192 (-42wb), -42.DD)
+      || CHECK (tests192 (-777777777wb), -777777777.DD)
+      || CHECK (tests192 (9999999999999000wb), 9999999999999000.DD)
+      || CHECK (tests192 (-9999999999999999wb), -9999999999999999.DD)
+      || CHECK (tests192 (-99999999999999994wb), -9999999999999999.e+1DD)
+      || CHECK (tests192 (99999999999999995wb), 1000000000000000.e+2DD)
+      || CHECK (tests192 (999999999999999900wb), 9999999999999999.e+2DD)
+      || CHECK (tests192 (999999999999999949wb), 9999999999999999.e+2DD)
+      || CHECK (tests192 (-9999999999999999000wb), -9999999999999999.e+3DD)
+      || CHECK (tests192 (9999999999999999499wb), 9999999999999999.e+3DD)
+      || CHECK (tests192 (999999999999999900000wb), 9999999999999999.e+5DD)
+      || CHECK (tests192 (999999999999999949999wb), 9999999999999999.e+5DD)
+      || CHECK (tests192 (-9999999999999999000000wb), -9999999999999999.e+6DD)
+      || CHECK (tests192 (-9999999999999999499999wb), -9999999999999999.e+6DD)
+      || CHECK (tests192 (123456789012345600000000wb), 1234567890123456.e+8DD)
+      || CHECK (tests192 (34242319854454290000000000000000000000wb), 3424231985445429e+22DD)
+      || CHECK (tests192 (999999999999999900000000000000000000000000000000wb), 9999999999999999.e+32DD)
+      || CHECK (tests192 (999999999999999949999999999999999999999999999999wb), 9999999999999999.e+32DD)
+      || CHECK (tests192 (-999999999999999900000000000000000000000000000000000000000wb), -9999999999999999.e+41DD)
+      || CHECK (tests192 (-2138550877694459000000000000000000000000000000000000000000wb), -2138550877694459e+42DD)
+      || CHECK (tests192 (-2138550877694459500000000000000000000000000000000000000000wb), -2138550877694460e+42DD)
+      || CHECK (tests192 (-2138550877694459499999999999999999999999999999999999999999wb), -2138550877694459e+42DD)
+      || CHECK (tests192 (-2138550877694459999999999999999999999999999999999999999999wb), -2138550877694460e+42DD)
+      || CHECK (tests192 (-2138550877694458000000000000000000000000000000000000000000wb), -2138550877694458e+42DD)
+      || CHECK (tests192 (-2138550877694458500000000000000000000000000000000000000000wb), -2138550877694458e+42DD)
+      || CHECK (tests192 (-2138550877694458500000000000000000000000000000000000000001wb), -2138550877694459e+42DD)
+      || CHECK (tests192 (3138550867693340000000000000000000000000000000000000000000wb), 3138550867693340e+42DD)
+      || CHECK (tests192 (3138550867693340381917894711603833208051177722232017256447wb), 3138550867693340e+42DD)
+      || CHECK (tests192 (-3138550867693340000000000000000000000000000000000000000000wb), -3138550867693340e+42DD)
+      || CHECK (tests192 (-3138550867693340381917894711603833208051177722232017256447wb - 1wb), -3138550867693340e+42DD))
+    __builtin_abort ();
+  if (CHECK (testu192 (0uwb), 0.DD)
+      || CHECK (testu192 (7uwb), 7.DD)
+      || CHECK (testu192 (42uwb), 42.DD)
+      || CHECK (testu192 (777777777uwb), 777777777.DD)
+      || CHECK (testu192 (9999999999999000uwb), 9999999999999000.DD)
+      || CHECK (testu192 (999999999999999900uwb), 9999999999999999.e+2DD)
+      || CHECK (testu192 (9999999999999999000uwb), 9999999999999999.e+3DD)
+      || CHECK (testu192 (99999999999999994999uwb), 9999999999999999.e+4DD)
+      || CHECK (testu192 (999999999999999900000uwb), 9999999999999999.e+5DD)
+      || CHECK (testu192 (9999999999999999000000uwb), 9999999999999999.e+6DD)
+      || CHECK (testu192 (123456789012345600000000uwb), 1234567890123456.e+8DD)
+      || CHECK (testu192 (34242319854454290000000000000000000000uwb), 3424231985445429e+22DD)
+      || CHECK (testu192 (9999999999999999000000000000000000000000000000000uwb), 9999999999999999.e+33DD)
+      || CHECK (testu192 (618935436546517900000000000000000000000000000000000000uwb), 6189354365465179e+38DD)
+      || CHECK (testu192 (618935436546517950000000000000000000000000000000000000uwb), 6189354365465180e+38DD)
+      || CHECK (testu192 (618935436546517949999999999999999999999999999999999999uwb), 6189354365465179e+38DD)
+      || CHECK (testu192 (618935436546517999999999999999999999999999999999999999uwb), 6189354365465180e+38DD)
+      || CHECK (testu192 (618935436546517800000000000000000000000000000000000000uwb), 6189354365465178e+38DD)
+      || CHECK (testu192 (618935436546517850000000000000000000000000000000000000uwb), 6189354365465178e+38DD)
+      || CHECK (testu192 (618935436546517850000000000000000000000000000000000001uwb), 6189354365465179e+38DD)
+      || CHECK (testu192 (99999999999999990000000000000000000000000000000000000000uwb), 9999999999999999.e+40DD)
+      || CHECK (testu192 (6277101735386680000000000000000000000000000000000000000000uwb), 6277101735386680e+42DD)
+      || CHECK (testu192 (6277101735386680499999999999999999999999999999999999999999uwb), 6277101735386680e+42DD)
+      || CHECK (testu192 (6277101735386680500000000000000000000000000000000000000000uwb), 6277101735386680e+42DD)
+      || CHECK (testu192 (6277101735386680500000000000000000000000000000000000000001uwb), 6277101735386681e+42DD)
+      || CHECK (testu192 (6277101735386680500000000000000000000010000000000000000000uwb), 6277101735386681e+42DD)
+      || CHECK (testu192 (6277101735386680763835789423207666416102355444464034512895uwb), 6277101735386681e+42DD))
+    __builtin_abort ();
+#endif
+#if __BITINT_MAXWIDTH__ >= 575
+  if (CHECK (tests575 (0wb), 0.DD)
+      || CHECK (tests575 (7wb), 7.DD)
+      || CHECK (tests575 (-42wb), -42.DD)
+      || CHECK (tests575 (-444444444wb), -444444444.DD)
+      || CHECK (tests575 (9999999999999000wb), 9999999999999000.DD)
+      || CHECK (tests575 (-9999999999999999wb), -9999999999999999.DD)
+      || CHECK (tests575 (999999999999999900wb), 9999999999999999.e+2DD)
+      || CHECK (tests575 (-9999999999999999000wb), -9999999999999999.e+3DD)
+      || CHECK (tests575 (999999999999999900000wb), 9999999999999999.e+5DD)
+      || CHECK (tests575 (-99999999999999990000000wb), -9999999999999999.e+7DD)
+      || CHECK (tests575 (1234567890123456000000000wb), 1234567890123456.e+9DD)
+      || CHECK (tests575 (3424231985445429000000000000000000000000wb), 3424231985445429e+24DD)
+      || CHECK (tests575 (99999999999999990000000000000000000000000000000000000000wb), 9999999999999999.e+40DD)
+      || CHECK (tests575 (-9999999999999999000000000000000000000000000000000000000000000000000000000000000wb), -9999999999999999.e+63DD)
+      || CHECK (tests575 (-213855087769445900000000000000000000000000000000000000000000000000000000000000000000000000000000000000wb), -2138550877694459e+86DD)
+      || CHECK (tests575 (-213855087769445950000000000000000000000000000000000000000000000000000000000000000000000000000000000000wb), -2138550877694460e+86DD)
+      || CHECK (tests575 (-213855087769445949999999999999999999999999999999999999999999999999999999999999999999999999999999999999wb), -2138550877694459e+86DD)
+      || CHECK (tests575 (-213855087769445999999999999999999999999999999999999999999999999999999999999999999999999999999999999999wb), -2138550877694460e+86DD)
+      || CHECK (tests575 (-213855087769445800000000000000000000000000000000000000000000000000000000000000000000000000000000000000wb), -2138550877694458e+86DD)
+      || CHECK (tests575 (-213855087769445850000000000000000000000000000000000000000000000000000000000000000000000000000000000000wb), -2138550877694458e+86DD)
+      || CHECK (tests575 (-213855087769445850000000000000000000000000000000000000000000000000000000000000000000000000000000000001wb), -2138550877694459e+86DD)
+      || CHECK (tests575 (61832600368276130000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000wb), 6183260036827613e+157DD)
+      || CHECK (tests575 (61832600368276133515125630254911797508782837275302959978515764023224306276632966792579100265310761247399417856504034834837841258576687802491886538775473291979151693037174783wb), 6183260036827613e+157DD)
+      || CHECK (tests575 (-61832600368276130000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000wb), -6183260036827613e+157DD)
+      || CHECK (tests575 (-61832600368276133515125630254911797508782837275302959978515764023224306276632966792579100265310761247399417856504034834837841258576687802491886538775473291979151693037174783wb - 1wb), -6183260036827613e+157DD))
+    __builtin_abort ();
+  if (CHECK (testu575 (0uwb), 0.DD)
+      || CHECK (testu575 (17uwb), 17.DD)
+      || CHECK (testu575 (420uwb), 420.DD)
+      || CHECK (testu575 (888888888uwb), 888888888.DD)
+      || CHECK (testu575 (9999999999999000uwb), 9999999999999000.DD)
+      || CHECK (testu575 (99999999999999990000000uwb), 9999999999999999.e+7DD)
+      || CHECK (testu575 (9999999999999999000000000uwb), 9999999999999999.e+9DD)
+      || CHECK (testu575 (99999999999999990000000000000uwb), 9999999999999999.e+13DD)
+      || CHECK (testu575 (9999999999999999000000000000000uwb), 9999999999999999.e+15DD)
+      || CHECK (testu575 (1234567890123456000000000000000000uwb), 1234567890123456.e+18DD)
+      || CHECK (testu575 (34242319854454290000000000000000000000uwb), 3424231985445429e+22DD)
+      || CHECK (testu575 (9999999999999999000000000000000000000000000000000uwb), 9999999999999999.e+33DD)
+      || CHECK (testu575 (618935436546517900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000uwb), 6189354365465179e+104DD)
+      || CHECK (testu575 (618935436546517950000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000uwb), 6189354365465180e+104DD)
+      || CHECK (testu575 (618935436546517949999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999uwb), 6189354365465179e+104DD)
+      || CHECK (testu575 (618935436546517999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999uwb), 6189354365465180e+104DD)
+      || CHECK (testu575 (618935436546517800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000uwb), 6189354365465178e+104DD)
+      || CHECK (testu575 (618935436546517850000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000uwb), 6189354365465178e+104DD)
+      || CHECK (testu575 (618935436546517850000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001uwb), 6189354365465179e+104DD)
+      || CHECK (testu575 (99999999999999990000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000uwb), 9999999999999999.e+139DD)
+      || CHECK (testu575 (123665200736552200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000uwb), 1236652007365522e+158DD)
+      || CHECK (testu575 (123665200736552249999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999uwb), 1236652007365522e+158DD)
+      || CHECK (testu575 (123665200736552250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000uwb), 1236652007365522e+158DD)
+      || CHECK (testu575 (123665200736552250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001uwb), 1236652007365523e+158DD)
+      || CHECK (testu575 (123665200736552250000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000uwb), 1236652007365523e+158DD)
+      || CHECK (testu575 (123665200736552267030251260509823595017565674550605919957031528046448612553265933585158200530621522494798835713008069669675682517153375604983773077550946583958303386074349567uwb), 1236652007365523e+158DD))
+    __builtin_abort ();
+#endif
+}
--- gcc/testsuite/gcc.dg/dfp/bitint-5.c.jj	2023-08-07 11:58:06.746843874 +0200
+++ gcc/testsuite/gcc.dg/dfp/bitint-5.c	2023-08-07 11:58:29.703520940 +0200
@@ -0,0 +1,159 @@ 
+/* PR c/102989 */
+/* { dg-do run { target bitint } } */
+/* { dg-options "-O2 -std=c2x -pedantic-errors" } */
+
+#if __BITINT_MAXWIDTH__ >= 192
+__attribute__((noipa)) _Decimal32
+tests192 (_BitInt(192) b)
+{
+  return b;
+}
+
+__attribute__((noipa)) _Decimal32
+testu192 (unsigned _BitInt(192) b)
+{
+  return b;
+}
+#endif
+
+#if __BITINT_MAXWIDTH__ >= 575
+__attribute__((noipa)) _Decimal32
+tests575 (_BitInt(575) b)
+{
+  return b;
+}
+
+__attribute__((noipa)) _Decimal32
+testu575 (unsigned _BitInt(575) b)
+{
+  return b;
+}
+#endif
+
+int
+main ()
+{
+  _Decimal32 a, b;
+#define CHECK(x, y) (a = (x), b = (y), a != (y) || __builtin_memcmp (&a, &b, sizeof (a)))
+#if __BITINT_MAXWIDTH__ >= 192
+  if (CHECK (tests192 (0wb), 0.DF)
+      || CHECK (tests192 (7wb), 7.DF)
+      || CHECK (tests192 (-42wb), -42.DF)
+      || CHECK (tests192 (-777777wb), -777777.DF)
+      || CHECK (tests192 (9999000wb), 9999000.DF)
+      || CHECK (tests192 (-9999999wb), -9999999.DF)
+      || CHECK (tests192 (99999994wb), 9999999.e+1DF)
+      || CHECK (tests192 (99999995wb), 1000000.e+2DF)
+      || CHECK (tests192 (999999900wb), 9999999.e+2DF)
+      || CHECK (tests192 (-9999999000wb), -9999999.e+3DF)
+      || CHECK (tests192 (999999900000wb), 9999999.e+5DF)
+      || CHECK (tests192 (-9999999000000wb), -9999999.e+6DF)
+      || CHECK (tests192 (123456700000000000wb), 1234567.e+11DF)
+      || CHECK (tests192 (34242310000000000000000000000wb), 3424231e+22DF)
+      || CHECK (tests192 (999999900000000000000000000000000000000wb), 9999999.e+32DF)
+      || CHECK (tests192 (-999999900000000000000000000000000000000000000000wb), -9999999.e+41DF)
+      || CHECK (tests192 (-2138551000000000000000000000000000000000000000000000000000wb), -2138551e+51DF)
+      || CHECK (tests192 (-2138551500000000000000000000000000000000000000000000000000wb), -2138552e+51DF)
+      || CHECK (tests192 (-2138551499999999999999999999999999999999999999999999999999wb), -2138551e+51DF)
+      || CHECK (tests192 (-2138551999999999999999999999999999999999999999999999999999wb), -2138552e+51DF)
+      || CHECK (tests192 (-2138552000000000000000000000000000000000000000000000000000wb), -2138552e+51DF)
+      || CHECK (tests192 (-2138552500000000000000000000000000000000000000000000000000wb), -2138552e+51DF)
+      || CHECK (tests192 (-2138552500000000000000000000000000000000000000000000000001wb), -2138553e+51DF)
+      || CHECK (tests192 (3138550000000000000000000000000000000000000000000000000000wb), 3138550e+51DF)
+      || CHECK (tests192 (3138550867693340381917894711603833208051177722232017256447wb), 3138551e+51DF)
+      || CHECK (tests192 (-3138550000000000000000000000000000000000000000000000000000wb), -3138550e+51DF)
+      || CHECK (tests192 (-3138550867693340381917894711603833208051177722232017256447wb - 1wb), -3138551e+51DF))
+    __builtin_abort ();
+  if (CHECK (testu192 (0uwb), 0.DF)
+      || CHECK (testu192 (7uwb), 7.DF)
+      || CHECK (testu192 (42uwb), 42.DF)
+      || CHECK (testu192 (77777uwb), 77777.DF)
+      || CHECK (testu192 (9999000uwb), 9999000.DF)
+      || CHECK (testu192 (999999900uwb), 9999999.e+2DF)
+      || CHECK (testu192 (999999949uwb), 9999999.e+2DF)
+      || CHECK (testu192 (9999999000uwb), 9999999.e+3DF)
+      || CHECK (testu192 (9999999499uwb), 9999999.e+3DF)
+      || CHECK (testu192 (999999900000uwb), 9999999.e+5DF)
+      || CHECK (testu192 (9999999000000uwb), 9999999.e+6DF)
+      || CHECK (testu192 (123456700000000uwb), 1234567.e+8DF)
+      || CHECK (testu192 (34242310000000000000000000000uwb), 3424231e+22DF)
+      || CHECK (testu192 (9999999000000000000000000000000000000000uwb), 9999999.e+33DF)
+      || CHECK (testu192 (61893590000000000000000000000000000000000000000000000uwb), 6189359e+46DF)
+      || CHECK (testu192 (61893595000000000000000000000000000000000000000000000uwb), 6189360e+46DF)
+      || CHECK (testu192 (61893594999999999999999999999999999999999999999999999uwb), 6189359e+46DF)
+      || CHECK (testu192 (61893599999999999999999999999999999999999999999999999uwb), 6189360e+46DF)
+      || CHECK (testu192 (61893580000000000000000000000000000000000000000000000uwb), 6189358e+46DF)
+      || CHECK (testu192 (61893585000000000000000000000000000000000000000000000uwb), 6189358e+46DF)
+      || CHECK (testu192 (61893585000000000000000000000000000000000000000000001uwb), 6189359e+46DF)
+      || CHECK (testu192 (999999900000000000000000000000000000000000000000000000uwb), 9999999.e+47DF)
+      || CHECK (testu192 (6277100500000000000000000000000000000000000000000000000000uwb), 6277100e+51DF)
+      || CHECK (testu192 (6277100500000000000000000000000000000000000000000000000001uwb), 6277101e+51DF)
+      || CHECK (testu192 (6277100500000000000000000000000000000010000000000000000000uwb), 6277101e+51DF)
+      || CHECK (testu192 (6277101000000000000000000000000000000000000000000000000000uwb), 6277101e+51DF)
+      || CHECK (testu192 (6277101499999999999999999999999999999999999999999999999999uwb), 6277101e+51DF)
+      || CHECK (testu192 (6277101500000000000000000000000000000000000000000000000000uwb), 6277102e+51DF)
+      || CHECK (testu192 (6277101735386680763835789423207666416102355444464034512895uwb), 6277102e+51DF))
+    __builtin_abort ();
+#endif
+#if __BITINT_MAXWIDTH__ >= 575
+  if (CHECK (tests575 (0wb), 0.DF)
+      || CHECK (tests575 (7wb), 7.DF)
+      || CHECK (tests575 (-42wb), -42.DF)
+      || CHECK (tests575 (-44444wb), -44444.DF)
+      || CHECK (tests575 (9999000wb), 9999000.DF)
+      || CHECK (tests575 (-9999999wb), -9999999.DF)
+      || CHECK (tests575 (999999900wb), 9999999.e+2DF)
+      || CHECK (tests575 (-9999999000wb), -9999999.e+3DF)
+      || CHECK (tests575 (999999900000wb), 9999999.e+5DF)
+      || CHECK (tests575 (999999949999wb), 9999999.e+5DF)
+      || CHECK (tests575 (-99999990000000wb), -9999999.e+7DF)
+      || CHECK (tests575 (1234567000000000000000000wb), 1234567.e+18DF)
+      || CHECK (tests575 (3424231000000000000000000000000000000000wb), 3424231e+33DF)
+      || CHECK (tests575 (99999990000000000000000000000000000000000000000wb), 9999999.e+40DF)
+      || CHECK (tests575 (-9999999000000000000000000000000000000000000000000000000000000000000000wb), -9999999.e+63DF)
+      || CHECK (tests575 (-2138559000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000wb), -2138559e+90DF)
+      || CHECK (tests575 (-2138559500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000wb), -2138560e+90DF)
+      || CHECK (tests575 (-2138559499999999999999999999999999999999999999999999999999999999999999999999999999999999999999999wb), -2138559e+90DF)
+      || CHECK (tests575 (-2138559999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999wb), -2138560e+90DF)
+      || CHECK (tests575 (-2138558000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000wb), -2138558e+90DF)
+      || CHECK (tests575 (-2138558500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000wb), -2138558e+90DF)
+      || CHECK (tests575 (-2138558500000000000000000000000000000000000000000000000000000000000000000000000000000000000000001wb), -2138559e+90DF)
+      || CHECK (tests575 (9999999000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000wb), 9999999e+90DF)
+      || CHECK (tests575 (9999999499999999999999999999999999999999999999999999999999999999999999999999999999999999999999999wb), 9999999e+90DF)
+      || CHECK (tests575 (9999999500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000wb), __builtin_infd32 ())
+      || CHECK (tests575 (-9999999000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000wb), -9999999e+90DF)
+      || CHECK (tests575 (-9999999499999999999999999999999999999999999999999999999999999999999999999999999999999999999999999wb), -9999999e+90DF)
+      || CHECK (tests575 (-9999999500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000wb), -__builtin_infd32 ())
+      || CHECK (tests575 (61832600368276133515125630254911797508782837275302959978515764023224306276632966792579100265310761247399417856504034834837841258576687802491886538775473291979151693037174783wb), __builtin_infd32 ())
+      || CHECK (tests575 (-61832600368276133515125630254911797508782837275302959978515764023224306276632966792579100265310761247399417856504034834837841258576687802491886538775473291979151693037174783wb - 1wb), -__builtin_infd32 ()))
+    __builtin_abort ();
+  if (CHECK (testu575 (0uwb), 0.DF)
+      || CHECK (testu575 (17uwb), 17.DF)
+      || CHECK (testu575 (420uwb), 420.DF)
+      || CHECK (testu575 (888uwb), 888.DF)
+      || CHECK (testu575 (9999000uwb), 9999000.DF)
+      || CHECK (testu575 (99999990000000uwb), 9999999.e+7DF)
+      || CHECK (testu575 (99999994999999uwb), 9999999.e+7DF)
+      || CHECK (testu575 (9999999000000000uwb), 9999999.e+9DF)
+      || CHECK (testu575 (9999999499999999uwb), 9999999.e+9DF)
+      || CHECK (testu575 (99999990000000000000uwb), 9999999.e+13DF)
+      || CHECK (testu575 (99999994999999999999uwb), 9999999.e+13DF)
+      || CHECK (testu575 (9999999000000000000000uwb), 9999999.e+15DF)
+      || CHECK (testu575 (9999999499999999999999uwb), 9999999.e+15DF)
+      || CHECK (testu575 (1234567000000000000000000uwb), 1234567.e+18DF)
+      || CHECK (testu575 (34242310000000000000000000000uwb), 3424231e+22DF)
+      || CHECK (testu575 (9999999000000000000000000000000000000000uwb), 9999999.e+33DF)
+      || CHECK (testu575 (61893590000000000000000000000000000000000000000000000000000000000000000000000000000000000000000uwb), 6189359e+88DF)
+      || CHECK (testu575 (61893595000000000000000000000000000000000000000000000000000000000000000000000000000000000000000uwb), 6189360e+88DF)
+      || CHECK (testu575 (61893594999999999999999999999999999999999999999999999999999999999999999999999999999999999999999uwb), 6189359e+88DF)
+      || CHECK (testu575 (61893599999999999999999999999999999999999999999999999999999999999999999999999999999999999999999uwb), 6189360e+88DF)
+      || CHECK (testu575 (61893580000000000000000000000000000000000000000000000000000000000000000000000000000000000000000uwb), 6189358e+88DF)
+      || CHECK (testu575 (61893585000000000000000000000000000000000000000000000000000000000000000000000000000000000000000uwb), 6189358e+88DF)
+      || CHECK (testu575 (61893585000000000000000000000000000000000000000000000000000000000000000000000000000000000000001uwb), 6189359e+88DF)
+      || CHECK (testu575 (9999999000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000uwb), 9999999.e+90DF)
+      || CHECK (tests575 (9999999499999999999999999999999999999999999999999999999999999999999999999999999999999999999999999uwb), 9999999e+90DF)
+      || CHECK (tests575 (9999999500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000uwb), __builtin_infd32 ())
+      || CHECK (testu575 (123665200736552267030251260509823595017565674550605919957031528046448612553265933585158200530621522494798835713008069669675682517153375604983773077550946583958303386074349567uwb), __builtin_infd32 ()))
+    __builtin_abort ();
+#endif
+}
--- gcc/testsuite/gcc.dg/dfp/bitint-6.c.jj	2023-08-07 17:58:14.588521246 +0200
+++ gcc/testsuite/gcc.dg/dfp/bitint-6.c	2023-08-07 17:57:32.271115340 +0200
@@ -0,0 +1,156 @@ 
+/* PR c/102989 */
+/* { dg-do run { target bitint } } */
+/* { dg-options "-O2 -std=c2x -pedantic-errors" } */
+
+#if __BITINT_MAXWIDTH__ >= 192
+__attribute__((noipa)) _Decimal128
+tests192 (_BitInt(192) b)
+{
+  return b;
+}
+
+__attribute__((noipa)) _Decimal128
+testu192 (unsigned _BitInt(192) b)
+{
+  return b;
+}
+#endif
+
+#if __BITINT_MAXWIDTH__ >= 575
+__attribute__((noipa)) _Decimal128
+tests575 (_BitInt(575) b)
+{
+  return b;
+}
+
+__attribute__((noipa)) _Decimal128
+testu575 (unsigned _BitInt(575) b)
+{
+  return b;
+}
+#endif
+
+int
+main ()
+{
+  _Decimal128 a, b;
+#define CHECK(x, y) (a = (x), b = (y), a != (y) || __builtin_memcmp (&a, &b, sizeof (a)))
+#if __BITINT_MAXWIDTH__ >= 192
+  if (CHECK (tests192 (0wb), 0.DL)
+      || CHECK (tests192 (7wb), 7.DL)
+      || CHECK (tests192 (-42wb), -42.DL)
+      || CHECK (tests192 (-777777777wb), -777777777.DL)
+      || CHECK (tests192 (-12345678912345wb), -12345678912345.DL)
+      || CHECK (tests192 (123456789123456789wb), 123456789123456789.DL)
+      || CHECK (tests192 (777777777777777777777777777wb), 777777777777777777777777777.DL)
+      || CHECK (tests192 (9999999999999999999999999900000000wb), 9999999999999999999999999900000000.DL)
+      || CHECK (tests192 (-9999999999999999999999999999999999wb), -9999999999999999999999999999999999.DL)
+      || CHECK (tests192 (-99999999999999999999999999999999994wb), -9999999999999999999999999999999999.e+1DL)
+      || CHECK (tests192 (99999999999999999999999999999999995wb), 1000000000000000000000000000000000.e+2DL)
+      || CHECK (tests192 (999999999999999999999999999999999900wb), 9999999999999999999999999999999999.e+2DL)
+      || CHECK (tests192 (999999999999999999999999999999999949wb), 9999999999999999999999999999999999.e+2DL)
+      || CHECK (tests192 (-9999999999999999999999999999999999000wb), -9999999999999999999999999999999999.e+3DL)
+      || CHECK (tests192 (9999999999999999999999999999999999499wb), 9999999999999999999999999999999999.e+3DL)
+      || CHECK (tests192 (34242319854454290000000000000000000000wb), 3424231985445429000000000000000000e+4DL)
+      || CHECK (tests192 (34242319854454294983573424983275760000wb), 3424231985445429498357342498327576e+4DL)
+      || CHECK (tests192 (999999999999999999999999999999999900000wb), 9999999999999999999999999999999999.e+5DL)
+      || CHECK (tests192 (999999999999999999999999999999999949999wb), 9999999999999999999999999999999999.e+5DL)
+      || CHECK (tests192 (-9999999999999999999999999999999999000000wb), -9999999999999999999999999999999999.e+6DL)
+      || CHECK (tests192 (-9999999999999999999999999999999999499999wb), -9999999999999999999999999999999999.e+6DL)
+      || CHECK (tests192 (123456789012345678901234567890123400000000wb), 1234567890123456789012345678901234.e+8DL)
+      || CHECK (tests192 (999999999999999999999999999999999900000000000000000000000wb), 9999999999999999999999999999999999.e+23DL)
+      || CHECK (tests192 (999999999999999999999999999999999949999999999999999999999wb), 9999999999999999999999999999999999.e+23DL)
+      || CHECK (tests192 (-999999999999999999999999999999999900000000000000000000000wb), -9999999999999999999999999999999999.e+23DL)
+      || CHECK (tests192 (-2138550877694459381917894711603833000000000000000000000000wb), -2138550877694459381917894711603833e+24DL)
+      || CHECK (tests192 (-2138550877694459381917894711603833500000000000000000000000wb), -2138550877694459381917894711603834e+24DL)
+      || CHECK (tests192 (-2138550877694459381917894711603833499999999999999999999999wb), -2138550877694459381917894711603833e+24DL)
+      || CHECK (tests192 (-2138550877694459381917894711603833999999999999999999999999wb), -2138550877694459381917894711603834e+24DL)
+      || CHECK (tests192 (-2138550877694459381917894711603832000000000000000000000000wb), -2138550877694459381917894711603832e+24DL)
+      || CHECK (tests192 (-2138550877694459381917894711603832500000000000000000000000wb), -2138550877694459381917894711603832e+24DL)
+      || CHECK (tests192 (-2138550877694459381917894711603832500000000000000000000001wb), -2138550877694459381917894711603833e+24DL)
+      || CHECK (tests192 (3138550867693340381917894711603833000000000000000000000000wb), 3138550867693340381917894711603833e+24DL)
+      || CHECK (tests192 (3138550867693340381917894711603833208051177722232017256447wb), 3138550867693340381917894711603833e+24DL)
+      || CHECK (tests192 (-3138550867693340381917894711603833000000000000000000000000wb), -3138550867693340381917894711603833e+24DL)
+      || CHECK (tests192 (-3138550867693340381917894711603833208051177722232017256447wb - 1wb), -3138550867693340381917894711603833e+24DL))
+    __builtin_abort ();
+  if (CHECK (testu192 (0uwb), 0.DL)
+      || CHECK (testu192 (7uwb), 7.DL)
+      || CHECK (testu192 (42uwb), 42.DL)
+      || CHECK (testu192 (777777777uwb), 777777777.DL)
+      || CHECK (testu192 (99999999999999999999999999000uwb), 99999999999999999999999999000.DL)
+      || CHECK (testu192 (999999999999999999999999999999999900uwb), 9999999999999999999999999999999999.e+2DL)
+      || CHECK (testu192 (9999999999999999999999999999999999000uwb), 9999999999999999999999999999999999.e+3DL)
+      || CHECK (testu192 (99999999999999999999999999999999994999uwb), 9999999999999999999999999999999999.e+4DL)
+      || CHECK (testu192 (999999999999999999999999999999999900000uwb), 9999999999999999999999999999999999.e+5DL)
+      || CHECK (testu192 (9999999999999999999999999999999999000000uwb), 9999999999999999999999999999999999.e+6DL)
+      || CHECK (testu192 (123456789012345600000000uwb), 123456789012345600000000.DL)
+      || CHECK (testu192 (34242319854454290000000000000000000000uwb), 3424231985445429000000000000000000e+4DL)
+      || CHECK (testu192 (999999999999999999999999999999999900000000000000000000000uwb), 9999999999999999999999999999999999.e+23DL)
+      || CHECK (testu192 (6189354365465174593875438957438959000000000000000000000000uwb), 6189354365465174593875438957438959e+24DL)
+      || CHECK (testu192 (6189354365465174593875438957438959500000000000000000000000uwb), 6189354365465174593875438957438960e+24DL)
+      || CHECK (testu192 (6189354365465174593875438957438959499999999999999999999999uwb), 6189354365465174593875438957438959e+24DL)
+      || CHECK (testu192 (6189354365465174593875438957438959999999999999999999999999uwb), 6189354365465174593875438957438960e+24DL)
+      || CHECK (testu192 (6189354365465174593875438957438958000000000000000000000000uwb), 6189354365465174593875438957438958e+24DL)
+      || CHECK (testu192 (6189354365465174593875438957438958500000000000000000000000uwb), 6189354365465174593875438957438958e+24DL)
+      || CHECK (testu192 (6189354365465174593875438957438958500000000000000000000001uwb), 6189354365465174593875438957438959e+24DL)
+      || CHECK (testu192 (6277101735386680763835789423207666000000000000000000000000uwb), 6277101735386680763835789423207666e+24DL)
+      || CHECK (testu192 (6277101735386680763835789423207666416102355444464034512895uwb), 6277101735386680763835789423207666e+24DL))
+    __builtin_abort ();
+#endif
+#if __BITINT_MAXWIDTH__ >= 575
+  if (CHECK (tests575 (0wb), 0.DL)
+      || CHECK (tests575 (7wb), 7.DL)
+      || CHECK (tests575 (-42wb), -42.DL)
+      || CHECK (tests575 (-444444444wb), -444444444.DL)
+      || CHECK (tests575 (-3333333333333333wb), -3333333333333333.DL)
+      || CHECK (tests575 (99999999999999999999999999000wb), 99999999999999999999999999000.DL)
+      || CHECK (tests575 (-9999999999999999999999999999999999wb), -9999999999999999999999999999999999.DL)
+      || CHECK (tests575 (999999999999999999999999999999999900wb), 9999999999999999999999999999999999.e+2DL)
+      || CHECK (tests575 (-9999999999999999999999999999999999000wb), -9999999999999999999999999999999999.e+3DL)
+      || CHECK (tests575 (999999999999999999999999999999999900000wb), 9999999999999999999999999999999999.e+5DL)
+      || CHECK (tests575 (-99999999999999999999999999999999990000000wb), -9999999999999999999999999999999999.e+7DL)
+      || CHECK (tests575 (1234567890123456000000000wb), 1234567890123456000000000.DL)
+      || CHECK (tests575 (3424231985445429000000000000000000000000wb), 3424231985445429000000000000000000e+6DL)
+      || CHECK (tests575 (99999999999999999999999999999999990000000000000000000000000000000000000000wb), 9999999999999999999999999999999999.e+40DL)
+      || CHECK (tests575 (-9999999999999999999999999999999999000000000000000000000000000000000000000000000000000000000000000wb), -9999999999999999999999999999999999.e+63DL)
+      || CHECK (tests575 (-213855087769441389758947543987475900000000000000000000000000000000000000000000000000000000000000000000000000000000000000wb), -2138550877694413897589475439874759e+86DL)
+      || CHECK (tests575 (-213855087769441389758947543987475950000000000000000000000000000000000000000000000000000000000000000000000000000000000000wb), -2138550877694413897589475439874760e+86DL)
+      || CHECK (tests575 (-213855087769441389758947543987475949999999999999999999999999999999999999999999999999999999999999999999999999999999999999wb), -2138550877694413897589475439874759e+86DL)
+      || CHECK (tests575 (-213855087769441389758947543987475999999999999999999999999999999999999999999999999999999999999999999999999999999999999999wb), -2138550877694413897589475439874760e+86DL)
+      || CHECK (tests575 (-213855087769441389758947543987475800000000000000000000000000000000000000000000000000000000000000000000000000000000000000wb), -2138550877694413897589475439874758e+86DL)
+      || CHECK (tests575 (-213855087769441389758947543987475850000000000000000000000000000000000000000000000000000000000000000000000000000000000000wb), -2138550877694413897589475439874758e+86DL)
+      || CHECK (tests575 (-213855087769441389758947543987475850000000000000000000000000000000000000000000000000000000000000000000000000000000000001wb), -2138550877694413897589475439874759e+86DL)
+      || CHECK (tests575 (61832600368276133515125630254911790000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000wb), 6183260036827613351512563025491179e+139DL)
+      || CHECK (tests575 (61832600368276133515125630254911797508782837275302959978515764023224306276632966792579100265310761247399417856504034834837841258576687802491886538775473291979151693037174783wb), 6183260036827613351512563025491180e+139DL)
+      || CHECK (tests575 (-61832600368276133515125630254911790000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000wb), -6183260036827613351512563025491179e+139DL)
+      || CHECK (tests575 (-61832600368276133515125630254911797508782837275302959978515764023224306276632966792579100265310761247399417856504034834837841258576687802491886538775473291979151693037174783wb - 1wb), -6183260036827613351512563025491180e+139DL))
+    __builtin_abort ();
+  if (CHECK (testu575 (0uwb), 0.DL)
+      || CHECK (testu575 (17uwb), 17.DL)
+      || CHECK (testu575 (420uwb), 420.DL)
+      || CHECK (testu575 (888888888uwb), 888888888.DL)
+      || CHECK (testu575 (9999999999999000uwb), 9999999999999000.DL)
+      || CHECK (testu575 (99999999999999999999999999999999990000000uwb), 9999999999999999999999999999999999.e+7DL)
+      || CHECK (testu575 (9999999999999999999999999999999999000000000uwb), 9999999999999999999999999999999999.e+9DL)
+      || CHECK (testu575 (99999999999999999999999999999999990000000000000uwb), 9999999999999999999999999999999999.e+13DL)
+      || CHECK (testu575 (9999999999999999999999999999999999000000000000000uwb), 9999999999999999999999999999999999.e+15DL)
+      || CHECK (testu575 (1234567890123456000000000000000000uwb), 1234567890123456000000000000000000.DL)
+      || CHECK (testu575 (34242319854454290000000000000000000000uwb), 3424231985445429000000000000000000e+4DL)
+      || CHECK (testu575 (9999999999999999999999999999999999000000000000000000000000000000000uwb), 9999999999999999999999999999999999.e+33DL)
+      || CHECK (testu575 (618935436546517949837539847534981700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000uwb), 6189354365465179498375398475349817e+104DL)
+      || CHECK (testu575 (618935436546517949837539847534981750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000uwb), 6189354365465179498375398475349818e+104DL)
+      || CHECK (testu575 (618935436546517949837539847534981749999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999uwb), 6189354365465179498375398475349817e+104DL)
+      || CHECK (testu575 (618935436546517949837539847534981799999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999uwb), 6189354365465179498375398475349818e+104DL)
+      || CHECK (testu575 (618935436546517949837539847534981800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000uwb), 6189354365465179498375398475349818e+104DL)
+      || CHECK (testu575 (618935436546517949837539847534981850000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000uwb), 6189354365465179498375398475349818e+104DL)
+      || CHECK (testu575 (618935436546517949837539847534981850000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001uwb), 6189354365465179498375398475349819e+104DL)
+      || CHECK (testu575 (99999999999999999999999999999999990000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000uwb), 9999999999999999999999999999999999.e+139DL)
+      || CHECK (testu575 (123665200736552267030251260509823500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000uwb), 1236652007365522670302512605098235e+140DL)
+      || CHECK (testu575 (123665200736552267030251260509823549999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999uwb), 1236652007365522670302512605098235e+140DL)
+      || CHECK (testu575 (123665200736552267030251260509823550000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000uwb), 1236652007365522670302512605098236e+140DL)
+      || CHECK (testu575 (123665200736552267030251260509823550000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001uwb), 1236652007365522670302512605098236e+140DL)
+      || CHECK (testu575 (123665200736552267030251260509823550000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000uwb), 1236652007365522670302512605098236e+140DL)
+      || CHECK (testu575 (123665200736552267030251260509823595017565674550605919957031528046448612553265933585158200530621522494798835713008069669675682517153375604983773077550946583958303386074349567uwb), 1236652007365522670302512605098236e+140DL))
+    __builtin_abort ();
+#endif
+}
--- libgcc/config/t-softfp.jj	2023-08-04 19:12:27.067454432 +0200
+++ libgcc/config/t-softfp	2023-08-07 15:29:03.244372189 +0200
@@ -68,7 +68,8 @@  softfp_floatbitint_funcs = fix$(m)bitint
 softfp_bid_list := 
 ifeq ($(decimal_float),yes)
 ifeq ($(enable_decimal_float),bid)
-softfp_bid_list += bitintpow10 $(foreach m,sd dd td,fix$(m)bitint)
+softfp_bid_list += bitintpow10 \
+		   $(foreach m,sd dd td,fix$(m)bitint floatbitint$(m))
 endif
 endif
 
--- libgcc/soft-fp/floatbitintsd.c.jj	2023-08-05 20:18:36.028033893 +0200
+++ libgcc/soft-fp/floatbitintsd.c	2023-08-07 17:28:35.780452933 +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-05 12:20:37.504414281 +0200
+++ libgcc/soft-fp/floatbitintdd.c	2023-08-07 17:27:10.526647391 +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-07 12:12:56.784323214 +0200
+++ libgcc/soft-fp/floatbitinttd.c	2023-08-07 17:26:44.194016328 +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