diff options
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/powerpc/divkc3-1.c | 22 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/powerpc/mulkc3-1.c | 22 | ||||
-rw-r--r-- | libgcc/ChangeLog | 9 | ||||
-rw-r--r-- | libgcc/config/rs6000/_divkc3.c | 64 | ||||
-rw-r--r-- | libgcc/config/rs6000/_mulkc3.c | 69 | ||||
-rw-r--r-- | libgcc/config/rs6000/quad-float128.h | 8 | ||||
-rw-r--r-- | libgcc/config/rs6000/t-float128 | 2 |
8 files changed, 200 insertions, 1 deletions
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 95b68598617..143a5bfc5ad 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2016-07-12 Bill Schmidt <wschmidt@linux.vnet.ibm.com> + + * gcc.target/powerpc/divkc3-1.c: New. + * gcc.target/powerpc/mulkc3-1.c: New. + 2016-07-12 Martin Liska <mliska@suse.cz> * gcc.dg/params/blocksort-part.c: New test. diff --git a/gcc/testsuite/gcc.target/powerpc/divkc3-1.c b/gcc/testsuite/gcc.target/powerpc/divkc3-1.c new file mode 100644 index 00000000000..7d9e1b1504a --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/divkc3-1.c @@ -0,0 +1,22 @@ +/* { dg-do run { target { powerpc64*-*-* && vsx_hw } } } */ +/* { dg-options "-mfloat128 -mvsx" } */ + +void abort (); + +typedef __complex float __cfloat128 __attribute__((mode(KC))); + +__cfloat128 divide (__cfloat128 x, __cfloat128 y) +{ + return x / y; +} + +__cfloat128 z, a; + +int main () +{ + z = divide (5.0q + 5.0jq, 2.0q + 1.0jq); + a = 3.0q + 1.0jq; + if (z != a) + abort (); + return 0; +} diff --git a/gcc/testsuite/gcc.target/powerpc/mulkc3-1.c b/gcc/testsuite/gcc.target/powerpc/mulkc3-1.c new file mode 100644 index 00000000000..bacc7ab058b --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/mulkc3-1.c @@ -0,0 +1,22 @@ +/* { dg-do run { target { powerpc64*-*-* && vsx_hw } } } */ +/* { dg-options "-mfloat128 -mvsx" } */ + +void abort (); + +typedef __complex float __cfloat128 __attribute__((mode(KC))); + +__cfloat128 multiply (__cfloat128 x, __cfloat128 y) +{ + return x * y; +} + +__cfloat128 z, a; + +int main () +{ + z = multiply (2.0q + 1.0jq, 3.0q + 1.0jq); + a = 5.0q + 5.0jq; + if (z != a) + abort (); + return 0; +} diff --git a/libgcc/ChangeLog b/libgcc/ChangeLog index 974ac5e5a4c..b3aaf3dc243 100644 --- a/libgcc/ChangeLog +++ b/libgcc/ChangeLog @@ -1,3 +1,12 @@ +2016-07-12 Bill Schmidt <wschmidt@linux.vnet.ibm.com> + + * config/rs6000/_divkc3.c: New. + * config/rs6000/_mulkc3.c: New. + * config/rs6000/quad-float128.h: Define TFtype; declare _mulkc3 + and _divkc3. + * config/rs6000/t-float128: Add _mulkc3 and _divkc3 to + fp128_ppc_funcs. + 2016-07-11 Hale Wang <hale.wang@arm.com> Andre Vieira <andre.simoesdiasvieira@arm.com> diff --git a/libgcc/config/rs6000/_divkc3.c b/libgcc/config/rs6000/_divkc3.c new file mode 100644 index 00000000000..9b9afd0a7b1 --- /dev/null +++ b/libgcc/config/rs6000/_divkc3.c @@ -0,0 +1,64 @@ +typedef float KFtype __attribute__ ((mode (KF))); +typedef __complex float KCtype __attribute__ ((mode (KC))); + +#define COPYSIGN(x,y) __builtin_copysignq (x, y) +#define INFINITY __builtin_infq () +#define FABS __builtin_fabsq +#define isnan __builtin_isnan +#define isinf __builtin_isinf +#define isfinite __builtin_isfinite + +KCtype +__divkc3 (KFtype a, KFtype b, KFtype c, KFtype d) +{ + KFtype denom, ratio, x, y; + KCtype res; + + /* ??? We can get better behavior from logarithmic scaling instead of + the division. But that would mean starting to link libgcc against + libm. We could implement something akin to ldexp/frexp as gcc builtins + fairly easily... */ + if (FABS (c) < FABS (d)) + { + ratio = c / d; + denom = (c * ratio) + d; + x = ((a * ratio) + b) / denom; + y = ((b * ratio) - a) / denom; + } + else + { + ratio = d / c; + denom = (d * ratio) + c; + x = ((b * ratio) + a) / denom; + y = (b - (a * ratio)) / denom; + } + + /* Recover infinities and zeros that computed as NaN+iNaN; the only cases + are nonzero/zero, infinite/finite, and finite/infinite. */ + if (isnan (x) && isnan (y)) + { + if (c == 0.0 && d == 0.0 && (!isnan (a) || !isnan (b))) + { + x = COPYSIGN (INFINITY, c) * a; + y = COPYSIGN (INFINITY, c) * b; + } + else if ((isinf (a) || isinf (b)) && isfinite (c) && isfinite (d)) + { + a = COPYSIGN (isinf (a) ? 1 : 0, a); + b = COPYSIGN (isinf (b) ? 1 : 0, b); + x = INFINITY * (a * c + b * d); + y = INFINITY * (b * c - a * d); + } + else if ((isinf (c) || isinf (d)) && isfinite (a) && isfinite (b)) + { + c = COPYSIGN (isinf (c) ? 1 : 0, c); + d = COPYSIGN (isinf (d) ? 1 : 0, d); + x = 0.0 * (a * c + b * d); + y = 0.0 * (b * c - a * d); + } + } + + __real__ res = x; + __imag__ res = y; + return res; +} diff --git a/libgcc/config/rs6000/_mulkc3.c b/libgcc/config/rs6000/_mulkc3.c new file mode 100644 index 00000000000..f89bf8c6368 --- /dev/null +++ b/libgcc/config/rs6000/_mulkc3.c @@ -0,0 +1,69 @@ +typedef float KFtype __attribute__ ((mode (KF))); +typedef __complex float KCtype __attribute__ ((mode (KC))); + +#define COPYSIGN(x,y) __builtin_copysignq (x, y) +#define INFINITY __builtin_infq () +#define isnan __builtin_isnan +#define isinf __builtin_isinf + +KCtype +__mulkc3 (KFtype a, KFtype b, KFtype c, KFtype d) +{ + KFtype ac, bd, ad, bc, x, y; + KCtype res; + + ac = a * c; + bd = b * d; + ad = a * d; + bc = b * c; + + x = ac - bd; + y = ad + bc; + + if (isnan (x) && isnan (y)) + { + /* Recover infinities that computed as NaN + iNaN. */ + _Bool recalc = 0; + if (isinf (a) || isinf (b)) + { + /* z is infinite. "Box" the infinity and change NaNs in + the other factor to 0. */ + a = COPYSIGN (isinf (a) ? 1 : 0, a); + b = COPYSIGN (isinf (b) ? 1 : 0, b); + if (isnan (c)) c = COPYSIGN (0, c); + if (isnan (d)) d = COPYSIGN (0, d); + recalc = 1; + } + if (isinf (c) || isinf (d)) + { + /* w is infinite. "Box" the infinity and change NaNs in + the other factor to 0. */ + c = COPYSIGN (isinf (c) ? 1 : 0, c); + d = COPYSIGN (isinf (d) ? 1 : 0, d); + if (isnan (a)) a = COPYSIGN (0, a); + if (isnan (b)) b = COPYSIGN (0, b); + recalc = 1; + } + if (!recalc + && (isinf (ac) || isinf (bd) + || isinf (ad) || isinf (bc))) + { + /* Recover infinities from overflow by changing NaNs to 0. */ + if (isnan (a)) a = COPYSIGN (0, a); + if (isnan (b)) b = COPYSIGN (0, b); + if (isnan (c)) c = COPYSIGN (0, c); + if (isnan (d)) d = COPYSIGN (0, d); + recalc = 1; + } + if (recalc) + { + x = INFINITY * (a * c - b * d); + y = INFINITY * (a * d + b * c); + } + } + + __real__ res = x; + __imag__ res = y; + return res; +} + diff --git a/libgcc/config/rs6000/quad-float128.h b/libgcc/config/rs6000/quad-float128.h index 62d198db20d..244a0475255 100644 --- a/libgcc/config/rs6000/quad-float128.h +++ b/libgcc/config/rs6000/quad-float128.h @@ -33,6 +33,10 @@ This define forces it to use KFmode (aka, ieee 128-bit floating point). */ #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))); + /* Force the use of the VSX instruction set. */ #if defined(_ARCH_PPC) && (!defined(__VSX__) || !defined(__FLOAT128__)) #pragma GCC target ("vsx,float128") @@ -154,6 +158,10 @@ extern TFtype __floatundikf (UDItype_ppc); 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); + /* 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. */ diff --git a/libgcc/config/rs6000/t-float128 b/libgcc/config/rs6000/t-float128 index 82dab3639ea..2c52ca64b65 100644 --- a/libgcc/config/rs6000/t-float128 +++ b/libgcc/config/rs6000/t-float128 @@ -25,7 +25,7 @@ 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 + sfp-exceptions _mulkc3 _divkc3 fp128_ppc_src = $(addprefix $(srcdir)/config/rs6000/,$(addsuffix \ .c,$(fp128_ppc_funcs))) |