[PATCH], PowerPC IEEE 128-bit fp, #11-rev2 (enable libgcc conversions)

Michael Meissner meissner@linux.vnet.ibm.com
Wed Jan 6 22:48:00 GMT 2016


I have reworked the libgcc library interface that was in my original patch
#11.  There are 2 attachments, the first attachment is for patches in the gcc
space, and the second attachment is for the libgcc changes.

I added the conversions between IBM extended double and IEEE 128-bit floating
point to the code that is built for emulation support (using the KF functions)
and code that enables ISA 3.0 (power9) support using direct instructions.
Unfortunately, I discovered some problems with the builtins to pack and unpack
IBM extended double that only show up with -mcpu=power9.  So, I fixed the code
generation problem (involving & constraints and multi-register data types on
little endian systems) to generate correct code.  While I was modifying the
pack and unpack routines, I added support to allow pack to read values from
memory and use the upper registers.  I tightened up the iterators to not allow
TFmode if long double is IEEE 128-bit floating point.  In looking towards the
day when long double is IEEE 128-bit floating point, I also added builtins to
take/return explict __ibm128 instead of long double.

In terms of the libgcc library functions:

    1)	I removed the extra clean rule, modifying Makefile.in.  Now the only
	changes are to the toplevel configuration files and within the
	config/rs6000 subdirectory.

    2)	I removed creating ifunc descriptors for the 4 functions that convert
	between signed/unsigned __int128 and __float128 since at present we
	don't have specific ISA 3.0 code for these conversions (suggestion from
	Joseph Myers).

    3)	I modified the ISA 3.0 version of the comparison functions, to simplify
	the code somewhat based on suggestions from Joseph Myers.

    4)	I used __getauxval instead of getauxval in ifunc module.  Ideally, we
	will soon have __builtin_cpu_supports to directly test if the machine
	has hardware IEEE 128-bit floating point.

    5)	I put the exception handling code under #ifndef _SOFT_FLOAT control so
	that the 32-bit PowerPC machines that don't have hardware floating
	point will not use this code (the exception handling uses hardware
	instructions to cause a particular fault).

    6)	In looking at the exception handling, I tweaked the asm code somewhat
	to have an explicit target.

    7)	As I mentioned above, I made the conversion between IFmode and KFmode
	have IEEE 128-bit emulation and IEEE 128-bit hardware support
	versions.  I modified it to use __builtin_unpack_ibm128 and
	__builtin_pack_ibm128.

I have done bootstrap builds on a big endian Power7 and a little endian Power8
machine with no regressions.  Are these patches ok to install in the trunk?

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

	* config/rs6000/rs6000-builtin.def (BU_FLOAT128_2): Add support
	for pack/unpack functions for __ibm128.
	(PACK_IF): Likewise.
	(UNPACK_IF): Likewise.

	* config/rs6000/rs6000.c (rs6000_builtin_mask_calculate): Add
	support for __ibm128 pack/unpack functions.
	(rs6000_invalid_builtin): Likewise.
	(rs6000_init_builtins): Likewise.
	(rs6000_opt_masks): Likewise.

	* config/rs6000/rs6000.h (MASK_FLOAT128): Add short name.
	(RS6000_BTM_FLOAT128): Add support for __ibm128 pack/unpack
	functions
	(RS6000_BTM_COMMON): Likewise.

	* config/rs6000/rs6000.md (f128_vsx): New mode attribute.
	(unpack<mode>): Use FMOVE128_FPR iterator instead of FMOVE128, to
	disallow __builtin_{pack,unpack}_longdouble if long double is IEEE
	128-bit floating point.  Add support for the double values to be
	in Altivec registers for TF/IF packing and unpacking, but restrict
	TD packing sub-fields to be FPR registers.  Don't allow overlapped
	register support for packing.  Allow pack inputs to be memory
	locations.  Don't build generator functions for unpack<mode>_dm
	and unpack<mode>_nodm.
	(unpack<mode>_dm): Likewise.
	(unpack<mode>_nodm): Likewise.
	(pack<mode>): Likewise.

	* config/rs6000/rs6000-builtin.def (__builtin_pack_ibm128): Add
	built-in functions to pack/unpack explicit __ibm128 values.
	(__builtin_unpack_ibm128): Likewise.

	* doc/extend.texi (PowerPC Built-in Functions): Document
	__builtin_pack_ibm128 and __builtin_unpack_ibm128.

[libgcc]
2016-01-06  Michael Meissner  <meissner@linux.vnet.ibm.com>
	    Steven Munroe (munroesj@linux.vnet.ibm.com)
	    Tulio Magno Quites Machado Filho <tulioqm@br.ibm.com>

	* config/rs6000/floattikf.c: New files for IEEE 128-bit floating
	point conversions.
	* config/rs6000/floatuntikf.c: Likewise.
	* config/rs6000/fixkfti.c: Likewise.
	* config/rs6000/fixunskfti.c: Likewise.
	* config/rs6000/extendkftf2-sw.c: Likewise.
	* config/rs6000/trunctfkf2-sw.c: Likewise.

	* config/rs6000/float128-hw.c: New file for ISA 3.0 IEEE 128-bit
	floating point hardware support.

	* config/rs6000/float128-ifunc.c: New file to pick either IEEE
	128-bit floating point software emulation or use ISA 3.0 hardware
	support if it is available.

	* config/rs6000/t-float128: New Makefile fragments to enable
	building __float128 emulation support.
	* config/rs6000/t-float128-hw: Likewise.

	* config/rs6000/sfp-exceptions.c: New file to provide exception
	support for IEEE 128-bit floating point.

	* config/rs6000/quad-float128.h: New file to support IEEE 128-bit
	floating point.

	* config/rs6000/float128-sed: New file to convert TF names to KF
	names for PowerPC IEEE 128-bit floating point support.

	* config/rs6000/sfp-machine.h (_FP_W_TYPE_SIZE): Use 64-bit types
	when building on 64-bit systems, or when VSX is enabled.
	(_FP_W_TYPE): Likewise.
	(_FP_WS_TYPE): Likewise.
	(_FP_I_TYPE): Likewise.
	(TItype): Define on 64-bit systems.
	(UTItype): Likewise.
	(TI_BITS): Likewise.
	(_FP_MUL_MEAT_D): Add support for using 64-bit types.
	(_FP_MUL_MEAT_Q): Likewise.
	(_FP_DIV_MEAT_D): Likewise.
	(_FP_DIV_MEAT_Q): Likewise.
	(_FP_NANFRAC_D): Likewise.
	(_FP_NANFRAC_Q): Likewise.
	(ISA_BIT): Add exception support if we are being compiled on a
	machine with hardware floating point support to build the IEEE
	128-bit emulation functions.
	(FP_EX_INVALID): Likewise.
	(FP_EX_OVERFLOW): Likewise.
	(FP_EX_UNDERFLOW): Likewise.
	(FP_EX_DIVZERO): Likewise.
	(FP_EX_INEXACT): Likewise.
	(FP_EX_ALL): Likewise.
	(__sfp_handle_exceptions): Likewise.
	(FP_HANDLE_EXCEPTIONS): Likewise.
	(FP_RND_NEAREST): Likewise.
	(FP_RND_ZERO): Likewise.
	(FP_RND_PINF): Likewise.
	(FP_RND_MINF): Likewise.
	(FP_RND_MASK): Likewise.
	(_FP_DECL_EX): Likewise.
	(FP_INIT_ROUNDMODE): Likewise.
	(FP_ROUNDMODE): Likewise.

	* libgcc/config.host (powerpc*-*-linux*): If compiler can compile
	VSX code, enable IEEE 128-bit floating point.

	* configure.ac (powerpc*-*-linux*): Check whether the PowerPC
	compiler can do __float128.
	* configure: Regenerate.



