diff mbox

, PowerPC IEEE 128-bit patch #8 (libgcc bits, revised)

Message ID 20151114000223.GA14976@ibm-tiger.the-meissners.org
State New
Headers show

Commit Message

Michael Meissner Nov. 14, 2015, 12:02 a.m. UTC
This patch should address the following IEEE problems with the libgcc emulator
with exceptions, etc.  Steve is working on patches to libdfp for Decimal
conversions.

When the PowerPC support for __builtin_cpu_is ("...") and
__builtin_cpu_supports ("...") go in, we will add support using IFUNC to
automatically switch between the software emulation functions in this patch,
and functions that use the PowerPC ISA 3.0 instructions.

This passes the bootstrap and regression tests (including the 2 test cases
added as part of IEEE 128-bit patch #9).  Is it ok to check into the trunk?

[gcc]
2015-11-13  Michael Meissner  <meissner@linux.vnet.ibm.com>

	* config/rs6000/rs6000.c (init_float128_ieee): Only initialize
	cmp_optab, not ucmp_optab.
	(rs6000_generate_compare): Use the standard comparison functions
	(eqkf2, gekf2, lekf2) for normal comparisons.  Call __cmpukf2 for
	IEEE comparisons where NaN is handled specially.

[libgcc]
2015-11-13  Michael Meissner  <meissner@linux.vnet.ibm.com>
	    Steve Munro <sjmunroe@us.ibm.com>
	    Tulio Magno Quites Machado Filho <tulioqm@br.ibm.com>

	<patch ieee #8>
	* Makefile.in (EXTRA_CLEAN): New variable of additional files to
	clean.
	(FLAGS_TO_PASS): Add EXTRA_CLEAN.
	(clean): Delete EXTRA_CLEAN files.

	* configure.ac (powerpc*-*-linux*): If the compiler is capable of
	generating __float128 code, build the __float128 emulation
	libraries.
	* configure: Regenerate.

	* config/rs6000/sfp-exceptions.c: New files for IEEE 128-bit
	floating point support.
	* config/rs6000/floattikf.c: Likewise.
	* config/rs6000/libgcc/config/rs6000/extendkftf2.c: Likewise.
	* config/rs6000/libgcc/config/rs6000/trunctfkf2.c: Likewise.
	* config/rs6000/libgcc/config/rs6000/fixunskfti.c: Likewise.
	* config/rs6000/libgcc/config/rs6000/fixkfti.c: Likewise.
	* config/rs6000/libgcc/config/rs6000/cmpukf2.c: Likewise.
	* config/rs6000/libgcc/config/rs6000/floatuntikf.c: Likewise.
	* config/rs6000/libgcc/config/rs6000/quad-float128.h: Likewise.
	* config/rs6000/libgcc/config/rs6000/t-float128: Likewise.
	* config/rs6000/libgcc/config/rs6000/float128-sed: Likewise.

	* config/rs6000/sfp-machine.h (_FP_W_TYPE_SIZE): Update
	defintiions to use 64-bit types for 64-bit systems or 32-bit VSX
	systems with IEEE 128-bit floating point support.
	(_FP_W_TYPE): Likewise.
	(_FP_WS_TYPE): Likewise.
	(_FP_I_TYPE): Likewise.
	(TItype): Add defintions for IEEE 128-bit floating point support.
	(UTItype): Likewise.
	(TI_BITS): Likewise.
	(_FP_MUL_MEAT_Q): Use 64-bit types on 64-bit systems and for
	32-bit VSX systems with IEEE 128-bit floating point.
	(_FP_DIV_MEAT_Q): Likewise.
	(_FP_NANFRAC_Q): Likewise.

Comments

Joseph Myers Nov. 16, 2015, 11:06 p.m. UTC | #1
On Fri, 13 Nov 2015, Michael Meissner wrote:

> This patch should address the following IEEE problems with the libgcc emulator
> with exceptions, etc.  Steve is working on patches to libdfp for Decimal
> conversions.

Are the libgcc2.c functions for KFmode and the corresponding complex mode 
KCmode (__divkc3 __mulkc3 __powikf2) also planned for GCC 6?

> 	* config/rs6000/sfp-machine.h (_FP_W_TYPE_SIZE): Update
> 	defintiions to use 64-bit types for 64-bit systems or 32-bit VSX
> 	systems with IEEE 128-bit floating point support.
> 	(_FP_W_TYPE): Likewise.
> 	(_FP_WS_TYPE): Likewise.
> 	(_FP_I_TYPE): Likewise.
> 	(TItype): Add defintions for IEEE 128-bit floating point support.
> 	(UTItype): Likewise.
> 	(TI_BITS): Likewise.
> 	(_FP_MUL_MEAT_Q): Use 64-bit types on 64-bit systems and for
> 	32-bit VSX systems with IEEE 128-bit floating point.
> 	(_FP_DIV_MEAT_Q): Likewise.
> 	(_FP_NANFRAC_Q): Likewise.

This ChangeLog entry doesn't seem to have been updated for the exceptions 
/ rounding modes support.

> +#define ISA_BIT(x) (1 << (63 - x))

I think all the new sfp-machine.h code for integration with hardware 
exceptions and rounding modes needs to be conditional on hard-float + 
FPRs, so it doesn't affect building for SFmode / DFmode for soft-float / 
e500.

> +  /* First do the unordered comparison.  */
> +  FP_CMP_UNORD_Q (r, A, B, 1);
> +  if (r)
> +    r2 = PPC_UNORDERED;
> +
> +  else
> +    {
> +      /* If the value is not unordered, do the normal comparison.  */
> +      FP_CMP_Q (r, A, B, 2, 2);
> +      if (r == CMP_INVALID)
> +	FP_SET_EXCEPTION (FP_EX_INVALID);
> +
> +      r2 = ((r < CMP_LOW || r > CMP_HIGH)
> +	    ? PPC_UNORDERED
> +	    : ppc_cr_map[r-CMP_LOW]);

This may be correct, but it's overly complicated.  All the handling in the 
"else" case for exceptions / unordered is dead code, since in that case 
you know that the values aren't unordered.  And you can more simply do

  FP_CMP_Q (r, A, B, 2, 1);

at which point "invalid" has been raised if appropriate (for signaling 
NaNs but not for other arguments), and r contains one of the values -1, 0, 
1, 2, which you can map directly to the appropriate return value.
diff mbox

Patch

Index: gcc/config/rs6000/rs6000.c
===================================================================
--- gcc/config/rs6000/rs6000.c	(revision 230347)
+++ gcc/config/rs6000/rs6000.c	(working copy)
@@ -16560,8 +16560,7 @@  init_float128_ieee (machine_mode mode)
       set_optab_libfunc (lt_optab, mode, "__ltkf2");
       set_optab_libfunc (le_optab, mode, "__lekf2");
       set_optab_libfunc (unord_optab, mode, "__unordkf2");
-      set_optab_libfunc (cmp_optab, mode, "__cmpokf2");		/* fcmpo */
-      set_optab_libfunc (ucmp_optab, mode, "__cmpukf2");	/* fcmpu */
+      set_optab_libfunc (cmp_optab, mode, "__cmpukf2");
 
       set_conv_libfunc (sext_optab, mode, SFmode, "__extendsfkf2");
       set_conv_libfunc (sext_optab, mode, DFmode, "__extenddfkf2");
@@ -20569,12 +20568,11 @@  rs6000_generate_compare (rtx cmp, machin
      instructions.  */
   else if (!TARGET_FLOAT128_HW && FLOAT128_IEEE_P (mode))
     {
-      rtx and_reg = gen_reg_rtx (SImode);
       rtx dest = gen_reg_rtx (SImode);
-      rtx libfunc = optab_libfunc (ucmp_optab, mode);
+      rtx libfunc = NULL_RTX;
       HOST_WIDE_INT mask_value = 0;
 
-      /* Values that __cmpokf2/__cmpukf2 returns.  */
+      /* Values that __cmpukf2 returns.  */
 #define PPC_CMP_UNORDERED	0x1		/* isnan (a) || isnan (b).  */
 #define PPC_CMP_EQUAL		0x2		/* a == b.  */
 #define PPC_CMP_GREATER_THEN	0x4		/* a > b.  */
@@ -20582,84 +20580,83 @@  rs6000_generate_compare (rtx cmp, machin
 
       switch (code)
 	{
+	/* Normal comparisons use __eqkf2, __gekf2, __lekf2.  */
 	case EQ:
-	  mask_value = PPC_CMP_EQUAL;
-	  code = NE;
-	  break;
-
 	case NE:
-	  mask_value = PPC_CMP_EQUAL;
-	  code = EQ;
+	  libfunc = optab_libfunc (eq_optab, mode);
 	  break;
 
 	case GT:
-	  mask_value = PPC_CMP_GREATER_THEN;
-	  code = NE;
-	  break;
-
 	case GE:
-	  mask_value = PPC_CMP_GREATER_THEN | PPC_CMP_EQUAL;
-	  code = NE;
+	  libfunc = optab_libfunc (ge_optab, mode);
 	  break;
 
 	case LT:
-	  mask_value = PPC_CMP_LESS_THEN;
-	  code = NE;
-	  break;
-
 	case LE:
-	  mask_value = PPC_CMP_LESS_THEN | PPC_CMP_EQUAL;
-	  code = NE;
+	  libfunc = optab_libfunc (le_optab, mode);
 	  break;
 
 	case UNLE:
+	  libfunc = optab_libfunc (cmp_optab, mode);
 	  mask_value = PPC_CMP_GREATER_THEN;
 	  code = EQ;
 	  break;
 
+	  /* IEEE comparisons that do not trap on NaN, call __cmpukf2 and
+	     return 4 bits for LT, EQ, GT, and Unordered.  */
 	case UNLT:
+	  libfunc = optab_libfunc (cmp_optab, mode);
 	  mask_value = PPC_CMP_GREATER_THEN | PPC_CMP_EQUAL;
 	  code = EQ;
 	  break;
 
 	case UNGE:
+	  libfunc = optab_libfunc (cmp_optab, mode);
 	  mask_value = PPC_CMP_LESS_THEN;
 	  code = EQ;
 	  break;
 
 	case UNGT:
+	  libfunc = optab_libfunc (cmp_optab, mode);
 	  mask_value = PPC_CMP_LESS_THEN | PPC_CMP_EQUAL;
 	  code = EQ;
 	  break;
 
 	case UNEQ:
+	  libfunc = optab_libfunc (cmp_optab, mode);
 	  mask_value = PPC_CMP_EQUAL | PPC_CMP_UNORDERED;
 	  code = NE;
 
 	case LTGT:
+	  libfunc = optab_libfunc (cmp_optab, mode);
 	  mask_value = PPC_CMP_EQUAL | PPC_CMP_UNORDERED;
 	  code = EQ;
 	  break;
 
 	case UNORDERED:
-	  mask_value = PPC_CMP_UNORDERED;
-	  code = NE;
-	  break;
-
 	case ORDERED:
-	  mask_value = PPC_CMP_UNORDERED;
-	  code = EQ;
+	  libfunc = optab_libfunc (unord_optab, mode);
+	  code = (code == UNORDERED) ? NE : EQ;
 	  break;
 
 	default:
 	  gcc_unreachable ();
 	}
 
-      gcc_assert (mask_value != 0);
-      and_reg = emit_library_call_value (libfunc, and_reg, LCT_CONST, SImode, 2,
-					 op0, mode, op1, mode);
+      gcc_assert (libfunc != NULL_RTX);
+      dest = emit_library_call_value (libfunc, dest, LCT_CONST, SImode, 2,
+				      op0, mode, op1, mode);
+
+      /* If this is an IEEE comparison, see if the particular bits that we are
+	 interested are set.  */
+      if (mask_value != 0)
+	{
+	  rtx dest2 = gen_reg_rtx (SImode);
+
+	  emit_insn (gen_andsi3 (dest2, dest, GEN_INT (mask_value)));
+	  dest = dest2;
+	}
 
-      emit_insn (gen_andsi3 (dest, and_reg, GEN_INT (mask_value)));
       compare_result = gen_reg_rtx (CCmode);
       comp_mode = CCmode;
 
Index: libgcc/config.host
===================================================================
--- libgcc/config.host	(revision 230345)
+++ libgcc/config.host	(working copy)
@@ -1059,6 +1059,11 @@  powerpc*-*-linux*)
 		exit 1
 		;;
 	esac
+
+	if test $libgcc_cv_powerpc_float128 = yes; then
+		tmake_file="${tmake_file} rs6000/t-float128"
+	fi
+
 	extra_parts="$extra_parts ecrti.o ecrtn.o ncrti.o ncrtn.o"
 	md_unwind_header=rs6000/linux-unwind.h
 	;;
Index: libgcc/Makefile.in
===================================================================
--- libgcc/Makefile.in	(revision 230345)
+++ libgcc/Makefile.in	(working copy)
@@ -70,6 +70,8 @@  INSTALL_DATA = @INSTALL_DATA@
 mkinstalldirs = $(SHELL) $(libgcc_topdir)/mkinstalldirs
 INSTALL_PARTS = $(EXTRA_PARTS)
 
+EXTRA_CLEAN =
+
 objext = .o
 
 AR = @AR@
@@ -90,6 +92,7 @@  FLAGS_TO_PASS = \
 	"CFLAGS=$(CFLAGS)" \
 	"DESTDIR=$(DESTDIR)" \
 	"EXTRA_OFILES=$(EXTRA_OFILES)" \
+	"EXTRA_CLEAN=$(EXTRA_CLEAN)" \
 	"HDEFINES=$(HDEFINES)" \
 	"INSTALL=$(INSTALL)" \
 	"INSTALL_DATA=$(INSTALL_DATA)" \
@@ -128,7 +131,7 @@  installcheck:
 clean:
 	-rm -f libgcc_tm.h libgcc.map
 	-rm -f libgcc_tm.stamp stmp-ldirs
-	-rm -f *$(objext)
+	-rm -f *$(objext) $(EXTRA_CLEAN)
 	-rm -f *.dep
 	-rm -f *.a
 	-rm -f libunwind$(SHLIB_EXT)
Index: libgcc/configure.ac
===================================================================
--- libgcc/configure.ac	(revision 230345)
+++ libgcc/configure.ac	(working copy)
@@ -373,6 +373,17 @@  esac
 ;;
 esac
 
+case ${host} in
+powerpc*-*-linux*)
+  AC_CACHE_CHECK([whether the PowerPC compiler can do __float128],
+		 [libgcc_cv_powerpc_float128],
+		 [AC_COMPILE_IFELSE(
+    [#pragma GCC target ("vsx,float128")
+     __float128 add (__float128 *a) { return *a + *(a+1); }],
+    [libgcc_cv_powerpc_float128=yes],
+    [libgcc_cv_powerpc_float128=no])])
+esac
+
 # Collect host-machine-specific information.
 . ${srcdir}/config.host
 
Index: libgcc/config/rs6000/sfp-exceptions.c
===================================================================
--- libgcc/config/rs6000/sfp-exceptions.c	(revision 0)
+++ libgcc/config/rs6000/sfp-exceptions.c	(revision 0)
@@ -0,0 +1,64 @@ 
+/*
+ * Copyright (C) 2015 Free Software Foundation, Inc.
+ *
+ * This file 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.
+ *
+ * This file 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.
+ *
+ * Under Section 7 of GPL version 3, you are granted additional
+ * permissions described in the GCC Runtime Library Exception, version
+ * 3.1, as published by the Free Software Foundation.
+ *
+ * You should have received a copy of the GNU General Public License and
+ * a copy of the GCC Runtime Library Exception along with this program;
+ * see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+
+#include "sfp-machine.h"
+
+void
+__sfp_handle_exceptions (int _fex)
+{
+  const double fp_max = __DBL_MAX__;
+  const double fp_min = __DBL_MIN__;
+  const double fp_zero = (double) 0.0;
+  const double fp_one = 1.0;
+
+  if (_fex & FP_EX_INVALID)
+    {
+      __asm__ __volatile__ ("fdiv %0, %0, %0"
+			    :
+			    : "f" (fp_zero));
+    }
+  if (_fex & FP_EX_DIVZERO)
+    {
+      __asm__ __volatile__ ("fdiv %0, %0, %1"
+			    :
+			    : "f" (fp_one), "f" (fp_zero));
+    }
+  if (_fex & FP_EX_OVERFLOW)
+    {
+      __asm__ __volatile__ ("fadd %0, %0, %0"
+			    :
+			    : "f" (fp_max));
+    }
+  if (_fex & FP_EX_UNDERFLOW)
+    {
+      __asm__ __volatile__ ("fmul %0, %0, %0"
+			    :
+			    : "f" (fp_min));
+    }
+  if (_fex & FP_EX_INEXACT)
+    {
+      __asm__ __volatile__ ("fsub %0, %0, %1"
+			    :
+			    : "f" (fp_max), "f" (fp_one));
+    }
+}
Index: libgcc/config/rs6000/floattikf.c
===================================================================
--- libgcc/config/rs6000/floattikf.c	(revision 0)
+++ libgcc/config/rs6000/floattikf.c	(revision 0)
@@ -0,0 +1,50 @@ 
+/* Software floating-point emulation.
+   Convert a 128bit signed integer to IEEE quad
+   Copyright (C) 2015 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Steven Munroe (munroesj@linux.vnet.ibm.com)
+   Code is based on the main soft-fp library written by:
+   	   Uros Bizjak (ubizjak@gmail.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/>.  */
+
+#ifdef _ARCH_PPC64
+#include "soft-fp.h"
+#include "quad-float128.h"
+
+TFtype
+__floattikf (TItype i)
+{
+  FP_DECL_EX;
+  FP_DECL_Q (A);
+  TFtype a;
+
+  FP_INIT_ROUNDMODE;
+  FP_FROM_INT_Q (A, i, TI_BITS, UTItype);
+  FP_PACK_RAW_Q (a, A);
+  FP_HANDLE_EXCEPTIONS;
+
+  return a;
+}
+#endif
Index: libgcc/config/rs6000/extendkftf2.c
===================================================================
--- libgcc/config/rs6000/extendkftf2.c	(revision 0)
+++ libgcc/config/rs6000/extendkftf2.c	(revision 0)
@@ -0,0 +1,62 @@ 
+/* Software IEEE 128-bit floating-point emulation for PowerPC.
+   Copyright (C) 2014 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/>.  */
+
+/* Convert IEEE 128-bit floating point to IBM long double.  */
+
+/* Force the use of the VSX instruction set.  */
+#if defined(_ARCH_PPC) && (!defined(__VSX__) || !defined(__FLOAT128__))
+#pragma GCC target ("vsx,float128")
+#endif
+
+extern __ibm128 __extendkftf2 (__float128);
+
+__ibm128
+__extendkftf2 (__float128 value)
+{
+  double high, low;
+
+  high = (double) value;
+  if (__builtin_isnan (high) || __builtin_isinf (high))
+    low = 0.0;
+
+  else
+    {
+	  double high_temp;
+
+      low = (double) (value - (__float128)high);
+      /* now renormalized the high/low into canonical IBM long double form.  */
+      high_temp = high + low;
+      low = (high - high_temp) + low;
+      high = high_temp;
+    }
+
+  return __builtin_pack_longdouble (high, low);
+}
Index: libgcc/config/rs6000/trunctfkf2.c
===================================================================
--- libgcc/config/rs6000/trunctfkf2.c	(revision 0)
+++ libgcc/config/rs6000/trunctfkf2.c	(revision 0)
@@ -0,0 +1,70 @@ 
+/* Software IEEE 128-bit floating-point emulation for PowerPC.
+   Copyright (C) 2014 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/>.  */
+
+/* Convert IBM long double to IEEE 128-bit floating point.  */
+
+/* Force the use of the VSX instruction set.  */
+#if defined(_ARCH_PPC) && (!defined(__VSX__) || !defined(__FLOAT128__))
+#pragma GCC target ("vsx,float128")
+#else
+#if 0
+typedef long double __ibm128;
+typedef long double __float128;
+#endif
+#endif
+
+extern __float128 __trunctfkf2 (__ibm128);
+
+#ifdef __LITTLE_ENDIAN__
+#define HIGH_WORD	1
+#define LOW_WORD	0
+#else
+#define HIGH_WORD	0
+#define LOW_WORD	1
+#endif
+
+__float128
+__trunctfkf2 (__ibm128 value)
+{
+  double high = __builtin_unpack_longdouble (value, HIGH_WORD);
+  double low = __builtin_unpack_longdouble (value, LOW_WORD);
+
+  /* Handle the special cases of NAN and inifinity.  */
+  if (__builtin_isnan (high) || __builtin_isinf (high))
+    return (__float128) 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.  */
+  if (low == 0.0)
+    return (__float128) high;
+
+  return ((__float128)high) + ((__float128)low);
+}
Index: libgcc/config/rs6000/sfp-machine.h
===================================================================
--- libgcc/config/rs6000/sfp-machine.h	(revision 230345)
+++ libgcc/config/rs6000/sfp-machine.h	(working copy)
@@ -1,7 +1,26 @@ 
+/* Decide whether to use 64 or 32-bit types to do the emulation.  If we are
+   doing IEEE-128 with VSX, use 64-bit emulation even if we are compiling for a
+   32-bit target.  */
+
+#if defined(_ARCH_PPC64) || defined(__VSX__) || defined(__FLOAT128__)
+#define _FP_W_TYPE_SIZE		64
+#define _FP_W_TYPE		unsigned long long
+#define _FP_WS_TYPE		signed long long
+#define _FP_I_TYPE		long long
+
+#ifdef _ARCH_PPC64
+typedef int TItype __attribute__ ((mode (TI)));
+typedef unsigned int UTItype __attribute__ ((mode (TI)));
+
+#define TI_BITS (__CHAR_BIT__ * (int)sizeof(TItype))
+#endif
+
+#else	/* 32-bits  */
 #define _FP_W_TYPE_SIZE		32
-#define _FP_W_TYPE		unsigned long
-#define _FP_WS_TYPE		signed long
-#define _FP_I_TYPE		long
+#define _FP_W_TYPE		unsigned int
+#define _FP_WS_TYPE		signed int
+#define _FP_I_TYPE		int
+#endif	/* 32-bits  */
 
 /* The type of the result of a floating point comparison.  This must
    match `__libgcc_cmp_return__' in GCC for the target.  */
@@ -10,18 +29,39 @@  typedef int __gcc_CMPtype __attribute__ 
 
 #define _FP_MUL_MEAT_S(R,X,Y)				\
   _FP_MUL_MEAT_1_wide(_FP_WFRACBITS_S,R,X,Y,umul_ppmm)
+
+#if (_FP_W_TYPE_SIZE==64)
+#define _FP_MUL_MEAT_D(R,X,Y)				\
+  _FP_MUL_MEAT_1_wide(_FP_WFRACBITS_D,R,X,Y,umul_ppmm)
+#define _FP_MUL_MEAT_Q(R,X,Y)				\
+  _FP_MUL_MEAT_2_wide(_FP_WFRACBITS_Q,R,X,Y,umul_ppmm)
+#else
 #define _FP_MUL_MEAT_D(R,X,Y)				\
   _FP_MUL_MEAT_2_wide(_FP_WFRACBITS_D,R,X,Y,umul_ppmm)
 #define _FP_MUL_MEAT_Q(R,X,Y)				\
   _FP_MUL_MEAT_4_wide(_FP_WFRACBITS_Q,R,X,Y,umul_ppmm)
+#endif
 
 #define _FP_DIV_MEAT_S(R,X,Y)	_FP_DIV_MEAT_1_loop(S,R,X,Y)
+
+#if (_FP_W_TYPE_SIZE==64)
+#define _FP_DIV_MEAT_D(R,X,Y)	_FP_DIV_MEAT_1_udiv(D,R,X,Y)
+#define _FP_DIV_MEAT_Q(R,X,Y)   _FP_DIV_MEAT_2_udiv(Q,R,X,Y)
+#else
 #define _FP_DIV_MEAT_D(R,X,Y)	_FP_DIV_MEAT_2_udiv(D,R,X,Y)
 #define _FP_DIV_MEAT_Q(R,X,Y)	_FP_DIV_MEAT_4_udiv(Q,R,X,Y)
+#endif
 
 #define _FP_NANFRAC_S		((_FP_QNANBIT_S << 1) - 1)
+
+#if (_FP_W_TYPE_SIZE==64)
+#define _FP_NANFRAC_D		((_FP_QNANBIT_D << 1) - 1)
+#define _FP_NANFRAC_Q		((_FP_QNANBIT_Q << 1) - 1), -1
+#else
 #define _FP_NANFRAC_D		((_FP_QNANBIT_D << 1) - 1), -1
 #define _FP_NANFRAC_Q		((_FP_QNANBIT_Q << 1) - 1), -1, -1, -1
+#endif
+
 #define _FP_NANSIGN_S		0
 #define _FP_NANSIGN_D		0
 #define _FP_NANSIGN_Q		0
@@ -64,6 +104,46 @@  typedef int __gcc_CMPtype __attribute__ 
 # endif
 #endif
 
+#define ISA_BIT(x) (1 << (63 - x))
+
+/* Use the same bits of the FPSCR.  */
+# define FP_EX_INVALID		ISA_BIT(34)
+# define FP_EX_OVERFLOW		ISA_BIT(35)
+# define FP_EX_UNDERFLOW	ISA_BIT(36)
+# define FP_EX_DIVZERO		ISA_BIT(37)
+# define FP_EX_INEXACT		ISA_BIT(38)
+# define FP_EX_ALL							\
+  (FP_EX_INVALID | FP_EX_OVERFLOW | FP_EX_UNDERFLOW | FP_EX_DIVZERO	\
+   | FP_EX_INEXACT)
+
+void __sfp_handle_exceptions (int);
+
+# define FP_HANDLE_EXCEPTIONS			\
+  do {						\
+    if (__builtin_expect (_fex, 0))		\
+      __sfp_handle_exceptions (_fex);		\
+  } while (0);
+/* A set bit indicates an exception is masked and a clear bit indicates it is
+   trapping.  */
+# define FP_TRAPPING_EXCEPTIONS (~_fpscr & (FP_EX_ALL >> 22))
+
+# define FP_RND_NEAREST	0x0
+# define FP_RND_ZERO	0x1
+# define FP_RND_PINF	0x2
+# define FP_RND_MINF	0x3
+# define FP_RND_MASK	0x3
+
+# define _FP_DECL_EX \
+  unsigned long long _fpscr __attribute__ ((unused)) = FP_RND_NEAREST
+
+#define FP_INIT_ROUNDMODE			\
+  do {						\
+    __asm__ __volatile__ ("mtfsf 255, %0"	\
+			  :			\
+			  : "f" (_fpscr));	\
+  } while (0)
+
+# define FP_ROUNDMODE	(_fpscr & FP_RND_MASK)
 
 /* Define ALIASNAME as a strong alias for NAME.  */
 # define strong_alias(name, aliasname) _strong_alias(name, aliasname)
Index: libgcc/config/rs6000/fixunskfti.c
===================================================================
--- libgcc/config/rs6000/fixunskfti.c	(revision 0)
+++ libgcc/config/rs6000/fixunskfti.c	(revision 0)
@@ -0,0 +1,50 @@ 
+/* Software floating-point emulation.
+   Convert IEEE quad to 128bit unsigned integer
+   Copyright (C) 2015 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Steven Munroe (munroesj@linux.vnet.ibm.com)
+   Code is based on the main soft-fp library written by:
+   	   Uros Bizjak (ubizjak@gmail.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/>.  */
+
+#ifdef _ARCH_PPC64
+#include "soft-fp.h"
+#include "quad-float128.h"
+
+UTItype
+__fixunskfti (TFtype a)
+{
+  FP_DECL_EX;
+  FP_DECL_Q (A);
+  UTItype r;
+
+  FP_INIT_EXCEPTIONS;
+  FP_UNPACK_RAW_Q (A, a);
+  FP_TO_INT_Q (r, A, TI_BITS, 0);
+  FP_HANDLE_EXCEPTIONS;
+
+  return r;
+}
+#endif
Index: libgcc/config/rs6000/fixkfti.c
===================================================================
--- libgcc/config/rs6000/fixkfti.c	(revision 0)
+++ libgcc/config/rs6000/fixkfti.c	(revision 0)
@@ -0,0 +1,50 @@ 
+/* Software floating-point emulation.
+   Convert IEEE quad to 128bit signed integer
+   Copyright (C) 2015 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Steven Munroe (munroesj@linux.vnet.ibm.com)
+   Code is based on the main soft-fp library written by:
+   	   Uros Bizjak (ubizjak@gmail.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/>.  */
+
+#ifdef _ARCH_PPC64
+#include "soft-fp.h"
+#include "quad-float128.h"
+
+TItype
+__fixkfti (TFtype a)
+{
+  FP_DECL_EX;
+  FP_DECL_Q (A);
+  UTItype r;
+
+  FP_INIT_EXCEPTIONS;
+  FP_UNPACK_RAW_Q (A, a);
+  FP_TO_INT_Q (r, A, TI_BITS, 1);
+  FP_HANDLE_EXCEPTIONS;
+
+  return r;
+}
+#endif
Index: libgcc/config/rs6000/cmpukf2.c
===================================================================
--- libgcc/config/rs6000/cmpukf2.c	(revision 0)
+++ libgcc/config/rs6000/cmpukf2.c	(revision 0)
@@ -0,0 +1,101 @@ 
+/* Software IEEE 128-bit floating-point emulation for PowerPC.
+   Copyright (C) 2015 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:
+	Joseph Myers (joseph@codesourcery.com),
+	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/>.  */
+
+/* This function is called for the IEEE comparisons that specifically handle
+   NaNs.  The normal comparisons use eqkf2, gekf2, lekf2, etc.  */
+
+#include "soft-fp.h"
+#include "double.h"
+#include "single.h"
+#include "quad-float128.h"
+
+/* PowerPC condition register bits.  */
+#define PPC_UNORDERED		0x1		/* isnan (a) || isnan (b).  */
+#define PPC_EQUAL		0x2		/* a == b.  */
+#define PPC_GREATER_THEN	0x4		/* a > b.  */
+#define PPC_LESS_THEN		0x8		/* a < b.  */
+
+/* Map FP_CMP_Q output to PowerPC condition register bits.  */
+#define CMP_UNORDERED		(-2)		/* isnan (a) || isnan (b).  */
+#define CMP_LESS_THEN		(-1)		/* a < b.  */
+#define CMP_EQUAL		0		/* a == b.  */
+#define CMP_GREATER_THEN	1		/* a < b.  */
+#define CMP_INVALID		2		/* raise invalid exception.  */
+
+#define CMP_LOW			CMP_UNORDERED	/* comparison low value.  */
+#define CMP_HIGH		CMP_INVALID	/* comparison high value.  */
+
+static const unsigned char ppc_cr_map[] = {
+  PPC_UNORDERED,				/* -2: unordered.  */
+  PPC_LESS_THEN,				/* -1: a < b.  */
+  PPC_EQUAL,					/*  0: a == b.  */
+  PPC_GREATER_THEN,				/*  1: a > b.  */
+  PPC_UNORDERED,				/*  2: invalid.  */
+};
+
+/* Compare two IEEE 128-bit floating point values and return the status.  We
+   return the status as a 4-bit value that uses the same values as the PowerPC
+   condition code register.  */
+
+CMPtype
+__cmpukf2 (TFtype a, TFtype b)
+{
+  FP_DECL_EX;
+  FP_DECL_Q (A);
+  FP_DECL_Q (B);
+  CMPtype r, r2;
+
+  FP_INIT_EXCEPTIONS;
+  FP_UNPACK_RAW_Q (A, a);
+  FP_UNPACK_RAW_Q (B, b);
+
+  /* First do the unordered comparison.  */
+  FP_CMP_UNORD_Q (r, A, B, 1);
+  if (r)
+    r2 = PPC_UNORDERED;
+
+  else
+    {
+      /* If the value is not unordered, do the normal comparison.  */
+      FP_CMP_Q (r, A, B, 2, 2);
+      if (r == CMP_INVALID)
+	FP_SET_EXCEPTION (FP_EX_INVALID);
+
+      r2 = ((r < CMP_LOW || r > CMP_HIGH)
+	    ? PPC_UNORDERED
+	    : ppc_cr_map[r-CMP_LOW]);
+    }
+
+  FP_HANDLE_EXCEPTIONS;
+
+  return r2;
+}
Index: libgcc/config/rs6000/floatuntikf.c
===================================================================
--- libgcc/config/rs6000/floatuntikf.c	(revision 0)
+++ libgcc/config/rs6000/floatuntikf.c	(revision 0)
@@ -0,0 +1,50 @@ 
+/* Software floating-point emulation.
+   Convert a 128bit unsigned integer to IEEE quad
+   Copyright (C) 2015 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Steven Munroe (munroesj@linux.vnet.ibm.com)
+   Code is based on the main soft-fp library written by:
+   	   Uros Bizjak (ubizjak@gmail.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/>.  */
+
+#ifdef _ARCH_PPC64
+#include "soft-fp.h"
+#include "quad-float128.h"
+
+TFtype
+__floatuntikf (UTItype i)
+{
+  FP_DECL_EX;
+  FP_DECL_Q (A);
+  TFtype a;
+
+  FP_INIT_ROUNDMODE;
+  FP_FROM_INT_Q (A, i, TI_BITS, UTItype);
+  FP_PACK_RAW_Q (a, A);
+  FP_HANDLE_EXCEPTIONS;
+
+  return a;
+}
+#endif
Index: libgcc/config/rs6000/quad-float128.h
===================================================================
--- libgcc/config/rs6000/quad-float128.h	(revision 0)
+++ libgcc/config/rs6000/quad-float128.h	(revision 0)
@@ -0,0 +1,87 @@ 
+/* Software floating-point emulation.
+   Definitions for IEEE Quad Precision on the PowerPC.
+   Copyright (C) 2015 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).  */
+#define TF KF
+
+/* Force the use of the VSX instruction set.  */
+#if defined(_ARCH_PPC) && (!defined(__VSX__) || !defined(__FLOAT128__))
+#pragma GCC target ("vsx,float128")
+#endif
+
+#include <quad.h>
+
+/* 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
+
+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 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 CMPtype __cmpukf2 (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);
+extern TFtype __floatunsikf (USItype_ppc);
+extern TFtype __floatundikf (UDItype_ppc);
+
+#ifdef _ARCH_PPC64
+extern TItype_ppc __fixkfti (TFtype);
+extern UTItype_ppc __fixunskfti (TFtype);
+extern TFtype __floattikf (TItype_ppc);
+extern TFtype __floatuntikf (UTItype_ppc);
+#endif
Index: libgcc/config/rs6000/t-float128
===================================================================
--- libgcc/config/rs6000/t-float128	(revision 0)
+++ libgcc/config/rs6000/t-float128	(revision 0)
@@ -0,0 +1,80 @@ 
+# Support for adding __float128 to the powerpc.
+
+# The standard 128-bit floating point support functions are TFmode.  Most
+# PowerPC targets use a long double format that has a pair of doubles to give
+# you more precision, but no extra expoenent range.  This long double format is
+# mostly compatible with the format used by the IBM XL compilers.  Some of the
+# names used by the IBM double-double format use TF in them, so we rename
+# all of the functions provided for the new IEEE 128-bit support.
+#
+# We use the TF functions in soft-fp for 128-bit floating point support, using
+# sed to transform the names in the files from TF names to KF names.
+
+# Emulator functions from the soft-fp directory
+fp128_softfp_funcs	= addkf3 subkf3 mulkf3 divkf3 negkf2 \
+			  unordkf2 eqkf2 gekf2 lekf2 \
+			  extendsfkf2 extenddfkf2 trunckfsf2 trunckfdf2 \
+			  fixkfsi fixkfdi fixunskfsi fixunskfdi \
+			  floatsikf floatdikf floatunsikf floatundikf
+
+fp128_softfp_src	= $(addsuffix .c,$(fp128_softfp_funcs))
+fp128_softfp_static_obj	= $(addsuffix $(objext),$(fp128_softfp_funcs))
+fp128_softfp_shared_obj	= $(addsuffix _s$(objext),$(fp128_softfp_funcs))
+fp128_softfp_obj	= $(fp128_softfp_static_obj) $(fp128_softfp_shared_obj)
+
+# New functions
+fp128_ppc_funcs		= floattikf floatuntikf fixkfti fixunskfti \
+			  extendkftf2 trunctfkf2 sfp-exceptions cmpukf2
+
+fp128_ppc_src		= $(addprefix $(srcdir)/config/rs6000/,$(addsuffix \
+				.c,$(fp128_ppc_funcs)))
+fp128_ppc_static_obj	= $(addsuffix $(objext),$(fp128_ppc_funcs))
+fp128_ppc_shared_obj	= $(addsuffix _s$(objext),$(fp128_ppc_funcs))
+fp128_ppc_obj		= $(fp128_ppc_static_obj) $(fp128_ppc_shared_obj)
+
+# All functions
+fp128_funcs		= $(fp128_softfp_funcs) $(fp128_ppc_funcs)
+fp128_src		= $(fp128_softfp_src) $(fp128_ppc_src)
+fp128_obj		= $(fp128_softfp_obj) $(fp128_ppc_obj)
+fp128_sed		= $(srcdir)/config/rs6000/float128-sed
+fp128_dep		= $(fp128_sed) $(srcdir)/config/rs6000/t-float128
+
+fp128_includes		= $(srcdir)/soft-fp/double.h \
+			  $(srcdir)/soft-fp/op-1.h \
+			  $(srcdir)/soft-fp/op-4.h \
+			  $(srcdir)/soft-fp/op-common.h \
+			  $(srcdir)/soft-fp/single.h \
+			  $(srcdir)/soft-fp/extended.h \
+			  $(srcdir)/soft-fp/op-2.h \
+			  $(srcdir)/soft-fp/op-8.h \
+			  $(srcdir)/soft-fp/quad.h \
+			  $(srcdir)/soft-fp/soft-fp.h
+
+EXTRA_CLEAN		+= $(fp128_softfp_src)
+
+FP128_CFLAGS		 = -Wno-type-limits -mvsx -mfloat128 \
+			   -I$(srcdir)/soft-fp \
+			   -I$(srcdir)/config/rs6000
+
+$(fp128_obj)		 : INTERNAL_CFLAGS += $(FP128_CFLAGS)
+$(fp128_obj)		 : $(fp128_includes)
+$(fp128_obj)		 : $(srcdir)/config/rs6000/quad-float128.h
+
+$(fp128_softfp_src) : $(srcdir)/soft-fp/$(subst kf,tf,$@) $(fp128_dep)
+	@src="$(srcdir)/soft-fp/$(subst kf,tf,$@)"; \
+	echo "Create $@"; \
+	(echo "/* file created from $$src */"; \
+	 echo; \
+	 sed -f $(fp128_sed) < $$src) > $@
+
+test:
+	@echo "fp128_src:"; \
+	for x in $(fp128_src); do echo "    $$x"; done; \
+	echo; \
+	echo "fp128_obj:"; \
+	for x in $(fp128_obj); do echo "    $$x"; done;
+
+# For now, only put it in the static library
+# LIB2ADD += $(fp128_src)
+
+LIB2ADD_ST += $(fp128_src)
Index: libgcc/config/rs6000/float128-sed
===================================================================
--- libgcc/config/rs6000/float128-sed	(revision 0)
+++ libgcc/config/rs6000/float128-sed	(revision 0)
@@ -0,0 +1,25 @@ 
+s/__addtf3/__addkf3/g
+s/__divtf3/__divkf3/g
+s/__eqtf2/__eqkf2/g
+s/__extenddftf2/__extenddfkf2/g
+s/__extendsftf2/__extendsfkf2/g
+s/__fixtfdi/__fixkfdi/g
+s/__fixtfsi/__fixkfsi/g
+s/__fixunstfdi/__fixunskfdi/g
+s/__fixunstfsi/__fixunskfsi/g
+s/__floatditf/__floatdikf/g
+s/__floatsitf/__floatsikf/g
+s/__floatunditf/__floatundikf/g
+s/__floatunsitf/__floatunsikf/g
+s/__getf2/__gekf2/g
+s/__gttf2/__gtkf2/g
+s/__letf2/__lekf2/g
+s/__lttf2/__ltkf2/g
+s/__multf3/__mulkf3/g
+s/__negtf2/__negkf2/g
+s/__netf2/__nekf2/g
+s/quad[.]h/quad-float128.h/g
+s/__subtf3/__subkf3/g
+s/__trunctfdf2/__trunckfdf2/g
+s/__trunctfsf2/__trunckfsf2/g
+s/__unordtf2/__unordkf2/g
Index: libgcc/configure
===================================================================
--- libgcc/configure	(revision 230345)
+++ libgcc/configure	(working copy)
@@ -4766,6 +4766,29 @@  esac
 ;;
 esac
 
+case ${host} in
+powerpc*-*-linux*)
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the PowerPC compiler can do __float128" >&5
+$as_echo_n "checking whether the PowerPC compiler can do __float128... " >&6; }
+if test "${libgcc_cv_powerpc_float128+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#pragma GCC target ("vsx,float128")
+     __float128 add (__float128 *a) { return *a + *(a+1); }
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  libgcc_cv_powerpc_float128=yes
+else
+  libgcc_cv_powerpc_float128=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libgcc_cv_powerpc_float128" >&5
+$as_echo "$libgcc_cv_powerpc_float128" >&6; }
+esac
+
 # Collect host-machine-specific information.
 . ${srcdir}/config.host