diff options
author | Michael Meissner <meissner@gcc.gnu.org> | 2016-01-13 20:07:12 +0000 |
---|---|---|
committer | Michael Meissner <meissner@gcc.gnu.org> | 2016-01-13 20:07:12 +0000 |
commit | 29176d57e6be3f93551b54bd87ccc92e830a28b9 (patch) | |
tree | 3e9e41b127e139ff3b252fcbc1363a8af5c6916b /libgcc | |
parent | 3342fd71e0465ab4a702480a35043b295fc6fa21 (diff) | |
download | gcc-29176d57e6be3f93551b54bd87ccc92e830a28b9.tar.gz |
rs6000-builtin.def (BU_FLOAT128_2): Add support for pack/unpack functions for __ibm128.
[gcc]
2016-01-13 Michael Meissner <meissner@linux.vnet.ibm.com>
* config/rs6000/rs6000-builtin.def (BU_FLOAT128_2): Add support
for pack/unpack functions for __ibm128.
(PACK_IF): Likewise.
(UNPACK_IF): Likewise.
* config/rs6000/rs6000.c (rs6000_builtin_mask_calculate): Add
support for __ibm128 pack/unpack functions.
(rs6000_invalid_builtin): Likewise.
(rs6000_init_builtins): Likewise.
(rs6000_opt_masks): Likewise.
* config/rs6000/rs6000.h (MASK_FLOAT128): Add short name.
(RS6000_BTM_FLOAT128): Add support for __ibm128 pack/unpack
functions
(RS6000_BTM_COMMON): Likewise.
* config/rs6000/rs6000.md (f128_vsx): New mode attribute.
(unpack<mode>): Use FMOVE128_FPR iterator instead of FMOVE128, to
disallow __builtin_{pack,unpack}_longdouble if long double is IEEE
128-bit floating point. Add support for the double values to be
in Altivec registers for TF/IF packing and unpacking, but restrict
TD packing sub-fields to be FPR registers. Don't allow overlapped
register support for packing. Allow pack inputs to be memory
locations. Don't build generator functions for unpack<mode>_dm
and unpack<mode>_nodm.
(unpack<mode>_dm): Likewise.
(unpack<mode>_nodm): Likewise.
(pack<mode>): Likewise.
* config/rs6000/rs6000-builtin.def (__builtin_pack_ibm128): Add
built-in functions to pack/unpack explicit __ibm128 values.
(__builtin_unpack_ibm128): Likewise.
* doc/extend.texi (PowerPC Built-in Functions): Document
__builtin_pack_ibm128 and __builtin_unpack_ibm128.
[libgcc]
2016-01-13 Michael Meissner <meissner@linux.vnet.ibm.com>
Steven Munroe <munroesj@linux.vnet.ibm.com>
Tulio Magno Quites Machado Filho <tulioqm@br.ibm.com>
* config/rs6000/sfp-exceptions.c: New file to provide exception
support for IEEE 128-bit floating point.
* config/rs6000/float128-hw.c: New file for ISA 3.0 IEEE 128-bit
floating point hardware support.
* config/rs6000/floattikf.c: New files for IEEE 128-bit floating
point conversions.
* config/rs6000/fixunskfti.c: Likewise.
* config/rs6000/fixkfti.c: Likewise.
* config/rs6000/floatuntikf.c: Likewise.
* config/rs6000/extendkftf2-sw.c: Likewise.
* config/rs6000/trunctfkf2-sw.c: Likewise.
* config/rs6000/float128-ifunc.c: New file to pick either IEEE
128-bit floating point software emulation or use ISA 3.0 hardware
support if it is available.
* config/rs6000/quad-float128.h: New file to support IEEE 128-bit
floating point.
* config/rs6000/t-float128: New Makefile fragments to enable
building __float128 emulation support.
* config/rs6000/t-float128-hw: Likewise.
* config/rs6000/float128-sed: New file to convert TF names to KF
names for PowerPC IEEE 128-bit floating point support.
* config/rs6000/sfp-machine.h (_FP_W_TYPE_SIZE): Use 64-bit types
when building on 64-bit systems, or when VSX is enabled.
(_FP_W_TYPE): Likewise.
(_FP_WS_TYPE): Likewise.
(_FP_I_TYPE): Likewise.
(TItype): Define on 64-bit systems.
(UTItype): Likewise.
(TI_BITS): Likewise.
(_FP_MUL_MEAT_D): Add support for using 64-bit types.
(_FP_MUL_MEAT_Q): Likewise.
(_FP_DIV_MEAT_D): Likewise.
(_FP_DIV_MEAT_Q): Likewise.
(_FP_NANFRAC_D): Likewise.
(_FP_NANFRAC_Q): Likewise.
(ISA_BIT): Add exception support if we are being compiled on a
machine with hardware floating point support to build the IEEE
128-bit emulation functions.
(FP_EX_INVALID): Likewise.
(FP_EX_OVERFLOW): Likewise.
(FP_EX_UNDERFLOW): Likewise.
(FP_EX_DIVZERO): Likewise.
(FP_EX_INEXACT): Likewise.
(FP_EX_ALL): Likewise.
(__sfp_handle_exceptions): Likewise.
(FP_HANDLE_EXCEPTIONS): Likewise.
(FP_RND_NEAREST): Likewise.
(FP_RND_ZERO): Likewise.
(FP_RND_PINF): Likewise.
(FP_RND_MINF): Likewise.
(FP_RND_MASK): Likewise.
(_FP_DECL_EX): Likewise.
(FP_INIT_ROUNDMODE): Likewise.
(FP_ROUNDMODE): Likewise.
* configure.ac (powerpc*-*-linux*): Check whether the PowerPC
compiler can do __float128.
* configure: Regenerate.
* libgcc/config.host (powerpc*-*-linux*): If compiler can compile
VSX code, enable IEEE 128-bit floating point.
From-SVN: r232346
Diffstat (limited to 'libgcc')
-rw-r--r-- | libgcc/ChangeLog | 77 | ||||
-rw-r--r-- | libgcc/config.host | 9 | ||||
-rw-r--r-- | libgcc/config/rs6000/extendkftf2-sw.c | 49 | ||||
-rw-r--r-- | libgcc/config/rs6000/fixkfti.c | 51 | ||||
-rw-r--r-- | libgcc/config/rs6000/fixunskfti.c | 51 | ||||
-rw-r--r-- | libgcc/config/rs6000/float128-hw.c | 207 | ||||
-rw-r--r-- | libgcc/config/rs6000/float128-ifunc.c | 358 | ||||
-rw-r--r-- | libgcc/config/rs6000/float128-sed | 25 | ||||
-rw-r--r-- | libgcc/config/rs6000/floattikf.c | 51 | ||||
-rw-r--r-- | libgcc/config/rs6000/floatuntikf.c | 51 | ||||
-rw-r--r-- | libgcc/config/rs6000/quad-float128.h | 203 | ||||
-rw-r--r-- | libgcc/config/rs6000/sfp-exceptions.c | 72 | ||||
-rw-r--r-- | libgcc/config/rs6000/sfp-machine.h | 94 | ||||
-rw-r--r-- | libgcc/config/rs6000/t-float128 | 95 | ||||
-rw-r--r-- | libgcc/config/rs6000/t-float128-hw | 24 | ||||
-rw-r--r-- | libgcc/config/rs6000/trunctfkf2-sw.c | 49 | ||||
-rw-r--r-- | libgcc/configure | 49 | ||||
-rw-r--r-- | libgcc/configure.ac | 25 |
18 files changed, 1535 insertions, 5 deletions
diff --git a/libgcc/ChangeLog b/libgcc/ChangeLog index 4a9b5d39b85..4219bc176cc 100644 --- a/libgcc/ChangeLog +++ b/libgcc/ChangeLog @@ -1,7 +1,80 @@ +2016-01-13 Michael Meissner <meissner@linux.vnet.ibm.com> + Steven Munroe <munroesj@linux.vnet.ibm.com> + Tulio Magno Quites Machado Filho <tulioqm@br.ibm.com> + + * config/rs6000/sfp-exceptions.c: New file to provide exception + support for IEEE 128-bit floating point. + + * config/rs6000/float128-hw.c: New file for ISA 3.0 IEEE 128-bit + floating point hardware support. + + * config/rs6000/floattikf.c: New files for IEEE 128-bit floating + point conversions. + * config/rs6000/fixunskfti.c: Likewise. + * config/rs6000/fixkfti.c: Likewise. + * config/rs6000/floatuntikf.c: Likewise. + * config/rs6000/extendkftf2-sw.c: Likewise. + * config/rs6000/trunctfkf2-sw.c: Likewise. + + * config/rs6000/float128-ifunc.c: New file to pick either IEEE + 128-bit floating point software emulation or use ISA 3.0 hardware + support if it is available. + + * config/rs6000/quad-float128.h: New file to support IEEE 128-bit + floating point. + + * config/rs6000/t-float128: New Makefile fragments to enable + building __float128 emulation support. + * config/rs6000/t-float128-hw: Likewise. + + * config/rs6000/float128-sed: New file to convert TF names to KF + names for PowerPC IEEE 128-bit floating point support. + + * config/rs6000/sfp-machine.h (_FP_W_TYPE_SIZE): Use 64-bit types + when building on 64-bit systems, or when VSX is enabled. + (_FP_W_TYPE): Likewise. + (_FP_WS_TYPE): Likewise. + (_FP_I_TYPE): Likewise. + (TItype): Define on 64-bit systems. + (UTItype): Likewise. + (TI_BITS): Likewise. + (_FP_MUL_MEAT_D): Add support for using 64-bit types. + (_FP_MUL_MEAT_Q): Likewise. + (_FP_DIV_MEAT_D): Likewise. + (_FP_DIV_MEAT_Q): Likewise. + (_FP_NANFRAC_D): Likewise. + (_FP_NANFRAC_Q): Likewise. + (ISA_BIT): Add exception support if we are being compiled on a + machine with hardware floating point support to build the IEEE + 128-bit emulation functions. + (FP_EX_INVALID): Likewise. + (FP_EX_OVERFLOW): Likewise. + (FP_EX_UNDERFLOW): Likewise. + (FP_EX_DIVZERO): Likewise. + (FP_EX_INEXACT): Likewise. + (FP_EX_ALL): Likewise. + (__sfp_handle_exceptions): Likewise. + (FP_HANDLE_EXCEPTIONS): Likewise. + (FP_RND_NEAREST): Likewise. + (FP_RND_ZERO): Likewise. + (FP_RND_PINF): Likewise. + (FP_RND_MINF): Likewise. + (FP_RND_MASK): Likewise. + (_FP_DECL_EX): Likewise. + (FP_INIT_ROUNDMODE): Likewise. + (FP_ROUNDMODE): Likewise. + + * configure.ac (powerpc*-*-linux*): Check whether the PowerPC + compiler can do __float128. + * configure: Regenerate. + + * libgcc/config.host (powerpc*-*-linux*): If compiler can compile + VSX code, enable IEEE 128-bit floating point. + 2016-01-05 Olivier Hainque <hainque@adacore.com> * config/rs6000/aix-unwind.h (ucontext_for): Handle AIX 7.1 - specificities. + specificities. 2016-01-04 Jakub Jelinek <jakub@redhat.com> @@ -10,7 +83,7 @@ 2015-12-18 Andris Pavenis <andris.pavenis@iki.fi> * config.host: Add *-*-msdosdjgpp to lists of i[34567]86-*-* - soft-fp targets + soft-fp targets. 2015-12-16 Bernd Edlinger <bernd.edlinger@hotmail.de> diff --git a/libgcc/config.host b/libgcc/config.host index f58ee4555f5..d8efd82d213 100644 --- a/libgcc/config.host +++ b/libgcc/config.host @@ -1063,6 +1063,15 @@ powerpc*-*-linux*) exit 1 ;; esac + + if test $libgcc_cv_powerpc_float128 = yes; then + tmake_file="${tmake_file} rs6000/t-float128" + fi + + if test $libgcc_cv_powerpc_float128_hw = yes; then + tmake_file="${tmake_file} rs6000/t-float128-hw" + fi + extra_parts="$extra_parts ecrti.o ecrtn.o ncrti.o ncrtn.o" md_unwind_header=rs6000/linux-unwind.h ;; diff --git a/libgcc/config/rs6000/extendkftf2-sw.c b/libgcc/config/rs6000/extendkftf2-sw.c new file mode 100644 index 00000000000..2418a392c56 --- /dev/null +++ b/libgcc/config/rs6000/extendkftf2-sw.c @@ -0,0 +1,49 @@ +/* Software IEEE 128-bit floating-point emulation for PowerPC. + + Copyright (C) 2016 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Michael Meissner (meissner@linux.vnet.ibm.com) + Code is based on the main soft-fp library written by: + Richard Henderson (rth@cygnus.com) and + Jakub Jelinek (jj@ultra.linux.cz). + + 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/>. */ + +/* Convert IEEE 128-bit floating point to IBM long double. */ + +#ifdef __FLOAT128_HARDWARE__ +#error "This module must not be compiled with IEEE 128-bit hardware support" +#endif + +#include "soft-fp.h" +#include "quad-float128.h" + +__ibm128 +__extendkftf2_sw (__float128 value) +{ + __ibm128 ret; + + CVT_FLOAT128_TO_IBM128 (ret, value); + return ret; +} diff --git a/libgcc/config/rs6000/fixkfti.c b/libgcc/config/rs6000/fixkfti.c new file mode 100644 index 00000000000..80e10f078c0 --- /dev/null +++ b/libgcc/config/rs6000/fixkfti.c @@ -0,0 +1,51 @@ +/* Software floating-point emulation, convert IEEE quad to 128bit signed + integer. + + Copyright (C) 2016 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Steven Munroe (munroesj@linux.vnet.ibm.com) + Code is based on the main soft-fp library written by: + Uros Bizjak (ubizjak@gmail.com). + + 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/>. */ + +#ifdef _ARCH_PPC64 +#include "soft-fp.h" +#include "quad-float128.h" + +TItype +__fixkfti (TFtype a) +{ + FP_DECL_EX; + FP_DECL_Q (A); + UTItype r; + + FP_INIT_EXCEPTIONS; + FP_UNPACK_RAW_Q (A, a); + FP_TO_INT_Q (r, A, TI_BITS, 1); + FP_HANDLE_EXCEPTIONS; + + return r; +} +#endif diff --git a/libgcc/config/rs6000/fixunskfti.c b/libgcc/config/rs6000/fixunskfti.c new file mode 100644 index 00000000000..56c36716120 --- /dev/null +++ b/libgcc/config/rs6000/fixunskfti.c @@ -0,0 +1,51 @@ +/* Software floating-point emulation, convert IEEE quad to 128bit unsigned + integer. + + Copyright (C) 2016 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Steven Munroe (munroesj@linux.vnet.ibm.com) + Code is based on the main soft-fp library written by: + Uros Bizjak (ubizjak@gmail.com). + + 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/>. */ + +#ifdef _ARCH_PPC64 +#include "soft-fp.h" +#include "quad-float128.h" + +UTItype +__fixunskfti (TFtype a) +{ + FP_DECL_EX; + FP_DECL_Q (A); + UTItype r; + + FP_INIT_EXCEPTIONS; + FP_UNPACK_RAW_Q (A, a); + FP_TO_INT_Q (r, A, TI_BITS, 0); + FP_HANDLE_EXCEPTIONS; + + return r; +} +#endif diff --git a/libgcc/config/rs6000/float128-hw.c b/libgcc/config/rs6000/float128-hw.c new file mode 100644 index 00000000000..da2fbbcafd1 --- /dev/null +++ b/libgcc/config/rs6000/float128-hw.c @@ -0,0 +1,207 @@ +/* Automatic switching between software and hardware IEEE 128-bit + floating-point emulation for PowerPC. + + Copyright (C) 2016 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Michael Meissner (meissner@linux.vnet.ibm.com) + Code is based on the main soft-fp library written by: + Richard Henderson (rth@cygnus.com) and + Jakub Jelinek (jj@ultra.linux.cz). + + 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/>. */ + +#include <soft-fp.h> +#include <quad-float128.h> + +#ifndef __FLOAT128_HARDWARE__ +#error "This module must be compiled with IEEE 128-bit hardware support" +#endif + +TFtype +__addkf3_hw (TFtype a, TFtype b) +{ + return a + b; +} + +TFtype +__subkf3_hw (TFtype a, TFtype b) +{ + return a - b; +} + +TFtype +__mulkf3_hw (TFtype a, TFtype b) +{ + return a * b; +} + +TFtype +__divkf3_hw (TFtype a, TFtype b) +{ + return a / b; +} + +TFtype +__negkf2_hw (TFtype a) +{ + return -a; +} + +TFtype +__floatsikf_hw (SItype_ppc a) +{ + return (TFtype) a; +} + +TFtype +__floatunsikf_hw (USItype_ppc a) +{ + return (TFtype) a; +} + +TFtype +__floatdikf_hw (DItype_ppc a) +{ + return (TFtype) a; +} + +TFtype +__floatundikf_hw (UDItype_ppc a) +{ + return (TFtype) a; +} + +SItype_ppc +__fixkfsi_hw (TFtype a) +{ + return (SItype_ppc) a; +} + +USItype_ppc +__fixunskfsi_hw (TFtype a) +{ + return (USItype_ppc) a; +} + +DItype_ppc +__fixkfdi_hw (TFtype a) +{ + return (DItype_ppc) a; +} + +UDItype_ppc +__fixunskfdi_hw (TFtype a) +{ + return (UDItype_ppc) a; +} + +TFtype +__extendsfkf2_hw (float a) +{ + return (TFtype) a; +} + +TFtype +__extenddfkf2_hw (double a) +{ + return (TFtype) a; +} + +float +__trunckfsf2_hw (TFtype a) +{ + return (float) a; +} + +double +__trunckfdf2_hw (TFtype a) +{ + return (double) a; +} + +/* __eqkf2 returns 0 if equal, or 1 if not equal or NaN. */ +CMPtype +__eqkf2_hw (TFtype a, TFtype b) +{ + return (a != b); +} + +/* __gekf2 returns -1 if a < b, 0 if a == b, +1 if a > b, or -2 if NaN. */ +CMPtype +__gekf2_hw (TFtype a, TFtype b) +{ + if (a < b) + return -1; + + else if (__builtin_isunordered (a, b)) + return -2; + + else if (a == b) + return 0; + + return 1; +} + +/* __lekf2 returns -1 if a < b, 0 if a == b, +1 if a > b, or +2 if NaN. */ +CMPtype +__lekf2_hw (TFtype a, TFtype b) +{ + if (a < b) + return -1; + + else if (__builtin_isunordered (a, b)) + return 2; + + else if (a == b) + return 0; + + return 1; +} + +/* __unordkf2 returns 1 if NaN or 0 otherwise. */ +CMPtype +__unordkf2_hw (TFtype a, TFtype b) +{ + return (__builtin_isunordered (a, b)) ? 1 : 0; +} + +/* Convert __float128 to __ibm128. */ +__ibm128 +__extendkftf2_hw (TFtype value) +{ + __ibm128 ret; + + CVT_FLOAT128_TO_IBM128 (ret, value); + return ret; +} + +/* Convert __ibm128 to __float128. */ +TFtype +__trunctfkf2_hw (__ibm128 value) +{ + TFtype ret; + + CVT_IBM128_TO_FLOAT128 (ret, value); + return ret; +} diff --git a/libgcc/config/rs6000/float128-ifunc.c b/libgcc/config/rs6000/float128-ifunc.c new file mode 100644 index 00000000000..6e14608d3a7 --- /dev/null +++ b/libgcc/config/rs6000/float128-ifunc.c @@ -0,0 +1,358 @@ +/* Automatic switching between software and hardware IEEE 128-bit + floating-point emulation for PowerPC. + + Copyright (C) 2016 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Michael Meissner (meissner@linux.vnet.ibm.com) + Code is based on the main soft-fp library written by: + Richard Henderson (rth@cygnus.com) and + Jakub Jelinek (jj@ultra.linux.cz). + + 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/>. */ + +#include <soft-fp.h> +#include <quad-float128.h> +#include <string.h> +#include <stdlib.h> +#include <ctype.h> + +#ifdef FLOAT128_HW_INSNS +#include <sys/auxv.h> + +/* Use the namespace clean version of getauxval. However, not all versions of + sys/auxv.h declare it, so declare it here. This code is intended to be + temporary until a suitable version of __builtin_cpu_supports is added that + allows us to tell quickly if the machine supports IEEE 128-bit hardware. */ +extern unsigned long __getauxval (unsigned long); + +static int +have_ieee_hw_p (void) +{ + static int ieee_hw_p = -1; + + if (ieee_hw_p < 0) + { + char *p = (char *) __getauxval (AT_PLATFORM); + + ieee_hw_p = 0; + + /* Don't use atoi/strtol/strncmp/etc. These may require the normal + environment to be setup to set errno to 0, and the ifunc resolvers run + before the whole glibc environment is initialized. */ + if (p && p[0] == 'p' && p[1] == 'o' && p[2] == 'w' && p[3] == 'e' + && p[4] == 'r') + { + long n = 0; + char ch; + + p += 5; + while ((ch = *p++) >= '0' && (ch <= '9')) + n = (n * 10) + (ch - '0'); + + if (n >= 9) + ieee_hw_p = 1; + } + } + + return ieee_hw_p; +} + +#define SW_OR_HW(SW, HW) (have_ieee_hw_p () ? HW : SW) +#else +#define SW_OR_HW(SW, HW) (SW) +#endif /* ISA 3.0 hardware available. */ + +/* Resolvers. */ + +/* We do not provide ifunc resolvers for __fixkfti, __fixunskfti, __floattikf, + and __floatuntikf. There is no ISA 3.0 instruction that converts between + 128-bit integer types and 128-bit IEEE floating point, or vice versa. So + use the emulator functions for these conversions. */ + +static void *__addkf3_resolve (void); +static void *__subkf3_resolve (void); +static void *__mulkf3_resolve (void); +static void *__divkf3_resolve (void); +static void *__negkf2_resolve (void); +static void *__eqkf2_resolve (void); +static void *__nekf2_resolve (void); +static void *__gekf2_resolve (void); +static void *__gtkf2_resolve (void); +static void *__lekf2_resolve (void); +static void *__ltkf2_resolve (void); +static void *__unordkf2_resolve (void); +static void *__extendsfkf2_resolve (void); +static void *__extenddfkf2_resolve (void); +static void *__trunckfsf2_resolve (void); +static void *__trunckfdf2_resolve (void); +static void *__fixkfsi_resolve (void); +static void *__fixkfdi_resolve (void); +static void *__fixunskfsi_resolve (void); +static void *__fixunskfdi_resolve (void); +static void *__floatsikf_resolve (void); +static void *__floatdikf_resolve (void); +static void *__floatunsikf_resolve (void); +static void *__floatundikf_resolve (void); +static void *__extendkftf2_resolve (void); +static void *__trunctfkf2_resolve (void); + +static void * +__addkf3_resolve (void) +{ + return (void *) SW_OR_HW (__addkf3_sw, __addkf3_hw); +} + +static void * +__subkf3_resolve (void) +{ + return (void *) SW_OR_HW (__subkf3_sw, __subkf3_hw); +} + +static void * +__mulkf3_resolve (void) +{ + return (void *) SW_OR_HW (__mulkf3_sw, __mulkf3_hw); +} + +static void * +__divkf3_resolve (void) +{ + return (void *) SW_OR_HW (__divkf3_sw, __divkf3_hw); +} + +static void * +__negkf2_resolve (void) +{ + return (void *) SW_OR_HW (__negkf2_sw, __negkf2_hw); +} + +static void * +__floatsikf_resolve (void) +{ + return (void *) SW_OR_HW (__floatsikf_sw, __floatsikf_hw); +} + +static void * +__floatdikf_resolve (void) +{ + return (void *) SW_OR_HW (__floatdikf_sw, __floatdikf_hw); +} + +static void * +__floatunsikf_resolve (void) +{ + return (void *) SW_OR_HW (__floatunsikf_sw, __floatunsikf_hw); +} + +static void * +__floatundikf_resolve (void) +{ + return (void *) SW_OR_HW (__floatundikf_sw, __floatundikf_hw); +} + +static void * +__fixkfsi_resolve (void) +{ + return (void *) SW_OR_HW (__fixkfsi_sw, __fixkfsi_hw); +} + +static void * +__fixkfdi_resolve (void) +{ + return (void *) SW_OR_HW (__fixkfdi_sw, __fixkfdi_hw); +} + +static void * +__fixunskfsi_resolve (void) +{ + return (void *) SW_OR_HW (__fixunskfsi_sw, __fixunskfsi_hw); +} + +static void * +__fixunskfdi_resolve (void) +{ + return (void *) SW_OR_HW (__fixunskfdi_sw, __fixunskfdi_hw); +} + +static void * +__extendsfkf2_resolve (void) +{ + return (void *) SW_OR_HW (__extendsfkf2_sw, __extendsfkf2_hw); +} + +static void * +__extenddfkf2_resolve (void) +{ + return (void *) SW_OR_HW (__extenddfkf2_sw, __extenddfkf2_hw); +} + +static void * +__trunckfsf2_resolve (void) +{ + return (void *) SW_OR_HW (__trunckfsf2_sw, __trunckfsf2_hw); +} + +static void * +__trunckfdf2_resolve (void) +{ + return (void *) SW_OR_HW (__trunckfdf2_sw, __trunckfdf2_hw); +} + +static void * +__extendkftf2_resolve (void) +{ + return (void *) SW_OR_HW (__extendkftf2_sw, __extendkftf2_hw); +} + +static void * +__trunctfkf2_resolve (void) +{ + return (void *) SW_OR_HW (__trunctfkf2_sw, __trunctfkf2_hw); +} + +static void * +__eqkf2_resolve (void) +{ + return (void *) SW_OR_HW (__eqkf2_sw, __eqkf2_hw); +} + +static void * +__gekf2_resolve (void) +{ + return (void *) SW_OR_HW (__gekf2_sw, __gekf2_hw); +} + +static void * +__lekf2_resolve (void) +{ + return (void *) SW_OR_HW (__lekf2_sw, __lekf2_hw); +} + +static void * +__unordkf2_resolve (void) +{ + return (void *) SW_OR_HW (__unordkf2_sw, __unordkf2_hw); +} + +/* Resolve __nekf2, __gtkf2, __ltkf2 like __eqkf2, __gekf2, and __lekf2, since + the functions return the same values. */ + +static void * +__nekf2_resolve (void) +{ + return (void *) SW_OR_HW (__eqkf2_sw, __eqkf2_hw); +} + +static void * +__gtkf2_resolve (void) +{ + return (void *) SW_OR_HW (__gekf2_sw, __gekf2_hw); +} + +static void * +__ltkf2_resolve (void) +{ + return (void *) SW_OR_HW (__lekf2_sw, __lekf2_hw); +} + + + +/* Ifunc definitions. */ +TFtype __addkf3 (TFtype, TFtype) + __attribute__ ((__ifunc__ ("__addkf3_resolve"))); + +TFtype __subkf3 (TFtype, TFtype) + __attribute__ ((__ifunc__ ("__subkf3_resolve"))); + +TFtype __mulkf3 (TFtype, TFtype) + __attribute__ ((__ifunc__ ("__mulkf3_resolve"))); + +TFtype __divkf3 (TFtype, TFtype) + __attribute__ ((__ifunc__ ("__divkf3_resolve"))); + +TFtype __negkf2 (TFtype) + __attribute__ ((__ifunc__ ("__negkf2_resolve"))); + +CMPtype __eqkf2 (TFtype, TFtype) + __attribute__ ((__ifunc__ ("__eqkf2_resolve"))); + +CMPtype __nekf2 (TFtype, TFtype) + __attribute__ ((__ifunc__ ("__nekf2_resolve"))); + +CMPtype __gekf2 (TFtype, TFtype) + __attribute__ ((__ifunc__ ("__gekf2_resolve"))); + +CMPtype __gtkf2 (TFtype, TFtype) + __attribute__ ((__ifunc__ ("__gtkf2_resolve"))); + +CMPtype __lekf2 (TFtype, TFtype) + __attribute__ ((__ifunc__ ("__lekf2_resolve"))); + +CMPtype __ltkf2 (TFtype, TFtype) + __attribute__ ((__ifunc__ ("__ltkf2_resolve"))); + +CMPtype __unordkf2 (TFtype, TFtype) + __attribute__ ((__ifunc__ ("__unordkf2_resolve"))); + +TFtype __extendsfkf2 (float) + __attribute__ ((__ifunc__ ("__extendsfkf2_resolve"))); + +TFtype __extenddfkf2 (double) + __attribute__ ((__ifunc__ ("__extenddfkf2_resolve"))); + +float __trunckfsf2 (TFtype) + __attribute__ ((__ifunc__ ("__trunckfsf2_resolve"))); + +double __trunckfdf2 (TFtype) + __attribute__ ((__ifunc__ ("__trunckfdf2_resolve"))); + +SItype_ppc __fixkfsi (TFtype) + __attribute__ ((__ifunc__ ("__fixkfsi_resolve"))); + +DItype_ppc __fixkfdi (TFtype) + __attribute__ ((__ifunc__ ("__fixkfdi_resolve"))); + +USItype_ppc __fixunskfsi (TFtype) + __attribute__ ((__ifunc__ ("__fixunskfsi_resolve"))); + +UDItype_ppc __fixunskfdi (TFtype) + __attribute__ ((__ifunc__ ("__fixunskfdi_resolve"))); + +TFtype __floatsikf (SItype_ppc) + __attribute__ ((__ifunc__ ("__floatsikf_resolve"))); + +TFtype __floatdikf (DItype_ppc) + __attribute__ ((__ifunc__ ("__floatdikf_resolve"))); + +TFtype __floatunsikf (USItype_ppc) + __attribute__ ((__ifunc__ ("__floatunsikf_resolve"))); + +TFtype __floatundikf (UDItype_ppc) + __attribute__ ((__ifunc__ ("__floatundikf_resolve"))); + +__ibm128 __extendkftf2 (TFtype) + __attribute__ ((__ifunc__ ("__extendkftf2_resolve"))); + +TFtype __trunctfkf2 (__ibm128) + __attribute__ ((__ifunc__ ("__trunctfkf2_resolve"))); diff --git a/libgcc/config/rs6000/float128-sed b/libgcc/config/rs6000/float128-sed new file mode 100644 index 00000000000..acf36b0c17d --- /dev/null +++ b/libgcc/config/rs6000/float128-sed @@ -0,0 +1,25 @@ +s/__addtf3/__addkf3_sw/g +s/__divtf3/__divkf3_sw/g +s/__eqtf2/__eqkf2_sw/g +s/__extenddftf2/__extenddfkf2_sw/g +s/__extendsftf2/__extendsfkf2_sw/g +s/__fixtfdi/__fixkfdi_sw/g +s/__fixtfsi/__fixkfsi_sw/g +s/__fixunstfdi/__fixunskfdi_sw/g +s/__fixunstfsi/__fixunskfsi_sw/g +s/__floatditf/__floatdikf_sw/g +s/__floatsitf/__floatsikf_sw/g +s/__floatunditf/__floatundikf_sw/g +s/__floatunsitf/__floatunsikf_sw/g +s/__getf2/__gekf2_sw/g +s/__gttf2/__gtkf2_sw/g +s/__letf2/__lekf2_sw/g +s/__lttf2/__ltkf2_sw/g +s/__multf3/__mulkf3_sw/g +s/__negtf2/__negkf2_sw/g +s/__netf2/__nekf2_sw/g +s/quad[.]h/quad-float128.h/g +s/__subtf3/__subkf3_sw/g +s/__trunctfdf2/__trunckfdf2_sw/g +s/__trunctfsf2/__trunckfsf2_sw/g +s/__unordtf2/__unordkf2_sw/g diff --git a/libgcc/config/rs6000/floattikf.c b/libgcc/config/rs6000/floattikf.c new file mode 100644 index 00000000000..4c652308158 --- /dev/null +++ b/libgcc/config/rs6000/floattikf.c @@ -0,0 +1,51 @@ +/* Software floating-point emulation, convert a 128bit signed integer to IEEE + quad. + + Copyright (C) 2016 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Steven Munroe (munroesj@linux.vnet.ibm.com) + Code is based on the main soft-fp library written by: + Uros Bizjak (ubizjak@gmail.com). + + 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/>. */ + +#ifdef _ARCH_PPC64 +#include "soft-fp.h" +#include "quad-float128.h" + +TFtype +__floattikf (TItype i) +{ + FP_DECL_EX; + FP_DECL_Q (A); + TFtype a; + + FP_INIT_ROUNDMODE; + FP_FROM_INT_Q (A, i, TI_BITS, UTItype); + FP_PACK_RAW_Q (a, A); + FP_HANDLE_EXCEPTIONS; + + return a; +} +#endif diff --git a/libgcc/config/rs6000/floatuntikf.c b/libgcc/config/rs6000/floatuntikf.c new file mode 100644 index 00000000000..6dabf7b33bd --- /dev/null +++ b/libgcc/config/rs6000/floatuntikf.c @@ -0,0 +1,51 @@ +/* Software floating-point emulation, convert a 128bit unsigned integer to IEEE + quad. + + Copyright (C) 2016 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Steven Munroe (munroesj@linux.vnet.ibm.com) + Code is based on the main soft-fp library written by: + Uros Bizjak (ubizjak@gmail.com). + + 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/>. */ + +#ifdef _ARCH_PPC64 +#include "soft-fp.h" +#include "quad-float128.h" + +TFtype +__floatuntikf (UTItype i) +{ + FP_DECL_EX; + FP_DECL_Q (A); + TFtype a; + + FP_INIT_ROUNDMODE; + FP_FROM_INT_Q (A, i, TI_BITS, UTItype); + FP_PACK_RAW_Q (a, A); + FP_HANDLE_EXCEPTIONS; + + return a; +} +#endif diff --git a/libgcc/config/rs6000/quad-float128.h b/libgcc/config/rs6000/quad-float128.h new file mode 100644 index 00000000000..423cb05d9ea --- /dev/null +++ b/libgcc/config/rs6000/quad-float128.h @@ -0,0 +1,203 @@ +/* Software floating-point emulation. + Definitions for IEEE Quad Precision on the PowerPC. + Copyright (C) 2016 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Michael Meissner (meissner@linux.vnet.ibm.com). + + 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/>. */ + +/* quad.h defines the TFtype type by: + typedef float TFtype __attribute__ ((mode (TF))); + + This define forces it to use KFmode (aka, ieee 128-bit floating point). */ +#define TF KF + +/* Force the use of the VSX instruction set. */ +#if defined(_ARCH_PPC) && (!defined(__VSX__) || !defined(__FLOAT128__)) +#pragma GCC target ("vsx,float128") +#endif + +#include <quad.h> + +/* Add prototypes of the library functions created. In case the appropriate + int/long types are not declared in scope by the time quad.h is included, + provide our own version. */ +typedef int SItype_ppc __attribute__ ((__mode__ (__SI__))); +typedef int DItype_ppc __attribute__ ((__mode__ (__DI__))); +typedef unsigned USItype_ppc __attribute__ ((__mode__ (__SI__))); +typedef unsigned UDItype_ppc __attribute__ ((__mode__ (__DI__))); + +#ifdef _ARCH_PPC64 +typedef int TItype_ppc __attribute__ ((__mode__ (__TI__))); +typedef unsigned UTItype_ppc __attribute__ ((__mode__ (__TI__))); +#endif + +/* Software emulation functions. */ +extern TFtype __addkf3_sw (TFtype, TFtype); +extern TFtype __subkf3_sw (TFtype, TFtype); +extern TFtype __mulkf3_sw (TFtype, TFtype); +extern TFtype __divkf3_sw (TFtype, TFtype); +extern TFtype __negkf2_sw (TFtype); +extern CMPtype __eqkf2_sw (TFtype, TFtype); +extern CMPtype __gekf2_sw (TFtype, TFtype); +extern CMPtype __lekf2_sw (TFtype, TFtype); +extern CMPtype __unordkf2_sw (TFtype, TFtype); +extern TFtype __extendsfkf2_sw (float); +extern TFtype __extenddfkf2_sw (double); +extern float __trunckfsf2_sw (TFtype); +extern double __trunckfdf2_sw (TFtype); +extern SItype_ppc __fixkfsi_sw (TFtype); +extern DItype_ppc __fixkfdi_sw (TFtype); +extern USItype_ppc __fixunskfsi_sw (TFtype); +extern UDItype_ppc __fixunskfdi_sw (TFtype); +extern TFtype __floatsikf_sw (SItype_ppc); +extern TFtype __floatdikf_sw (DItype_ppc); +extern TFtype __floatunsikf_sw (USItype_ppc); +extern TFtype __floatundikf_sw (UDItype_ppc); +extern __ibm128 __extendkftf2_sw (TFtype); +extern TFtype __trunctfkf2_sw (__ibm128); + +#ifdef _ARCH_PPC64 +/* We do not provide ifunc resolvers for __fixkfti, __fixunskfti, __floattikf, + and __floatuntikf. There is no ISA 3.0 instruction that converts between + 128-bit integer types and 128-bit IEEE floating point, or vice versa. So + use the emulator functions for these conversions. */ + +extern TItype_ppc __fixkfti (TFtype); +extern UTItype_ppc __fixunskfti (TFtype); +extern TFtype __floattikf (TItype_ppc); +extern TFtype __floatuntikf (UTItype_ppc); +#endif + +/* Functions using the ISA 3.0 hardware support. If the code is compiled with + -mcpu=power9, it will not use these functions, but if it was compiled with + -mcpu=power7 or -mcpu=power8 and run on a ISA 3.0 system, it will use the + hardware instruction. */ +extern TFtype __addkf3_hw (TFtype, TFtype); +extern TFtype __subkf3_hw (TFtype, TFtype); +extern TFtype __mulkf3_hw (TFtype, TFtype); +extern TFtype __divkf3_hw (TFtype, TFtype); +extern TFtype __negkf2_hw (TFtype); +extern CMPtype __eqkf2_hw (TFtype, TFtype); +extern CMPtype __gekf2_hw (TFtype, TFtype); +extern CMPtype __lekf2_hw (TFtype, TFtype); +extern CMPtype __unordkf2_hw (TFtype, TFtype); +extern TFtype __extendsfkf2_hw (float); +extern TFtype __extenddfkf2_hw (double); +extern float __trunckfsf2_hw (TFtype); +extern double __trunckfdf2_hw (TFtype); +extern SItype_ppc __fixkfsi_hw (TFtype); +extern DItype_ppc __fixkfdi_hw (TFtype); +extern USItype_ppc __fixunskfsi_hw (TFtype); +extern UDItype_ppc __fixunskfdi_hw (TFtype); +extern TFtype __floatsikf_hw (SItype_ppc); +extern TFtype __floatdikf_hw (DItype_ppc); +extern TFtype __floatunsikf_hw (USItype_ppc); +extern TFtype __floatundikf_hw (UDItype_ppc); +extern __ibm128 __extendkftf2_hw (TFtype); +extern TFtype __trunctfkf2_hw (__ibm128); + +/* Ifunc function declarations, to automatically switch between software + emulation and hardware support. */ +extern TFtype __addkf3 (TFtype, TFtype); +extern TFtype __subkf3 (TFtype, TFtype); +extern TFtype __mulkf3 (TFtype, TFtype); +extern TFtype __divkf3 (TFtype, TFtype); +extern TFtype __negkf2 (TFtype); +extern CMPtype __eqkf2 (TFtype, TFtype); +extern CMPtype __nekf2 (TFtype, TFtype); +extern CMPtype __gekf2 (TFtype, TFtype); +extern CMPtype __gtkf2 (TFtype, TFtype); +extern CMPtype __lekf2 (TFtype, TFtype); +extern CMPtype __ltkf2 (TFtype, TFtype); +extern CMPtype __unordkf2 (TFtype, TFtype); +extern TFtype __extendsfkf2 (float); +extern TFtype __extenddfkf2 (double); +extern float __trunckfsf2 (TFtype); +extern double __trunckfdf2 (TFtype); +extern SItype_ppc __fixkfsi (TFtype); +extern DItype_ppc __fixkfdi (TFtype); +extern USItype_ppc __fixunskfsi (TFtype); +extern UDItype_ppc __fixunskfdi (TFtype); +extern TFtype __floatsikf (SItype_ppc); +extern TFtype __floatdikf (DItype_ppc); +extern TFtype __floatunsikf (USItype_ppc); +extern TFtype __floatundikf (UDItype_ppc); +extern __ibm128 __extendkftf2 (TFtype); +extern TFtype __trunctfkf2 (__ibm128); + +#ifdef __LITTLE_ENDIAN__ +#define HIGH_WORD 1 +#define LOW_WORD 0 +#else +#define HIGH_WORD 0 +#define LOW_WORD 1 +#endif + +/* Implementation of conversions between __ibm128 and __float128, to allow the + same code to be used on systems with IEEE 128-bit emulation and with IEEE + 128-bit hardware support. */ + +#define CVT_FLOAT128_TO_IBM128(RESULT, VALUE) \ +{ \ + double __high, __low; \ + __float128 __value = (VALUE); \ + \ + __high = (double) __value; \ + if (__builtin_isnan (__high) || __builtin_isinf (__high)) \ + __low = 0.0; \ + \ + else \ + { \ + double __high_temp; \ + \ + __low = (double) (__value - (__float128) __high); \ + /* Renormalize low/high and move them into canonical IBM long \ + double form. */ \ + __high_temp = __high + __low; \ + __low = (__high - __high_temp) + __low; \ + __high = __high_temp; \ + } \ + \ + RESULT = __builtin_pack_ibm128 (__high, __low); \ +} + +#define CVT_IBM128_TO_FLOAT128(RESULT, VALUE) \ +{ \ + __ibm128 __value = (VALUE); \ + double __high = __builtin_unpack_ibm128 (__value, HIGH_WORD); \ + double __low = __builtin_unpack_ibm128 (__value, LOW_WORD); \ + \ + /* Handle the special cases of NAN and infinity. */ \ + if (__builtin_isnan (__high) || __builtin_isinf (__high)) \ + RESULT = (__float128) __high; \ + \ + /* If low is 0.0, there no need to do the add. In addition, \ + avoiding the add produces the correct sign if high is -0.0. */ \ + else if (__low == 0.0) \ + RESULT = (__float128) __high; \ + \ + else \ + RESULT = ((__float128) __high) + ((__float128) __low); \ +} diff --git a/libgcc/config/rs6000/sfp-exceptions.c b/libgcc/config/rs6000/sfp-exceptions.c new file mode 100644 index 00000000000..efd21da5320 --- /dev/null +++ b/libgcc/config/rs6000/sfp-exceptions.c @@ -0,0 +1,72 @@ +/* Copyright (C) 2016 Free Software Foundation, Inc. + + This file 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. + + This file 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/>. */ + +#include "sfp-machine.h" + +/* Only provide exception support if we have hardware floating point and we can + execute the mtfsf instruction. This would only be true if we are using the + emulation routines for IEEE 128-bit floating point on pre-ISA 3.0 machines + without the IEEE 128-bit floating point support. */ + +#ifndef __NO_FPRS__ + +void +__sfp_handle_exceptions (int _fex) +{ + const double fp_max = __DBL_MAX__; + const double fp_min = __DBL_MIN__; + const double fp_zero = (double) 0.0; + const double fp_one = 1.0; + double tmp; + + if (_fex & FP_EX_INVALID) + { + __asm__ __volatile__ ("fdiv %0, %1, %1" + : "=f" (tmp) + : "f" (fp_zero)); + } + if (_fex & FP_EX_DIVZERO) + { + __asm__ __volatile__ ("fdiv %0, %1, %2" + : "=f" (tmp) + : "f" (fp_one), "f" (fp_zero)); + } + if (_fex & FP_EX_OVERFLOW) + { + __asm__ __volatile__ ("fadd %0, %1, %1" + : "=f" (tmp) + : "f" (fp_max)); + } + if (_fex & FP_EX_UNDERFLOW) + { + __asm__ __volatile__ ("fmul %0, %1, %1" + : "=f" (tmp) + : "f" (fp_min)); + } + if (_fex & FP_EX_INEXACT) + { + __asm__ __volatile__ ("fsub %0, %1, %2" + : "=f" (tmp) + : "f" (fp_max), "f" (fp_one)); + } +} + +#endif /* !__NO_FPRS__ */ diff --git a/libgcc/config/rs6000/sfp-machine.h b/libgcc/config/rs6000/sfp-machine.h index 40436337ffb..91f82ae1f09 100644 --- a/libgcc/config/rs6000/sfp-machine.h +++ b/libgcc/config/rs6000/sfp-machine.h @@ -1,7 +1,26 @@ +/* Decide whether to use 64 or 32-bit types to do the emulation. If we are + doing IEEE-128 with VSX, use 64-bit emulation even if we are compiling for a + 32-bit target. */ + +#if defined(_ARCH_PPC64) || defined(__VSX__) || defined(__FLOAT128__) +#define _FP_W_TYPE_SIZE 64 +#define _FP_W_TYPE unsigned long long +#define _FP_WS_TYPE signed long long +#define _FP_I_TYPE long long + +#ifdef _ARCH_PPC64 +typedef int TItype __attribute__ ((mode (TI))); +typedef unsigned int UTItype __attribute__ ((mode (TI))); + +#define TI_BITS (__CHAR_BIT__ * (int)sizeof(TItype)) +#endif + +#else /* 32-bits */ #define _FP_W_TYPE_SIZE 32 -#define _FP_W_TYPE unsigned long -#define _FP_WS_TYPE signed long -#define _FP_I_TYPE long +#define _FP_W_TYPE unsigned int +#define _FP_WS_TYPE signed int +#define _FP_I_TYPE int +#endif /* 32-bits */ /* The type of the result of a floating point comparison. This must match `__libgcc_cmp_return__' in GCC for the target. */ @@ -10,18 +29,39 @@ typedef int __gcc_CMPtype __attribute__ ((mode (__libgcc_cmp_return__))); #define _FP_MUL_MEAT_S(R,X,Y) \ _FP_MUL_MEAT_1_wide(_FP_WFRACBITS_S,R,X,Y,umul_ppmm) + +#if (_FP_W_TYPE_SIZE==64) +#define _FP_MUL_MEAT_D(R,X,Y) \ + _FP_MUL_MEAT_1_wide(_FP_WFRACBITS_D,R,X,Y,umul_ppmm) +#define _FP_MUL_MEAT_Q(R,X,Y) \ + _FP_MUL_MEAT_2_wide(_FP_WFRACBITS_Q,R,X,Y,umul_ppmm) +#else #define _FP_MUL_MEAT_D(R,X,Y) \ _FP_MUL_MEAT_2_wide(_FP_WFRACBITS_D,R,X,Y,umul_ppmm) #define _FP_MUL_MEAT_Q(R,X,Y) \ _FP_MUL_MEAT_4_wide(_FP_WFRACBITS_Q,R,X,Y,umul_ppmm) +#endif #define _FP_DIV_MEAT_S(R,X,Y) _FP_DIV_MEAT_1_loop(S,R,X,Y) + +#if (_FP_W_TYPE_SIZE==64) +#define _FP_DIV_MEAT_D(R,X,Y) _FP_DIV_MEAT_1_udiv(D,R,X,Y) +#define _FP_DIV_MEAT_Q(R,X,Y) _FP_DIV_MEAT_2_udiv(Q,R,X,Y) +#else #define _FP_DIV_MEAT_D(R,X,Y) _FP_DIV_MEAT_2_udiv(D,R,X,Y) #define _FP_DIV_MEAT_Q(R,X,Y) _FP_DIV_MEAT_4_udiv(Q,R,X,Y) +#endif #define _FP_NANFRAC_S ((_FP_QNANBIT_S << 1) - 1) + +#if (_FP_W_TYPE_SIZE==64) +#define _FP_NANFRAC_D ((_FP_QNANBIT_D << 1) - 1) +#define _FP_NANFRAC_Q ((_FP_QNANBIT_Q << 1) - 1), -1 +#else #define _FP_NANFRAC_D ((_FP_QNANBIT_D << 1) - 1), -1 #define _FP_NANFRAC_Q ((_FP_QNANBIT_Q << 1) - 1), -1, -1, -1 +#endif + #define _FP_NANSIGN_S 0 #define _FP_NANSIGN_D 0 #define _FP_NANSIGN_Q 0 @@ -64,6 +104,54 @@ typedef int __gcc_CMPtype __attribute__ ((mode (__libgcc_cmp_return__))); # endif #endif +/* Only provide exception support if we have hardware floating point using + floating point registers and we can execute the mtfsf instruction. This + would only be true if we are using the emulation routines for IEEE 128-bit + floating point on pre-ISA 3.0 machines without the IEEE 128-bit floating + point support. */ + +#ifndef ___NO_FPRS__ +#define ISA_BIT(x) (1LL << (63 - x)) + +/* Use the same bits of the FPSCR. */ +# define FP_EX_INVALID ISA_BIT(34) +# define FP_EX_OVERFLOW ISA_BIT(35) +# define FP_EX_UNDERFLOW ISA_BIT(36) +# define FP_EX_DIVZERO ISA_BIT(37) +# define FP_EX_INEXACT ISA_BIT(38) +# define FP_EX_ALL (FP_EX_INVALID | FP_EX_OVERFLOW \ + | FP_EX_UNDERFLOW | FP_EX_DIVZERO \ + | FP_EX_INEXACT) + +void __sfp_handle_exceptions (int); + +# define FP_HANDLE_EXCEPTIONS \ + do { \ + if (__builtin_expect (_fex, 0)) \ + __sfp_handle_exceptions (_fex); \ + } while (0); +/* A set bit indicates an exception is masked and a clear bit indicates it is + trapping. */ +# define FP_TRAPPING_EXCEPTIONS (~_fpscr & (FP_EX_ALL >> 22)) + +# define FP_RND_NEAREST 0x0 +# define FP_RND_ZERO 0x1 +# define FP_RND_PINF 0x2 +# define FP_RND_MINF 0x3 +# define FP_RND_MASK 0x3 + +# define _FP_DECL_EX \ + unsigned long long _fpscr __attribute__ ((unused)) = FP_RND_NEAREST + +#define FP_INIT_ROUNDMODE \ + do { \ + __asm__ __volatile__ ("mtfsf 255, %0" \ + : \ + : "f" (_fpscr)); \ + } while (0) + +# define FP_ROUNDMODE (_fpscr & FP_RND_MASK) +#endif /* !__NO_FPRS__ */ /* Define ALIASNAME as a strong alias for NAME. */ # define strong_alias(name, aliasname) _strong_alias(name, aliasname) diff --git a/libgcc/config/rs6000/t-float128 b/libgcc/config/rs6000/t-float128 new file mode 100644 index 00000000000..4145c574174 --- /dev/null +++ b/libgcc/config/rs6000/t-float128 @@ -0,0 +1,95 @@ +# Support for adding __float128 to the powerpc. + +# The standard 128-bit floating point support functions are TFmode. Most +# PowerPC targets use a long double format that has a pair of doubles to give +# you more precision, but no extra expoenent range. This long double format is +# mostly compatible with the format used by the IBM XL compilers. Some of the +# names used by the IBM double-double format use TF in them, so we rename +# all of the functions provided for the new IEEE 128-bit support. +# +# We use the TF functions in soft-fp for 128-bit floating point support, using +# sed to transform the names in the files from TF names to KF names. + +# Emulator functions from the soft-fp directory +fp128_softfp_funcs = addkf3 subkf3 mulkf3 divkf3 negkf2 \ + unordkf2 eqkf2 gekf2 lekf2 \ + extendsfkf2 extenddfkf2 trunckfsf2 trunckfdf2 \ + fixkfsi fixkfdi fixunskfsi fixunskfdi \ + floatsikf floatdikf floatunsikf floatundikf + +fp128_softfp_src = $(addsuffix -sw.c,$(fp128_softfp_funcs)) +fp128_softfp_static_obj = $(addsuffix -sw$(objext),$(fp128_softfp_funcs)) +fp128_softfp_shared_obj = $(addsuffix -sw_s$(objext),$(fp128_softfp_funcs)) +fp128_softfp_obj = $(fp128_softfp_static_obj) $(fp128_softfp_shared_obj) + +# New functions for software emulation +fp128_ppc_funcs = floattikf floatuntikf fixkfti fixunskfti \ + extendkftf2-sw trunctfkf2-sw \ + sfp-exceptions float128-ifunc + +fp128_ppc_src = $(addprefix $(srcdir)/config/rs6000/,$(addsuffix \ + .c,$(fp128_ppc_funcs))) +fp128_ppc_static_obj = $(addsuffix $(objext),$(fp128_ppc_funcs)) +fp128_ppc_shared_obj = $(addsuffix _s$(objext),$(fp128_ppc_funcs)) +fp128_ppc_obj = $(fp128_ppc_static_obj) $(fp128_ppc_shared_obj) + +# All functions +fp128_funcs = $(fp128_softfp_funcs) $(fp128_ppc_funcs) \ + $(fp128_hw_funcs) + +fp128_src = $(fp128_softfp_src) $(fp128_ppc_src) \ + $(fp128_hw_src) + +fp128_obj = $(fp128_softfp_obj) $(fp128_ppc_obj) \ + $(fp128_hw_obj) + +fp128_sed = $(srcdir)/config/rs6000/float128-sed +fp128_dep = $(fp128_sed) $(srcdir)/config/rs6000/t-float128 + +fp128_includes = $(srcdir)/soft-fp/double.h \ + $(srcdir)/soft-fp/op-1.h \ + $(srcdir)/soft-fp/op-4.h \ + $(srcdir)/soft-fp/op-common.h \ + $(srcdir)/soft-fp/single.h \ + $(srcdir)/soft-fp/extended.h \ + $(srcdir)/soft-fp/op-2.h \ + $(srcdir)/soft-fp/op-8.h \ + $(srcdir)/soft-fp/quad.h \ + $(srcdir)/soft-fp/soft-fp.h + +# Build the emulator without ISA 3.0 hardware support. +FP128_CFLAGS_SW = -Wno-type-limits -mvsx -mfloat128 \ + -mno-float128-hardware \ + -I$(srcdir)/soft-fp \ + -I$(srcdir)/config/rs6000 \ + $(FLOAT128_HW_INSNS) + +$(fp128_softfp_obj) : INTERNAL_CFLAGS += $(FP128_CFLAGS_SW) +$(fp128_ppc_obj) : INTERNAL_CFLAGS += $(FP128_CFLAGS_SW) +$(fp128_obj) : $(fp128_includes) +$(fp128_obj) : $(srcdir)/config/rs6000/quad-float128.h + +$(fp128_softfp_src) : $(srcdir)/soft-fp/$(subst -sw,,$(subst kf,tf,$@)) $(fp128_dep) + @src="$(srcdir)/soft-fp/$(subst -sw,,$(subst kf,tf,$@))"; \ + echo "Create $@"; \ + (echo "/* file created from $$src */"; \ + echo; \ + sed -f $(fp128_sed) < $$src) > $@ + +.PHONY: test clean-float128 + +test: + @echo "fp128_src:"; \ + for x in $(fp128_src); do echo " $$x"; done; \ + echo; \ + echo "fp128_obj:"; \ + for x in $(fp128_obj); do echo " $$x"; done; + +clean-float128: + rm -rf $(fp128_softfp_src) + @$(MULTICLEAN) multi-clean DO=clean-float128 + +# For now, only put it in the static library +# LIB2ADD += $(fp128_src) + +LIB2ADD_ST += $(fp128_src) diff --git a/libgcc/config/rs6000/t-float128-hw b/libgcc/config/rs6000/t-float128-hw new file mode 100644 index 00000000000..daae802189d --- /dev/null +++ b/libgcc/config/rs6000/t-float128-hw @@ -0,0 +1,24 @@ +# Support for adding __float128 hardware support to the powerpc. +# Tell the float128 functions that the ISA 3.0 hardware support can +# be compiled it to be selected via IFUNC functions. + +FLOAT128_HW_INSNS = -DFLOAT128_HW_INSNS + +# New functions for hardware support +fp128_hw_funcs = float128-hw +fp128_hw_src = $(srcdir)/config/rs6000/float128-hw.c +fp128_hw_static_obj = float128-hw$(objext) +fp128_hw_shared_obj = float128-hw_s$(objext) +fp128_hw_obj = $(fp128_hw_static_obj) $(fp128_hw_shared_obj) + +# Build the hardware support functions with appropriate hardware support +FP128_CFLAGS_HW = -Wno-type-limits -mvsx -mfloat128 \ + -mpower8-vector -mpower9-vector \ + -mfloat128-hardware \ + -I$(srcdir)/soft-fp \ + -I$(srcdir)/config/rs6000 \ + $(FLOAT128_HW_INSNS) + +$(fp128_hw_obj) : INTERNAL_CFLAGS += $(FP128_CFLAGS_HW) +$(fp128_hw_obj) : $(srcdir)/config/rs6000/t-float128-hw + diff --git a/libgcc/config/rs6000/trunctfkf2-sw.c b/libgcc/config/rs6000/trunctfkf2-sw.c new file mode 100644 index 00000000000..653866337f5 --- /dev/null +++ b/libgcc/config/rs6000/trunctfkf2-sw.c @@ -0,0 +1,49 @@ +/* Software IEEE 128-bit floating-point emulation for PowerPC. + + Copyright (C) 2016 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Michael Meissner (meissner@linux.vnet.ibm.com) + Code is based on the main soft-fp library written by: + Richard Henderson (rth@cygnus.com) and + Jakub Jelinek (jj@ultra.linux.cz). + + 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/>. */ + +/* Convert IBM long double to IEEE 128-bit floating point. */ + +#ifdef __FLOAT128_HARDWARE__ +#error "This module must not be compiled with IEEE 128-bit hardware support" +#endif + +#include "soft-fp.h" +#include "quad-float128.h" + +__float128 +__trunctfkf2_sw (__ibm128 value) +{ + __float128 ret; + + CVT_IBM128_TO_FLOAT128 (ret, value); + return ret; +} diff --git a/libgcc/configure b/libgcc/configure index 78708c7f407..7cf6e9b1979 100644 --- a/libgcc/configure +++ b/libgcc/configure @@ -4766,6 +4766,55 @@ esac ;; esac +case ${host} in +powerpc*-*-linux*) + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the PowerPC compiler can do __float128" >&5 +$as_echo_n "checking whether the PowerPC compiler can do __float128... " >&6; } +if test "${libgcc_cv_powerpc_float128+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#pragma GCC target ("vsx,float128") + __float128 add (__float128 *a) { return *a + *(a+1); } +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + libgcc_cv_powerpc_float128=yes +else + libgcc_cv_powerpc_float128=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libgcc_cv_powerpc_float128" >&5 +$as_echo "$libgcc_cv_powerpc_float128" >&6; } + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the PowerPC compiler can do hardware __float128" >&5 +$as_echo_n "checking whether the PowerPC compiler can do hardware __float128... " >&6; } +if test "${libgcc_cv_powerpc_float128_hw+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#pragma GCC target ("cpu=power9,float128,float128-hardware") + #include <sys/auxv.h> + __float128 add (__float128 a, __float128 b) + { + __float128 ret; + __asm__ ("xsaddqp %0,%1,%2" : "=v" (ret) : "v" (a), "v" (b)); + return ret; + } +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + libgcc_cv_powerpc_float128_hw=yes +else + libgcc_cv_powerpc_float128_hw=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libgcc_cv_powerpc_float128_hw" >&5 +$as_echo "$libgcc_cv_powerpc_float128_hw" >&6; } +esac + # Collect host-machine-specific information. . ${srcdir}/config.host diff --git a/libgcc/configure.ac b/libgcc/configure.ac index 9d831a76997..b96d4bca435 100644 --- a/libgcc/configure.ac +++ b/libgcc/configure.ac @@ -373,6 +373,31 @@ esac ;; esac +case ${host} in +powerpc*-*-linux*) + AC_CACHE_CHECK([whether the PowerPC compiler can do __float128], + [libgcc_cv_powerpc_float128], + [AC_COMPILE_IFELSE( + [#pragma GCC target ("vsx,float128") + __float128 add (__float128 *a) { return *a + *(a+1); }], + [libgcc_cv_powerpc_float128=yes], + [libgcc_cv_powerpc_float128=no])]) + + AC_CACHE_CHECK([whether the PowerPC compiler can do hardware __float128], + [libgcc_cv_powerpc_float128_hw], + [AC_COMPILE_IFELSE( + [#pragma GCC target ("cpu=power9,float128,float128-hardware") + #include <sys/auxv.h> + __float128 add (__float128 a, __float128 b) + { + __float128 ret; + __asm__ ("xsaddqp %0,%1,%2" : "=v" (ret) : "v" (a), "v" (b)); + return ret; + }], + [libgcc_cv_powerpc_float128_hw=yes], + [libgcc_cv_powerpc_float128_hw=no])]) +esac + # Collect host-machine-specific information. . ${srcdir}/config.host |