https://gcc.gnu.org/g:6369c6b55cc13fad5deefe9579e66fe477bd83f0

commit 6369c6b55cc13fad5deefe9579e66fe477bd83f0
Author: Michael Meissner <[email protected]>
Date:   Tue Sep 29 21:01:46 2026 -0400

    Add fixbfbitint, fixhfbitint.  Fix 16-bit fp bitint calls.
    
    2026-09-26  Michael Meissner  <[email protected]>
    
    gcc/
    
            * config/rs6000/rs6000.cc (init_float16): Properly set up the
            conversions between 16-bit floating point and bitint to pass 
arguments
            in GPRs.
    
    libgcc/
    
            * config/rs6000/ppc-fixbfbitint.c: New file.
            * config/rs6000/ppc-fixhfbitint.c: Likewise.
            * config/rs6000/t-float16: Build ppc-fixbfbitint and 
ppc-fixhfbitint.

Diff:
---
 gcc/config/rs6000/rs6000.cc            |   7 ++
 libgcc/config/rs6000/ppc-fixbfbitint.c | 128 +++++++++++++++++++++++++++++++++
 libgcc/config/rs6000/ppc-fixhfbitint.c | 127 ++++++++++++++++++++++++++++++++
 libgcc/config/rs6000/t-float16         |   4 +-
 4 files changed, 264 insertions(+), 2 deletions(-)

diff --git a/gcc/config/rs6000/rs6000.cc b/gcc/config/rs6000/rs6000.cc
index 1aed909feab6..6e4c13ecd523 100644
--- a/gcc/config/rs6000/rs6000.cc
+++ b/gcc/config/rs6000/rs6000.cc
@@ -11949,6 +11949,13 @@ init_float16 (void)
              set_conv_libfunc (trunc_optab, fp16_mode2, fp16_mode, fname);
            }
        }
+
+      /* Bitint support.  */
+      sprintf (fname, "__floatbitint%s_gpr", fp16_name);
+      set_optab_libfunc (bitinttofp_optab, fp16_mode, fname);
+
+      sprintf (fname, "__fix%sbitint_gpr", fp16_name);
+      set_optab_libfunc (bitintfromfp_optab, fp16_mode, fname);
     }
 }
 
