https://gcc.gnu.org/g:3e664c715bfa5f3d64b74f7a6b1c1ad38d80526d

commit 3e664c715bfa5f3d64b74f7a6b1c1ad38d80526d
Author: Michael Meissner <[email protected]>
Date:   Thu Oct 1 18:22:04 2026 -0400

    Generate 16-bit floating point truncate functions
    
    Add support for automatically converting the soft-ftp extend functions for
    16-bit.
    
    2026-10-01  Michael Meissner  <[email protected]>
    
    libgcc/
    
            * config/rs6000/convert-16bit-fp-trunc: New perl script.
            * config/rs6000/t-float16: Update.
            * config/rs6000/truncsfdf-bf2.c: Delete.
            * config/rs6000/truncsfdf-hf2.c: Likewise.

Diff:
---
 libgcc/config/rs6000/convert-16bit-fp-trunc | 221 ++++++++++++++++++++++++++++
 libgcc/config/rs6000/t-float16              |  25 +++-
 libgcc/config/rs6000/truncsfdf-bf2.c        |  95 ------------
 libgcc/config/rs6000/truncsfdf-hf2.c        |  87 -----------
 4 files changed, 240 insertions(+), 188 deletions(-)

diff --git a/libgcc/config/rs6000/convert-16bit-fp-trunc 
b/libgcc/config/rs6000/convert-16bit-fp-trunc
new file mode 100755
index 000000000000..99695cd3c5fc
--- /dev/null
+++ b/libgcc/config/rs6000/convert-16bit-fp-trunc
@@ -0,0 +1,221 @@
+#! /usr/bin/perl -w
+# Convert a libgcc/soft-fp fix<fp><int> fuunction for the PowerPC
+
+# Copyright (C) 2020-2026 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.
+#
+# You should have received a copy of the GNU General Public License
+# along with GCC; see the file COPYING3.  If not see
+# <http://www.gnu.org/licenses/>.
+#
+# The PowerPC 16-bit floating point support is considering requiring
+# 16-bit floating point arguments to the 32/64-bit scalar format in
+# registers and similarly returning the 16-bit floating point return to
+# a 32/64-bit scalar value.  However, this presents a problem in that
+# if a machine doesn't have instructions to do a conversion in
+# hardware, you can't call the soft-fp conversion function using the
+# native calling sequence.
+#
+# This perl script converts a trunc<fp1><fp2>.c to do the conversion
+# from BFtype (Google brain 16-bit float) or HFtype (IEEE 754 _Float16).
+# It produces 2 functions, one that has the normal name and takes the
+# normal arguments, and the other that adds a _gpr suffix and changes
+# the 16-bit floating point to unsigned short.
+#
+# A typical trunc* conversion file looks like:
+#
+# <copyright message>
+#
+# #include "soft-fp.h"
+# #include "half.h"
+# #include "double.h"
+#
+# HFtype
+# __truncdfhf2 (DFtype a)
+# {
+#   FP_DECL_EX;
+#   FP_DECL_D (A);
+#   FP_DECL_H (R);
+#   HFtype r;
+#
+#   FP_INIT_ROUNDMODE;
+#   FP_UNPACK_SEMIRAW_D (A, a);
+# #if _FP_W_TYPE_SIZE < _FP_FRACBITS_D
+#   FP_TRUNC (H, D, 1, 2, R, A);
+# #else
+#   FP_TRUNC (H, D, 1, 1, R, A);
+# #endif
+#   FP_PACK_SEMIRAW_H (r, R);
+#   FP_HANDLE_EXCEPTIONS;
+#
+#   return r;
+# }
+
+use warnings;
+use strict;
+use Getopt::Std;
+
+use vars qw($opt_t);
+
+$opt_t = undef;
+
+&getopts ("t:") || die "Useage $0 [-t type] <input >output\n";
+
+die "$0: No -t option.\n"                      if (! defined ($opt_t));
+
+my ($input_lc, $output_lc);
+
+if ($opt_t =~ /trunc([sd])f([bh])f2/) {
+       ($input_lc, $output_lc) = ($1, $2);
+
+} else {
+       die "$0: Invalid -t ${opt_t}\n";
+}
+
+my $input_uc   = uc ($input_lc);
+my $input_uc_F = "${input_uc}F";
+my $input_lc_f = "${input_lc}f";
+my $input_type = "${input_uc}Ftype";
+
+my $output_uc  = uc ($output_lc);
+my $output_uc_F        = "${output_uc}F";
+my $output_lc_f        = "${output_lc}f";
+my $output_type        = "${output_uc}Ftype";
+
+my %include_file = ("bf" => "#include \"brain.h\"",
+                   "hf" => "#include \"half.h\"",
+                   "sf" => "#include \"single.h\"",
+                   "df" => "#include \"double.h\"");
+
+# Scan the input and put out the copyright message
+
+my $line;
+my $input = $ARGV[0];
+
+while ($line = <>) {
+       chomp $line;
+
+       last                    if ($line =~ /^[#](include|define)/);
+       print $line, "\n";
+}
+
+if ($input) {
+       print "/* Automatically converted from $input.  */\n";
+       print "\n";
+}
+
+# Change the include file from the floating point type to either half.h
+# or brain.h.
+
+die "$0: No include files\n"   if (! defined ($line));
+
+my $include_found = 0;
+
+do {
+       if ($line =~ /^#include ["](brain|half|single|double|quad)[.]h["]$/) {
+               if (!$include_found) {
+                       print $include_file{$input_lc_f}, "\n";
+                       print $include_file{$output_lc_f}, "\n";
+                       $include_found = 1;
+               }
+
+       } else {
+               print $line, "\n";
+       }
+
+       $line = <>;
+
+} while (defined ($line) && $line =~ /^(\s*$|[#](include|define))/);
+
+# Scoop up the rest of the file, convert the input and function to
+# operate on HFtype or BFtype.
+
+die "$0: No main source\n"     if (! defined ($line));
+
+my @func = ();
+my $FP   = "BDHSTQ";
+
+do {
+       chomp $line;
+
+       # Return type
+       if ($line =~ /^[${FP}]Ftype$/) {
+               $line = $output_type;
+
+       # Function line
+       } elsif ($line =~ /^__trunc/) {
+               $line = "__trunc${input_lc_f}${output_lc_f}2 (${input_type} a)";
+
+       # Declaration line of the input type
+       } elsif ($line =~ /^(\s*FP_DECL_)[${FP}] [(]A[)];/) {
+               $line = "${1}${input_uc} (A);";
+
+       # Declaration line of the output type
+       } elsif ($line =~ /^(\s*FP_DECL_)[${FP}] [(]R[)];/) {
+               $line = "${1}${output_uc} (R);";
+
+       # Declaration of the actual result
+       } elsif ($line =~ /^(\s*)[${FP}]Ftype r;/) {
+               $line = "${1}${output_type} r;";
+
+       } else {
+               # Unpack input type
+               $line =~ 
s/FP_UNPACK_(SEMI)?RAW_[${FP}]/FP_UNPACK_${1}RAW_${input_uc}/;
+
+               # Pack output type
+               $line =~ 
s/FP_PACK_(SEMI)?RAW_[${FP}]/FP_PACK_${1}RAW_${output_uc}/;
+
+               # Trunc line
+               $line =~ s/FP_TRUNC [(][${FP}], [${FP}],/FP_TRUNC 
(${output_uc}, ${input_uc},/;
+       }
+
+       push (@func, $line);
+       $line = <>;
+
+} while (defined ($line));
+
+# Print out the normal conversion function
+
+print "/* ${output_type} returned in FPR registers.  */\n";
+
+foreach $line (@func) {
+       print $line, "\n";
+}
+
+# Print out the conversion function that uses GPRs
+
+print "\n";
+print "/* ${output_type} returned in GPR registers.  */\n";
+
+foreach $line (@func) {
+       if ($line =~ /^[${FP}]Ftype$/) {
+               $line = "unsigned short";
+
+       } elsif ($line =~ /^__trunc/) {
+               $line = "__trunc${input_lc_f}${output_lc_f}2_gpr (${input_type} 
a)";
+
+       } elsif ($line =~ /^(\s*)return r;/) {
+               print "${1}u.${output_lc_f} = r;\n";
+               $line = "${1}return u.us;";
+       }
+
+       print $line, "\n";
+
+       if ($line =~ /^(\s*)[${FP}]Ftype r;/) {
+               print "${1}union ushort_${output_lc_f} u;\n";
+       }
+}
+
+# Done
+exit 0;
diff --git a/libgcc/config/rs6000/t-float16 b/libgcc/config/rs6000/t-float16
index af6254a70249..d6010ca12781 100644
--- a/libgcc/config/rs6000/t-float16
+++ b/libgcc/config/rs6000/t-float16
@@ -1,8 +1,7 @@
 PERL           := perl
 
 # _Float16 library support, source files in soft-ftp
-fp16_funcs     = truncsfdf-hf2 \
-                 ppc-eqhf2 ppc-floatbitinthf ppc-fixhfbitint
+fp16_funcs     = ppc-eqhf2 ppc-floatbitinthf ppc-fixhfbitint
 
 fp16_src       = $(addprefix $(srcdir)/config/rs6000/,$(addsuffix 
.c,$(fp16_funcs)))
 fp16_obj       = $(addsuffix $(objext),$(fp16_funcs))
@@ -14,8 +13,7 @@ FP16_CFLAGS   = -mfloat16 -Wno-psabi \
 $(fp16_obj)    : INTERNAL_CFLAGS += $(FP16_CFLAGS)
 
 # __bf16 library support, source files in config/rs6000
-bfp16_funcs    = truncsfdf-bf2 \
-                 ppc-eqbf2 ppc-floatbitintbf ppc-fixbfbitint
+bfp16_funcs    = ppc-eqbf2 ppc-floatbitintbf ppc-fixbfbitint
 
 bfp16_src      = $(addprefix $(srcdir)/config/rs6000/,$(addsuffix 
.c,$(bfp16_funcs)))
 bfp16_obj      = $(addsuffix $(objext),$(bfp16_funcs))
@@ -45,10 +43,12 @@ float16_fixuns_ti_orig      = $(srcdir)/soft-fp/fixunshfti.c
 float16_fixuns_di_orig = $(srcdir)/soft-fp/fixhunsfdi.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_func    = fixhfti fixbfti
 float16_fix_di_func    = fixhfti fixbfti
@@ -96,13 +96,21 @@ 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_extend_funcs) \
+                         $(float16_trunc_funcs)
 
 float16_all_src                = $(float16_fix_src) \
                          $(float16_float_src) \
-                         $(float16_extend_src)
+                         $(float16_extend_src) \
+                         $(float16_trunc_src)
 
 float16_all_obj                = $(addprefix $(float16_prefix),$(addsuffix 
$(objext),$(float16_all_funcs)))
 
@@ -137,6 +145,9 @@ $(float16_float_src) : $(subst 
$(float16_prefix),$(srcdir)/soft-fp/,$@) $(float1
 $(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) $(float16_all_src)
 
@@ -184,10 +195,12 @@ test-float16:
        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:
diff --git a/libgcc/config/rs6000/truncsfdf-bf2.c 
b/libgcc/config/rs6000/truncsfdf-bf2.c
deleted file mode 100644
index 6733c8df2419..000000000000
--- a/libgcc/config/rs6000/truncsfdf-bf2.c
+++ /dev/null
@@ -1,95 +0,0 @@
-/* Software floating-point emulation.
-   Truncate IEEE single into IEEE half.
-   Copyright (C) 2021-2022 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   In addition to the permissions in the GNU Lesser General Public
-   License, the Free Software Foundation gives you unlimited
-   permission to link the compiled version of this file into
-   combinations with other programs, and to distribute those
-   combinations without any restriction coming from the use of this
-   file.  (The Lesser General Public License restrictions do apply in
-   other respects; for example, they cover modification of the file,
-   and distribution when not linked into a combine executable.)
-
-   The GNU C Library 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
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, see
-   <http://www.gnu.org/licenses/>.
-
-   This is a clone of soft-fp/truncdfbf2.c for the PowerPC.
-
-   We provide an alternative version of the conversion that retunrs the HFtype
-   value as unsigned short.  This is to allow the calling sequence where
-   arguments are converted to the 32/64-bit scalar format.  If we don't have
-   the hardware support, we can't use the standard __trunc function.  */
-
-#include "soft-fp.h"
-#include "brain.h"
-#include "single.h"
-#include "double.h"
-
-/* Return BFtype in a FPR register.  */
-BFtype
-__truncsfbf2 (SFtype a)
-{
-  FP_DECL_EX;
-  FP_DECL_S (A);
-  FP_DECL_B (R);
-  BFtype r;
-
-  FP_INIT_ROUNDMODE;
-  FP_UNPACK_SEMIRAW_D (A, a);
-#if _FP_W_TYPE_SIZE < _FP_FRACBITS_D
-  FP_TRUNC (B, D, 1, 2, R, A);
-#else
-  FP_TRUNC (B, D, 1, 1, R, A);
-#endif
-  FP_PACK_SEMIRAW_B (r, R);
-  FP_HANDLE_EXCEPTIONS;
-
-  return r;
-}
-
-/* Return BFtype in a GPR register.  */
-unsigned short
-__truncsfbf2_gpr (SFtype a)
-{
-  union ushort_bf u;
-
-  FP_DECL_EX;
-  FP_DECL_S (A);
-  FP_DECL_B (R);
-  BFtype r;
-
-  FP_INIT_ROUNDMODE;
-  FP_UNPACK_SEMIRAW_D (A, a);
-#if _FP_W_TYPE_SIZE < _FP_FRACBITS_D
-  FP_TRUNC (B, D, 1, 2, R, A);
-#else
-  FP_TRUNC (B, D, 1, 1, R, A);
-#endif
-  FP_PACK_SEMIRAW_B (r, R);
-  FP_HANDLE_EXCEPTIONS;
-
-  u.bf = r;
-  return u.us;
-}
-
-/* On the PowerPC DFtype scalars use the same encoding as SFtype, so use the
-   same function for both.  */
-__asm__ ("\n"
-        "\t.globl __truncdfbf2\n"
-        "__truncdfbf2 = __truncsfbf2\n"
-        "\n"
-        "\t.globl __truncdfbf2_gpr\n"
-        "__truncdfbf2_gpr = __truncsfbf2_gpr\n");
diff --git a/libgcc/config/rs6000/truncsfdf-hf2.c 
b/libgcc/config/rs6000/truncsfdf-hf2.c
deleted file mode 100644
index c2392e60262b..000000000000
--- a/libgcc/config/rs6000/truncsfdf-hf2.c
+++ /dev/null
@@ -1,87 +0,0 @@
-/* Software floating-point emulation.
-   Truncate IEEE single into IEEE half.
-   Copyright (C) 2021-2022 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   In addition to the permissions in the GNU Lesser General Public
-   License, the Free Software Foundation gives you unlimited
-   permission to link the compiled version of this file into
-   combinations with other programs, and to distribute those
-   combinations without any restriction coming from the use of this
-   file.  (The Lesser General Public License restrictions do apply in
-   other respects; for example, they cover modification of the file,
-   and distribution when not linked into a combine executable.)
-
-   The GNU C Library 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
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, see
-   <http://www.gnu.org/licenses/>.
-
-   This is a clone of soft-fp/truncsfhf2.c for the PowerPC.
-
-   We provide an alternative version of the conversion that retunrs the HFtype
-   value as unsigned short.  This is to allow the calling sequence where
-   arguments are converted to the 32/64-bit scalar format.  If we don't have
-   the hardware support, we can't use the standard __trunc function.  */
-
-#include "soft-fp.h"
-#include "half.h"
-#include "single.h"
-#include "double.h"
-
-/* Return HFtype in a FPR register.  */
-HFtype
-__truncsfhf2 (SFtype a)
-{
-  FP_DECL_EX;
-  FP_DECL_S (A);
-  FP_DECL_H (R);
-  HFtype r;
-
-  FP_INIT_ROUNDMODE;
-  FP_UNPACK_SEMIRAW_S (A, a);
-  FP_TRUNC (H, S, 1, 1, R, A);
-  FP_PACK_SEMIRAW_H (r, R);
-  FP_HANDLE_EXCEPTIONS;
-
-  return r;
-}
-
-/* Return HFtype in a GPR register.  */
-unsigned short
-__truncsfhf2_gpr (SFtype a)
-{
-  union ushort_hf u;
-
-  FP_DECL_EX;
-  FP_DECL_S (A);
-  FP_DECL_H (R);
-  HFtype r;
-
-  FP_INIT_ROUNDMODE;
-  FP_UNPACK_SEMIRAW_S (A, a);
-  FP_TRUNC (H, S, 1, 1, R, A);
-  FP_PACK_SEMIRAW_H (r, R);
-  FP_HANDLE_EXCEPTIONS;
-
-  u.hf = r;
-  return u.us;
-}
-
-/* On the PowerPC DFtype scalars use the same encoding as SFtype, so use the
-   same function for both.  */
-__asm__ ("\n"
-        "\t.globl __truncdfhf2\n"
-        "__truncdfhf2 = __truncsfhf2\n"
-        "\n"
-        "\t.globl __truncdfhf2_gpr\n"
-        "__truncdfhf2_gpr = __truncsfhf2_gpr\n");

Reply via email to