https://gcc.gnu.org/g:2a050daab641a2d6d01f0efd3f238f07df57a572

commit 2a050daab641a2d6d01f0efd3f238f07df57a572
Author: Michael Meissner <[email protected]>
Date:   Thu Oct 22 04:05:31 2026 -0400

    Pass and return 16-bit fp library values in GPRs
    
    This patch changes all of the 16-bit floating point library functions to 
pass
    and return 16-bit floating point values as unsigned short.  The intention 
is to
    prepare for modifying the calling sequence so that the values are converted 
to
    32/64-bit scalar floating point.  However, we can't call the library 
functions
    which are used to do the conversion if we have to convert the argument on a
    machine that does not have native conversion instructions.
    
    This patch adds support in libgcc to build the normal conversion functions 
and a
    modified conversion that has a _gpr suffix, and are the functions called 
when
    -mfloat16-gpr-convert is one.
    
    This patch also does conversions between TFmode, KFmode, IFmode and BFmode 
or
    HFmode even if we do not have hardware support for BFmode or HFmode.
    
    2026-10-21  Michael Meissner  <[email protected]>
    
    gcc/
    
            * config/rs6000/float16.md
            (extend<FP16_HW:mode><FP16_FLOAT_CONVERT:mode>2): Allow insn even 
if we
            do not have hardware support.
            (trunc<FP16_FLOAT_CONVERT:mode><FP16_HW:mode>2): Likewise.
            * config/rs6000/rs6000-call.cc (FP16_USE_GPR): New macro.
            (USE_FP_FOR_ARG_P) Add support for 16-bit fp library functions 
passing
            16-bit fp in GPR registers.
            (init_cumulative_args): Print the function name if it exists and if 
the
            function is a library function when -mdebug=ag is used.
            * config/rs6000/rs6000.cc (rs6000_debug_reg_global): Print 16-bit
            floating point information if -mdebug=reg.
            (init_float16): New function.  Mark all of the 16-bit floating point
            library functions as passing/returning 16-bit floating point values 
in
            GPR registers and change the name to have a '_gpr' suffix.
            (rs6000_init_libfuncs): Likewise.
            (rs6000_opt_vars): Add -mfloat16-gpr-convert switch.
            * config/rs6000/rs6000.opt (-mfloat16-gpr-convert): New switch.
    
    libgcc/
    
            * config/rs6000/convert-16bit-fp-extend: New file.
            * config/rs6000/convert-16bit-fp-fix: Likewise.
            * config/rs6000/convert-16bit-fp-float: Likewise.
            * config/rs6000/convert-16bit-fp-trunc: Likewise.
            * config/rs6000/ppc-eqbf2.c: Likewise.
            * config/rs6000/ppc-eqhf2.c: Likewise.
            * config/rs6000/ppc-fixbfbitint.c: Likewise.
            * config/rs6000/ppc-fixhfbitint.c: Likewise.
            * config/rs6000/ppc-floatbitintbf.c: Likewise.
            * config/rs6000/ppc-floatbitinthf.c: Likewise.
            * config/rs6000/ppc-truncbfhf2.c: Likewise.
            * config/rs6000/ppc-trunchfbf2.c: Likewise.
            * config/rs6000/sfp-machine.h: Add declarations for declaring the 
*_gpr
            library functions.
            * config/rs6000/t-float16: Build all of the new 16-bit floating 
point
            conversion functions that pass and return 16-bit floating point in 
GPR
            registers.

Diff:
---
 gcc/config/rs6000/float16.md       |   8 +-
 gcc/config/rs6000/rs6000-call.cc   |  23 ++++-
 gcc/config/rs6000/rs6000.cc        | 158 +++++++++++++++++++++++++++++
 gcc/config/rs6000/rs6000.opt       |   4 +
 libgcc/config/rs6000/sfp-machine.h | 111 +++++++++++++++-----
 libgcc/config/rs6000/t-float16     | 202 +++++++++++++++++++++++++++++++++----
 6 files changed, 453 insertions(+), 53 deletions(-)

diff --git a/gcc/config/rs6000/float16.md b/gcc/config/rs6000/float16.md
index 1bbad9729c5e..6485f4d2d62d 100644
--- a/gcc/config/rs6000/float16.md
+++ b/gcc/config/rs6000/float16.md
@@ -729,9 +729,9 @@
 ;; types might not have valid RTX expanders.  We use DFmode as the
 ;; intermediate conversion destination.
 
-(define_expand "extend<FP16_HW:mode><FP16_FLOAT_CONVERT:mode>2"
+(define_expand "extend<FP16:mode><FP16_FLOAT_CONVERT:mode>2"
   [(use (match_operand:FP16_FLOAT_CONVERT 0 "vsx_register_operand"))
-   (use (match_operand:FP16_HW 1 "vsx_register_operand"))]
+   (use (match_operand:FP16 1 "vsx_register_operand"))]
   "can_create_pseudo_p ()"
 {
   rtx df_tmp = gen_reg_rtx (DFmode);
@@ -741,8 +741,8 @@
   DONE;
 })
 