diff --git a/libgcc/config/rs6000/ppc-fixbfbitint.c 
b/libgcc/config/rs6000/ppc-fixbfbitint.c
new file mode 100644
index 000000000000..3271912dc260
--- /dev/null
+++ b/libgcc/config/rs6000/ppc-fixbfbitint.c
@@ -0,0 +1,128 @@
+/* Software floating-point emulation.
+   Convert IEEE single to signed or unsigned _BitInt.
+
+   Copyright (C) 2023 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<http://www.gnu.org/licenses/>.
+
+This is a clone of softfp/fixsfbit.c
+
+We provide 2 conversions, one that passes the BFtype in a floating point
+register and the other returns it in a general purpose register that is used
+when BFtype must be converted to the 32/64-bit scalar type.  */
+
+#include "soft-fp.h"
+#include "brain.h"
+#include "bitint.h"
+
+#ifdef __BITINT_MAXWIDTH__
+/* Silence declaration without prototype warning.  */
+extern void __fixbfbitint     (UBILtype *, SItype, BFtype);
+extern void __fixbfbitint_gpr (UBILtype *, SItype, unsigned short);
+
+/* BFtype is passed in FPR registers.  */
+void
+__fixbfbitint (UBILtype *r, SItype rprec, BFtype a)
+{
+  FP_DECL_EX;
+  FP_DECL_B (A);
+  USItype arprec = rprec < 0 ? -rprec : rprec;
+  USItype rn = ((USItype) arprec + BIL_TYPE_SIZE - 1) / BIL_TYPE_SIZE;
+  USItype rv;
+  USItype rsize = arprec > SI_BITS ? SI_BITS : arprec;
+  USItype rsigned = rprec < 0;
+  USItype ovf = 0;
+  USItype shift = 0;
+
+  FP_INIT_EXCEPTIONS;
+  FP_UNPACK_RAW_B (A, a);
+  if (arprec > SI_BITS)
+    {
+      if (A_e < _FP_EXPBIAS_B || (A_s && !rsigned))
+       ovf = 1;
+      else if (A_e >= (_FP_EXPMAX_B < _FP_EXPBIAS_B + arprec
+                      ? _FP_EXPMAX_B
+                      : _FP_EXPBIAS_B + arprec - rsigned))
+       {
+         ovf = 1;
+         if (A_s
+             && A_e == _FP_EXPBIAS_B + arprec - 1
+             && A_e < _FP_EXPMAX_B)
+           A_e -= arprec - SI_BITS;
+       }
+      else if (A_e >= _FP_EXPBIAS_B + SI_BITS - rsigned)
+       {
+         shift = A_e - (_FP_EXPBIAS_B + SI_BITS - rsigned - 1);
+         A_e -= shift;
+       }
+    }
+  FP_TO_INT_B (rv, A, rsize, rsigned);
+  FP_HANDLE_EXCEPTIONS;
+  FP_TO_BITINT (r, rn, arprec, shift, rv, rsize, rsigned, ovf, SI);
+}
+
+/* BFtype is passed in GPR registers.  */
+void
+__fixbfbitint_gpr (UBILtype *r, SItype rprec, unsigned short us)
+{
+  FP_DECL_EX;
+  FP_DECL_B (A);
+  USItype arprec = rprec < 0 ? -rprec : rprec;
+  USItype rn = ((USItype) arprec + BIL_TYPE_SIZE - 1) / BIL_TYPE_SIZE;
+  USItype rv;
+  USItype rsize = arprec > SI_BITS ? SI_BITS : arprec;
+  USItype rsigned = rprec < 0;
+  USItype ovf = 0;
+  USItype shift = 0;
+  BFtype a;
+  union ushort_bf u;
+
+  u.us = us;
+  a = u.bf;
+
+  FP_INIT_EXCEPTIONS;
+  FP_UNPACK_RAW_B (A, a);
+  if (arprec > SI_BITS)
+    {
+      if (A_e < _FP_EXPBIAS_B || (A_s && !rsigned))
+       ovf = 1;
+      else if (A_e >= (_FP_EXPMAX_B < _FP_EXPBIAS_B + arprec
+                      ? _FP_EXPMAX_B
+                      : _FP_EXPBIAS_B + arprec - rsigned))
+       {
+         ovf = 1;
+         if (A_s
+             && A_e == _FP_EXPBIAS_B + arprec - 1
+             && A_e < _FP_EXPMAX_B)
+           A_e -= arprec - SI_BITS;
+       }
+      else if (A_e >= _FP_EXPBIAS_B + SI_BITS - rsigned)
+       {
+         shift = A_e - (_FP_EXPBIAS_B + SI_BITS - rsigned - 1);
+         A_e -= shift;
+       }
+    }
+  FP_TO_INT_B (rv, A, rsize, rsigned);
+  FP_HANDLE_EXCEPTIONS;
+  FP_TO_BITINT (r, rn, arprec, shift, rv, rsize, rsigned, ovf, SI);
+}
+#endif
diff --git a/libgcc/config/rs6000/ppc-fixhfbitint.c 
b/libgcc/config/rs6000/ppc-fixhfbitint.c
new file mode 100644
index 000000000000..bb1818ec0695
--- /dev/null
+++ b/libgcc/config/rs6000/ppc-fixhfbitint.c
@@ -0,0 +1,127 @@
+/* Software floating-point emulation.
+   Convert IEEE single to signed or unsigned _BitInt.
+
+   Copyright (C) 2023 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<http://www.gnu.org/licenses/>.
+
+This is a clone of softfp/fixsfbit.c
+
+We provide 2 conversions, one that passes the HFtype in a floating point
+register and the other returns it in a general purpose register that is used
+when HFtype must be converted to the 32/64-bit scalar type.  */
+
+#include "soft-fp.h"
+#include "half.h"
+#include "bitint.h"
+
+#ifdef __BITINT_MAXWIDTH__
+extern void __fixhfbitint     (UBILtype *, SItype, HFtype);
+extern void __fixhfbitint_gpr (UBILtype *, SItype, unsigned short);
+
+/* HFtype is passed in FPR registers.  */
+void
+__fixhfbitint (UBILtype *r, SItype rprec, HFtype a)
+{
+  FP_DECL_EX;
+  FP_DECL_H (A);
+  USItype arprec = rprec < 0 ? -rprec : rprec;
+  USItype rn = ((USItype) arprec + BIL_TYPE_SIZE - 1) / BIL_TYPE_SIZE;
+  USItype rv;
+  USItype rsize = arprec > SI_BITS ? SI_BITS : arprec;
+  USItype rsigned = rprec < 0;
+  USItype ovf = 0;
+  USItype shift = 0;
+
+  FP_INIT_EXCEPTIONS;
+  FP_UNPACK_RAW_H (A, a);
+  if (arprec > SI_BITS)
+    {
+      if (A_e < _FP_EXPBIAS_H || (A_s && !rsigned))
+       ovf = 1;
+      else if (A_e >= (_FP_EXPMAX_H < _FP_EXPBIAS_H + arprec
+                      ? _FP_EXPMAX_H
+                      : _FP_EXPBIAS_H + arprec - rsigned))
+       {
+         ovf = 1;
+         if (A_s
+             && A_e == _FP_EXPBIAS_H + arprec - 1
+             && A_e < _FP_EXPMAX_H)
+           A_e -= arprec - SI_BITS;
+       }
+      else if (A_e >= _FP_EXPBIAS_H + SI_BITS - rsigned)
+       {
+         shift = A_e - (_FP_EXPBIAS_H + SI_BITS - rsigned - 1);
+         A_e -= shift;
+       }
+    }
+  FP_TO_INT_H (rv, A, rsize, rsigned);
+  FP_HANDLE_EXCEPTIONS;
+  FP_TO_BITINT (r, rn, arprec, shift, rv, rsize, rsigned, ovf, SI);
+}
+
+/* HFtype is passed in GPR registers.  */
+void
+__fixhfbitint_gpr (UBILtype *r, SItype rprec, unsigned short us)
+{
+  FP_DECL_EX;
+  FP_DECL_H (A);
+  USItype arprec = rprec < 0 ? -rprec : rprec;
+  USItype rn = ((USItype) arprec + BIL_TYPE_SIZE - 1) / BIL_TYPE_SIZE;
+  USItype rv;
+  USItype rsize = arprec > SI_BITS ? SI_BITS : arprec;
+  USItype rsigned = rprec < 0;
+  USItype ovf = 0;
+  USItype shift = 0;
+  HFtype a;
+  union ushort_hf u;
+
+  u.us = us;
+  a = u.hf;
+
+  FP_INIT_EXCEPTIONS;
+  FP_UNPACK_RAW_H (A, a);
+  if (arprec > SI_BITS)
+    {
+      if (A_e < _FP_EXPBIAS_H || (A_s && !rsigned))
+       ovf = 1;
+      else if (A_e >= (_FP_EXPMAX_H < _FP_EXPBIAS_H + arprec
+                      ? _FP_EXPMAX_H
+                      : _FP_EXPBIAS_H + arprec - rsigned))
+       {
+         ovf = 1;
+         if (A_s
+             && A_e == _FP_EXPBIAS_H + arprec - 1
+             && A_e < _FP_EXPMAX_H)
+           A_e -= arprec - SI_BITS;
+       }
+      else if (A_e >= _FP_EXPBIAS_H + SI_BITS - rsigned)
+       {
+         shift = A_e - (_FP_EXPBIAS_H + SI_BITS - rsigned - 1);
+         A_e -= shift;
+       }
+    }
+  FP_TO_INT_H (rv, A, rsize, rsigned);
+  FP_HANDLE_EXCEPTIONS;
+  FP_TO_BITINT (r, rn, arprec, shift, rv, rsize, rsigned, ovf, SI);
+}
+#endif
diff --git a/libgcc/config/rs6000/t-float16 b/libgcc/config/rs6000/t-float16
index b6d342e25312..6b548b084fef 100644
--- a/libgcc/config/rs6000/t-float16
+++ b/libgcc/config/rs6000/t-float16
@@ -4,7 +4,7 @@ fp16_funcs      = extendhf-sfdf2 truncsfdf-hf2 \
                  ppc-fixunshfsi ppc-fixunshfdi ppc-fixunshfti \
                  ppc-floatsihf ppc-floatdihf ppc-floattihf \
                  ppc-floatunsihf ppc-floatundihf ppc-floatuntihf \
-                 ppc-eqhf2 ppc-floatbitinthf
+                 ppc-eqhf2 ppc-floatbitinthf ppc-fixhfbitint
 
 fp16_src       = $(addprefix $(srcdir)/config/rs6000/,$(addsuffix 
.c,$(fp16_funcs)))
 fp16_obj       = $(addsuffix $(objext),$(fp16_funcs))
@@ -21,7 +21,7 @@ bfp16_funcs   = extendbf-sfdf2 truncsfdf-bf2 \
                  ppc-floatunsibf ppc-floatundibf ppc-floatuntibf \
                  ppc-fixbfsi  ppc-fixbfdi ppc-fixbfti \
                  ppc-fixunsbfsi  ppc-fixunsbfdi ppc-fixunsbfti \
-                 ppc-eqbf2 ppc-floatbitintbf
+                 ppc-eqbf2 ppc-floatbitintbf ppc-fixbfbitint
 
 bfp16_src      = $(addprefix $(srcdir)/config/rs6000/,$(addsuffix 
.c,$(bfp16_funcs)))
 bfp16_obj      = $(addsuffix $(objext),$(bfp16_funcs))

Reply via email to