[PATCH], Add optional IEEE/IBM long double multilib support

Michael Meissner meissner@linux.vnet.ibm.com
Thu Jan 4 23:06:00 GMT 2018


This patch is the beginning step to switching the PowerPC long double support
from IBM extended double to IEEE 128-bit floating point on PowerPC servers.  It
will be necessary to have this patch or a similar patch to allow the GLIBC team
to begin their modifications in GLIBC 2.28, so that by the time GCC 9 comes
out, we can decide to switch the default.  It is likely, the default will only
be switched on the 64-bit little endian PowerPC systems, when a distribution
goes through a major level, such that they can contemplate major changes.

If you do not use the configuration option --with-long-double-format=ieee or
--with-long-double-format=ibm, the system will not build multilibs, and just
build normal libraries with the default set to IBM extended double.  If you do
use either of the switches, and allow multilibs, it will build two sets of
multilibs, one for -mabi=ieeelongdouble and one for -mabi=ibmlongdouble.

Now, to build a compiler with multilibs, you need to do the following steps:

1) Install the IBM Advance Toolchain AT 11.0-2.

2) Clone the AT directory:
	# rsync -aH /opt/at11.0/ /opt/at11.0-ieee/

3) Go into the new directory and add a symlink from lib64 to ieee64.
Eventually once we have versions of the libraries compiled for
-mabi=ieeelongdouble, these libraries and objects would go into the ieee64
directory.  However, to do a build, you need the crt files in order to build
the shared libraries.

4) Configure the compiler with these options:
	--with-long-double-128			# should be default
	--with-cpu=power8			# or power9
	--with-long-double-format=ibm		# specify long double format
	--enable-multilib			# enable multilibs
	--with-system-libz			# do not build our own libz
	--with-advance-toolchain=at11.0-ieee	# use the special AT library
						# Use the AT library's includes
	--with-native-system-header-dir=/opt/at11.0-ieee/include
	--with-gnu-ld=/opt/at11.0-ieee/bin/ld	# specify as/ld locations
	--with-gnu-as=/opt/at11.0-ieee/bin/as
	--with-ld=/opt/at11.0-ieee/bin/ld
	--with-as=/opt/at11.0-ieee/bin/as

The libgcc changes were changes that show up when you build libgcc with the
default set to IEEE 128-bit.

There is a work around in rs6000-c.c to allow the AT 11.0-2 include files to be
used as is.  Otherwise, we need to modify /opt/at11.0/include/bits/floatn.h to
specify the correct IEEE 128-bit complex type in C++ (C++ does not support the
_Float128 keyword, and __float128 _Complex does not work, so we have to use the
mode attribute to declare the type).  When -mabi=ieeelongdouble is used, the
default Float128 types are TFmode for scalar and TCmode for complex.  With the
default -mabi=ibmlongdouble is used, the default Float128 types are KFmode and
KCmode.  It is hoped that in AT 11.0-3, we can fix floatn.h to declare the
appropriate type.

I have built bootstrap builds on a little endian power8 system without using
the --with-long-double-format switch and it runs the same as the unpatched
compiler.

I have also built bootstrap builds on a little endian power8 system with the
switches listed above, and the tests for the default long double format are the
same.  Obviously, we can't run multilib make checks until the necessary work
has been done in GLIBC.

I will do a big endian build shortly to make sure it builds normally.

What changes or additional tests do you feel I need to make before checking
this into the trunk?

[gcc]
2018-01-04  Michael Meissner  <meissner@linux.vnet.ibm.com>

	* configure.ac (--with-long-double-format): Add support for
	configuration option to change the default long double format in
	PowerPC Linux systems.
	* configure: Regenerate.
	* config.gcc (powerpc*-linux*-*): Add support for
	--with-long-double-format={ieee,ibm}.  If the format is explicit
	set, also set up IBM and IEEE multilibs.
	* config/rs6000/rs6000.h (FLOAT128_IEEE_P): Explicitly check for
	128-bit long doubles before checking TFmode or TCmode.
	(FLOAT128_IBM_P): Likewise.
	(TARGET_IEEEQUAD_MULTILIB): Set to 0 if not already defined.
	* config/rs6000/rs6000.c (rs6000_option_override_internal): If we
	have IBM/IEEE multilibs, don't give a warning if the user chagnes
	the long double format.
	(is_complex_IBM_long_double): Explicitly check for 128-bit long
	doubles before checking TCmode.
	* config/rs6000/rs6000-c.c (rs6000_cpu_cpp_builtins): If long
	double is IEEE, define __KC__ and __KF__ to allow floatn.h to be
	used without modification.
	* config/rs6000/linux64.h (MULTILIB_DEFAULTS_IEEE): Specify the
	-mabi={ieee,ibm}longdouble default for multilibs.
	(MULTILIB_DEFAULTS): Likewise.
	* config/rs6000/t-ldouble: New file, add IEEE/IBM long double
	multilibs.

