123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257 |
- /* Software floating-point emulation.
- Definitions for IEEE Quad Precision on the PowerPC.
- Copyright (C) 2016-2022 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).
- However, when the compiler's default is changed so that long double is IEEE
- 128-bit floating point, we need to go back to using TFmode and TCmode. */
- #ifndef __LONG_DOUBLE_IEEE128__
- #define TF KF
- /* We also need TCtype to represent complex ieee 128-bit float for
- __mulkc3 and __divkc3. */
- typedef __complex float TCtype __attribute__ ((mode (KC)));
- #else
- typedef __complex float TCtype __attribute__ ((mode (TC)));
- #endif
- /* Force the use of the VSX instruction set. */
- #if defined(_ARCH_PPC) && (!defined(__VSX__) || !defined(__FLOAT128__))
- #pragma GCC target ("vsx,float128")
- #endif
- #include <stddef.h>
- #include <quad.h>
- #define IBM128_TYPE __ibm128
- /* 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 TFtype __powikf2_sw (TFtype, SItype_ppc);
- 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);
- #ifdef _ARCH_PPC64
- extern TFtype __floattikf_sw (TItype_ppc);
- #endif
- extern TFtype __floatunsikf_sw (USItype_ppc);
- extern TFtype __floatundikf_sw (UDItype_ppc);
- #ifdef _ARCH_PPC64
- extern TFtype __floatuntikf_sw (UTItype_ppc);
- extern TItype_ppc __fixkfti_sw (TFtype);
- extern UTItype_ppc __fixunskfti_sw (TFtype);
- #endif
- extern IBM128_TYPE __extendkftf2_sw (TFtype);
- extern TFtype __trunctfkf2_sw (IBM128_TYPE);
- extern TCtype __mulkc3_sw (TFtype, TFtype, TFtype, TFtype);
- extern TCtype __divkc3_sw (TFtype, TFtype, TFtype, TFtype);
- #ifdef _ARCH_PPC64
- 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 TFtype __powikf2_hw (TFtype, SItype_ppc);
- 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);
- #ifdef _ARCH_PPC64
- extern TFtype __floattikf_hw (TItype_ppc);
- #endif
- extern TFtype __floatunsikf_hw (USItype_ppc);
- extern TFtype __floatundikf_hw (UDItype_ppc);
- #ifdef _ARCH_PPC64
- extern TFtype __floatuntikf_hw (UTItype_ppc);
- extern TItype_ppc __fixkfti_hw (TFtype);
- extern UTItype_ppc __fixunskfti_hw (TFtype);
- #endif
- extern IBM128_TYPE __extendkftf2_hw (TFtype);
- extern TFtype __trunctfkf2_hw (IBM128_TYPE);
- extern TCtype __mulkc3_hw (TFtype, TFtype, TFtype, TFtype);
- extern TCtype __divkc3_hw (TFtype, TFtype, TFtype, TFtype);
- /* 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 TFtype __powikf2 (TFtype, SItype_ppc);
- 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);
- #ifdef _ARCH_PPC64
- extern TFtype __floattikf (TItype_ppc);
- #endif
- extern TFtype __floatunsikf (USItype_ppc);
- extern TFtype __floatundikf (UDItype_ppc);
- #ifdef _ARCH_PPC64
- extern TFtype __floatuntikf (UTItype_ppc);
- extern TItype_ppc __fixkfti (TFtype);
- extern UTItype_ppc __fixunskfti (TFtype);
- #endif
- extern IBM128_TYPE __extendkftf2 (TFtype);
- extern TFtype __trunctfkf2 (IBM128_TYPE);
- /* Complex __float128 built on __float128 interfaces. */
- extern TCtype __mulkc3 (TFtype, TFtype, TFtype, TFtype);
- extern TCtype __divkc3 (TFtype, TFtype, TFtype, TFtype);
- /* Convert IEEE 128-bit floating point to/from string. We explicitly use
- _Float128 instead of TFmode because _strtokf and _strfromkf must be compiled
- with long double being IBM 128. */
- extern _Float128 __strtokf (const char *, char **);
- extern int __strfromkf (char *restrict, size_t, const char *restrict,
- _Float128);
- /* 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. */
- union ibm128_union {
- IBM128_TYPE ibm128;
- double dbl[2];
- };
- #define CVT_FLOAT128_TO_IBM128(RESULT, VALUE) \
- { \
- double __high, __low; \
- TFtype __value = (VALUE); \
- union ibm128_union u; \
- \
- __high = (double) __value; \
- if (__builtin_isnan (__high) || __builtin_isinf (__high)) \
- __low = 0.0; \
- \
- else \
- { \
- double __high_temp; \
- \
- __low = (double) (__value - (TFtype) __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; \
- } \
- \
- u.dbl[0] = __high; \
- u.dbl[1] = __low; \
- RESULT = u.ibm128; \
- }
- #define CVT_IBM128_TO_FLOAT128(RESULT, VALUE) \
- { \
- union ibm128_union u; \
- double __high, __low; \
- \
- u.ibm128 = (VALUE); \
- __high = u.dbl[0]; \
- __low = u.dbl[1]; \
- \
- /* Handle the special cases of NAN and infinity. */ \
- if (__builtin_isnan (__high) || __builtin_isinf (__high)) \
- RESULT = (TFtype) __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 = (TFtype) __high; \
- \
- else \
- RESULT = ((TFtype) __high) + ((TFtype) __low); \
- }
|