# _Decimal* to _BitInt conversion support [PR102989]

Message ID ZM0/srtB/QHE+vs2@tucnak New _Decimal* to _BitInt 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_check--master-arm warning Patch failed to apply
linaro-tcwg-bot/tcwg_gcc_build--master-aarch64 warning Patch failed to apply

## Commit Message

Jakub Jelinek Aug. 4, 2023, 6:13 p.m. UTC
```  Hi!

Repost because the patch was too large.

On Fri, Jul 28, 2023 at 06:03:33PM +0000, Joseph Myers wrote:
> Note that representations with too-large significand are defined to be
> noncanonical representations of zero, so you need to take care of that in
> decoding BID.

Done.

> You could e.g. have a table up to 10^(N-1) for some N, and 10^N, 10^2N
> etc. up to 10^6144 (or rather up to 10^6111, which can then be multiplied
> by a 34-digit integer significand), so that only one multiplication is
> needed to get the power of 10 and then a second multiplication by the
> significand.  (Or split into three parts at the cost of an extra
> multiplication, or multiply the significand by 1, 10, 100, 1000 or 10000
> as a multiplication within 128 bits and so only need to compute 10^k for k
> a multiple of 5, or any number of variations on those themes.)

So, I've used N 256 and applied a little further space optimization,
omitting least significant whole limbs full of just zeros (for 32-bit limbs
actually pairs of those limbs, otherwise it would be a nightmare).
With that I got down to 32KiB or so (32128 bytes the limb array and
560 bytes the offset array), tables generated such that they can be used
with both 32-bit and 64-bit limbs and both little and big endian ordering of
them.

The following patch implements for now just the _Decimal -> _BitInt
conversions and uses the soft-fp infrastructure to raise exceptions (not
heavily tight to that, if the bitint.h header from soft-fp is copied/tweaked
and a few typedefs are provided it could be also in libbid if it grows
usable exception support).

I'll work on _BitInt -> _Decimal next and hope to use the __bid_pow10bitint
function in there as well (guess some safe lower power of 10 divisor,
use __divmodbitint4 to divide by that power of 10 including computing
remainder, analyze that remainder (check if it is 0, exact half of the
power of 10, or something smaller or larger than that) and if guessed too
low, divide the usually much smaller quotient again to get exact answer
(+ again check remainder).

The bitintpow10.c patch is included compressed, as the single source file is
408KiB.

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

PR c/102989
gcc/
* gimple-lower-bitint.cc (bitint_large_huge::lower_float_conv_stmt):
Handle _Decimal* to _BitInt conversions.
* internal-fn.cc (expand_FLOATTOBITINT): Likewise.
gcc/testsuite/
* gcc.dg/dfp/bitint-1.c: New test.
* gcc.dg/dfp/bitint-2.c: New test.
* gcc.dg/dfp/bitint-3.c: New test.
libgcc/
* config/t-softfp (softfp_bid_list, softfp_bid_file_list): New
variables.
* soft-fp/fixsdbitint.c: New file.
* soft-fp/fixddbitint.c: New file.
* soft-fp/fixtdbitint.c: New file.
* soft-fp/bitint.h (bitint_negate): New static inline function.
(__mulbitint3, __divmodbitint4, __bid_pow10bitint): Declare.
* soft-fp/bitintpow10.c: New file.

Jakub
```

## Patch

