https://gcc.gnu.org/g:af586b6d6c01e6acce9815183fca8883bfe36f83
commit af586b6d6c01e6acce9815183fca8883bfe36f83 Author: Michael Meissner <[email protected]> Date: Thu Oct 29 23:11:37 2026 -0400 Update libgcc to pass and return 16-bit fp library values in GPRs 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-29 Michael Meissner <[email protected]> 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-powibf.c: Likewise. * config/rs6000/ppc-powihf.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: --- libgcc/config/rs6000/convert-16bit-fp-extend | 220 ++++++++++++++++++++++++++ libgcc/config/rs6000/convert-16bit-fp-fix | 210 +++++++++++++++++++++++++ libgcc/config/rs6000/convert-16bit-fp-float | 216 ++++++++++++++++++++++++++ libgcc/config/rs6000/convert-16bit-fp-trunc | 221 +++++++++++++++++++++++++++ libgcc/config/rs6000/ppc-eqbf2.c | 83 ++++++++++ libgcc/config/rs6000/ppc-eqhf2.c | 83 ++++++++++ libgcc/config/rs6000/ppc-fixbfbitint.c | 128 ++++++++++++++++ libgcc/config/rs6000/ppc-fixhfbitint.c | 127 +++++++++++++++ libgcc/config/rs6000/ppc-floatbitintbf.c | 102 +++++++++++++ libgcc/config/rs6000/ppc-floatbitinthf.c | 102 +++++++++++++ libgcc/config/rs6000/ppc-powibf.c | 97 ++++++++++++ libgcc/config/rs6000/ppc-powihf.c | 102 +++++++++++++ libgcc/config/rs6000/ppc-truncbfhf2.c | 130 ++++++++++++++++ libgcc/config/rs6000/ppc-trunchfbf2.c | 96 ++++++++++++ libgcc/config/rs6000/sfp-machine.h | 125 ++++++++++++--- libgcc/config/rs6000/t-float16 | 202 +++++++++++++++++++++--- 16 files changed, 2200 insertions(+), 44 deletions(-) diff --git a/libgcc/config/rs6000/convert-16bit-fp-extend b/libgcc/config/rs6000/convert-16bit-fp-extend new file mode 100755 index 000000000000..157fe3f48a68 --- /dev/null +++ b/libgcc/config/rs6000/convert-16bit-fp-extend @@ -0,0 +1,220 @@ +#! /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 extend<fp1><fp2>.c to do the conversion +# to 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 extend* conversion file looks like: +# +# <copyright message> +# +# #define FP_NO_EXACT_UNDERFLOW +# #include "soft-fp.h" +# #include "single.h" +# #include "double.h" +# +# DFtype +# __extendsfdf2 (SFtype a) +# { +# FP_DECL_EX; +# FP_DECL_S (A); +# FP_DECL_D (R); +# DFtype r; +# +# FP_INIT_EXCEPTIONS; +# FP_UNPACK_RAW_S (A, a); +# #if _FP_W_TYPE_SIZE < _FP_FRACBITS_D +# FP_EXTEND (D, S, 2, 1, R, A); +# #else +# FP_EXTEND (D, S, 1, 1, R, A); +# #endif +# FP_PACK_RAW_D (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 =~ /extend([bh])f([sd])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 =~ /^__extend/) { + $line = "__extend${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_RAW_[${FP}]/FP_UNPACK_RAW_${input_uc}/; + + # Pack output type + $line =~ s/FP_PACK_RAW_[${FP}]/FP_PACK_RAW_${output_uc}/; + + # Extend line + $line =~ s/FP_EXTEND [(][${FP}], [${FP}],/FP_EXTEND (${output_uc}, ${input_uc},/; + } + + push (@func, $line); + $line = <>; + +} while (defined ($line)); + +# Print out the normal conversion function + +print "/* ${input_type} passed in FPR registers. */\n"; + +foreach $line (@func) { + print $line, "\n"; +} + +# Print out the conversion function that uses GPRs + +print "\n"; +print "/* ${input_type} passed in GPR registers. */\n"; + +foreach $line (@func) { + if ($line =~ /^__extend/) { + $line = "__extend${input_lc_f}${output_lc_f}2_gpr (unsigned short us)"; + } + + print $line, "\n"; + + + if ($line =~ /^(\s*)[${FP}]Ftype r;/) { + print "${1}union ushort_${input_lc_f} u;\n"; + print "${1}${input_type} a;\n"; + print "\n"; + print "${1}u.us = us;\n"; + print "${1}a = u.${input_lc_f};\n"; + } +} + +# Done +exit 0; diff --git a/libgcc/config/rs6000/convert-16bit-fp-fix b/libgcc/config/rs6000/convert-16bit-fp-fix new file mode 100755 index 000000000000..5878b0d3c50b --- /dev/null +++ b/libgcc/config/rs6000/convert-16bit-fp-fix @@ -0,0 +1,210 @@ +#! /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 fix<fp><int>.c. or fixuns<fp><int>.c file +# to do the conversion to 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 fix* conversion file looks like: +# +# <copyright message> +# +# #include "soft-fp.h" +# #include "single.h" +# +# DItype +# __fixsfdi (SFtype a) +# { +# FP_DECL_EX; +# FP_DECL_S (A); +# UDItype r; +# +# FP_INIT_EXCEPTIONS; +# FP_UNPACK_RAW_S (A, a); +# FP_TO_INT_S (r, A, DI_BITS, 1); +# 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, + $uns_lc, + $uns_uc_U, + $uns_sign); + +if ($opt_t =~ /fix(|uns)([bh])f([sdt])i/) { + if (defined ($1) && $1 ne "") { + ($uns_lc, $uns_uc_U, $uns_sign) = ("uns", "U", 0); + + } else { + ($uns_lc, $uns_uc_U, $uns_sign) = ("", "", 1); + } + + ($input_lc, $output_lc) = ($2, $3); + +} 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_I = "${output_uc}I"; +my $output_lc_i = "${output_lc}i"; +my $output_type = "${uns_uc_U}${output_uc}Itype"; + +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)); + +do { + if ($line =~ /^[#]include [\"](single|double|extended|half|quad|brain)[.]h[\"]$/) { + print $include_file{$input_lc_f}, "\n"; + + } else { + print $line, "\n"; + } + + $line = <>; + +} while (defined ($line) && $line =~ /^[#](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 = "BDHST"; +my $INT = "QHSDT"; + +do { + chomp $line; + + # Function line + if ($line =~ /^__fix/) { + $line = "__fix${uns_lc}${input_lc_f}${output_lc_i} (${input_type} a)"; + + # Return type for function + } elsif ($line =~ /^(U)?[${INT}]Itype$/) { + $line = $output_type; + + # Return value + } elsif ($line =~ /^(\s*)(U)?[${INT}]Itype r;/) { + $line = "${1}${output_type} r;"; + + # Conversion to int + } elsif ($line =~ /^(\s*)FP_TO_INT_[${FP}] [(]r, A, [${INT}]I_BITS, [01][)];/) { + $line = "${1}FP_TO_INT_${input_uc} (r, A, ${output_uc_I}_BITS, ${uns_sign});"; + + } else { + $line =~ s/_(DECL|RAW|INT)_[${FP}]/_${1}_${input_uc}/; + } + + push (@func, $line); + $line = <>; + +} while (defined ($line)); + +# Print out the normal conversion function + +print "\n"; +print "/* ${input_type} passed in FPR registers. */\n"; + +foreach $line (@func) { + print $line, "\n"; +} + +# Print out the special GPR function. + +print "\n"; +print "/* ${input_type} passed in GPR registers. */\n"; + +foreach $line (@func) { + + # Function header + if ($line =~ /^__(fix|fixuns)([bh]f)([sdt]i)/) { + $line = "__${1}${2}${3}_gpr (unsigned short us)"; + } + + print $line, "\n"; + + # Add conversion from unsigned short + if ($line =~ /^(\s*)U?[${INT}]Itype r;/) { + print "${1}${input_type} a;\n"; + print "${1}union ushort_${input_lc_f} u;\n"; + print "\n"; + print "${1}u.us = us;\n"; + print "${1}a = u.${input_lc_f};\n"; + } +} + +# Done +exit 0; diff --git a/libgcc/config/rs6000/convert-16bit-fp-float b/libgcc/config/rs6000/convert-16bit-fp-float new file mode 100755 index 000000000000..232c498bb22a --- /dev/null +++ b/libgcc/config/rs6000/convert-16bit-fp-float @@ -0,0 +1,216 @@ +#! /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 float<int><fp>.c. or floatun<int><fp>.c +# file to do the conversion to 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 fix* conversion file looks like: +# +# <copyright message> +# +# DFtype +# __floatdidf (DItype i) +# { +# FP_DECL_EX; +# FP_DECL_D (A); +# DFtype a; +# +# FP_INIT_ROUNDMODE; +# FP_FROM_INT_D (A, i, DI_BITS, UDItype); +# FP_PACK_RAW_D (a, A); +# FP_HANDLE_EXCEPTIONS; +# +# return a; +# } + +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, + $uns_lc, + $uns_uc_U); + +if ($opt_t =~ /float(|un)([sdt])i([bh])f/) { + if (defined ($1) && $1 ne "") { + ($uns_lc, $uns_uc_U) = ("un", "U"); + + } else { + ($uns_lc, $uns_uc_U) = ("", ""); + } + + ($input_lc, $output_lc) = ($2, $3); + +} else { + die "$0: Invalid -t ${opt_t}\n"; +} + +my $input_uc = uc ($input_lc); +my $input_uc_I = "${input_uc}I"; +my $input_lc_i = "${input_lc}i"; +my $input_type = "${uns_uc_U}${input_uc}Itype"; + +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)); + +do { + if ($line =~ /^[#]include [\"](single|double|extended|half|quad|brain)[.]h[\"]$/) { + print $include_file{$output_lc_f}, "\n"; + + } else { + print $line, "\n"; + } + + $line = <>; + +} while (defined ($line) && $line =~ /^[#](include|define)/); + +# Scoop up the rest of the file, convert the function to +# return a HFtype or BFtype type. + +die "$0: No main source\n" if (! defined ($line)); + +my @func = (); +my $FP = "BDHST"; +my $fp = lc ($FP); +my $INT = "QHSDT"; +my $int = lc ($INT); + +do { + chomp $line; + + # Function return + if ($line =~ /^[${FP}]Ftype$/) { + $line = $output_type; + + # Function line + } elsif ($line =~ /^__float/) { + $line = "__float${uns_lc}${input_lc_i}${output_lc_f} (${input_type} i)"; + + # Return variable declaration + } elsif ($line =~ /^(\s*)[${FP}]Ftype a;/) { + $line = "${1}${output_type} a;"; + + # Int input + } elsif ($line =~ /FROM_INT_[${INT}]/) { + $line =~ s/FROM_INT_[${INT}]/FROM_INT_${output_uc}/; + $line =~ s/[${INT}]I_BITS/${input_uc_I}_BITS/; + $line =~ s/(U)?[${INT}]Itype/${input_type}/; + } + + $line =~ s/_(DECL|RAW)_[${FP}]/_${1}_${output_uc}/; + + push (@func, $line); + $line = <>; + +} while (defined ($line)); + +# Print out the normal conversion function + +print "\n"; +print "/* ${output_type} returned in FPR registers. */\n"; + +foreach $line (@func) { + print $line, "\n"; +} + +# Print out the special GPR function. + +print "\n"; +print "/* ${output_type} returned in GPR registers. */\n"; + +foreach $line (@func) { + + # Function return + if ($line eq $output_type) { + $line = "unsigned short"; + + # Function header + } elsif ($line =~ /^__(float|floatun)([sdt]i)([bh]f) (.*)$/) { + $line = "__${1}${2}${3}_gpr ${4}"; + + # Return value + } elsif ($line =~ /^(\s*)return a;/) { + print "${1}u.${output_lc_f} = a;\n"; + $line = "${1}return u.us;"; + } + + print $line, "\n"; + + # Add declartion of union + if ($line =~ /^(\s*)[${FP}]Ftype a;/) { + print " union ushort_${output_lc_f} u;\n"; + } + +} + +# Done +exit 0; 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/ppc-eqbf2.c b/libgcc/config/rs6000/ppc-eqbf2.c new file mode 100644 index 000000000000..a43b6b673282 --- /dev/null +++ b/libgcc/config/rs6000/ppc-eqbf2.c @@ -0,0 +1,83 @@ +/* Software floating-point emulation. + Return 0 iff a == b, 1 otherwise + 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 softfp/eqhf2.c. + + We provide 2 conversions, one that returns 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" + +/* When BFtype is passed in FPR registers. */ +CMPtype +__eqbf2 (BFtype a, BFtype b) +{ + FP_DECL_EX; + FP_DECL_B (A); + FP_DECL_B (B); + CMPtype r; + + FP_INIT_EXCEPTIONS; + FP_UNPACK_RAW_B (A, a); + FP_UNPACK_RAW_B (B, b); + FP_CMP_EQ_B (r, A, B, 1); + FP_HANDLE_EXCEPTIONS; + + return r; +} + +strong_alias (__eqbf2, __nebf2); + +/* When BFtype is passed in GPR registers. */ +CMPtype +__eqbf2_gpr (unsigned short us_a, unsigned short us_b) +{ + FP_DECL_EX; + FP_DECL_B (A); + FP_DECL_B (B); + CMPtype r; + union ushort_bf u_a, u_b; + BFtype a, b; + + u_a.us = us_a; + u_b.us = us_b; + a = u_a.bf; + b = u_b.bf; + + FP_INIT_EXCEPTIONS; + FP_UNPACK_RAW_B (A, a); + FP_UNPACK_RAW_B (B, b); + FP_CMP_EQ_B (r, A, B, 1); + FP_HANDLE_EXCEPTIONS; + + return r; +} + +strong_alias (__eqbf2_gpr, __nebf2_gpr); diff --git a/libgcc/config/rs6000/ppc-eqhf2.c b/libgcc/config/rs6000/ppc-eqhf2.c new file mode 100644 index 000000000000..e6c8dabf5b1c --- /dev/null +++ b/libgcc/config/rs6000/ppc-eqhf2.c @@ -0,0 +1,83 @@ +/* Software floating-point emulation. + Return 0 iff a == b, 1 otherwise + 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 softfp/eqhf2.c. + + We provide 2 conversions, one that returns 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 "half.h" + +/* When HFtype is passed in FPR registers. */ +CMPtype +__eqhf2 (HFtype a, HFtype b) +{ + FP_DECL_EX; + FP_DECL_H (A); + FP_DECL_H (B); + CMPtype r; + + FP_INIT_EXCEPTIONS; + FP_UNPACK_RAW_H (A, a); + FP_UNPACK_RAW_H (B, b); + FP_CMP_EQ_H (r, A, B, 1); + FP_HANDLE_EXCEPTIONS; + + return r; +} + +strong_alias (__eqhf2, __nehf2); + +/* When HFtype is passed in GPR registers. */ +CMPtype +__eqhf2_gpr (unsigned short us_a, unsigned short us_b) +{ + FP_DECL_EX; + FP_DECL_H (A); + FP_DECL_H (B); + CMPtype r; + union ushort_hf u_a, u_b; + HFtype a, b; + + u_a.us = us_a; + u_b.us = us_b; + a = u_a.hf; + b = u_b.hf; + + FP_INIT_EXCEPTIONS; + FP_UNPACK_RAW_H (A, a); + FP_UNPACK_RAW_H (B, b); + FP_CMP_EQ_H (r, A, B, 1); + FP_HANDLE_EXCEPTIONS; + + return r; +} + +strong_alias (__eqhf2_gpr, __nehf2_gpr); 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/ppc-floatbitintbf.c b/libgcc/config/rs6000/ppc-floatbitintbf.c new file mode 100644 index 000000000000..bc3be1ed8886 --- /dev/null +++ b/libgcc/config/rs6000/ppc-floatbitintbf.c @@ -0,0 +1,102 @@ +/* Software floating-point emulation. + Convert a _BitInt to bfloat16. + + 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/floatbitintbf.c. + +We provide 2 conversions, one that returns 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 BFtype __floatbitintbf (const UBILtype *, SItype); +extern unsigned short __floatbitintbf_gpr (const UBILtype *, SItype); + +/* BFtype returned in FPRs. */ +BFtype +__floatbitintbf (const UBILtype *i, SItype iprec) +{ + SItype iv; + USItype shift = 0; + FP_DECL_EX; + FP_DECL_B (A); + BFtype a; + + FP_FROM_BITINT (i, iprec, iv, shift, SI); + FP_INIT_ROUNDMODE; + FP_FROM_INT_B (A, iv, SI_BITS, USItype); + if (shift) + { + A_e += shift; + if (A_e >= _FP_EXPMAX_B) + { + /* Exponent too big; overflow to infinity. */ + _FP_OVERFLOW_SEMIRAW (B, 1, A); + _FP_PACK_SEMIRAW (B, 1, A); + } + } + FP_PACK_RAW_B (a, A); + FP_HANDLE_EXCEPTIONS; + + return a; +} + +/* BFtype returned in GPRs. */ +unsigned short +__floatbitintbf_gpr (const UBILtype *i, SItype iprec) +{ + SItype iv; + USItype shift = 0; + FP_DECL_EX; + FP_DECL_B (A); + BFtype a; + union ushort_bf u; + + FP_FROM_BITINT (i, iprec, iv, shift, SI); + FP_INIT_ROUNDMODE; + FP_FROM_INT_B (A, iv, SI_BITS, USItype); + if (shift) + { + A_e += shift; + if (A_e >= _FP_EXPMAX_B) + { + /* Exponent too big; overflow to infinity. */ + _FP_OVERFLOW_SEMIRAW (B, 1, A); + _FP_PACK_SEMIRAW (B, 1, A); + } + } + FP_PACK_RAW_B (a, A); + FP_HANDLE_EXCEPTIONS; + + u.bf = a; + return u.us; +} +#endif diff --git a/libgcc/config/rs6000/ppc-floatbitinthf.c b/libgcc/config/rs6000/ppc-floatbitinthf.c new file mode 100644 index 000000000000..f92376994fb6 --- /dev/null +++ b/libgcc/config/rs6000/ppc-floatbitinthf.c @@ -0,0 +1,102 @@ +/* Software floating-point emulation. + Convert a _BitInt to IEEE half. + + 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/floatbitinthf.c. + +We provide 2 conversions, one that returns 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 "half.h" +#include "bitint.h" + +#ifdef __BITINT_MAXWIDTH__ + +/* Silence declaration without prototype warning. */ +extern HFtype __floatbitinthf (const UBILtype *, SItype); +extern unsigned short __floatbitinthf_gpr (const UBILtype *, SItype); + +/* HFtype returned in FPRs. */ +HFtype +__floatbitinthf (const UBILtype *i, SItype iprec) +{ + SItype iv; + USItype shift = 0; + FP_DECL_EX; + FP_DECL_H (A); + HFtype a; + + FP_FROM_BITINT (i, iprec, iv, shift, SI); + FP_INIT_ROUNDMODE; + FP_FROM_INT_H (A, iv, SI_BITS, USItype); + if (shift) + { + A_e += shift; + if (A_e >= _FP_EXPMAX_H) + { + /* Exponent too big; overflow to infinity. */ + _FP_OVERFLOW_SEMIRAW (H, 1, A); + _FP_PACK_SEMIRAW (H, 1, A); + } + } + FP_PACK_RAW_H (a, A); + FP_HANDLE_EXCEPTIONS; + + return a; +} + +/* HFtype returned in FPRs. */ +unsigned short +__floatbitinthf_gpr (const UBILtype *i, SItype iprec) +{ + SItype iv; + USItype shift = 0; + FP_DECL_EX; + FP_DECL_H (A); + HFtype a; + union ushort_hf u; + + FP_FROM_BITINT (i, iprec, iv, shift, SI); + FP_INIT_ROUNDMODE; + FP_FROM_INT_H (A, iv, SI_BITS, USItype); + if (shift) + { + A_e += shift; + if (A_e >= _FP_EXPMAX_H) + { + /* Exponent too big; overflow to infinity. */ + _FP_OVERFLOW_SEMIRAW (H, 1, A); + _FP_PACK_SEMIRAW (H, 1, A); + } + } + FP_PACK_RAW_H (a, A); + FP_HANDLE_EXCEPTIONS; + + u.hf = a; + return u.us; +} +#endif diff --git a/libgcc/config/rs6000/ppc-powibf.c b/libgcc/config/rs6000/ppc-powibf.c new file mode 100644 index 000000000000..dca7a27f02fd --- /dev/null +++ b/libgcc/config/rs6000/ppc-powibf.c @@ -0,0 +1,97 @@ +/* Software floating-point emulation. + Return 0 iff a == b, 1 otherwise + 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/>. + + The code is cloned from the code in libgcc2.c (which handles the standard + SF, DF, TF, and XF types). + + We provide 2 conversions, one that returns 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. + + In addition, we use the target_clones attribute so that if the user is + running on a power9 or power10, they get a version that is compiled to use + the HF conversions. If the default for the compiler is power10 or greater, + we don't use target_clones. */ + +#include "soft-fp.h" +#include "brain.h" + +#if defined(_ARCH_PWR10) +#define ATTRIBUTE_TARGET_CLONES + +#else +#define ATTRIBUTE_TARGET_CLONES \ + __attribute__((target_clones("cpu=power10,default"))) +#endif + +#define ONE ((BFtype) 1.0) + + +ATTRIBUTE_TARGET_CLONES +BFtype +__powibf2 (BFtype x, SItype m) +{ + unsigned int n = m < 0 ? -m : m; + BFtype y = n % 2 ? x : ONE; + + while (n >>= 1) + { + x = x * x; + if (n % 2) + y = y * x; + } + + return m < 0 ? ONE/y : y; +} + +/* Version of the powi function that passes and return __bf16 values in + gprs. */ + +ATTRIBUTE_TARGET_CLONES +unsigned short +__powibf2_gpr (unsigned short us_x, SItype m) +{ + union ushort_bf u_x, u_r; + unsigned int n; + BFtype x, y; + + u_x.us = us_x; + n = m < 0 ? -m : m; + x = u_x.bf; + y = n % 2 ? x : ONE; + + while (n >>= 1) + { + x = x * x; + if (n % 2) + y = y * x; + } + + u_r.bf = m < 0 ? ONE/y : y; + return u_r.us; +} diff --git a/libgcc/config/rs6000/ppc-powihf.c b/libgcc/config/rs6000/ppc-powihf.c new file mode 100644 index 000000000000..c3081b7a575b --- /dev/null +++ b/libgcc/config/rs6000/ppc-powihf.c @@ -0,0 +1,102 @@ +/* Software floating-point emulation. + Return 0 iff a == b, 1 otherwise + 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/>. + + The code is cloned from the code in libgcc2.c (which handles the standard + SF, DF, TF, and XF types). + + We provide 2 conversions, one that returns 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. + + In addition, we use the target_clones attribute so that if the user is + running on a power9 or power10, they get a version that is compiled to use + the HF conversions. If the default for the compiler is power10 or greater, + we don't use target_clones. */ + +#include "soft-fp.h" +#include "half.h" + +#if defined(_ARCH_PWR10) +#define ATTRIBUTE_TARGET_CLONES + +#elif defined(_ARCH_PWR9) +#define ATTRIBUTE_TARGET_CLONES \ + __attribute__((target_clones("cpu=power10,default"))) + +#else +#define ATTRIBUTE_TARGET_CLONES \ + __attribute__((target_clones("cpu=power10,power9,default"))) +#endif + +#define ONE ((HFtype) 1.0) + + +ATTRIBUTE_TARGET_CLONES +HFtype +__powihf2 (HFtype x, SItype m) +{ + unsigned int n = m < 0 ? -m : m; + HFtype y = n % 2 ? x : ONE; + + while (n >>= 1) + { + x = x * x; + if (n % 2) + y = y * x; + } + + return m < 0 ? ONE/y : y; +} + +/* Version of the powi function that passes and return _Float16 values in + gprs. */ + + +ATTRIBUTE_TARGET_CLONES +unsigned short +__powihf2_gpr (unsigned short us_x, SItype m) +{ + union ushort_hf u_x, u_r; + unsigned int n; + HFtype x, y; + + u_x.us = us_x; + n = m < 0 ? -m : m; + x = u_x.hf; + y = n % 2 ? x : ONE; + + while (n >>= 1) + { + x = x * x; + if (n % 2) + y = y * x; + } + + u_r.hf = m < 0 ? ONE/y : y; + return u_r.us; +} diff --git a/libgcc/config/rs6000/ppc-truncbfhf2.c b/libgcc/config/rs6000/ppc-truncbfhf2.c new file mode 100644 index 000000000000..ff660ad52e7d --- /dev/null +++ b/libgcc/config/rs6000/ppc-truncbfhf2.c @@ -0,0 +1,130 @@ +/* Software floating-point emulation. + Truncate bfloat16 into IEEE half. + Copyright (C) 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/truncbfhf2.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 "brain.h" +#include "single.h" + +/* BFtype and HFtype are unordered, neither is a superset or subset + of each other. Convert BFtype to SFtype (lossless) and then + truncate to HFtype. */ + +/* BFtype passed in FPR, HFtype returned in FPR. */ +HFtype +__truncbfhf2 (BFtype a) +{ + FP_DECL_EX; + FP_DECL_H (A); + FP_DECL_S (B); + FP_DECL_B (R); + SFtype b; + HFtype r; + + FP_INIT_ROUNDMODE; + /* Optimize BFtype to SFtype conversion to simple left shift + by 16 if possible, we don't need to raise exceptions on sNaN + here as the SFtype to HFtype truncation should do that too. */ + if (sizeof (BFtype) == 2 + && sizeof (unsigned short) == 2 + && sizeof (SFtype) == 4 + && sizeof (unsigned int) == 4) + { + union { BFtype a; unsigned short b; } u1; + union { SFtype a; unsigned int b; } u2; + u1.a = a; + u2.b = (u1.b << 8) << 8; + b = u2.a; + } + else + { + FP_UNPACK_RAW_B (A, a); + FP_EXTEND (S, B, 1, 1, B, A); + FP_PACK_RAW_S (b, B); + } + FP_UNPACK_SEMIRAW_S (B, b); + FP_TRUNC (H, S, 1, 1, R, B); + FP_PACK_SEMIRAW_H (r, R); + FP_HANDLE_EXCEPTIONS; + + return r; +} + +/* BFtype passed in GPR, HFtype returned in GPR. */ +unsigned short +__truncbfhf2_gpr (unsigned short us) +{ + FP_DECL_EX; + FP_DECL_H (A); + FP_DECL_S (B); + FP_DECL_B (R); + SFtype b; + HFtype r; + BFtype a; + union ushort_bf ubf; + union ushort_hf uhf; + + ubf.us = us; + a = ubf.bf; + + FP_INIT_ROUNDMODE; + /* Optimize BFtype to SFtype conversion to simple left shift + by 16 if possible, we don't need to raise exceptions on sNaN + here as the SFtype to HFtype truncation should do that too. */ + if (sizeof (BFtype) == 2 + && sizeof (unsigned short) == 2 + && sizeof (SFtype) == 4 + && sizeof (unsigned int) == 4) + { + union { BFtype a; unsigned short b; } u1; + union { SFtype a; unsigned int b; } u2; + u1.a = a; + u2.b = (u1.b << 8) << 8; + b = u2.a; + } + else + { + FP_UNPACK_RAW_B (A, a); + FP_EXTEND (S, B, 1, 1, B, A); + FP_PACK_RAW_S (b, B); + } + FP_UNPACK_SEMIRAW_S (B, b); + FP_TRUNC (H, S, 1, 1, R, B); + FP_PACK_SEMIRAW_H (r, R); + FP_HANDLE_EXCEPTIONS; + + uhf.hf = r; + return uhf.us; +} diff --git a/libgcc/config/rs6000/ppc-trunchfbf2.c b/libgcc/config/rs6000/ppc-trunchfbf2.c new file mode 100644 index 000000000000..747a90c996ef --- /dev/null +++ b/libgcc/config/rs6000/ppc-trunchfbf2.c @@ -0,0 +1,96 @@ +/* Software floating-point emulation. + Truncate IEEE half into bfloat16. + Copyright (C) 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/trunchfbf2.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 "half.h" +#include "single.h" + +/* BFtype and HFtype are unordered, neither is a superset or subset + of each other. Convert HFtype to SFtype (lossless) and then + truncate to BFtype. */ + +/* HFtype passed in FPR, BFtype returned in FPR. */ +BFtype +__trunchfbf2 (HFtype a) +{ + FP_DECL_EX; + FP_DECL_H (A); + FP_DECL_S (B); + FP_DECL_B (R); + SFtype b; + BFtype r; + + FP_INIT_ROUNDMODE; + FP_UNPACK_RAW_H (A, a); + FP_EXTEND (S, H, 1, 1, B, A); + FP_PACK_RAW_S (b, B); + FP_UNPACK_SEMIRAW_S (B, b); + FP_TRUNC (B, S, 1, 1, R, B); + FP_PACK_SEMIRAW_B (r, R); + FP_HANDLE_EXCEPTIONS; + + return r; +} + +/* HFtype passed in GPR, BFtype returned in GPR. */ +unsigned short +__trunchfbf2_gpr (unsigned short us) +{ + FP_DECL_EX; + FP_DECL_H (A); + FP_DECL_S (B); + FP_DECL_B (R); + SFtype b; + BFtype r; + HFtype a; + union ushort_bf ubf; + union ushort_hf uhf; + + uhf.us = us; + a = uhf.hf; + + FP_INIT_ROUNDMODE; + FP_UNPACK_RAW_H (A, a); + FP_EXTEND (S, H, 1, 1, B, A); + FP_PACK_RAW_S (b, B); + FP_UNPACK_SEMIRAW_S (B, b); + FP_TRUNC (B, S, 1, 1, R, B); + FP_PACK_SEMIRAW_B (r, R); + FP_HANDLE_EXCEPTIONS; + + ubf.bf = r; + return ubf.us; +} diff --git a/libgcc/config/rs6000/sfp-machine.h b/libgcc/config/rs6000/sfp-machine.h index b6dd03a710e3..dffe71304e3f 100644 --- a/libgcc/config/rs6000/sfp-machine.h +++ b/libgcc/config/rs6000/sfp-machine.h @@ -170,42 +170,119 @@ 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))); +#ifdef _ARCH_PPC64 +typedef int TItype2 __attribute__ ((mode (TI))); +typedef unsigned int UTItype2 __attribute__ ((mode (TI))); +#endif + +/* 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 (__fixunshfsi, USItype2, HFtype2); +PASS_FP16 (__fixunshfdi, UDItype2, HFtype2); + +RETURN_FP16 (__floatsihf, HFtype2, SItype2); +RETURN_FP16 (__floatdihf, HFtype2, DItype2); + +RETURN_FP16 (__floatunsihf, HFtype2, USItype2); +RETURN_FP16 (__floatundihf, HFtype2, UDItype2); + +RETURN_FP16 (__truncsfhf2, HFtype2, SFtype2); +RETURN_FP16 (__truncdfhf2, HFtype2, DFtype2); + +#ifdef _ARCH_PPC64 +PASS_FP16 (__fixhfti, TItype2, HFtype2); +PASS_FP16 (__fixunshfti, UTItype2, HFtype2); +RETURN_FP16 (__floattihf, HFtype2, TItype2); +RETURN_FP16 (__floatuntihf, HFtype2, UTItype2); +#endif + +extern HFtype2 __powihf2 (HFtype2, SItype2); +extern UHItype2 __powihf2_gpr (UHItype2, SItype2); #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 (__fixunsbfsi, USItype2, BFtype2); +PASS_FP16 (__fixunsbfdi, UDItype2, BFtype2); + +RETURN_FP16 (__floatsibf, BFtype2, SItype2); +RETURN_FP16 (__floatdibf, BFtype2, DItype2); + +RETURN_FP16 (__floatunsibf, BFtype2, USItype2); +RETURN_FP16 (__floatundibf, BFtype2, UDItype2); + +RETURN_FP16 (__truncsfbf2, BFtype2, SFtype2); +RETURN_FP16 (__truncdfbf2, BFtype2, DFtype2); + +#ifdef _ARCH_PPC64 +PASS_FP16 (__fixbfti, TItype2, BFtype2); +PASS_FP16 (__fixunsbfti, UTItype2, BFtype2); +RETURN_FP16 (__floattibf, BFtype2, TItype2); +RETURN_FP16 (__floatuntibf, BFtype2, UTItype2); +#endif + +extern BFtype2 __powibf2 (BFtype2, SItype2); +extern UHItype2 __powibf2_gpr (UHItype2, SItype2); #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..644df8e09d96 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 ppc-powihf -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 ppc-powibf -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