-- 
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/config/rs6000/rs6000-builtin.def
===================================================================
--- gcc/config/rs6000/rs6000-builtin.def	(.../svn+ssh://meissner@gcc.gnu.org/svn/gcc/trunk/gcc/config/rs6000)	(revision 232093)
+++ gcc/config/rs6000/rs6000-builtin.def	(.../gcc/config/rs6000)	(working copy)
@@ -647,6 +647,15 @@
 		     | RS6000_BTC_BINARY),				\
 		    CODE_FOR_ ## ICODE)			/* ICODE */
 
+/* __float128 floating point builtins.  */
+#define BU_FLOAT128_2(ENUM, NAME, ATTR, ICODE)				\
+  RS6000_BUILTIN_2 (MISC_BUILTIN_ ## ENUM,		/* ENUM */	\
+		    "__builtin_" NAME,			/* NAME */	\
+		    RS6000_BTM_FLOAT128,		/* MASK */	\
+		    (RS6000_BTC_ ## ATTR		/* ATTR */	\
+		     | RS6000_BTC_BINARY),				\
+		    CODE_FOR_ ## ICODE)			/* ICODE */
+
 #endif
 
 /* Insure 0 is not a legitimate index.  */
@@ -1642,6 +1651,9 @@ BU_DFP_MISC_2 (UNPACK_TD,	"unpack_dec128
 BU_LDBL128_2 (PACK_TF,		"pack_longdouble",	CONST,	packtf)
 BU_LDBL128_2 (UNPACK_TF,	"unpack_longdouble",	CONST,	unpacktf)
 
+BU_FLOAT128_2 (PACK_IF,		"pack_ibm128",		CONST,	packif)
+BU_FLOAT128_2 (UNPACK_IF,	"unpack_ibm128",	CONST,	unpackif)
+
 BU_P7_MISC_2 (PACK_V1TI,	"pack_vector_int128",	CONST,	packv1ti)
 BU_P7_MISC_2 (UNPACK_V1TI,	"unpack_vector_int128",	CONST,	unpackv1ti)
 
Index: gcc/config/rs6000/rs6000.c
===================================================================
--- gcc/config/rs6000/rs6000.c	(.../svn+ssh://meissner@gcc.gnu.org/svn/gcc/trunk/gcc/config/rs6000)	(revision 232093)
+++ gcc/config/rs6000/rs6000.c	(.../gcc/config/rs6000)	(working copy)
@@ -3521,7 +3521,8 @@ rs6000_builtin_mask_calculate (void)
 	  | ((TARGET_HTM)		    ? RS6000_BTM_HTM	   : 0)
 	  | ((TARGET_DFP)		    ? RS6000_BTM_DFP	   : 0)
 	  | ((TARGET_HARD_FLOAT)	    ? RS6000_BTM_HARD_FLOAT : 0)
-	  | ((TARGET_LONG_DOUBLE_128)	    ? RS6000_BTM_LDBL128 : 0));
+	  | ((TARGET_LONG_DOUBLE_128)	    ? RS6000_BTM_LDBL128   : 0)
+	  | ((TARGET_FLOAT128)		    ? RS6000_BTM_FLOAT128  : 0));
 }
 
 /* Implement TARGET_MD_ASM_ADJUST.  All asm statements are considered
@@ -14605,6 +14606,8 @@ rs6000_invalid_builtin (enum rs6000_buil
 	   " -mlong-double-128 options", name);
   else if ((fnmask & RS6000_BTM_HARD_FLOAT) != 0)
     error ("Builtin function %s requires the -mhard-float option", name);
+  else if ((fnmask & RS6000_BTM_FLOAT128) != 0)
+    error ("Builtin function %s requires the -mfloat128 options", name);
   else
     error ("Builtin function %s is not supported with the current options",
 	   name);
@@ -14894,19 +14897,21 @@ rs6000_init_builtins (void)
      IFmode is the IBM extended 128-bit format that is a pair of doubles.
      TFmode will be either IEEE 128-bit floating point or the IBM double-double
      format that uses a pair of doubles, depending on the switches and
-     defaults.  */
+     defaults.  Always create the types even if we don't register the keywords
+     to allow built-in functions using these types to be created.  */
+
+  ibm128_float_type_node = make_node (REAL_TYPE);
+  TYPE_PRECISION (ibm128_float_type_node) = 128;
+  layout_type (ibm128_float_type_node);
+  SET_TYPE_MODE (ibm128_float_type_node, IFmode);
+
+  ieee128_float_type_node = make_node (REAL_TYPE);
+  TYPE_PRECISION (ieee128_float_type_node) = 128;
+  layout_type (ieee128_float_type_node);
+  SET_TYPE_MODE (ieee128_float_type_node, KFmode);
+
   if (TARGET_FLOAT128)
     {
-      ibm128_float_type_node = make_node (REAL_TYPE);
-      TYPE_PRECISION (ibm128_float_type_node) = 128;
-      layout_type (ibm128_float_type_node);
-      SET_TYPE_MODE (ibm128_float_type_node, IFmode);
-
-      ieee128_float_type_node = make_node (REAL_TYPE);
-      TYPE_PRECISION (ieee128_float_type_node) = 128;
-      layout_type (ieee128_float_type_node);
-      SET_TYPE_MODE (ieee128_float_type_node, KFmode);
-
       lang_hooks.types.register_builtin_type (ieee128_float_type_node,
 					      "__float128");
 
@@ -34223,6 +34228,7 @@ static struct rs6000_opt_mask const rs60
   { "hard-dfp",		 RS6000_BTM_DFP,	false, false },
   { "hard-float",	 RS6000_BTM_HARD_FLOAT,	false, false },
   { "long-double-128",	 RS6000_BTM_LDBL128,	false, false },
+  { "float128",		 RS6000_BTM_FLOAT128,	false, false },
 };
 
 /* Option variables that we want to support inside attribute((target)) and
Index: gcc/config/rs6000/rs6000.h
===================================================================
--- gcc/config/rs6000/rs6000.h	(.../svn+ssh://meissner@gcc.gnu.org/svn/gcc/trunk/gcc/config/rs6000)	(revision 232093)
+++ gcc/config/rs6000/rs6000.h	(.../gcc/config/rs6000)	(working copy)
@@ -605,6 +605,7 @@ extern int rs6000_vector_align[];
 #define MASK_DLMZB			OPTION_MASK_DLMZB
 #define MASK_EABI			OPTION_MASK_EABI
 #define MASK_FPRND			OPTION_MASK_FPRND
+#define MASK_FLOAT128			OPTION_MASK_FLOAT128
 #define MASK_P8_FUSION			OPTION_MASK_P8_FUSION
 #define MASK_HARD_FLOAT			OPTION_MASK_HARD_FLOAT
 #define MASK_HTM			OPTION_MASK_HTM
@@ -2670,6 +2671,7 @@ extern int frame_pointer_needed;
 #define RS6000_BTM_DFP		MASK_DFP	/* Decimal floating point.  */
 #define RS6000_BTM_HARD_FLOAT	MASK_SOFT_FLOAT	/* Hardware floating point.  */
 #define RS6000_BTM_LDBL128	MASK_MULTIPLE	/* 128-bit long double.  */