[libgcc]
2018-01-04  Michael Meissner  <meissner@linux.vnet.ibm.com>

	* config/rs6000/quad-float128.h (IBM128_TYPE): Explicitly use
	__ibm128, instead of trying to use long double.
	(CVT_FLOAT128_TO_IBM128): Use TFtype instead of __float128 to
	accomidate -mabi=ieeelongdouble multilibs.
	(CVT_IBM128_TO_FLOAT128): Likewise.
	* config/rs6000/ibm-ldouble.c (IBM128_TYPE): New macro to define
	the appropriate IBM extended double type.
	(__gcc_qadd): Change all occurances of long double to IBM128_TYPE.
	(__gcc_qsub): Likewise.
	(__gcc_qmul): Likewise.
	(__gcc_qdiv): Likewise.
	(pack_ldouble): Likewise.
	(__gcc_qneg): Likewise.
	(__gcc_qeq): Likewise.
	(__gcc_qne): Likewise.
	(__gcc_qge): Likewise.
	(__gcc_qle): Likewise.
	(__gcc_stoq): Likewise.
	(__gcc_dtoq): Likewise.
	(__gcc_itoq): Likewise.
	(__gcc_utoq): Likewise.
	(__gcc_qunord): Likewise.
	* config/rs6000/_mulkc3.c (toplevel): Include soft-fp.h and
	quad-float128.h for the definitions.
	(COPYSIGN): Use the f128 version instead of the q version.
	(INFINITY): Likewise.
	(__mulkc3): Use TFmode/TCmode for float128 scalar/complex types.
	* config/rs6000/_divkc3.c (toplevel): Include soft-fp.h and
	quad-float128.h for the definitions.
	(COPYSIGN): Use the f128 version instead of the q version.
	(INFINITY): Likewise.
	(FABS): Likewise.
	(__divkc3): Use TFmode/TCmode for float128 scalar/complex types.
	* config/rs6000/extendkftf2-sw.c (__extendkftf2_sw): Likewise.
	* config/rs6000/trunctfkf2-sw.c (__trunctfkf2_sw): Likewise.

-- 
Michael Meissner, IBM
IBM, M/S 2506R, 550 King Street, Littleton, MA 01460-6245, USA
email: meissner@linux.vnet.ibm.com, phone: +1 (978) 899-4797
-------------- next part --------------
Index: gcc/configure.ac
===================================================================
--- gcc/configure.ac	(revision 256120)
+++ gcc/configure.ac	(working copy)
@@ -5885,6 +5885,30 @@ if test x$gcc_cv_target_ldbl128 = xyes; 
 	    [Define if TFmode long double should be the default])
 fi
 
+# Check if TFmode long double target should use the IBM extended double or IEEE
+# 128-bit floating point formats if long doubles are 128-bits long.  The long
+# double type can only be switched on powerpc64 bit Linux systems where VSX is
+# supported.  Other PowerPC systems do not build the IEEE 128-bit emulator in
+# liggcc.
+AC_ARG_WITH([long-double-format],
+  [AS_HELP_STRING([--with-long-double-format={ieee,ibm}]
+		  [Specify whether PowerPC long double uses IEEE or IBM format])],[
+case "$target:$with_cpu:$with_long_double_format" in
+  powerpc*-*-linux*:power[789]:ieee | powerpc*-*-linux*:power[1-9][0-9]+:ieee | \
+  powerpc*-*-linux*:power[789]:ibm | powerpc*-*-linux*:power[1-9][0-9]+:ibm | \
+  powerpc64le-*-linux*:*:ieee | powerpc64le-*-linux*:*:ibm)
+    ;;
+  powerpc*-*-linux*:power[789]:* | powerpc*-*-linux*:power[1-9][0-9]+:* | \
+  powerpc64le-*-linux*:*:*)
+    AC_MSG_ERROR([--with-long-double-format argument should be ibm or ieee])
+    ;;
+  *)
+    AC_MSG_ERROR([Configure option --with-long-double-format is only supported \
+for PowerPC VSX Linux systems])
+    ;;
+esac],
+  [])
+
 # Check if the target LIBC supports exporting the AT_PLATFORM and AT_HWCAP
 # values in the TCB.  Currently, only GLIBC 2.23 and later support this.
 gcc_cv_libc_provides_hwcap_in_tcb=no
