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");