-(define_expand "trunc<FP16_FLOAT_CONVERT:mode><FP16_HW:mode>2"
-  [(use (match_operand:FP16_HW 0 "vsx_register_operand"))
+(define_expand "trunc<FP16_FLOAT_CONVERT:mode><FP16:mode>2"
+  [(use (match_operand:FP16 0 "vsx_register_operand"))
    (use (match_operand:FP16_FLOAT_CONVERT 1 "vsx_register_operand"))]
   "can_create_pseudo_p ()"
 {
diff --git a/gcc/config/rs6000/rs6000-call.cc b/gcc/config/rs6000/rs6000-call.cc
index 790f86218870..e970f63f2f08 100644
--- a/gcc/config/rs6000/rs6000-call.cc
+++ b/gcc/config/rs6000/rs6000-call.cc
@@ -81,10 +81,17 @@
 #define TARGET_NO_PROTOTYPE 0
 #endif
 
-/* Nonzero if we can use a floating-point register to pass this arg.  */
-#define USE_FP_FOR_ARG_P(CUM,MODE)             \
-  (SCALAR_FLOAT_MODE_NOT_VECTOR_P (MODE)               \
-   && (CUM)->fregno <= FP_ARG_MAX_REG          \
+/* Whether we pass 16-bit floating point values in GPRs for library
+   calls.  */
+#define FP16_USE_GPR(MODE, LIBCALL)                                    \
+  (FP16_SCALAR_MODE_P (MODE) && TARGET_FLOAT16_GPR_CONVERT && LIBCALL)
+
+/* Nonzero if we can use a floating-point register to pass this arg.  16-bit
+   floating point arguments to library functions are passed as ints.  */
+#define USE_FP_FOR_ARG_P(CUM,MODE)                                     \
+  (SCALAR_FLOAT_MODE_NOT_VECTOR_P (MODE)                               \
+   && !FP16_USE_GPR (MODE, (CUM)->libcall)                             \
+   && (CUM)->fregno <= FP_ARG_MAX_REG                                  \
    && TARGET_HARD_FLOAT)
 
 /* Nonzero if we can use an AltiVec register to pass this arg.  */
@@ -590,7 +597,7 @@ call_ABI_of_interest (tree fndecl)
 
 void
 init_cumulative_args (CUMULATIVE_ARGS *cum, tree fntype,
-                     rtx libname ATTRIBUTE_UNUSED, int incoming,
+                     rtx libname, int incoming,
                      int libcall, int n_named_args,
                      tree fndecl,
                      machine_mode return_mode ATTRIBUTE_UNUSED)
@@ -653,6 +660,12 @@ init_cumulative_args (CUMULATIVE_ARGS *cum, tree fntype,
       if (cum->call_cookie & CALL_LONG)
        fprintf (stderr, " longcall,");
 
+      if (libname)
+       fprintf (stderr, " name=%s,", XSTR (libname, 0));
+
+      if (libcall)
+       fprintf (stderr, " libcall,");
+
       fprintf (stderr, " proto = %d, nargs = %d\n",
               cum->prototype, cum->nargs_prototype);
     }
diff --git a/gcc/config/rs6000/rs6000.cc b/gcc/config/rs6000/rs6000.cc
index 7ae3c55f8a69..8107cd14a9a3 100644
--- a/gcc/config/rs6000/rs6000.cc
+++ b/gcc/config/rs6000/rs6000.cc
@@ -2636,6 +2636,33 @@ rs6000_debug_reg_global (void)
   if (TARGET_DIRECT_MOVE_128)
     fprintf (stderr, DEBUG_FMT_D, "VSX easy 64-bit mfvsrld element",
             (int)VECTOR_ELEMENT_MFVSRLD_64BIT);
+
+  if (TARGET_FLOAT16)
+    {
+      fprintf (stderr, DEBUG_FMT_S, "_Float16",
+              (TARGET_FLOAT16_HW ? "hardware" : "software"));
+      fprintf (stderr, DEBUG_FMT_S, "__bf16",
+              (TARGET_BFLOAT16_HW ? "hardware" : "software"));
+      fprintf (stderr, DEBUG_FMT_S, "-mfloat16-gpr-convert",
+              (TARGET_FLOAT16_GPR_CONVERT ? "yes" : "no"));
+
+#if POWERPC_FLOAT16_DEFAULT
+      fprintf (stderr, DEBUG_FMT_S, "float16 configured", "enabled");
+#else
+      fprintf (stderr, DEBUG_FMT_S, "float16 configured", "disabled");
+#endif
+
+#if POWERPC_FLOAT16_DISABLE_WARNING
+      fprintf (stderr, DEBUG_FMT_S, "float16 call warnings", "disabled");
+#else
+      fprintf (stderr, DEBUG_FMT_S, "float16 call warnings", "enabled");
+#endif
+    }
+  else
+    {
+      fprintf (stderr, DEBUG_FMT_S, "_Float16", "disabled");
+      fprintf (stderr, DEBUG_FMT_S, "__bf16", "disabled");
+    }
 }
 
 
@@ -11837,6 +11864,128 @@ init_float128_ieee (machine_mode mode)
     }
 }
 
+/* For 16-bit floating point, mark the identifier of the conversion functions
+   so they pass/register the HFmode and BFmode in a GPR register rather than a
+   floating point register.  Thus if HFmode/BFmode are converted to DFmode for
+   passing and returning values, we can do the conversion on machines that
+   don't have the conversions.  */
+
+static void
+init_float16 (void)
+{
+  char fname[80];
+
+  /* Map mode to a string.  */
+  struct mode_string  {
+    const enum machine_mode mode;
+    const char *const name;
+  };
+
+  const static struct mode_string fp16_modes[] = {
+    { E_BFmode, "bf" },
+    { E_HFmode, "hf" },
+  };
+
+  const static struct mode_string fp_modes[] = {
+    { E_SFmode, "sf" },
+    { E_DFmode, "df" },
+  };
+
+  const static struct mode_string int_modes[] = {
+    { E_SImode, "si" },
+    { E_DImode, "di" },
+    { E_TImode, "ti" },
+  };
+
+  for (size_t i = 0; i < ARRAY_SIZE (fp16_modes); i++)
+    {
+      enum machine_mode fp16_mode = fp16_modes[i].mode;
+      const char *fp16_name = fp16_modes[i].name;
+
+      /* Conversions between {SFmode,DFmode} <=> {BFmode,HFmode}.  */
+      for (size_t j = 0; j < ARRAY_SIZE (fp_modes); j++)
+       {
+         enum machine_mode fp_mode = fp_modes[j].mode;
+         const char *fp_name = fp_modes[j].name;
+
+         sprintf (fname, "__extend%s%s2_gpr", fp16_name, fp_name);
+         set_conv_libfunc (sext_optab, fp_mode, fp16_mode, fname);
+         if (TARGET_DEBUG_ARG)
+           fprintf (stderr, "Special %s to %s conversion: %s\n",
+                    fp16_name, fp_name, fname);
+
+         sprintf (fname, "__trunc%s%s2_gpr", fp_name, fp16_name);
+         set_conv_libfunc (trunc_optab, fp16_mode, fp_mode, fname);
+         if (TARGET_DEBUG_ARG)
+           fprintf (stderr, "Special %s to %s conversion: %s\n",
+                    fp_name, fp16_name, fname);
+       }
+
+      /* Conversions between {SImode,DImode} <=> {BFmode,HFmode}.  */
+      for (size_t j = 0; j < ARRAY_SIZE (int_modes); j++)
+       {
+         enum machine_mode int_mode = int_modes[j].mode;
+         const char *int_name = int_modes[j].name;
+
+         if (int_mode == SImode || TARGET_POWERPC64)
+           {
+             sprintf (fname, "__float%s%s_gpr", int_name, fp16_name);
+             set_conv_libfunc (sfloat_optab, fp16_mode, int_mode, fname);
+             if (TARGET_DEBUG_ARG)
+               fprintf (stderr, "Special signed %s to %s conversion: %s\n",
+                        int_name, fp16_name, fname);
+
+             sprintf (fname, "__floatun%s%s_gpr", int_name, fp16_name);
+             set_conv_libfunc (ufloat_optab, fp16_mode, int_mode, fname);
+             if (TARGET_DEBUG_ARG)
+               fprintf (stderr, "Special unsigned %s to %s conversion: %s\n",
+                        int_name, fp16_name, fname);
+
+             sprintf (fname, "__fix%s%s_gpr", fp16_name, int_name);
+             set_conv_libfunc (sfix_optab, int_mode, fp16_mode, fname);
+             if (TARGET_DEBUG_ARG)
+               fprintf (stderr, "Special signed %s to %s conversion: %s\n",
+                        fp16_name, int_name, fname);
+
+             sprintf (fname, "__fixuns%s%s_gpr", fp16_name, int_name);
+             set_conv_libfunc (ufix_optab, int_mode, fp16_mode, fname);
+             if (TARGET_DEBUG_ARG)
+               fprintf (stderr, "Special unsigned %s to %s conversion: %s\n",
+                        fp16_name, int_name, fname);
+           }
+       }
+
+      /* Conversions between the two 16-bit floating point formats.  */
+      for (size_t j = 0; j < ARRAY_SIZE (fp16_modes); j++)
+       {
+         enum machine_mode fp16_mode2 = fp16_modes[j].mode;
+         const char *fp16_name2 = fp16_modes[j].name;
+
+         if (fp16_mode != fp16_mode2)
+           {
+             sprintf (fname, "__trunc%s%s2_gpr", fp16_name, fp16_name2);
+             set_conv_libfunc (trunc_optab, fp16_mode2, fp16_mode, fname);
+             if (TARGET_DEBUG_ARG)
+               fprintf (stderr, "Special signed %s to %s conversion: %s\n",
+                        fp16_name, fp16_name2, fname);
+           }
+       }
+
+      /* Bitint support.  */
+      sprintf (fname, "__floatbitint%s_gpr", fp16_name);
+      set_optab_libfunc (bitinttofp_optab, fp16_mode, fname);
+      if (TARGET_DEBUG_ARG)
+       fprintf (stderr, "Special %s to bitint conversion: %s\n",
+                fp16_name, fname);
+
+      sprintf (fname, "__fix%sbitint_gpr", fp16_name);
+      set_optab_libfunc (bitintfromfp_optab, fp16_mode, fname);
+      if (TARGET_DEBUG_ARG)
+       fprintf (stderr, "Special bitint to %s conversion: %s\n",
+                fp16_name, fname);
+    }
+}
+
 static void
 rs6000_init_libfuncs (void)
 {
@@ -11857,6 +12006,10 @@ rs6000_init_libfuncs (void)
       else
        init_float128_ieee (TFmode);
     }
+
+  /* 16-bit float support functions.  */
+  if (TARGET_FLOAT16 && TARGET_FLOAT16_GPR_CONVERT)
+    init_float16 ();
 }
 
 /* Emit a potentially record-form instruction, setting DST from SRC.
@@ -24450,6 +24603,8 @@ rs6000_libcall_value (machine_mode mode)
   if (DECIMAL_FLOAT_MODE_P (mode) && TARGET_HARD_FLOAT)
     /* _Decimal128 must use an even/odd register pair.  */
     regno = (mode == TDmode) ? FP_ARG_RETURN + 1 : FP_ARG_RETURN;
+  else if (FP16_SCALAR_MODE_P (mode) && TARGET_FLOAT16_GPR_CONVERT)
+    regno = GP_ARG_RETURN;
   else if (SCALAR_FLOAT_MODE_NOT_VECTOR_P (mode) && TARGET_HARD_FLOAT)
     regno = FP_ARG_RETURN;
   /* VSX is a superset of Altivec and adds V2DImode/V2DFmode.  Since the same
@@ -25042,6 +25197,9 @@ static struct rs6000_opt_var const rs6000_opt_vars[] =
   { "speculate-indirect-jumps",
     offsetof (struct gcc_options, x_rs6000_speculate_indirect_jumps),
     offsetof (struct cl_target_option, x_rs6000_speculate_indirect_jumps), },
+  { "float16-gpr-convert",
+    offsetof (struct gcc_options, x_TARGET_FLOAT16_GPR_CONVERT),
+    offsetof (struct cl_target_option, x_TARGET_FLOAT16_GPR_CONVERT), },
 };
 
 /* Inner function to handle attribute((target("..."))) and #pragma GCC target
diff --git a/gcc/config/rs6000/rs6000.opt b/gcc/config/rs6000/rs6000.opt
index f39d6f0a3107..83b99bd1b491 100644
--- a/gcc/config/rs6000/rs6000.opt
+++ b/gcc/config/rs6000/rs6000.opt
@@ -658,6 +658,10 @@ mfloat16-debug2
 Target Undocumented Var(TARGET_FLOAT16_DEBUG2) Init(0) Save
 Turn on float16 debugging #2.
 
+mfloat16-gpr-convert
+Target Undocumented Var(TARGET_FLOAT16_GPR_CONVERT) Init(1) Save
+Pass/return (do not pass/return) 16-it float conversions in GPR registers.
+
 ; Documented parameters
 
 -param=rs6000-vect-unroll-limit=
diff --git a/libgcc/config/rs6000/sfp-machine.h 
b/libgcc/config/rs6000/sfp-machine.h
index b6dd03a710e3..b37bf0903a87 100644
--- a/libgcc/config/rs6000/sfp-machine.h
+++ b/libgcc/config/rs6000/sfp-machine.h
@@ -170,42 +170,105 @@ void __sfp_handle_exceptions (int);
 /* Add prototypes for the HFmode and BFmode functions.  */
 typedef double DFtype2;
 typedef float SFtype2;
-typedef int DItype2 __attribute__ ((mode (DI)));
-typedef unsigned int UDItype2 __attribute__ ((mode (DI)));
+typedef int HItype2 __attribute__ ((mode (HI)));
+typedef unsigned int UHItype2 __attribute__ ((mode (HI)));
 typedef int SItype2 __attribute__ ((mode (SI)));
 typedef unsigned int USItype2 __attribute__ ((mode (SI)));
+typedef int DItype2 __attribute__ ((mode (DI)));
+typedef unsigned int UDItype2 __attribute__ ((mode (DI)));
+typedef int TItype2 __attribute__ ((mode (TI)));
+typedef unsigned int UTItype2 __attribute__ ((mode (TI)));
+
+/* We have 2 different conversion functions.  One passes or returns the 16-bit
+   floating point type in a floating point register, and the other passes or
+   returns it in a general purpose register.  If 16-bit floating point is
+   normally converted to the 32/64-bit scalar represention, we need a function
+   that does not do this conversion.  */
+#define PASS_FP16(NAME, RET, FP16)                                     \
+extern RET NAME (FP16);                                                        
\
+extern RET NAME ## _gpr (UHItype2)
+
+#define PASS_FP16_2(NAME, RET, FP16_1, FP16_2)                         \
+extern RET NAME (FP16_1, FP16_2);                                      \
+extern RET NAME ## _gpr (UHItype2, UHItype2)
+
+#define RETURN_FP16(NAME, FP16, ARG)                                   \
+extern FP16 NAME (ARG);                                                        
\
+extern UHItype2 NAME ## _gpr (ARG)
+
+#define CONVERT_FP16(NAME, FP16_RET, FP16_ARG)                         \
+extern FP16_RET NAME (FP16_ARG);                                       \
+extern UHItype2 NAME ## _gpr (UHItype2)
 
 #ifdef __FLOAT16__
 typedef float HFtype2 __attribute__ ((mode (HF)));
 
-extern CMPtype __eqhf2 (HFtype2, HFtype2);
-extern DFtype2 __extendhfdf2 (HFtype2);
-extern SFtype2 __extendhfsf2 (HFtype2);
-extern DItype2 __fixhfdi (HFtype2);
-extern SItype2 __fixhfsi (HFtype2);
-extern UDItype2 __fixunshfdi (HFtype2);
-extern USItype2 __fixunshfsi (HFtype2);
-extern HFtype2 __floatdihf (DItype2);
-extern HFtype2 __floatsihf (SItype2);
-extern HFtype2 __floatundihf (UDItype2);
-extern HFtype2 __floatunsihf (USItype2);
-extern HFtype2 __truncdfhf2 (DFtype2);
-extern HFtype2 __truncsfhf2 (SFtype2);
+/* Move between HFtype and unsigned short.  */
+union ushort_hf {
+  unsigned short us;
+  HFtype2 hf;
+};
+
+PASS_FP16_2 (__eqhf2, CMPtype, HFtype2, HFtype2);
+
+PASS_FP16 (__extendhfsf2, SFtype2, HFtype2);
+PASS_FP16 (__extendhfdf2, DFtype2, HFtype2);
+
+PASS_FP16 (__fixhfsi, SItype2, HFtype2);
+PASS_FP16 (__fixhfdi, DItype2, HFtype2);
+PASS_FP16 (__fixhfti, TItype2, HFtype2);
+
+PASS_FP16 (__fixunshfsi, USItype2, HFtype2);
+PASS_FP16 (__fixunshfdi, UDItype2, HFtype2);
+PASS_FP16 (__fixunshfti, UTItype2, HFtype2);
+
+RETURN_FP16 (__floatsihf, HFtype2, SItype2);
+RETURN_FP16 (__floatdihf, HFtype2, DItype2);
+RETURN_FP16 (__floattihf, HFtype2, TItype2);
+
+RETURN_FP16 (__floatunsihf, HFtype2, USItype2);
+RETURN_FP16 (__floatundihf, HFtype2, UDItype2);
+RETURN_FP16 (__floatuntihf, HFtype2, UTItype2);
+
+RETURN_FP16 (__truncsfhf2, HFtype2, SFtype2);
+RETURN_FP16 (__truncdfhf2, HFtype2, DFtype2);
 #endif
 
 #ifdef __BFLOAT16__
 typedef float BFtype2 __attribute__ ((mode (BF)));
 
-extern SFtype2 __extendbfsf2 (BFtype2);
-extern BFtype2 __floatdibf (DItype2);
-extern BFtype2 __floatsibf (SItype2);
-extern BFtype2 __floatundibf (UDItype2);
-extern BFtype2 __floatunsibf (USItype2);
-extern BFtype2 __truncdfbf2 (DFtype2);
-extern BFtype2 __truncsfbf2 (SFtype2);
+/* Move between BFtype and unsigned short.  */
+union ushort_bf {
+  unsigned short us;
+  BFtype2 bf;
+};
+
+PASS_FP16_2 (__eqbf2, CMPtype, BFtype2, BFtype2);
+
+PASS_FP16 (__extendbfsf2, SFtype2, BFtype2);
+PASS_FP16 (__extendbfdf2, DFtype2, BFtype2);
+
+PASS_FP16 (__fixbfsi, SItype2, BFtype2);
+PASS_FP16 (__fixbfdi, DItype2, BFtype2);
+PASS_FP16 (__fixbfti, TItype2, BFtype2);
+
+PASS_FP16 (__fixunsbfsi, USItype2, BFtype2);
+PASS_FP16 (__fixunsbfdi, UDItype2, BFtype2);
+PASS_FP16 (__fixunsbfti, UTItype2, BFtype2);
+
+RETURN_FP16 (__floatsibf, BFtype2, SItype2);
+RETURN_FP16 (__floatdibf, BFtype2, DItype2);
+RETURN_FP16 (__floattibf, BFtype2, TItype2);
+
+RETURN_FP16 (__floatunsibf, BFtype2, USItype2);
+RETURN_FP16 (__floatundibf, BFtype2, UDItype2);
+RETURN_FP16 (__floatuntibf, BFtype2, UTItype2);
+
+RETURN_FP16 (__truncsfbf2, BFtype2, SFtype2);
+RETURN_FP16 (__truncdfbf2, BFtype2, DFtype2);
 #endif
 
 #if defined(__FLOAT16__) && defined(__BFLOAT16__)
-extern HFtype2 __truncbfhf2 (BFtype2);
-extern BFtype2 __trunchfbf2 (HFtype2);
+CONVERT_FP16 (__truncbfhf2, HFtype2, BFtype2);
+CONVERT_FP16 (__trunchfbf2, BFtype2, HFtype2);
 #endif
diff --git a/libgcc/config/rs6000/t-float16 b/libgcc/config/rs6000/t-float16
index f77df910b3ff..2e5c04e44a7c 100644
--- a/libgcc/config/rs6000/t-float16
+++ b/libgcc/config/rs6000/t-float16
@@ -1,42 +1,160 @@
-# _Float16 library support
+PERL           := perl
 
-fp16_funcs     = eqhf2 extendhfdf2 extendhfsf2 \
-                 fixhfsi  fixhfdi fixhfti fixunshfsi fixunshfdi fixunshfti \
-                 floatsihf floatdihf floattihf floatunsihf floatundihf 
floatuntihf \
-                 truncdfhf2 truncsfhf2
+# _Float16 library support, source files in soft-ftp
+fp16_funcs     = ppc-eqhf2 ppc-floatbitinthf ppc-fixhfbitint
 
-fp16_src       = $(addprefix $(srcdir)/soft-fp/,$(addsuffix .c,$(fp16_funcs)))
+fp16_src       = $(addprefix $(srcdir)/config/rs6000/,$(addsuffix 
.c,$(fp16_funcs)))
 fp16_obj       = $(addsuffix $(objext),$(fp16_funcs))
 
 FP16_CFLAGS    = -mfloat16 -Wno-psabi \
-                 -I$(srcdir)/soft-fp -I$(srcdir)/config/rs6000
+                 -I$(srcdir)/soft-fp \
+                 -I$(srcdir)/config/rs6000
 
 $(fp16_obj)    : INTERNAL_CFLAGS += $(FP16_CFLAGS)
 
-# __bfloat16 library support
+# __bf16 library support, source files in config/rs6000
+bfp16_funcs    = ppc-eqbf2 ppc-floatbitintbf ppc-fixbfbitint
 
-bfp16_funcs    = extendbfsf2 floatdibf floatsibf floatundibf floatunsibf \
-                 truncdfbf2 truncsfbf2
-
-bfp16_src      = $(addprefix $(srcdir)/soft-fp/,$(addsuffix .c,$(bfp16_funcs)))
+bfp16_src      = $(addprefix $(srcdir)/config/rs6000/,$(addsuffix 
.c,$(bfp16_funcs)))
 bfp16_obj      = $(addsuffix $(objext),$(bfp16_funcs))
 
 $(bfp16_obj)   : INTERNAL_CFLAGS += $(FP16_CFLAGS)
 
-# Conversion between __bfloat16 and _Float16
-
-both_fp16_funcs         = truncbfhf2 trunchfbf2
-both_fp16_src   = $(addprefix $(srcdir)/soft-fp/,$(addsuffix 
.c,$(both_fp16_funcs)))
+# Conversion between __bf16 and _Float16
+both_fp16_funcs         = ppc-truncbfhf2 ppc-trunchfbf2
+both_fp16_src   = $(addprefix $(srcdir)/config/rs6000/,$(addsuffix 
.c,$(both_fp16_funcs)))
 both_fp16_obj   = $(addsuffix $(objext),$(both_fp16_funcs))
 
 $(both_fp16_obj) : INTERNAL_CFLAGS += $(FP16_CFLAGS)
 
+# Convert functions in soft-fp to powerpc, building 2 versions, one
+# with normal __bf16/_Float16 arguments, and the other where we
+# pass/return 16-bit floating point in gprs.
+
+float16_prefix         = ppc-
+float16_dep            = $(srcdir)/config/rs6000/t-float16
+
+# We don't have a full set of BFmode conversions in soft-fp, so modify the 
HFmode
+# conversions to do what we want for BFmode as well as HFmode.
+float16_fix_ti_orig    = $(srcdir)/soft-fp/fixhfti.c
+float16_fix_di_orig    = $(srcdir)/soft-fp/fixhfdi.c
+float16_fix_si_orig    = $(srcdir)/soft-fp/fixhfsi.c
+float16_fixuns_ti_orig = $(srcdir)/soft-fp/fixunshfti.c
+float16_fixuns_di_orig = $(srcdir)/soft-fp/fixunshfdi.c
+float16_fixuns_si_orig = $(srcdir)/soft-fp/fixunshfsi.c
+float16_extend_orig    = $(srcdir)/soft-fp/extendhfsf2.c
+float16_trunc_orig     = $(srcdir)/soft-fp/truncsfhf2.c
+
+float16_fix_script     = $(srcdir)/config/rs6000/convert-16bit-fp-fix
+float16_float_script   = $(srcdir)/config/rs6000/convert-16bit-fp-float
+float16_extend_script  = $(srcdir)/config/rs6000/convert-16bit-fp-extend
+float16_trunc_script   = $(srcdir)/config/rs6000/convert-16bit-fp-trunc
+
+float16_fix_ti_funcs   = fixhfti fixbfti
+float16_fix_di_funcs   = fixhfdi fixbfdi
+float16_fix_si_funcs   = fixhfsi fixbfsi
+float16_fixuns_ti_funcs        = fixunshfti fixunsbfti
+float16_fixuns_di_funcs        = fixunshfdi fixunsbfdi
+float16_fixuns_si_funcs        = fixunshfsi fixunsbfsi
+
+float16_fix_ti_src     = $(addprefix $(float16_prefix),$(addsuffix 
.c,$(float16_fix_ti_funcs)))
+float16_fix_di_src     = $(addprefix $(float16_prefix),$(addsuffix 
.c,$(float16_fix_di_funcs)))
+float16_fix_si_src     = $(addprefix $(float16_prefix),$(addsuffix 
.c,$(float16_fix_si_funcs)))
+float16_fixuns_ti_src  = $(addprefix $(float16_prefix),$(addsuffix 
.c,$(float16_fixuns_ti_funcs)))
+float16_fixuns_di_src  = $(addprefix $(float16_prefix),$(addsuffix 
.c,$(float16_fixuns_di_funcs)))
+float16_fixuns_si_src  = $(addprefix $(float16_prefix),$(addsuffix 
.c,$(float16_fixuns_si_funcs)))
+
+float16_fix_funcs      = $(float16_fix_ti_funcs) \
+                         $(float16_fix_di_funcs) \
+                         $(float16_fix_si_funcs) \
+                         $(float16_fixuns_ti_funcs) \
+                         $(float16_fixuns_di_funcs) \
+                         $(float16_fixuns_si_funcs)
+
+float16_fix_src                = $(addprefix $(float16_prefix),$(addsuffix 
.c,$(float16_fix_funcs)))
+float16_fix_dep                = $(float16_fix_orig) \
+                         $(float16_fix_script) \
+                         $(float16_dep)
+
+float16_float_sign_funcs = floattihf floatdihf floatsihf \
+                          floattibf floatdibf floatsibf
+
+float16_float_uns_funcs        = floatuntihf floatundihf floatunsihf \
+                         floatuntibf floatundibf floatunsibf
+
+float16_float_uns_obj  = $(addprefix $(float16_prefix),$(addsuffix 
$(objext),$(float16_float_uns_funcs)))
+
+float16_float_funcs    = $(float16_float_sign_funcs) \
+                         $(float16_float_uns_funcs)
+
+float16_float_src      = $(addprefix $(float16_prefix),$(addsuffix 
.c,$(float16_float_funcs)))
+float16_float_dep      = $(float16_float_script) \
+
+float16_extend_funcs   = extendhfsf2 extendhfdf2 extendbfsf2 extendbfdf2
+float16_extend_src     = $(addprefix $(float16_prefix),$(addsuffix 
.c,$(float16_extend_funcs)))
+float16_extend_dep     = $(float16_extend_orig) \
+                         $(float16_extend_script) \
+                         $(float16_dep)
+
+float16_trunc_funcs    = truncdfbf2 truncdfhf2 truncsfbf2 truncsfhf2
+float16_trunc_src      = $(addprefix $(float16_prefix),$(addsuffix 
.c,$(float16_trunc_funcs)))
+float16_trunc_dep      = $(float16_trunc_orig) \
+                         $(float16_trunc_script) \
+                         $(float16_dep)
+
+float16_all_funcs      = $(float16_fix_funcs) \
+                         $(float16_float_funcs) \
+                         $(float16_extend_funcs) \
+                         $(float16_trunc_funcs)
+
+float16_all_src                = $(float16_fix_src) \
+                         $(float16_float_src) \
+                         $(float16_extend_src) \
+                         $(float16_trunc_src)
+
+float16_all_obj                = $(addprefix $(float16_prefix),$(addsuffix 
$(objext),$(float16_all_funcs)))
+
+$(float16_all_obj)     : INTERNAL_CFLAGS += $(FP16_CFLAGS)
+
+# Turn off the unsigned comparison is always false warning in the
+# conversion from unsigned int to float
+$(float16_float_uns_obj) : INTERNAL_CFLAGS += -Wno-type-limits
+
+# Build the ppc-* sources
+$(float16_fix_ti_src) : $(float16_fix_ti_orig) $(float16_fix_dep)
+       $(PERL) $(float16_fix_script) -t $@ $(float16_fix_ti_orig) > $@
+
+$(float16_fix_di_src) : $(float16_fix_di_orig) $(float16_fix_dep)
+       $(PERL) $(float16_fix_script) -t $@ $(float16_fix_di_orig) > $@
+
+$(float16_fix_si_src) : $(float16_fix_si_orig) $(float16_fix_dep)
+       $(PERL) $(float16_fix_script) -t $@ $(float16_fix_si_orig) > $@
+
+$(float16_fixuns_ti_src) : $(float16_fixuns_ti_orig) $(float16_fix_dep)
+       $(PERL) $(float16_fix_script) -t $@ $(float16_fixuns_ti_orig) > $@
+
+$(float16_fixuns_di_src) : $(float16_fixuns_di_orig) $(float16_fix_dep)
+       $(PERL) $(float16_fix_script) -t $@ $(float16_fixuns_di_orig) > $@
+
+$(float16_fixuns_si_src) : $(float16_fixuns_si_orig) $(float16_fix_dep)
+       $(PERL) $(float16_fix_script) -t $@ $(float16_fixuns_si_orig) > $@
+
+$(float16_float_src) : $(subst $(float16_prefix),$(srcdir)/soft-fp/,$@) 
$(float16_float_dep)
+       $(PERL) $(float16_float_script) -t $@ $(subst 
$(float16_prefix),$(srcdir)/soft-fp/,$@) > $@
+
+$(float16_extend_src) : $(float16_extend_dep)
+       $(PERL) $(float16_extend_script) -t $@ $(float16_extend_orig) > $@
+
+$(float16_trunc_src) : $(float16_trunc_dep)
+       $(PERL) $(float16_trunc_script) -t $@ $(float16_trunc_orig) > $@
+
 # For now, only put it in the static library
-# LIB2ADD      += $(fp16_src) $(bfp16_src) $(both_fp16_src)
+# LIB2ADD      += $(fp16_src) $(bfp16_src) $(both_fp16_src) $(float16_all_src)
 
-LIB2ADD_ST     += $(fp16_src) $(bfp16_src) $(both_fp16_src)
+LIB2ADD_ST     += $(fp16_src) $(bfp16_src) $(both_fp16_src) \
+                  $(float16_all_src)
 
-.PHONY: test-float16 clean-float16
+.PHONY: test-float16 clean-float16 ppc-srcfiles
 
 test-float16:
        @echo "fp16_src:"; \
@@ -55,7 +173,51 @@ test-float16:
        for x in $(bfp16_obj); do echo "    $$x"; done; \
        echo; \
        echo "both_fp16_obj:"; \
-       for x in $(bfp16_obj); do echo "    $$x"; done;
+       for x in $(bfp16_obj); do echo "    $$x"; done; \
+       echo; \
+       echo "float16_fix_funcs:"; \
+       for x in $(float16_fix_funcs); do echo "    $$x"; done; \
+       echo; \
+       echo "float16_float_funcs:"; \
+       for x in $(float16_float_funcs); do echo "    $$x"; done; \
+       echo; \
+       echo "float16_extend_funcs:"; \
+       for x in $(float16_extend_funcs); do echo "    $$x"; done; \
+       echo; \
+       echo "float16_trunc_funcs:"; \
+       for x in $(float16_trunc_funcs); do echo "    $$x"; done; \
+       echo; \
+       echo "float16_all_funcs:"; \
+       for x in $(float16_all_funcs); do echo "    $$x"; done; \
+       echo; \
+       echo "float16_all_src:"; \
+       for x in $(float16_all_src); do echo "    $$x"; done; \
+       echo; \
+       echo "float16_all_obj:"; \
+       for x in $(float16_all_obj); do echo "    $$x"; done; \
+       echo; \
+       echo "LIB2ADD_ST:"; \
+       for x in $(LIB2ADD_ST); do echo "    $$x"; done; \
+       echo; \
+       echo "float16_prefix         = $(float16_prefix)"; \
+       echo "float16_fix_ti_orig    = $(float16_fix_ti_orig)"; \
+       echo "float16_fix_di_orig    = $(float16_fix_di_orig)"; \
+       echo "float16_fix_si_orig    = $(float16_fix_si_orig)"; \
+       echo "float16_fixuns_ti_orig = $(float16_fixuns_ti_orig)"; \
+       echo "float16_fixuns_di_orig = $(float16_fixuns_di_orig)"; \
+       echo "float16_fixuns_si_orig = $(float16_fixuns_si_orig)"; \
+       echo "float16_extend_orig    = $(float16_extend_orig)"; \
+       echo "float16_trunc_orig     = $(float16_trunc_orig)"; \
+       echo; \
+       echo "float16_fix_script     = $(float16_fix_script)"; \
+       echo "float16_float_script   = $(float16_float_script)"; \
+       echo "float16_extend_script  = $(float16_extend_script)"; \
+       echo "float16_trunc_script   = $(float16_trunc_script)"; \
+       echo
 
 clean-float16:
        @$(MULTICLEAN) multi-clean DO=clean-float16
+       rm -f $(float16_all_src) ppc-srcfiles
+
+ppc-srcfiles: $(float16_all_src)
+       @touch ppc-srcfiles

Reply via email to