```--- gcc/gimple-lower-bitint.cc.jj	2023-08-02 17:36:15.439915237 +0200
+++ gcc/gimple-lower-bitint.cc	2023-08-04 09:40:14.271005211 +0200
@@ -3363,8 +3363,7 @@  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 (rhs1)))
-      || DECIMAL_FLOAT_MODE_P (TYPE_MODE (TREE_TYPE (lhs))))
+  if (DECIMAL_FLOAT_MODE_P (TYPE_MODE (TREE_TYPE (lhs))))
{
sorry_at (gimple_location (stmt),
"unsupported conversion between %<_BitInt(%d)%> and %qT",
--- gcc/internal-fn.cc.jj	2023-07-26 10:06:29.233849044 +0200
+++ gcc/internal-fn.cc	2023-08-04 09:47:58.368480546 +0200
@@ -4846,11 +4846,25 @@  expand_FLOATTOBITINT (internal_fn, gcall
const char *mname = GET_MODE_NAME (mode);
unsigned mname_len = strlen (mname);
int len = 12 + 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, "__fix", 5);
-  p += 5;
+  if (DECIMAL_FLOAT_MODE_P (mode))
+    {
+#if ENABLE_DECIMAL_BID_FORMAT
+      memcpy (p, "__bid_fix", 9);
+#else
+      memcpy (p, "__dpd_fix", 9);
+#endif
+      p += 9;
+    }
+  else
+    {
+      memcpy (p, "__fix", 5);
+      p += 5;
+    }
for (q = mname; *q; q++)
*p++ = TOLOWER (*q);
memcpy (p, "bitint", 7);
--- gcc/testsuite/gcc.dg/dfp/bitint-1.c.jj	2023-08-04 14:30:24.615100334 +0200
+++ gcc/testsuite/gcc.dg/dfp/bitint-1.c	2023-08-04 19:37:26.834790279 +0200
@@ -0,0 +1,98 @@
+/* PR c/102989 */
+/* { dg-do run { target bitint } } */
+/* { dg-options "-O2 -std=c2x -pedantic-errors" } */
+
+#if __BITINT_MAXWIDTH__ >= 192
+__attribute__((noipa)) _BitInt(192)
+tests192 (_Decimal64 d)
+{
+  return d;
+}
+
+__attribute__((noipa)) unsigned _BitInt(192)
+testu192 (_Decimal64 d)
+{
+  return d;
+}
+#endif
+
+#if __BITINT_MAXWIDTH__ >= 575
+__attribute__((noipa)) _BitInt(575)
+tests575 (_Decimal64 d)
+{
+  return d;
+}
+
+__attribute__((noipa)) unsigned _BitInt(575)
+testu575 (_Decimal64 d)
+{
+  return d;
+}
+#endif
+
+int
+main ()
+{
+#if __BITINT_MAXWIDTH__ >= 192
+  if (tests192 (0.DD) != 0wb
+      || tests192 (0.9999999999999999DD) != 0wb
+      || tests192 (7.999999999999999DD) != 7wb
+      || tests192 (-42.5DD) != -42wb
+      || tests192 (-34242319854.45429e+27DD) != -34242319854454290000000000000000000000wb
+      || tests192 (-213855087769445.9e+43DD) != -2138550877694459000000000000000000000000000000000000000000wb
+      || tests192 (313855086769334.0e+43DD) != 3138550867693340000000000000000000000000000000000000000000wb
+      || tests192 (-313855086769334.0e+43DD) != -3138550867693340000000000000000000000000000000000000000000wb)
+    __builtin_abort ();
+  if (tests192 (313855086769334.1e+43DD) != 3138550867693340381917894711603833208051177722232017256447wb
+      || tests192 (9999999999999999e+369DD) != 3138550867693340381917894711603833208051177722232017256447wb
+      || tests192 (-313855086769334.1e+43DD) != -3138550867693340381917894711603833208051177722232017256447wb - 1wb
+      || tests192 (-9999999999999999e+369DD) != -3138550867693340381917894711603833208051177722232017256447wb - 1wb)
+    __builtin_abort ();
+  if (testu192 (0.DD) != 0uwb
+      || testu192 (0.9999999999999999DD) != 0uwb
+      || testu192 (-0.9999999999999999DD) != 0uwb
+      || testu192 (-0.5DD) != 0uwb
+      || testu192 (42.99999999999999DD) != 42uwb
+      || testu192 (42.e+21DD) != 42000000000000000000000uwb
+      || testu192 (34272319854.45429e+27DD) != 34272319854454290000000000000000000000uwb
+      || testu192 (627710173538668.0e+43DD) != 6277101735386680000000000000000000000000000000000000000000uwb)
+    __builtin_abort ();
+  if (testu192 (-1.DD) != 0uwb
+      || testu192 (-42.5e+15DD) != 0uwb
+      || testu192 (-9999999999999999e+369DD) != 0uwb
+      || testu192 (627710173538668.1e+43DD) != 6277101735386680763835789423207666416102355444464034512895uwb
+      || testu192 (9999999999999999e+369DD) != 6277101735386680763835789423207666416102355444464034512895uwb)
+    __builtin_abort ();
+#endif
+#if __BITINT_MAXWIDTH__ >= 575
+  if (tests575 (0.DD) != 0wb
+      || tests575 (0.999999DD) != 0wb
+      || tests575 (12.9999999999999DD) != 12wb
+      || tests575 (-89.5DD) != -89wb
+      || tests575 (-34242319854.45429e+37DD) != -342423198544542900000000000000000000000000000000wb
+      || tests575 (-518326003682761.2e+158DD) != -51832600368276120000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000wb
+      || tests575 (6183260036827613.0e+157DD) != 61832600368276130000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000wb
+      || tests575 (-6183260036827613.0e+157DD) != -61832600368276130000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000wb)
+    __builtin_abort ();
+  if (tests575 (6183260036827614.0e+157DD) != 61832600368276133515125630254911797508782837275302959978515764023224306276632966792579100265310761247399417856504034834837841258576687802491886538775473291979151693037174783wb
+      || tests575 (9999999999999999e+369DD) != 61832600368276133515125630254911797508782837275302959978515764023224306276632966792579100265310761247399417856504034834837841258576687802491886538775473291979151693037174783wb
+      || tests575 (-6183260036827614.0e+157DD) != -61832600368276133515125630254911797508782837275302959978515764023224306276632966792579100265310761247399417856504034834837841258576687802491886538775473291979151693037174783wb - 1wb
+      || tests575 (-9999999999999999e+369DD) != -61832600368276133515125630254911797508782837275302959978515764023224306276632966792579100265310761247399417856504034834837841258576687802491886538775473291979151693037174783wb - 1wb)
+    __builtin_abort ();
+  if (testu575 (0.DD) != 0uwb
+      || testu575 (0.5555555555555555DD) != 0uwb
+      || testu575 (-0.7777777777777777DD) != 0uwb
+      || testu575 (-0.99DD) != 0uwb
+      || testu575 (42.99999999999999DD) != 42uwb
+      || testu575 (42.e+21DD) != 42000000000000000000000uwb
+      || testu575 (94272319854.45429e+27DD) != 94272319854454290000000000000000000000uwb
+      || testu575 (1236652007365522.0e+158DD) != 123665200736552200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000uwb)
+    __builtin_abort ();
+  if (testu575 (-1.DD) != 0uwb
+      || testu575 (-42.5e+15DD) != 0uwb
+      || testu575 (-9999999999999999e+369DD) != 0uwb
+      || testu575 (1236652007365523.0e+158DD) != 123665200736552267030251260509823595017565674550605919957031528046448612553265933585158200530621522494798835713008069669675682517153375604983773077550946583958303386074349567uwb
+      || testu575 (9999999999999999e+369DD) != 123665200736552267030251260509823595017565674550605919957031528046448612553265933585158200530621522494798835713008069669675682517153375604983773077550946583958303386074349567uwb)
+    __builtin_abort ();
+#endif
+}
--- gcc/testsuite/gcc.dg/dfp/bitint-2.c.jj	2023-08-04 15:11:01.831381336 +0200
+++ gcc/testsuite/gcc.dg/dfp/bitint-2.c	2023-08-04 19:37:36.703654308 +0200
@@ -0,0 +1,91 @@
+/* PR c/102989 */
+/* { dg-do run { target bitint } } */
+/* { dg-options "-O2 -std=c2x -pedantic-errors" } */
+
+#if __BITINT_MAXWIDTH__ >= 192
+__attribute__((noipa)) _BitInt(192)
+tests192 (_Decimal32 d)
+{
+  return d;
+}
+
+__attribute__((noipa)) unsigned _BitInt(192)
+testu192 (_Decimal32 d)
+{
+  return d;
+}
+#endif
+
+#if __BITINT_MAXWIDTH__ >= 575
+__attribute__((noipa)) _BitInt(575)
+tests575 (_Decimal32 d)
+{
+  return d;
+}
+
+__attribute__((noipa)) unsigned _BitInt(575)
+testu575 (_Decimal32 d)
+{
+  return d;
+}
+#endif
+
+int
+main ()
+{
+#if __BITINT_MAXWIDTH__ >= 192
+  if (tests192 (0.DF) != 0wb
+      || tests192 (0.9999999DF) != 0wb
+      || tests192 (7.999999DF) != 7wb
+      || tests192 (-42.5DF) != -42wb
+      || tests192 (-3424.231e+27DF) != -3424231000000000000000000000000wb
+      || tests192 (-213855.9e+43DF) != -2138559000000000000000000000000000000000000000000wb
+      || tests192 (313855.0e+52DF) != 3138550000000000000000000000000000000000000000000000000000wb
+      || tests192 (-3138550.e+51DF) != -3138550000000000000000000000000000000000000000000000000000wb)
+    __builtin_abort ();
+  if (tests192 (313855.1e+52DF) != 3138550867693340381917894711603833208051177722232017256447wb
+      || tests192 (9999999e+90DF) != 3138550867693340381917894711603833208051177722232017256447wb
+      || tests192 (-3138551e+51DF) != -3138550867693340381917894711603833208051177722232017256447wb - 1wb
+      || tests192 (-9999999e+90DF) != -3138550867693340381917894711603833208051177722232017256447wb - 1wb)
+    __builtin_abort ();
+  if (testu192 (0.DF) != 0uwb
+      || testu192 (0.9999999DF) != 0uwb
+      || testu192 (-0.9999999DF) != 0uwb
+      || testu192 (-0.5DF) != 0uwb
+      || testu192 (42.99999DF) != 42uwb
+      || testu192 (42.e+21DF) != 42000000000000000000000uwb
+      || testu192 (3427.231e+29DF) != 342723100000000000000000000000000uwb
+      || testu192 (6277101.0e+51DF) != 6277101000000000000000000000000000000000000000000000000000uwb)
+    __builtin_abort ();
+  if (testu192 (-1.DF) != 0uwb
+      || testu192 (-42.5e+15DF) != 0uwb
+      || testu192 (-9999999e+90DF) != 0uwb
+      || testu192 (6277102.0e+51DF) != 6277101735386680763835789423207666416102355444464034512895uwb
+      || testu192 (9999999e+90DF) != 6277101735386680763835789423207666416102355444464034512895uwb)
+    __builtin_abort ();
+#endif
+#if __BITINT_MAXWIDTH__ >= 575
+  if (tests575 (0.DF) != 0wb
+      || tests575 (0.999999DF) != 0wb
+      || tests575 (12.9999DF) != 12wb
+      || tests575 (-89.5DF) != -89wb
+      || tests575 (-34242.31e+37DF) != -342423100000000000000000000000000000000000wb
+      || tests575 (-518326.2e+88DF) != -5183262000000000000000000000000000000000000000000000000000000000000000000000000000000000000000wb
+      || tests575 (9999999e+90DF) != 9999999000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000wb
+      || tests575 (-9999999e+90DF) != -9999999000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000wb)
+    __builtin_abort ();
+  if (testu575 (0.DF) != 0uwb
+      || testu575 (0.5555555DF) != 0uwb
+      || testu575 (-0.7777777DF) != 0uwb
+      || testu575 (-0.99DF) != 0uwb
+      || testu575 (42.99999DF) != 42uwb
+      || testu575 (42.e+21DF) != 42000000000000000000000uwb
+      || testu575 (9427.231e+27DF) != 9427231000000000000000000000000uwb
+      || testu575 (9999999e+90DF) != 9999999000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000uwb)
+    __builtin_abort ();
+  if (testu575 (-1.DF) != 0uwb
+      || testu575 (-42.5e+15DF) != 0uwb
+      || testu575 (-9999999e+90DF) != 0uwb)
+    __builtin_abort ();
+#endif
+}
--- gcc/testsuite/gcc.dg/dfp/bitint-3.c.jj	2023-08-04 19:35:27.738431329 +0200
+++ gcc/testsuite/gcc.dg/dfp/bitint-3.c	2023-08-04 19:37:45.922527271 +0200
@@ -0,0 +1,98 @@
+/* PR c/102989 */
+/* { dg-do run { target bitint } } */
+/* { dg-options "-O2 -std=c2x -pedantic-errors" } */
+
+#if __BITINT_MAXWIDTH__ >= 192
+__attribute__((noipa)) _BitInt(192)
+tests192 (_Decimal128 d)
+{
+  return d;
+}
+
+__attribute__((noipa)) unsigned _BitInt(192)
+testu192 (_Decimal128 d)
+{
+  return d;
+}
+#endif
+
+#if __BITINT_MAXWIDTH__ >= 575
+__attribute__((noipa)) _BitInt(575)
+tests575 (_Decimal128 d)
+{
+  return d;
+}
+
+__attribute__((noipa)) unsigned _BitInt(575)
+testu575 (_Decimal128 d)
+{
+  return d;
+}
+#endif
+
+int
+main ()
+{
+#if __BITINT_MAXWIDTH__ >= 192
+  if (tests192 (0.DL) != 0wb
+      || tests192 (0.9999999999999999999999999999999999DL) != 0wb
+      || tests192 (7.999999999999999999999999999999999DL) != 7wb
+      || tests192 (-42.5DL) != -42wb
+      || tests192 (-34242319854.45429439857871298745432e+27DL) != -34242319854454294398578712987454320000wb
+      || tests192 (-213855087769445.9e+43DL) != -2138550877694459000000000000000000000000000000000000000000wb
+      || tests192 (3138550867693340381917894711603833.0e+24DL) != 3138550867693340381917894711603833000000000000000000000000wb
+      || tests192 (-3138550867693340381917894711603833.0e+24DL) != -3138550867693340381917894711603833000000000000000000000000wb)
+    __builtin_abort ();
+  if (tests192 (3138550867693340381917894711603834.0e+24DL) != 3138550867693340381917894711603833208051177722232017256447wb
+      || tests192 (9999999999999999999999999999999999e+6111DL) != 3138550867693340381917894711603833208051177722232017256447wb
+      || tests192 (-3138550867693340381917894711603834.0e+24DL) != -3138550867693340381917894711603833208051177722232017256447wb - 1wb
+      || tests192 (-9999999999999999999999999999999999e+6111DL) != -3138550867693340381917894711603833208051177722232017256447wb - 1wb)
+    __builtin_abort ();
+  if (testu192 (0.DL) != 0uwb
+      || testu192 (0.9999999999999999999999999999999999DL) != 0uwb
+      || testu192 (-0.9999999999999999999999999999999999DL) != 0uwb
+      || testu192 (-0.5DL) != 0uwb
+      || testu192 (42.99999999999999999999999999999999DL) != 42uwb
+      || testu192 (42.e+21DL) != 42000000000000000000000uwb
+      || testu192 (34242319854.45429439857871298745432e+21DL) != 34242319854454294398578712987454uwb
+      || testu192 (6277101735386680763835789423207666.0e+24DL) != 6277101735386680763835789423207666000000000000000000000000uwb)
+    __builtin_abort ();
+  if (testu192 (-1.DL) != 0uwb
+      || testu192 (-42.5e+15DL) != 0uwb
+      || testu192 (-9999999999999999999999999999999999e+6111DL) != 0uwb
+      || testu192 (6277101735386680763835789423207667.0e+24DL) != 6277101735386680763835789423207666416102355444464034512895uwb
+      || testu192 (9999999999999999999999999999999999e+6111DL) != 6277101735386680763835789423207666416102355444464034512895uwb)
+    __builtin_abort ();
+#endif
+#if __BITINT_MAXWIDTH__ >= 575
+  if (tests575 (0.DL) != 0wb
+      || tests575 (0.999999999999999999999DL) != 0wb
+      || tests575 (12.99999999999999999999999999999DL) != 12wb
+      || tests575 (-89.5DL) != -89wb
+      || tests575 (-34242319854.45429986754986758972345e+37DL) != -342423198544542998675498675897234500000000000000wb
+      || tests575 (-518326003682761.2e+158DL) != -51832600368276120000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000wb
+      || tests575 (6183260036827613351512563025491179.0e+139DL) != 61832600368276133515125630254911790000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000wb
+      || tests575 (-6183260036827613351512563025491179.0e+139DL) != -61832600368276133515125630254911790000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000wb)
+    __builtin_abort ();
+  if (tests575 (618326003682761335151256302549118.0e+140DL) != 61832600368276133515125630254911797508782837275302959978515764023224306276632966792579100265310761247399417856504034834837841258576687802491886538775473291979151693037174783wb
+      || tests575 (9999999999999999999999999999999999e+6111DL) != 61832600368276133515125630254911797508782837275302959978515764023224306276632966792579100265310761247399417856504034834837841258576687802491886538775473291979151693037174783wb
+      || tests575 (-6183260036827613351512563025491180.0e+139DL) != -61832600368276133515125630254911797508782837275302959978515764023224306276632966792579100265310761247399417856504034834837841258576687802491886538775473291979151693037174783wb - 1wb
+      || tests575 (-9999999999999999999999999999999999e+6111DL) != -61832600368276133515125630254911797508782837275302959978515764023224306276632966792579100265310761247399417856504034834837841258576687802491886538775473291979151693037174783wb - 1wb)
+    __builtin_abort ();
+  if (testu575 (0.DL) != 0uwb
+      || testu575 (0.5555555555555555555555555555555555DL) != 0uwb
+      || testu575 (-0.7777777777777777777777777777777777DL) != 0uwb
+      || testu575 (-0.99DL) != 0uwb
+      || testu575 (42.99999999999999999999999999999999DL) != 42uwb
+      || testu575 (42.e+21DL) != 42000000000000000000000uwb
+      || testu575 (94272319854.45429e+27DL) != 94272319854454290000000000000000000000uwb
+      || testu575 (1236652007365522670302512605098235.0e+140DL) != 123665200736552267030251260509823500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000uwb)
+    __builtin_abort ();
+  if (testu575 (-1.DL) != 0uwb
+      || testu575 (-42.5e+15DL) != 0uwb
+      || testu575 (-9999999999999999999999999999999999e+6111DL) != 0uwb
+      || testu575 (1236652007365522670302512605098236.0e+140DL) != 123665200736552267030251260509823595017565674550605919957031528046448612553265933585158200530621522494798835713008069669675682517153375604983773077550946583958303386074349567uwb
+      || testu575 (9999999999999999999999999999999999e+6111DL) != 123665200736552267030251260509823595017565674550605919957031528046448612553265933585158200530621522494798835713008069669675682517153375604983773077550946583958303386074349567uwb)
+    __builtin_abort ();
+#endif
+}
--- libgcc/config/t-softfp.jj	2023-07-17 09:35:07.802912565 +0200
+++ libgcc/config/t-softfp	2023-08-04 19:12:27.067454432 +0200
@@ -65,6 +65,12 @@  softfp_float_funcs = add\$(m)3 div\$(m)3 e
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)
+endif
+endif

softfp_func_list := \
\$(foreach m,\$(softfp_float_modes), \
@@ -118,6 +124,8 @@  softfp_file_list := \
endif
endif
+softfp_bid_file_list := \

# Disable missing prototype and type limit warnings.  The prototypes
# for the functions in the soft-fp files have not been brought across
@@ -131,6 +139,7 @@  soft-fp-objects = \$(addsuffix \$(objext),
\$(soft-fp-objects) : INTERNAL_CFLAGS += -Wno-missing-prototypes -Wno-type-limits

ifneq (\$(softfp_exclude_libgcc2),y)
# Functions in libgcc2.c are excluded for each soft-float mode (a
--- libgcc/soft-fp/fixsdbitint.c.jj	2023-08-04 14:34:26.613747923 +0200
+++ libgcc/soft-fp/fixsdbitint.c	2023-08-04 14:43:18.104385171 +0200
@@ -0,0 +1,187 @@
+/* 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
+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
+
+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
+
+#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)
+    {
+      extern UDItype __bid_ten2k64[];
+      UDItype d = __bid_ten2k64[-exponent];
+      USItype 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-03 18:53:40.456511156 +0200
+++ libgcc/soft-fp/fixddbitint.c	2023-08-04 14:22:34.543612036 +0200
@@ -0,0 +1,197 @@
+/* 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
+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
+
+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
+
+#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)
+    {
+      extern UDItype __bid_ten2k64[];
+      UDItype d = __bid_ten2k64[-exponent];
+      UDItype 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-04 18:19:17.986391454 +0200
+++ libgcc/soft-fp/fixtdbitint.c	2023-08-04 19:11:20.053377659 +0200
@@ -0,0 +1,264 @@
+/* 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
+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
+
+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
+
+#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;
+    }
+  else if ((t & (3 << 12)) != (3 << 12))
+    {
+      mantissahi &= ((((UDItype) 1) << 47) - 1);
+      mantissahi |= ((UDItype) 1) << 49;
+      exponent = t & 0x3fff;
+      if (mantissahi > (UDItype) 0x1ed09bead87c0
+	  || (mantissahi == (UDItype) 0x1ed09bead87c0
+	      && mantissalo > 0x378d8e63ffffffff))
+	{
+	  mantissahi = 0;
+	  mantissalo = 0;
+	}
+    }
+  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)
+    {
+      extern UDItype __bid_ten2k64[];
+      typedef __attribute__ ((aligned(16))) struct { UDItype w[2]; } UINT128;
+      extern UINT128 __bid_ten2k128[];
+      UBILtype limbs[4 * 128 / BIL_TYPE_SIZE];
+#if BIL_TYPE_SIZE == 64
+      limbs[BITINT_END (0, 1)] = mantissahi;
+      limbs[BITINT_END (1, 0)] = mantissalo;
+      if (exponent >= -19)
+	limbs[2] = __bid_ten2k64[-exponent];
+      else
+	{
+	  limbs[BITINT_END (2, 3)] = __bid_ten2k128[-20 - exponent].w[1];
+	  limbs[BITINT_END (3, 2)] = __bid_ten2k128[-20 - exponent].w[0];
+	}
+#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;
+      if (exponent >= -19)
+	{
+	  limbs[BITINT_END (4, 5)] = __bid_ten2k64[-exponent] >> 32;
+	  limbs[BITINT_END (5, 4)] = __bid_ten2k64[-exponent];
+	}
+      else
+	{
+	  limbs[BITINT_END (4, 7)] = __bid_ten2k128[-20 - exponent].w[1] >> 32;
+	  limbs[BITINT_END (5, 6)] = __bid_ten2k128[-20 - exponent].w[1];
+	  limbs[BITINT_END (6, 5)] = __bid_ten2k128[-20 - exponent].w[0] >> 32;
+	  limbs[BITINT_END (7, 4)] = __bid_ten2k128[-20 - exponent].w[0];
+	}
+#elif
+# error Unhandled BIL_TYPE_SIZE
+#endif
+      __divmodbitint4 (&limbs[2 * 128 / BIL_TYPE_SIZE], 128,
+		       &limbs[3 * 128 / BIL_TYPE_SIZE], 128,
+		       &limbs[0], 128, &limbs[128 / BIL_TYPE_SIZE],
+		       exponent >= -19 ? 64 : 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/bitint.h.jj	2023-07-14 23:35:51.539466644 +0200
+++ libgcc/soft-fp/bitint.h	2023-08-04 18:47:43.753878151 +0200
@@ -160,6 +160,21 @@  bitint_reduce_prec (const UBILtype **p,
# 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)								\
{									\
@@ -301,6 +316,14 @@  bitint_reduce_prec (const UBILtype **p,
}									\
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 */

```