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/config/rs6000/float128-ifunc.c | |
parent | 3342fd71e0465ab4a702480a35043b295fc6fa21 (diff) | |
download | gcc-29176d57e6be3f93551b54bd87ccc92e830a28b9.zip gcc-29176d57e6be3f93551b54bd87ccc92e830a28b9.tar.gz gcc-29176d57e6be3f93551b54bd87ccc92e830a28b9.tar.bz2 |
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/config/rs6000/float128-ifunc.c')
-rw-r--r-- | libgcc/config/rs6000/float128-ifunc.c | 358 |
1 files changed, 358 insertions, 0 deletions
diff --git a/libgcc/config/rs6000/float128-ifunc.c b/libgcc/config/rs6000/float128-ifunc.c new file mode 100644 index 0000000..6e14608 --- /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"))); |