Index: gcc/configure
===================================================================
--- gcc/configure	(revision 256120)
+++ gcc/configure	(working copy)
@@ -945,6 +945,7 @@ enable_linker_build_id
 enable_libssp
 enable_default_ssp
 with_long_double_128
+with_long_double_format
 with_gc
 with_system_zlib
 enable_maintainer_mode
@@ -1738,6 +1739,9 @@ Optional Packages:
   --with-glibc-version=M.N
                           assume GCC used with glibc version M.N or later
   --with-long-double-128  use 128-bit long double by default
+  --with-long-double-format={ieee,ibm}
+		  Specify whether PowerPC long double uses IEEE or IBM format
+
   --with-gc={page,zone}   this option is not supported anymore. It used to
                           choose the garbage collection mechanism to use with
                           the compiler
@@ -18442,7 +18446,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<_LT_EOF
-#line 18445 "configure"
+#line 18449 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -18548,7 +18552,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<_LT_EOF
-#line 18551 "configure"
+#line 18555 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -29185,6 +29189,32 @@ $as_echo "#define TARGET_DEFAULT_LONG_DO
 
 fi
 
+# Check if TFmode long double target should use the IBM extended double or IEEE
+# 128-bit floating point formats if long doubles are 128-bits long.  The long
+# double type can only be switched on powerpc64 bit Linux systems where VSX is
+# supported.  Other PowerPC systems do not build the IEEE 128-bit emulator in
+# liggcc.
+
+# Check whether --with-long-double-format was given.
+if test "${with_long_double_format+set}" = set; then :
+  withval=$with_long_double_format;
+case "$target:$with_cpu:$with_long_double_format" in
+  powerpc*-*-linux*:power789:ieee | powerpc*-*-linux*:power1-90-9+:ieee | \
+  powerpc*-*-linux*:power789:ibm | powerpc*-*-linux*:power1-90-9+:ibm | \
+  powerpc64le-*-linux*:*:ieee | powerpc64le-*-linux*:*:ibm)
+    ;;
+  powerpc*-*-linux*:power789:* | powerpc*-*-linux*:power1-90-9+:* | \
+  powerpc64le-*-linux*:*:*)
+    as_fn_error "--with-long-double-format argument should be ibm or ieee" "$LINENO" 5
+    ;;
+  *)
+    as_fn_error "Configure option --with-long-double-format is only supported \
+for PowerPC VSX Linux systems" "$LINENO" 5
+    ;;
+esac
+fi
+
+
 # Check if the target LIBC supports exporting the AT_PLATFORM and AT_HWCAP
 # values in the TCB.  Currently, only GLIBC 2.23 and later support this.
 gcc_cv_libc_provides_hwcap_in_tcb=no
Index: gcc/config.gcc
===================================================================
--- gcc/config.gcc	(revision 256120)
+++ gcc/config.gcc	(working copy)
@@ -4392,6 +4392,24 @@ case "${target}" in
 			exit 1
 		    fi
 		fi
+
+		# Set up the default long double format.  Only enable the
+		# IEEE/IBM multilibs if the user explicitly set the long double
+		# format and did not do --disable-multilib.
+		if test x$with_long_double_format = xieee; then
+		    tm_defines="${tm_defines} TARGET_IEEEQUAD_DEFAULT=1"
+		    if test x$enable_multilib = xyes; then
+			tm_defines="${tm_defines} TARGET_IEEEQUAD_MULTILIB=1"
+			tmake_file="${tmake_file} rs6000/t-ldouble"
+		    fi
+
+		elif test x$with_long_double_format = xibm; then
+		    tm_defines="${tm_defines} TARGET_IEEEQUAD_DEFAULT=0"
+		    if test x$enable_multilib = xyes; then
+			tm_defines="${tm_defines} TARGET_IEEEQUAD_MULTILIB=1"
+			tmake_file="${tmake_file} rs6000/t-ldouble"
+		    fi
+		fi
 		;;
 
 	s390*-*-*)
Index: gcc/config/rs6000/rs6000.h
===================================================================
--- gcc/config/rs6000/rs6000.h	(revision 256120)
+++ gcc/config/rs6000/rs6000.h	(working copy)
@@ -437,11 +437,13 @@ extern const char *host_detect_local_cpu
    Similarly IFmode is the IBM long double format even if the default is IEEE
    128-bit.  Don't allow IFmode if -msoft-float.  */
 #define FLOAT128_IEEE_P(MODE)						\