+#define RS6000_BTM_FLOAT128	MASK_FLOAT128	/* IEEE 128-bit fp.  */
 
 #define RS6000_BTM_COMMON	(RS6000_BTM_ALTIVEC			\
 				 | RS6000_BTM_VSX			\
@@ -2684,7 +2686,8 @@ extern int frame_pointer_needed;
 				 | RS6000_BTM_CELL			\
 				 | RS6000_BTM_DFP			\
 				 | RS6000_BTM_HARD_FLOAT		\
-				 | RS6000_BTM_LDBL128)
+				 | RS6000_BTM_LDBL128			\
+				 | RS6000_BTM_FLOAT128)
 
 /* Define builtin enum index.  */
 
Index: gcc/config/rs6000/rs6000.md
===================================================================
--- gcc/config/rs6000/rs6000.md	(.../svn+ssh://meissner@gcc.gnu.org/svn/gcc/trunk/gcc/config/rs6000)	(revision 232093)
+++ gcc/config/rs6000/rs6000.md	(.../gcc/config/rs6000)	(working copy)
@@ -469,6 +469,9 @@ (define_mode_attr f64_av  [(DF "wv") (DD
 ; Definitions for 64-bit access to ISA 3.0 (power9) vector
 (define_mode_attr f64_p9  [(DF "wb") (DD "wn")])
 
+; Definitions for 128-bit IBM extended double word pack/unpack
+(define_mode_attr f128_vsx [(TF "ws") (IF "ws") (TD "d")])
+
 ; These modes do not fit in integer registers in 32-bit mode.
 ; but on e500v2, the gpr are 64 bit registers
 (define_mode_iterator DIFD [DI (DF "!TARGET_E500_DOUBLE") DD])
@@ -13109,16 +13112,16 @@ (define_mode_attr FP128_64 [(TF "DF")
 (define_expand "unpack<mode>"
   [(set (match_operand:<FP128_64> 0 "nonimmediate_operand" "")
 	(unspec:<FP128_64>
-	 [(match_operand:FMOVE128 1 "register_operand" "")
+	 [(match_operand:FMOVE128_FPR 1 "register_operand" "")
 	  (match_operand:QI 2 "const_0_to_1_operand" "")]
 	 UNSPEC_UNPACK_128BIT))]
   "FLOAT128_2REG_P (<MODE>mode)"
   "")
 
-(define_insn_and_split "unpack<mode>_dm"
-  [(set (match_operand:<FP128_64> 0 "nonimmediate_operand" "=d,m,d,r,m")
+(define_insn_and_split "*unpack<mode>_dm"
+  [(set (match_operand:<FP128_64> 0 "nonimmediate_operand" "=<f128_vsx>,m,<f128_vsx>,r,m")
 	(unspec:<FP128_64>
-	 [(match_operand:FMOVE128 1 "register_operand" "d,d,r,d,r")
+	 [(match_operand:FMOVE128_FPR 1 "register_operand" "d,d,r,d,r")
 	  (match_operand:QI 2 "const_0_to_1_operand" "i,i,i,i,i")]
 	 UNSPEC_UNPACK_128BIT))]
   "TARGET_POWERPC64 && TARGET_DIRECT_MOVE && FLOAT128_2REG_P (<MODE>mode)"
@@ -13139,10 +13142,10 @@ (define_insn_and_split "unpack<mode>_dm"
   [(set_attr "type" "fp,fpstore,mffgpr,mftgpr,store")
    (set_attr "length" "4")])
 
-(define_insn_and_split "unpack<mode>_nodm"
-  [(set (match_operand:<FP128_64> 0 "nonimmediate_operand" "=d,m")
+(define_insn_and_split "*unpack<mode>_nodm"
+  [(set (match_operand:<FP128_64> 0 "nonimmediate_operand" "=<f128_vsx>,m")
 	(unspec:<FP128_64>
-	 [(match_operand:FMOVE128 1 "register_operand" "d,d")
+	 [(match_operand:FMOVE128_FPR 1 "register_operand" "d,d")
 	  (match_operand:QI 2 "const_0_to_1_operand" "i,i")]
 	 UNSPEC_UNPACK_128BIT))]
   "(!TARGET_POWERPC64 || !TARGET_DIRECT_MOVE) && FLOAT128_2REG_P (<MODE>mode)"
@@ -13164,30 +13167,31 @@ (define_insn_and_split "unpack<mode>_nod
    (set_attr "length" "4")])
 
 (define_insn_and_split "pack<mode>"
-  [(set (match_operand:FMOVE128 0 "register_operand" "=d,&d")
-	(unspec:FMOVE128
-	 [(match_operand:<FP128_64> 1 "register_operand" "0,d")
-	  (match_operand:<FP128_64> 2 "register_operand" "d,d")]
+  [(set (match_operand:FMOVE128_FPR 0 "register_operand" "=&d,&d,&d,&d")
+	(unspec:FMOVE128_FPR
+	 [(match_operand:<FP128_64> 1 "input_operand" "<f128_vsx>,<f128_vsx>,m,m")
+	  (match_operand:<FP128_64> 2 "input_operand" "<f128_vsx>,m,<f128_vsx>,m")]
 	 UNSPEC_PACK_128BIT))]
   "FLOAT128_2REG_P (<MODE>mode)"
-  "@
-   fmr %L0,%2
-   #"
-  "&& reload_completed && REGNO (operands[0]) != REGNO (operands[1])"
+  "#"
+  "&& reload_completed"
   [(set (match_dup 3) (match_dup 1))
    (set (match_dup 4) (match_dup 2))]
 {
-  unsigned dest_hi = REGNO (operands[0]);
+  rtx op0 = operands[0];
+  rtx op1 = operands[1];
+  rtx op2 = operands[2];
+  unsigned dest_hi = REGNO (op0);
   unsigned dest_lo = dest_hi + 1;
 
-  gcc_assert (!IN_RANGE (REGNO (operands[1]), dest_hi, dest_lo));
-  gcc_assert (!IN_RANGE (REGNO (operands[2]), dest_hi, dest_lo));
+  gcc_assert (!REG_P (op1) || !IN_RANGE (REGNO (op1), dest_hi, dest_lo));
+  gcc_assert (!REG_P (op2) || !IN_RANGE (REGNO (op2), dest_hi, dest_lo));
 
   operands[3] = gen_rtx_REG (<FP128_64>mode, dest_hi);
   operands[4] = gen_rtx_REG (<FP128_64>mode, dest_lo);
 }
-  [(set_attr "type" "fp,fp")
-   (set_attr "length" "4,8")])
+  [(set_attr "type" "fp,fpload,fpload,fpload")
+   (set_attr "length" "8")])
 
 (define_insn "unpack<mode>"
   [(set (match_operand:DI 0 "register_operand" "=d,d")
Index: gcc/doc/extend.texi
===================================================================
--- gcc/doc/extend.texi	(.../svn+ssh://meissner@gcc.gnu.org/svn/gcc/trunk/gcc/doc)	(revision 232093)
+++ gcc/doc/extend.texi	(.../gcc/doc)	(working copy)
@@ -13512,6 +13512,8 @@ uint64_t __builtin_ppc_get_timebase ();
 unsigned long __builtin_ppc_mftb ();
 double __builtin_unpack_longdouble (long double, int);
 long double __builtin_pack_longdouble (double, double);
+double __builtin_unpack_ibm128 (__ibm128, int);
+__ibm128 __builtin_pack_ibm128 (double, double);
 @end smallexample
 
 The @code{vec_rsqrt}, @code{__builtin_rsqrt}, and
-------------- next part --------------
Index: libgcc/config/rs6000/sfp-exceptions.c
===================================================================
--- libgcc/config/rs6000/sfp-exceptions.c	(.../svn+ssh://meissner@gcc.gnu.org/svn/gcc/trunk/libgcc)	(revision 0)
+++ libgcc/config/rs6000/sfp-exceptions.c	(.../libgcc)	(revision 232096)
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2016 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"
+
+/* Only provide exception support if we have hardware floating point and we can
+   execute the mtfsf instruction.  This would only be true if we are using the
+   emulation routines for IEEE 128-bit floating point on pre-ISA 3.0 machines
+   without the IEEE 128-bit floating point support.  */
+
+#ifndef _SOFT_FLOAT
+
+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;
+  double tmp;
+
+  if (_fex & FP_EX_INVALID)
+    {
+      __asm__ __volatile__ ("fdiv %0, %1, %1"
+			    : "=f" (tmp)
+			    : "f" (fp_zero));
+    }
+  if (_fex & FP_EX_DIVZERO)
+    {
+      __asm__ __volatile__ ("fdiv %0, %1, %2"
+			    : "=f" (tmp)
+			    : "f" (fp_one), "f" (fp_zero));
+    }
+  if (_fex & FP_EX_OVERFLOW)
+    {
+      __asm__ __volatile__ ("fadd %0, %1, %1"
+			    : "=f" (tmp)
+			    : "f" (fp_max));
+    }
+  if (_fex & FP_EX_UNDERFLOW)
+    {
+      __asm__ __volatile__ ("fmul %0, %1, %1"
+			    : "=f" (tmp)
+			    : "f" (fp_min));
+    }
+  if (_fex & FP_EX_INEXACT)
+    {
+      __asm__ __volatile__ ("fsub %0, %1, %2"
+			    : "=f" (tmp)
+			    : "f" (fp_max), "f" (fp_one));
+    }
+}
+
+#endif	/* !_SOFT_FLOAT  */
Index: libgcc/config/rs6000/float128-hw.c
===================================================================
--- libgcc/config/rs6000/float128-hw.c	(.../svn+ssh://meissner@gcc.gnu.org/svn/gcc/trunk/libgcc)	(revision 0)
+++ libgcc/config/rs6000/float128-hw.c	(.../libgcc)	(revision 232096)
@@ -0,0 +1,207 @@
+/* Automatic switching between software and hardware IEEE 128-bit
+   floating-point emulation for PowerPC.
+
+   Copyright (C) 2016 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/>.  */
+
+#include <soft-fp.h>
+#include <quad-float128.h>
+
+#ifndef __FLOAT128_HARDWARE__
+#error "This module must be compiled with IEEE 128-bit hardware support"
+#endif
+
+TFtype
+__addkf3_hw (TFtype a, TFtype b)
+{
+  return a + b;
+}
+
+TFtype
+__subkf3_hw (TFtype a, TFtype b)
+{
+  return a - b;
+}
+
+TFtype
+__mulkf3_hw (TFtype a, TFtype b)
+{
+  return a * b;
+}
+
+TFtype
+__divkf3_hw (TFtype a, TFtype b)
+{
+  return a / b;
+}
+
+TFtype
+__negkf2_hw (TFtype a)
+{
+  return -a;
+}
+
+TFtype
+__floatsikf_hw (SItype_ppc a)
+{
+  return (TFtype)a;
+}
+
+TFtype
+__floatunsikf_hw (USItype_ppc a)
+{
+  return (TFtype)a;
+}
+
+TFtype
+__floatdikf_hw (DItype_ppc a)
+{
+  return (TFtype)a;
+}
+
+TFtype
+__floatundikf_hw (UDItype_ppc a)
+{
+  return (TFtype)a;
+}
+
+SItype_ppc
+__fixkfsi_hw (TFtype a)
+{
+  return (SItype_ppc)a;
+}
+
+USItype_ppc
+__fixunskfsi_hw (TFtype a)
+{
+  return (USItype_ppc)a;
+}
+
+DItype_ppc
+__fixkfdi_hw (TFtype a)
+{
+  return (DItype_ppc)a;
+}
+
+UDItype_ppc
+__fixunskfdi_hw (TFtype a)
+{
+  return (UDItype_ppc)a;
+}
+
+TFtype
+__extendsfkf2_hw (float a)
+{
+  return (TFtype)a;
+}
+
+TFtype
+__extenddfkf2_hw (double a)
+{
+  return (TFtype)a;
+}
+
+float
+__trunckfsf2_hw (TFtype a)
+{
+  return (float)a;
+}
+
+double
+__trunckfdf2_hw (TFtype a)
+{
+  return (double)a;
+}
+
+/* __eqkf2 returns 0 if equal, or 1 if not equal or NaN.  */
+CMPtype
+__eqkf2_hw (TFtype a, TFtype b)
+{
+  return (a != b);
+}
+
+/* __gekf2 returns -1 if a < b, 0 if a == b, +1 if a > b, or -2 if NaN.  */
+CMPtype
+__gekf2_hw (TFtype a, TFtype b)
+{
+  if (a < b)
+    return -1;
+
+  else if (__builtin_isunordered (a, b))
+    return -2;
+
+  else if (a == b)
+    return 0;
+
+  return 1;
+}
+
+/* __lekf2 returns -1 if a < b, 0 if a == b, +1 if a > b, or +2 if NaN.  */
+CMPtype
+__lekf2_hw (TFtype a, TFtype b)
+{
+  if (a < b)
+    return -1;
+
+  else if (__builtin_isunordered (a, b))
+    return 2;
+
+  else if (a == b)
+    return 0;
+
+  return 1;
+}
+
+/* __unordkf2 returns 1 if Nan or 0 otherwise.  */
+CMPtype
+__unordkf2_hw (TFtype a, TFtype b)
+{
+  return (__builtin_isunordered (a, b)) ? 1 : 0;
+}
+
+/* Convert __float128 to __ibm128.  */
+__ibm128
+__extendkftf2_hw (TFtype value)
+{
+  __ibm128 ret;
+
+  CVT_FLOAT128_TO_IBM128 (ret, value);
+  return ret;
+}
+
+/* Convert __ibm128 to __float128.  */
+TFtype
+__trunctfkf2_hw (__ibm128 value)
+{
+  TFtype ret;
+
+  CVT_IBM128_TO_FLOAT128 (ret, value);
+  return ret;
+}
Index: libgcc/config/rs6000/floattikf.c
===================================================================
--- libgcc/config/rs6000/floattikf.c	(.../svn+ssh://meissner@gcc.gnu.org/svn/gcc/trunk/libgcc)	(revision 0)
+++ libgcc/config/rs6000/floattikf.c	(.../libgcc)	(revision 232096)
@@ -0,0 +1,51 @@
+/* Software floating-point emulation, convert a 128bit signed integer to IEEE
+   quad.
+
+   Copyright (C) 2016 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/fixunskfti.c
===================================================================
--- libgcc/config/rs6000/fixunskfti.c	(.../svn+ssh://meissner@gcc.gnu.org/svn/gcc/trunk/libgcc)	(revision 0)
+++ libgcc/config/rs6000/fixunskfti.c	(.../libgcc)	(revision 232096)
@@ -0,0 +1,51 @@
+/* Software floating-point emulation, convert IEEE quad to 128bit unsigned
+   integer.
+
+   Copyright (C) 2016 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/float128-ifunc.c
===================================================================
--- libgcc/config/rs6000/float128-ifunc.c	(.../svn+ssh://meissner@gcc.gnu.org/svn/gcc/trunk/libgcc)	(revision 0)
+++ libgcc/config/rs6000/float128-ifunc.c	(.../libgcc)	(revision 232096)
@@ -0,0 +1,358 @@
+/* Automatic switching between software and hardware IEEE 128-bit
+   floating-point emulation for PowerPC.
+
+   Copyright (C) 2016 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/>.  */
+
+#include <soft-fp.h>
+#include <quad-float128.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+
+#ifdef FLOAT128_HW_INSNS 
+#include <sys/auxv.h>
+
+/* Use the namespace clean version of getauxval.  However, not all versions of
+   sys/auxv.h declare it, so declare it here.  This code is intended to be
+   temporary until a suitable version of __builtin_cpu_supports is added that
+   allows us to tell quickly if the machine supports IEEE 128-bit hardware.  */
+extern unsigned long __getauxval (unsigned long);
+
+static int
+have_ieee_hw_p (void)
+{
+  static int ieee_hw_p = -1;
+
+  if (ieee_hw_p < 0)
+    {
+      char *p = (char *) __getauxval (AT_PLATFORM);
+
+      ieee_hw_p = 0;
+
+      /* Don't use atoi/strtol/strncmp/etc.  These may require the normal
+	 environment to be setup to set errno to 0, and the ifunc resolvers run
+	 before the whole glibc environment is initialized.  */
+      if (p && p[0] == 'p' && p[1] == 'o' && p[2] == 'w' && p[3] == 'e'
+	  && p[4] == 'r')
+	{
+	  long n = 0;
+	  char ch;
+
+	  p += 5;
+	  while ((ch = *p++) >= '0' && (ch <= '9'))
+	    n = (n * 10) + (ch - '0');
+
+	  if (n >= 9)
+	    ieee_hw_p = 1;
+	}
+    }
+
+  return ieee_hw_p;
+}
+
+#define SW_OR_HW(SW, HW) (have_ieee_hw_p () ? HW : SW)
+#else
+#define SW_OR_HW(SW, HW) (SW)
+#endif	/* ISA 3.0 hardware available.  */
+
+/* Resolvers.  */
+
+/* We do not provide ifunc resolvers for __fixkfti, __fixunskfti, __floattikf,
+   and __floatuntikf.  There is no ISA 3.0 instruction that converts between
+   128-bit integer types and 128-bit IEEE floating point, or vice versa.  So
+   use the emulator functions for these conversions.  */
+
+static void *__addkf3_resolve (void);
+static void *__subkf3_resolve (void);
+static void *__mulkf3_resolve (void);
+static void *__divkf3_resolve (void);
+static void *__negkf2_resolve (void);
+static void *__eqkf2_resolve (void);
+static void *__nekf2_resolve (void);
+static void *__gekf2_resolve (void);
+static void *__gtkf2_resolve (void);
+static void *__lekf2_resolve (void);
+static void *__ltkf2_resolve (void);
+static void *__unordkf2_resolve (void);
+static void *__extendsfkf2_resolve (void);
+static void *__extenddfkf2_resolve (void);
+static void *__trunckfsf2_resolve (void);
+static void *__trunckfdf2_resolve (void);
+static void *__fixkfsi_resolve (void);
+static void *__fixkfdi_resolve (void);
+static void *__fixunskfsi_resolve (void);
+static void *__fixunskfdi_resolve (void);
+static void *__floatsikf_resolve (void);
+static void *__floatdikf_resolve (void);
+static void *__floatunsikf_resolve (void);
+static void *__floatundikf_resolve (void);
+static void *__extendkftf2_resolve (void);
+static void *__trunctfkf2_resolve (void);
+
+static void *
+__addkf3_resolve (void)
+{
+  return (void *) SW_OR_HW (__addkf3_sw, __addkf3_hw);
+}
+
+static void *
+__subkf3_resolve (void)
+{
+  return (void *) SW_OR_HW (__subkf3_sw, __subkf3_hw);
+}
+
+static void *
+__mulkf3_resolve (void)
+{
+  return (void *) SW_OR_HW (__mulkf3_sw, __mulkf3_hw);
+}
+
+static void *
+__divkf3_resolve (void)
+{
+  return (void *) SW_OR_HW (__divkf3_sw, __divkf3_hw);
+}
+
+static void *
+__negkf2_resolve (void)
+{
+  return (void *) SW_OR_HW (__negkf2_sw, __negkf2_hw);
+}
+
+static void *
+__floatsikf_resolve (void)
+{
+  return (void *) SW_OR_HW (__floatsikf_sw, __floatsikf_hw);
+}
+
+static void *
+__floatdikf_resolve (void)
+{
+  return (void *) SW_OR_HW (__floatdikf_sw, __floatdikf_hw);
+}
+
+static void *
+__floatunsikf_resolve (void)
+{
+  return (void *) SW_OR_HW (__floatunsikf_sw, __floatunsikf_hw);
+}
+
+static void *
+__floatundikf_resolve (void)
+{
+  return (void *) SW_OR_HW (__floatundikf_sw, __floatundikf_hw);
+}
+
+static void *
+__fixkfsi_resolve (void)
+{
+  return (void *) SW_OR_HW (__fixkfsi_sw, __fixkfsi_hw);
+}
+
+static void *
+__fixkfdi_resolve (void)
+{
+  return (void *) SW_OR_HW (__fixkfdi_sw, __fixkfdi_hw);
+}
+
+static void *
+__fixunskfsi_resolve (void)
+{
+  return (void *) SW_OR_HW (__fixunskfsi_sw, __fixunskfsi_hw);
+}
+
+static void *
+__fixunskfdi_resolve (void)
+{
+  return (void *) SW_OR_HW (__fixunskfdi_sw, __fixunskfdi_hw);
+}
+
+static void *
+__extendsfkf2_resolve (void)
+{
+  return (void *) SW_OR_HW (__extendsfkf2_sw, __extendsfkf2_hw);
+}
+
+static void *
+__extenddfkf2_resolve (void)
+{
+  return (void *) SW_OR_HW (__extenddfkf2_sw, __extenddfkf2_hw);
+}
+
+static void *
+__trunckfsf2_resolve (void)
+{
+  return (void *) SW_OR_HW (__trunckfsf2_sw, __trunckfsf2_hw);
+}
+
+static void *
+__trunckfdf2_resolve (void)
+{
+  return (void *) SW_OR_HW (__trunckfdf2_sw, __trunckfdf2_hw);
+}
+
+static void *
+__extendkftf2_resolve (void)
+{
+  return (void *) SW_OR_HW (__extendkftf2_sw, __extendkftf2_hw);
+}
+
+static void *
+__trunctfkf2_resolve (void)
+{
+  return (void *) SW_OR_HW (__trunctfkf2_sw, __trunctfkf2_hw);
+}
+
+static void *
+__eqkf2_resolve (void)
+{
+  return (void *) SW_OR_HW (__eqkf2_sw, __eqkf2_hw);
+}
+
+static void *
+__gekf2_resolve (void)
+{
+  return (void *) SW_OR_HW (__gekf2_sw, __gekf2_hw);
+}
+
+static void *
+__lekf2_resolve (void)
+{
+  return (void *) SW_OR_HW (__lekf2_sw, __lekf2_hw);
+}
+
+static void *
+__unordkf2_resolve (void)
+{
+  return (void *) SW_OR_HW (__unordkf2_sw, __unordkf2_hw);
+}
+
+/* Resolve __nekf2, __gtkf2, __ltkf2 like __eqkf2, __gekf2, and __lekf2, since
+   the functions return the same values.  */
+
+static void *
+__nekf2_resolve (void)
+{
+  return (void *) SW_OR_HW (__eqkf2_sw, __eqkf2_hw);
+}
+
+static void *
+__gtkf2_resolve (void)
+{
+  return (void *) SW_OR_HW (__gekf2_sw, __gekf2_hw);
+}
+
+static void *
+__ltkf2_resolve (void)
+{
+  return (void *) SW_OR_HW (__lekf2_sw, __lekf2_hw);
+}
+
+
+
+/* Ifunc definitions.  */
+TFtype __addkf3 (TFtype, TFtype)
+  __attribute__ ((__ifunc__ ("__addkf3_resolve")));
+
+TFtype __subkf3 (TFtype, TFtype)
+  __attribute__ ((__ifunc__ ("__subkf3_resolve")));
+
+TFtype __mulkf3 (TFtype, TFtype)
+  __attribute__ ((__ifunc__ ("__mulkf3_resolve")));
+
+TFtype __divkf3 (TFtype, TFtype)
+  __attribute__ ((__ifunc__ ("__divkf3_resolve")));
+
+TFtype __negkf2 (TFtype)
+  __attribute__ ((__ifunc__ ("__negkf2_resolve")));
+
+CMPtype __eqkf2 (TFtype, TFtype)
+  __attribute__ ((__ifunc__ ("__eqkf2_resolve")));
+
+CMPtype __nekf2 (TFtype, TFtype)
+  __attribute__ ((__ifunc__ ("__nekf2_resolve")));
+
+CMPtype __gekf2 (TFtype, TFtype)
+  __attribute__ ((__ifunc__ ("__gekf2_resolve")));
+
+CMPtype __gtkf2 (TFtype, TFtype)
+  __attribute__ ((__ifunc__ ("__gtkf2_resolve")));
+
+CMPtype __lekf2 (TFtype, TFtype)
+  __attribute__ ((__ifunc__ ("__lekf2_resolve")));
+
+CMPtype __ltkf2 (TFtype, TFtype)
+  __attribute__ ((__ifunc__ ("__ltkf2_resolve")));
+
+CMPtype __unordkf2 (TFtype, TFtype)
+  __attribute__ ((__ifunc__ ("__unordkf2_resolve")));
+
+TFtype __extendsfkf2 (float)
+  __attribute__ ((__ifunc__ ("__extendsfkf2_resolve")));
+
+TFtype __extenddfkf2 (double)
+  __attribute__ ((__ifunc__ ("__extenddfkf2_resolve")));
+
+float __trunckfsf2 (TFtype)
+  __attribute__ ((__ifunc__ ("__trunckfsf2_resolve")));
+
+double __trunckfdf2 (TFtype)
+  __attribute__ ((__ifunc__ ("__trunckfdf2_resolve")));
+
+SItype_ppc __fixkfsi (TFtype)
+  __attribute__ ((__ifunc__ ("__fixkfsi_resolve")));
+
+DItype_ppc __fixkfdi (TFtype)
+  __attribute__ ((__ifunc__ ("__fixkfdi_resolve")));
+
+USItype_ppc __fixunskfsi (TFtype)
+  __attribute__ ((__ifunc__ ("__fixunskfsi_resolve")));
+
+UDItype_ppc __fixunskfdi (TFtype)
+  __attribute__ ((__ifunc__ ("__fixunskfdi_resolve")));
+
+TFtype __floatsikf (SItype_ppc)
+  __attribute__ ((__ifunc__ ("__floatsikf_resolve")));
+
+TFtype __floatdikf (DItype_ppc)
+  __attribute__ ((__ifunc__ ("__floatdikf_resolve")));
+
+TFtype __floatunsikf (USItype_ppc)
+  __attribute__ ((__ifunc__ ("__floatunsikf_resolve")));
+
+TFtype __floatundikf (UDItype_ppc)
+  __attribute__ ((__ifunc__ ("__floatundikf_resolve")));
+
+__ibm128 __extendkftf2 (TFtype)
+  __attribute__ ((__ifunc__ ("__extendkftf2_resolve")));
+
+TFtype __trunctfkf2 (__ibm128)
+  __attribute__ ((__ifunc__ ("__trunctfkf2_resolve")));
Index: libgcc/config/rs6000/fixkfti.c
===================================================================
--- libgcc/config/rs6000/fixkfti.c	(.../svn+ssh://meissner@gcc.gnu.org/svn/gcc/trunk/libgcc)	(revision 0)
+++ libgcc/config/rs6000/fixkfti.c	(.../libgcc)	(revision 232096)
@@ -0,0 +1,51 @@
+/* Software floating-point emulation, convert IEEE quad to 128bit signed
+   integer.
+
+   Copyright (C) 2016 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/floatuntikf.c
===================================================================
--- libgcc/config/rs6000/floatuntikf.c	(.../svn+ssh://meissner@gcc.gnu.org/svn/gcc/trunk/libgcc)	(revision 0)
+++ libgcc/config/rs6000/floatuntikf.c	(.../libgcc)	(revision 232096)
@@ -0,0 +1,51 @@
+/* Software floating-point emulation, convert a 128bit unsigned integer to IEEE
+   quad.
+
+   Copyright (C) 2016 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	(.../svn+ssh://meissner@gcc.gnu.org/svn/gcc/trunk/libgcc)	(revision 0)
+++ libgcc/config/rs6000/quad-float128.h	(.../libgcc)	(revision 232096)
@@ -0,0 +1,203 @@
+/* Software floating-point emulation.
+   Definitions for IEEE Quad Precision on the PowerPC.
+   Copyright (C) 2016 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
+
+/* 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 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);
+extern TFtype __floatunsikf_sw (USItype_ppc);
+extern TFtype __floatundikf_sw (UDItype_ppc);
+extern __ibm128 __extendkftf2_sw (TFtype);
+extern TFtype __trunctfkf2_sw (__ibm128);
+
+#ifdef _ARCH_PPC64
+/* We do not provide ifunc resolvers for __fixkfti, __fixunskfti, __floattikf,
+   and __floatuntikf.  There is no ISA 3.0 instruction that converts between
+   128-bit integer types and 128-bit IEEE floating point, or vice versa.  So
+   use the emulator functions for these conversions.  */
+
+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 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);
+extern TFtype __floatunsikf_hw (USItype_ppc);
+extern TFtype __floatundikf_hw (UDItype_ppc);
+extern __ibm128 __extendkftf2_hw (TFtype);
+extern TFtype __trunctfkf2_hw (__ibm128);
+
+/* 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 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);
+extern TFtype __floatunsikf (USItype_ppc);
+extern TFtype __floatundikf (UDItype_ppc);
+extern __ibm128 __extendkftf2 (TFtype);
+extern TFtype __trunctfkf2 (__ibm128);
+
+#ifdef __LITTLE_ENDIAN__
+#define HIGH_WORD	1
+#define LOW_WORD	0
+#else
+#define HIGH_WORD	0
+#define LOW_WORD	1
+#endif
+
+/* 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.  */
+
+#define CVT_FLOAT128_TO_IBM128(RESULT, VALUE)				\
+{									\
+  double __high, __low;							\
+  __float128 __value = (VALUE);						\
+									\
+  __high = (double) __value;						\
+  if (__builtin_isnan (__high) || __builtin_isinf (__high))		\
+    __low = 0.0;							\
+									\
+  else									\
+    {									\
+      double __high_temp;						\
+									\
+      __low = (double) (__value - (__float128)__high);			\
+      /* now renormalized move the high/low into canonical IBM long	\
+	 double form.  */						\
+      __high_temp = __high + __low;					\
+      __low = (__high - __high_temp) + __low;				\
+      __high = __high_temp;						\
+    }									\
+									\
+  RESULT = __builtin_pack_ibm128 (__high, __low);			\
+}
+
+#define CVT_IBM128_TO_FLOAT128(RESULT, VALUE)				\
+{									\
+  __ibm128 __value = (VALUE);						\
+  double __high = __builtin_unpack_ibm128 (__value, HIGH_WORD);		\
+  double __low = __builtin_unpack_ibm128 (__value, LOW_WORD);		\
+									\
+  /* Handle the special cases of NAN and inifinity.  */			\
+  if (__builtin_isnan (__high) || __builtin_isinf (__high))		\
+    RESULT = (__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.  */	\
+  else if (__low == 0.0)						\
+    RESULT = (__float128) __high;					\
+									\
+  else									\
+    RESULT = ((__float128)__high) + ((__float128)__low);		\
+}
Index: libgcc/config/rs6000/extendkftf2-sw.c
===================================================================
--- libgcc/config/rs6000/extendkftf2-sw.c	(.../svn+ssh://meissner@gcc.gnu.org/svn/gcc/trunk/libgcc)	(revision 0)
+++ libgcc/config/rs6000/extendkftf2-sw.c	(.../libgcc)	(revision 232096)
@@ -0,0 +1,49 @@
+/* Software IEEE 128-bit floating-point emulation for PowerPC.
+
+   Copyright (C) 2016 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.  */
+
+#ifdef __FLOAT128_HARDWARE__
+#error "This module must not be compiled with IEEE 128-bit hardware support"
+#endif
+
+#include "soft-fp.h"
+#include "quad-float128.h"
+
+__ibm128
+__extendkftf2_sw (__float128 value)
+{
+  __ibm128 ret;
+
+  CVT_FLOAT128_TO_IBM128 (ret, value);
+  return ret;
+}
Index: libgcc/config/rs6000/trunctfkf2-sw.c
===================================================================
--- libgcc/config/rs6000/trunctfkf2-sw.c	(.../svn+ssh://meissner@gcc.gnu.org/svn/gcc/trunk/libgcc)	(revision 0)
+++ libgcc/config/rs6000/trunctfkf2-sw.c	(.../libgcc)	(revision 232096)
@@ -0,0 +1,49 @@
+/* Software IEEE 128-bit floating-point emulation for PowerPC.
+
+   Copyright (C) 2016 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.  */
+
+#ifdef __FLOAT128_HARDWARE__
+#error "This module must not be compiled with IEEE 128-bit hardware support"
+#endif
+
+#include "soft-fp.h"
+#include "quad-float128.h"
+
+__float128
+__trunctfkf2_sw (__ibm128 value)
+{
+  __float128 ret;
+
+  CVT_IBM128_TO_FLOAT128 (ret, value);
+  return ret;
+}
Index: libgcc/config/rs6000/t-float128
===================================================================
--- libgcc/config/rs6000/t-float128	(.../svn+ssh://meissner@gcc.gnu.org/svn/gcc/trunk/libgcc)	(revision 0)
+++ libgcc/config/rs6000/t-float128	(.../libgcc)	(revision 232096)
@@ -0,0 +1,95 @@
+# 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 -sw.c,$(fp128_softfp_funcs))
+fp128_softfp_static_obj	= $(addsuffix -sw$(objext),$(fp128_softfp_funcs))
+fp128_softfp_shared_obj	= $(addsuffix -sw_s$(objext),$(fp128_softfp_funcs))
+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 float128-ifunc
+
+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_hw_funcs)
+
+fp128_src		= $(fp128_softfp_src) $(fp128_ppc_src) \
+			  $(fp128_hw_src)
+
+fp128_obj		= $(fp128_softfp_obj) $(fp128_ppc_obj) \
+			  $(fp128_hw_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
+
+# Build the emulator without ISA 3.0 hardware support.
+FP128_CFLAGS_SW		 = -Wno-type-limits -mvsx -mfloat128 \
+			   -mno-float128-hardware \
+			   -I$(srcdir)/soft-fp \
+			   -I$(srcdir)/config/rs6000 \
+			   $(FLOAT128_HW_INSNS)
+
+$(fp128_softfp_obj)	 : INTERNAL_CFLAGS += $(FP128_CFLAGS_SW)
+$(fp128_ppc_obj)	 : INTERNAL_CFLAGS += $(FP128_CFLAGS_SW)
+$(fp128_obj)		 : $(fp128_includes)
+$(fp128_obj)		 : $(srcdir)/config/rs6000/quad-float128.h
+
+$(fp128_softfp_src) : $(srcdir)/soft-fp/$(subst -sw,,$(subst kf,tf,$@)) $(fp128_dep)
+	@src="$(srcdir)/soft-fp/$(subst -sw,,$(subst kf,tf,$@))"; \
+	echo "Create $@"; \
+	(echo "/* file created from $$src */"; \
+	 echo; \
+	 sed -f $(fp128_sed) < $$src) > $@
+
+.PHONY: test clean-float128
+
+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;
+
+clean-float128:
+	rm -rf $(fp128_softfp_src)
+	@$(MULTICLEAN) multi-clean DO=clean-float128
+
+# 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	(.../svn+ssh://meissner@gcc.gnu.org/svn/gcc/trunk/libgcc)	(revision 0)
+++ libgcc/config/rs6000/float128-sed	(.../libgcc)	(revision 232096)
@@ -0,0 +1,25 @@
+s/__addtf3/__addkf3_sw/g
+s/__divtf3/__divkf3_sw/g
+s/__eqtf2/__eqkf2_sw/g
+s/__extenddftf2/__extenddfkf2_sw/g
+s/__extendsftf2/__extendsfkf2_sw/g
+s/__fixtfdi/__fixkfdi_sw/g
+s/__fixtfsi/__fixkfsi_sw/g
+s/__fixunstfdi/__fixunskfdi_sw/g
+s/__fixunstfsi/__fixunskfsi_sw/g
+s/__floatditf/__floatdikf_sw/g
+s/__floatsitf/__floatsikf_sw/g
+s/__floatunditf/__floatundikf_sw/g
+s/__floatunsitf/__floatunsikf_sw/g
+s/__getf2/__gekf2_sw/g
+s/__gttf2/__gtkf2_sw/g
+s/__letf2/__lekf2_sw/g
+s/__lttf2/__ltkf2_sw/g
+s/__multf3/__mulkf3_sw/g
+s/__negtf2/__negkf2_sw/g
+s/__netf2/__nekf2_sw/g
+s/quad[.]h/quad-float128.h/g
+s/__subtf3/__subkf3_sw/g
+s/__trunctfdf2/__trunckfdf2_sw/g
+s/__trunctfsf2/__trunckfsf2_sw/g
+s/__unordtf2/__unordkf2_sw/g
Index: libgcc/config/rs6000/t-float128-hw
===================================================================
--- libgcc/config/rs6000/t-float128-hw	(.../svn+ssh://meissner@gcc.gnu.org/svn/gcc/trunk/libgcc)	(revision 0)
+++ libgcc/config/rs6000/t-float128-hw	(.../libgcc)	(revision 232096)
@@ -0,0 +1,24 @@
+# Support for adding __float128 hardware support to the powerpc.
+# Tell the float128 functions that the ISA 3.0 hardware support can
+# be compiled it to be selected via IFUNC functions.
+
+FLOAT128_HW_INSNS	= -DFLOAT128_HW_INSNS
+
+# New functions for hardware support
+fp128_hw_funcs		= float128-hw
+fp128_hw_src		= $(srcdir)/config/rs6000/float128-hw.c
+fp128_hw_static_obj	= float128-hw$(objext)
+fp128_hw_shared_obj	= float128-hw_s$(objext)
+fp128_hw_obj		= $(fp128_hw_static_obj) $(fp128_hw_shared_obj)
+
+# Build the hardware support functions with appropriate hardware support
+FP128_CFLAGS_HW		 = -Wno-type-limits -mvsx -mfloat128 \
+			   -mpower8-vector -mpower9-vector \
+			   -mfloat128-hardware \
+			   -I$(srcdir)/soft-fp \
+			   -I$(srcdir)/config/rs6000 \
+			   $(FLOAT128_HW_INSNS)
+
+$(fp128_hw_obj)		 : INTERNAL_CFLAGS += $(FP128_CFLAGS_HW)
+$(fp128_hw_obj)		 : $(srcdir)/config/rs6000/t-float128-hw
+
Index: libgcc/config/rs6000/sfp-machine.h
===================================================================
--- libgcc/config/rs6000/sfp-machine.h	(.../svn+ssh://meissner@gcc.gnu.org/svn/gcc/trunk/libgcc)	(revision 232093)
+++ libgcc/config/rs6000/sfp-machine.h	(.../libgcc)	(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,53 @@ typedef int __gcc_CMPtype __attribute__ 
 # endif
 #endif
 
+/* Only provide exception support if we have hardware floating point and we can
+   execute the mtfsf instruction.  This would only be true if we are using the
+   emulation routines for IEEE 128-bit floating point on pre-ISA 3.0 machines
+   without the IEEE 128-bit floating point support.  */
+
+#ifndef _SOFT_FLOAT
+#define ISA_BIT(x) (1LL << (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)
+#endif	/* !_SOFT_FLOAT */
 
 /* Define ALIASNAME as a strong alias for NAME.  */
 # define strong_alias(name, aliasname) _strong_alias(name, aliasname)
Index: libgcc/configure.ac
===================================================================
--- libgcc/configure.ac	(.../svn+ssh://meissner@gcc.gnu.org/svn/gcc/trunk/libgcc)	(revision 232093)
+++ libgcc/configure.ac	(.../libgcc)	(working copy)
@@ -373,6 +373,31 @@ 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])])
+
+  AC_CACHE_CHECK([whether the PowerPC compiler can do hardware __float128],
+		 [libgcc_cv_powerpc_float128_hw],
+		 [AC_COMPILE_IFELSE(
+    [#pragma GCC target ("cpu=power9,float128,float128-hardware")
+     #include <sys/auxv.h>
+     __float128 add (__float128 a, __float128 b)
+     {
+       __float128 ret;
+       __asm__ ("xsaddqp %0,%1,%2" : "=v" (ret) : "v" (a), "v" (b));
+       return ret;
+     }],
+    [libgcc_cv_powerpc_float128_hw=yes],
+    [libgcc_cv_powerpc_float128_hw=no])])
+esac
+
 # Collect host-machine-specific information.
 . ${srcdir}/config.host
 
Index: libgcc/configure
===================================================================
--- libgcc/configure	(.../svn+ssh://meissner@gcc.gnu.org/svn/gcc/trunk/libgcc)	(revision 232093)
+++ libgcc/configure	(.../libgcc)	(working copy)
@@ -4766,6 +4766,55 @@ 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; }
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the PowerPC compiler can do hardware __float128" >&5
+$as_echo_n "checking whether the PowerPC compiler can do hardware __float128... " >&6; }
+if test "${libgcc_cv_powerpc_float128_hw+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#pragma GCC target ("cpu=power9,float128,float128-hardware")
+     #include <sys/auxv.h>
+     __float128 add (__float128 a, __float128 b)
+     {
+       __float128 ret;
+       __asm__ ("xsaddqp %0,%1,%2" : "=v" (ret) : "v" (a), "v" (b));
+       return ret;
+     }
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  libgcc_cv_powerpc_float128_hw=yes
+else
+  libgcc_cv_powerpc_float128_hw=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_hw" >&5
+$as_echo "$libgcc_cv_powerpc_float128_hw" >&6; }
+esac
+
 # Collect host-machine-specific information.
 . ${srcdir}/config.host
 


More information about the Gcc-patches mailing list