PowerPC: Update IEEE <-> IBM 128-bit floating point conversions. This patch changes the code for doing conversions between IEEE 128-bit floating point and IBM 128-bit extended double floating point. It moves the conversion functions to a separate file. It uses explicit __ibm128 instead of long double to allow the long double type to be set to IEEE 128-bit.
libgcc/ 2020-09-23 Michael Meissner <meiss...@linux.ibm.com> * config/rs6000/extendkftf2-sw.c: Move __float128 to __ibm128 conversion into float128-convert.h. * config/rs6000/float128-convert.h: New file. * config/rs6000/float128-hw.c: Move conversions between __float128 and __ibm128 into float128-convert.h. * config/rs6000/quad-float128.h: Move conversions between __float128 and __ibm128 into float128-convert.h. * config/rs6000/trunctfkf2-sw.c: Move __ibm128 to __float128 conversion to float128-convert.h. --- libgcc/config/rs6000/extendkftf2-sw.c | 6 +- libgcc/config/rs6000/float128-convert.h | 77 +++++++++++++++++++++++++ libgcc/config/rs6000/float128-hw.c | 11 +--- libgcc/config/rs6000/quad-float128.h | 58 ------------------- libgcc/config/rs6000/trunctfkf2-sw.c | 6 +- 5 files changed, 84 insertions(+), 74 deletions(-) create mode 100644 libgcc/config/rs6000/float128-convert.h diff --git a/libgcc/config/rs6000/extendkftf2-sw.c b/libgcc/config/rs6000/extendkftf2-sw.c index f0de1784c43..80b48c20d9c 100644 --- a/libgcc/config/rs6000/extendkftf2-sw.c +++ b/libgcc/config/rs6000/extendkftf2-sw.c @@ -38,6 +38,7 @@ #include "soft-fp.h" #include "quad-float128.h" +#include "float128-convert.h" #ifndef FLOAT128_HW_INSNS #define __extendkftf2_sw __extendkftf2 @@ -46,8 +47,5 @@ IBM128_TYPE __extendkftf2_sw (TFtype value) { - IBM128_TYPE ret; - - CVT_FLOAT128_TO_IBM128 (ret, value); - return ret; + return convert_float128_to_ibm128 (value); } diff --git a/libgcc/config/rs6000/float128-convert.h b/libgcc/config/rs6000/float128-convert.h new file mode 100644 index 00000000000..bb6b3d71889 --- /dev/null +++ b/libgcc/config/rs6000/float128-convert.h @@ -0,0 +1,77 @@ +/* Convert between IEEE 128-bit and IBM 128-bit floating point types. + Copyright (C) 2016-2020 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Michael Meissner (meiss...@linux.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/>. */ + +/* 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. + + These functions are called by the actual conversion functions called by the + compiler. This code is here to allow being built at power8 (no hardware + float128) and power9 (hardware float128) varients that is selected by an + IFUNC function. */ + +static inline __ibm128 convert_float128_to_ibm128 (__float128); +static inline __float128 convert_ibm128_to_float128 (__ibm128); + +static inline __ibm128 +convert_float128_to_ibm128 (__float128 value) +{ + double high, high_temp, low; + + high = (double) value; + if (__builtin_isnan (high) || __builtin_isinf (high)) + low = 0.0; + + else + { + 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; + } + + return __builtin_pack_ibm128 (high, low); +} + +static inline __float128 +convert_ibm128_to_float128 (__ibm128 value) +{ + double high = __builtin_unpack_ibm128 (value, 0); + double low = __builtin_unpack_ibm128 (value, 1); + + /* Handle the special cases of NAN and infinity. Similarly, 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. */ + if (__builtin_isnan (high) || __builtin_isinf (high) || low == 0.0) + return (__float128) high; + + else + return ((__float128) high) + ((__float128) low); +} diff --git a/libgcc/config/rs6000/float128-hw.c b/libgcc/config/rs6000/float128-hw.c index 8705b53e22a..b9b04cd2feb 100644 --- a/libgcc/config/rs6000/float128-hw.c +++ b/libgcc/config/rs6000/float128-hw.c @@ -33,6 +33,7 @@ #include <soft-fp.h> #include <quad-float128.h> +#include "float128-convert.h" #ifndef __FLOAT128_HARDWARE__ #error "This module must be compiled with IEEE 128-bit hardware support" @@ -190,18 +191,12 @@ __unordkf2_hw (TFtype a, TFtype b) IBM128_TYPE __extendkftf2_hw (TFtype value) { - IBM128_TYPE ret; - - CVT_FLOAT128_TO_IBM128 (ret, value); - return ret; + return convert_float128_to_ibm128 (value); } /* Convert __ibm128 to __float128. */ TFtype __trunctfkf2_hw (IBM128_TYPE value) { - TFtype ret; - - CVT_IBM128_TO_FLOAT128 (ret, value); - return ret; + return convert_ibm128_to_float128 (value); } diff --git a/libgcc/config/rs6000/quad-float128.h b/libgcc/config/rs6000/quad-float128.h index 32ef328a8ea..15880c2ab30 100644 --- a/libgcc/config/rs6000/quad-float128.h +++ b/libgcc/config/rs6000/quad-float128.h @@ -170,61 +170,3 @@ 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. */ - -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); \ -} diff --git a/libgcc/config/rs6000/trunctfkf2-sw.c b/libgcc/config/rs6000/trunctfkf2-sw.c index 3e8af25a585..af52cff5954 100644 --- a/libgcc/config/rs6000/trunctfkf2-sw.c +++ b/libgcc/config/rs6000/trunctfkf2-sw.c @@ -38,6 +38,7 @@ #include "soft-fp.h" #include "quad-float128.h" +#include "float128-convert.h" #ifndef FLOAT128_HW_INSNS #define __trunctfkf2_sw __trunctfkf2 @@ -46,8 +47,5 @@ TFtype __trunctfkf2_sw (IBM128_TYPE value) { - TFtype ret; - - CVT_IBM128_TO_FLOAT128 (ret, value); - return ret; + return convert_ibm128_to_float128 (value); } -- 2.22.0 -- Michael Meissner, IBM IBM, M/S 2506R, 550 King Street, Littleton, MA 01460-6245, USA email: meiss...@linux.ibm.com, phone: +1 (978) 899-4797