-  ((TARGET_IEEEQUAD && ((MODE) == TFmode || (MODE) == TCmode))		\
+  ((TARGET_IEEEQUAD && TARGET_LONG_DOUBLE_128				\
+    && ((MODE) == TFmode || (MODE) == TCmode))				\
    || ((MODE) == KFmode) || ((MODE) == KCmode))
 
 #define FLOAT128_IBM_P(MODE)						\
-  ((!TARGET_IEEEQUAD && ((MODE) == TFmode || (MODE) == TCmode))		\
+  ((!TARGET_IEEEQUAD && TARGET_LONG_DOUBLE_128				\
+    && ((MODE) == TFmode || (MODE) == TCmode))				\
    || (TARGET_HARD_FLOAT && ((MODE) == IFmode || (MODE) == ICmode)))
 
 /* Helper macros to say whether a 128-bit floating point type can go in a
@@ -562,6 +564,12 @@ extern int rs6000_vector_align[];
 #define TARGET_ALTIVEC_ABI rs6000_altivec_abi
 #define TARGET_LDBRX (TARGET_POPCNTD || rs6000_cpu == PROCESSOR_CELL)
 
+/* Define as 1 if we support multilibs for switching long double between IEEE
+   128-bit floating point and IBM extended double.  */
+#ifndef TARGET_IEEEQUAD_MULTILIB
+#define TARGET_IEEEQUAD_MULTILIB 0
+#endif
+
 /* ISA 2.01 allowed FCFID to be done in 32-bit, previously it was 64-bit only.
    Enable 32-bit fcfid's on any of the switches for newer ISA machines or
    XILINX.  */
Index: gcc/config/rs6000/rs6000.c
===================================================================
--- gcc/config/rs6000/rs6000.c	(revision 256120)
+++ gcc/config/rs6000/rs6000.c	(working copy)
@@ -4600,11 +4600,15 @@ rs6000_option_override_internal (bool gl
      systems will also set long double to be IEEE 128-bit.  AIX and Darwin
      explicitly redefine TARGET_IEEEQUAD and TARGET_IEEEQUAD_DEFAULT to 0, so
      those systems will not pick up this default.  Warn if the user changes the
-     default unless -Wno-psabi.  */
+     default unless either the user used the -Wno-psabi option, or the compiler
+     was built to enable multilibs to switch between the two long double
+     types.  */
   if (!global_options_set.x_rs6000_ieeequad)
     rs6000_ieeequad = TARGET_IEEEQUAD_DEFAULT;
 
-  else if (rs6000_ieeequad != TARGET_IEEEQUAD_DEFAULT && TARGET_LONG_DOUBLE_128)
+  else if (!TARGET_IEEEQUAD_MULTILIB
+	   && rs6000_ieeequad != TARGET_IEEEQUAD_DEFAULT
+	   && TARGET_LONG_DOUBLE_128)
     {
       static bool warned_change_long_double;
       if (!warned_change_long_double)
@@ -11424,7 +11428,9 @@ rs6000_must_pass_in_stack (machine_mode 
 static inline bool
 is_complex_IBM_long_double (machine_mode mode)
 {
-  return mode == ICmode || (!TARGET_IEEEQUAD && mode == TCmode);
+  return mode == ICmode || (!TARGET_IEEEQUAD
+			    && TARGET_LONG_DOUBLE_128
+			    && mode == TCmode);
 }
 
 /* Whether ABI_V4 passes MODE args to a function in floating point
Index: gcc/config/rs6000/rs6000-c.c
===================================================================
--- gcc/config/rs6000/rs6000-c.c	(revision 256120)
+++ gcc/config/rs6000/rs6000-c.c	(working copy)
@@ -708,7 +708,18 @@ rs6000_cpu_cpp_builtins (cpp_reader *pfi
       builtin_define ("__LONGDOUBLE128");
 
       if (TARGET_IEEEQUAD)
-	builtin_define ("__LONG_DOUBLE_IEEE128__");
+	{
+	  /* Older versions of GLIBC used __attribute__((__KC__)) to create the
+	     IEEE 128-bit floating point complex type for C++ (which does not
+	     support _Float128 _Complex).  If the default for long double is
+	     IEEE 128-bit mode, the library would need to use
+	     __attribute__((__TC__)) instead.  Defining __KF__ and __KC__
+	     is a stop-gap to build with the older libraries, until we
+	     get an updated library.  */
+	  builtin_define ("__LONG_DOUBLE_IEEE128__");
+	  builtin_define ("__KF__=__TF__");
+	  builtin_define ("__KC__=__TC__");
+	}
       else
 	builtin_define ("__LONG_DOUBLE_IBM128__");
     }
Index: gcc/config/rs6000/linux64.h
===================================================================
--- gcc/config/rs6000/linux64.h	(revision 256120)
+++ gcc/config/rs6000/linux64.h	(working copy)
@@ -245,11 +245,23 @@ extern int dot_symbols;
 #define DYNAMIC_LINKER_PREFIX	""
 #endif
 
+#if TARGET_IEEEQUAD_MULTILIB
+#if TARGET_IEEEQUAD_DEFAULT
+#define MULTILIB_DEFAULTS_IEEE , "mabi=ieeelongdouble"
+
+#else	/* TARGET_IEEEQUAD_DEFAULT.  */
+#define MULTILIB_DEFAULTS_IEEE , "mabi=ibmlongdouble"
+#endif	/* TARGET_IEEEQUAD_DEFAULT.  */
+
+#else	/* TARGET_IEEEQUAD_MULTILIB.  */
+#define MULTILIB_DEFAULTS_IEEE
+#endif	/* TARGET_IEEEQUAD_MULTILIB.  */
+
 #undef	MULTILIB_DEFAULTS
 #if DEFAULT_ARCH64_P
-#define MULTILIB_DEFAULTS { "m64" }
+#define MULTILIB_DEFAULTS { "m64" MULTILIB_DEFAULTS_IEEE }
 #else
-#define MULTILIB_DEFAULTS { "m32" }
+#define MULTILIB_DEFAULTS { "m32" MULTILIB_DEFAULTS_IEEE }
 #endif
 
 /* Split stack is only supported for 64 bit, and requires glibc >= 2.18.  */
Index: gcc/config/rs6000/t-ldouble
===================================================================
--- gcc/config/rs6000/t-ldouble	(revision 0)
+++ gcc/config/rs6000/t-ldouble	(revision 0)
@@ -0,0 +1,24 @@
+# Copyright (C) 2017 Free Software Foundation, Inc.
+#
+# This file is part of GCC.
+#
+# GCC 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.
+#
+# GCC 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.
+#
+# You should have received a copy of the GNU General Public License
+# along with GCC; see the file COPYING3.  If not see
+# <http://www.gnu.org/licenses/>.
+
+# Enable building IEEE 128-bit floating point multilibs on a system that
+# defaults to IBM extended double floating point.
+MULTILIB_OPTIONS        += mabi=ibmlongdouble/mabi=ieeelongdouble
+MULTILIB_DIRNAMES       += ibm128 ieee128
+MULTILIB_OSDIRNAMES     += mabi.ibmlongdouble=../lib64 mabi.ieeelongdouble=../ieee64 ../lib64
+
Index: libgcc/config/rs6000/quad-float128.h
===================================================================
--- libgcc/config/rs6000/quad-float128.h	(revision 256120)
+++ libgcc/config/rs6000/quad-float128.h	(working copy)
@@ -51,12 +51,7 @@ typedef __complex float TCtype __attribu
 
 #include <quad.h>
 
-#ifdef __LONG_DOUBLE_IEEE128__
-#define IBM128_TYPE		__ibm128
-
-#else
-#define IBM128_TYPE		long double
-#endif
+#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,
@@ -185,7 +180,7 @@ union ibm128_union {
 #define CVT_FLOAT128_TO_IBM128(RESULT, VALUE)				\
 {									\
   double __high, __low;							\
-  __float128 __value = (VALUE);						\
+  TFtype __value = (VALUE);						\
   union ibm128_union u;							\
 									\
   __high = (double) __value;						\
@@ -196,7 +191,7 @@ union ibm128_union {
     {									\
       double __high_temp;						\
 									\
-      __low = (double) (__value - (__float128) __high);			\
+      __low = (double) (__value - (TFtype) __high);			\
       /* Renormalize low/high and move them into canonical IBM long	\
 	 double form.  */						\
       __high_temp = __high + __low;					\
@@ -220,13 +215,13 @@ union ibm128_union {
 									\
   /* Handle the special cases of NAN and infinity.  */			\
   if (__builtin_isnan (__high) || __builtin_isinf (__high))		\
-    RESULT = (__float128) __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 = (__float128) __high;					\
+    RESULT = (TFtype) __high;						\
 									\
   else									\
-    RESULT = ((__float128) __high) + ((__float128) __low);		\
+    RESULT = ((TFtype) __high) + ((TFtype) __low);			\
 }
Index: libgcc/config/rs6000/ibm-ldouble.c
===================================================================
--- libgcc/config/rs6000/ibm-ldouble.c	(revision 256120)
+++ libgcc/config/rs6000/ibm-ldouble.c	(working copy)
@@ -56,6 +56,15 @@ see the files COPYING3 and COPYING.RUNTI
 
 #define nonfinite(a) unlikely (! isless (fabs (a), inf ()))
 
+/* If we have __float128/_Float128, use __ibm128 instead of long double.  On
+   other systems, use long double, because __ibm128 might not have been
+   created.  */
+#ifdef __FLOAT128__
+#define IBM128_TYPE __ibm128
+#else
+#define IBM128_TYPE long double
+#endif
+
 /* Define ALIASNAME as a strong alias for NAME.  */
 # define strong_alias(name, aliasname) _strong_alias(name, aliasname)
 # define _strong_alias(name, aliasname) \
@@ -65,10 +74,10 @@ see the files COPYING3 and COPYING.RUNTI
    but GCC currently generates poor code when a union is used to turn
    a long double into a pair of doubles.  */
 
-long double __gcc_qadd (double, double, double, double);
-long double __gcc_qsub (double, double, double, double);
-long double __gcc_qmul (double, double, double, double);
-long double __gcc_qdiv (double, double, double, double);
+IBM128_TYPE __gcc_qadd (double, double, double, double);
+IBM128_TYPE __gcc_qsub (double, double, double, double);
+IBM128_TYPE __gcc_qmul (double, double, double, double);
+IBM128_TYPE __gcc_qdiv (double, double, double, double);
 
 #if defined __ELF__ && defined SHARED \
     && (defined __powerpc64__ || !(defined __linux__ || defined __gnu_hurd__))
@@ -88,17 +97,17 @@ __asm__ (".symver __gcc_qadd,_xlqadd@GCC
 	 ".symver .__gcc_qdiv,._xlqdiv@GCC_3.4");
 #endif
 
-/* Combine two 'double' values into one 'long double' and return the result.  */
-static inline long double
+/* Combine two 'double' values into one 'IBM128_TYPE' and return the result.  */
+static inline IBM128_TYPE
 pack_ldouble (double dh, double dl)
 {
-#if defined (__LONG_DOUBLE_128__) \
+#if defined (__LONG_DOUBLE_128__) && defined (__LONG_DOUBLE_IBM128__)	\
     && !(defined (_SOFT_FLOAT) || defined (__NO_FPRS__))
   return __builtin_pack_longdouble (dh, dl);
 #else
   union
   {
-    long double ldval;
+    IBM128_TYPE ldval;
     double dval[2];
   } x;
   x.dval[0] = dh;
@@ -107,8 +116,8 @@ pack_ldouble (double dh, double dl)
 #endif
 }
 
-/* Add two 'long double' values and return the result.	*/
-long double
+/* Add two 'IBM128_TYPE' values and return the result.	*/
+IBM128_TYPE
 __gcc_qadd (double a, double aa, double c, double cc)
 {
   double xh, xl, z, q, zz;
@@ -147,7 +156,7 @@ __gcc_qadd (double a, double aa, double 
   return pack_ldouble (xh, xl);
 }
 
-long double
+IBM128_TYPE
 __gcc_qsub (double a, double b, double c, double d)
 {
   return __gcc_qadd (a, b, -c, -d);
@@ -157,7 +166,7 @@ __gcc_qsub (double a, double b, double c
 static double fmsub (double, double, double);
 #endif
 
-long double
+IBM128_TYPE
 __gcc_qmul (double a, double b, double c, double d)
 {
   double xh, xl, t, tau, u, v, w;
@@ -181,7 +190,7 @@ __gcc_qmul (double a, double b, double c
   tau += v + w;	    /* Add in other second-order terms.	 */
   u = t + tau;
 
-  /* Construct long double result.  */
+  /* Construct IBM128_TYPE result.  */
   if (nonfinite (u))
     return u;
   xh = u;
@@ -189,7 +198,7 @@ __gcc_qmul (double a, double b, double c
   return pack_ldouble (xh, xl);
 }
 
-long double
+IBM128_TYPE
 __gcc_qdiv (double a, double b, double c, double d)
 {
   double xh, xl, s, sigma, t, tau, u, v, w;
@@ -226,7 +235,7 @@ __gcc_qdiv (double a, double b, double c
   tau = ((v-sigma)+w)/c;   /* Correction to t.  */
   u = t + tau;
 
-  /* Construct long double result.  */
+  /* Construct IBM128_TYPE result.  */
   if (nonfinite (u))
     return u;
   xh = u;
@@ -236,32 +245,32 @@ __gcc_qdiv (double a, double b, double c
 
 #if defined (_SOFT_DOUBLE) && defined (__LONG_DOUBLE_128__)
 
-long double __gcc_qneg (double, double);
+IBM128_TYPE __gcc_qneg (double, double);
 int __gcc_qeq (double, double, double, double);
 int __gcc_qne (double, double, double, double);
 int __gcc_qge (double, double, double, double);
 int __gcc_qle (double, double, double, double);
-long double __gcc_stoq (float);
-long double __gcc_dtoq (double);
+IBM128_TYPE __gcc_stoq (float);
+IBM128_TYPE __gcc_dtoq (double);
 float __gcc_qtos (double, double);
 double __gcc_qtod (double, double);
 int __gcc_qtoi (double, double);
 unsigned int __gcc_qtou (double, double);
-long double __gcc_itoq (int);
-long double __gcc_utoq (unsigned int);
+IBM128_TYPE __gcc_itoq (int);
+IBM128_TYPE __gcc_utoq (unsigned int);
 
 extern int __eqdf2 (double, double);
 extern int __ledf2 (double, double);
 extern int __gedf2 (double, double);
 
-/* Negate 'long double' value and return the result.	*/
-long double
+/* Negate 'IBM128_TYPE' value and return the result.	*/
+IBM128_TYPE
 __gcc_qneg (double a, double aa)
 {
   return pack_ldouble (-a, -aa);
 }
 
-/* Compare two 'long double' values for equality.  */
+/* Compare two 'IBM128_TYPE' values for equality.  */
 int
 __gcc_qeq (double a, double aa, double c, double cc)
 {
@@ -272,7 +281,7 @@ __gcc_qeq (double a, double aa, double c
 
 strong_alias (__gcc_qeq, __gcc_qne);
 
-/* Compare two 'long double' values for less than or equal.  */
+/* Compare two 'IBM128_TYPE' values for less than or equal.  */
 int
 __gcc_qle (double a, double aa, double c, double cc)
 {
@@ -283,7 +292,7 @@ __gcc_qle (double a, double aa, double c
 
 strong_alias (__gcc_qle, __gcc_qlt);
 
-/* Compare two 'long double' values for greater than or equal.  */
+/* Compare two 'IBM128_TYPE' values for greater than or equal.  */
 int
 __gcc_qge (double a, double aa, double c, double cc)
 {
@@ -294,35 +303,35 @@ __gcc_qge (double a, double aa, double c
 
 strong_alias (__gcc_qge, __gcc_qgt);
 
-/* Convert single to long double.  */
-long double
+/* Convert single to IBM128_TYPE.  */
+IBM128_TYPE
 __gcc_stoq (float a)
 {
   return pack_ldouble ((double) a, 0.0);
 }
 
-/* Convert double to long double.  */
-long double
+/* Convert double to IBM128_TYPE.  */
+IBM128_TYPE
 __gcc_dtoq (double a)
 {
   return pack_ldouble (a, 0.0);
 }
 
-/* Convert long double to single.  */
+/* Convert IBM128_TYPE to single.  */
 float
 __gcc_qtos (double a, double aa __attribute__ ((__unused__)))
 {
   return (float) a;
 }
 
-/* Convert long double to double.  */
+/* Convert IBM128_TYPE to double.  */
 double
 __gcc_qtod (double a, double aa __attribute__ ((__unused__)))
 {
   return a;
 }
 
-/* Convert long double to int.  */
+/* Convert IBM128_TYPE to int.  */
 int
 __gcc_qtoi (double a, double aa)
 {
@@ -330,7 +339,7 @@ __gcc_qtoi (double a, double aa)
   return (int) z;
 }
 
-/* Convert long double to unsigned int.  */
+/* Convert IBM128_TYPE to unsigned int.  */
 unsigned int
 __gcc_qtou (double a, double aa)
 {
@@ -338,15 +347,15 @@ __gcc_qtou (double a, double aa)
   return (unsigned int) z;
 }
 
-/* Convert int to long double.  */
-long double
+/* Convert int to IBM128_TYPE.  */
+IBM128_TYPE
 __gcc_itoq (int a)
 {
   return __gcc_dtoq ((double) a);
 }
 
-/* Convert unsigned int to long double.  */
-long double
+/* Convert unsigned int to IBM128_TYPE.  */
+IBM128_TYPE
 __gcc_utoq (unsigned int a)
 {
   return __gcc_dtoq ((double) a);
@@ -361,7 +370,7 @@ int __gcc_qunord (double, double, double
 extern int __eqdf2 (double, double);
 extern int __unorddf2 (double, double);
 
-/* Compare two 'long double' values for unordered.  */
+/* Compare two 'IBM128_TYPE' values for unordered.  */
 int
 __gcc_qunord (double a, double aa, double c, double cc)
 {
@@ -389,7 +398,7 @@ fmsub (double a, double b, double c)
     FP_DECL_Q(V);
     FP_DECL_D(R);
     double r;
-    long double u, x, y, z;
+    IBM128_TYPE u, x, y, z;
 
     FP_INIT_ROUNDMODE;
     FP_UNPACK_RAW_D (A, a);
Index: libgcc/config/rs6000/_mulkc3.c
===================================================================
--- libgcc/config/rs6000/_mulkc3.c	(revision 256120)
+++ libgcc/config/rs6000/_mulkc3.c	(working copy)
@@ -23,11 +23,11 @@ see the files COPYING3 and COPYING.RUNTI
 
 /* This is a temporary specialization of code from libgcc/libgcc2.c.  */
 
-typedef float KFtype __attribute__ ((mode (KF)));
-typedef __complex float KCtype __attribute__ ((mode (KC)));
+#include "soft-fp.h"
+#include "quad-float128.h"
 
-#define COPYSIGN(x,y) __builtin_copysignq (x, y)
-#define INFINITY __builtin_infq ()
+#define COPYSIGN(x,y) __builtin_copysignf128 (x, y)
+#define INFINITY __builtin_inff128 ()
 #define isnan __builtin_isnan
 #define isinf __builtin_isinf
 
@@ -35,13 +35,11 @@ typedef __complex float KCtype __attribu
 #define __mulkc3 __mulkc3_sw
 #endif
 
-extern KCtype __mulkc3 (KFtype, KFtype, KFtype, KFtype);
-
-KCtype
-__mulkc3 (KFtype a, KFtype b, KFtype c, KFtype d)
+TCtype
+__mulkc3 (TFtype a, TFtype b, TFtype c, TFtype d)
 {
-  KFtype ac, bd, ad, bc, x, y;
-  KCtype res;
+  TFtype ac, bd, ad, bc, x, y;
+  TCtype res;
 
   ac = a * c;
   bd = b * d;
Index: libgcc/config/rs6000/_divkc3.c
===================================================================
--- libgcc/config/rs6000/_divkc3.c	(revision 256120)
+++ libgcc/config/rs6000/_divkc3.c	(working copy)
@@ -23,12 +23,12 @@ see the files COPYING3 and COPYING.RUNTI
 
 /* This is a temporary specialization of code from libgcc/libgcc2.c.  */
 
-typedef float KFtype __attribute__ ((mode (KF)));
-typedef __complex float KCtype __attribute__ ((mode (KC)));
+#include "soft-fp.h"
+#include "quad-float128.h"
 
-#define COPYSIGN(x,y) __builtin_copysignq (x, y)
-#define INFINITY __builtin_infq ()
-#define FABS __builtin_fabsq
+#define COPYSIGN(x,y) __builtin_copysignf128 (x, y)
+#define INFINITY __builtin_inff128 ()
+#define FABS __builtin_fabsf128
 #define isnan __builtin_isnan
 #define isinf __builtin_isinf
 #define isfinite __builtin_isfinite
@@ -37,13 +37,11 @@ typedef __complex float KCtype __attribu
 #define __divkc3 __divkc3_sw
 #endif
 
-extern KCtype __divkc3 (KFtype, KFtype, KFtype, KFtype);
-
-KCtype
-__divkc3 (KFtype a, KFtype b, KFtype c, KFtype d)
+TCtype
+__divkc3 (TFtype a, TFtype b, TFtype c, TFtype d)
 {
-  KFtype denom, ratio, x, y;
-  KCtype res;
+  TFtype denom, ratio, x, y;
+  TCtype res;
 
   /* ??? We can get better behavior from logarithmic scaling instead of
      the division.  But that would mean starting to link libgcc against
Index: libgcc/config/rs6000/extendkftf2-sw.c
===================================================================
--- libgcc/config/rs6000/extendkftf2-sw.c	(revision 256120)
+++ libgcc/config/rs6000/extendkftf2-sw.c	(working copy)
@@ -44,7 +44,7 @@
 #endif
 
 IBM128_TYPE
-__extendkftf2_sw (__float128 value)
+__extendkftf2_sw (TFtype value)
 {
   IBM128_TYPE ret;
 
Index: libgcc/config/rs6000/trunctfkf2-sw.c
===================================================================
--- libgcc/config/rs6000/trunctfkf2-sw.c	(revision 256120)
+++ libgcc/config/rs6000/trunctfkf2-sw.c	(working copy)
@@ -43,10 +43,10 @@
 #define __trunctfkf2_sw __trunctfkf2
 #endif
 
-__float128
+TFtype
 __trunctfkf2_sw (IBM128_TYPE value)
 {
-  __float128 ret;
+  TFtype ret;
 
   CVT_IBM128_TO_FLOAT128 (ret, value);
   return ret;


More information about the Gcc-patches mailing list