public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH], PowerPC IEEE 128-bit fp, #11 (enable libgcc conversions)
@ 2015-12-29 16:38 Michael Meissner
  2015-12-29 16:53 ` Michael Meissner
                   ` (3 more replies)
  0 siblings, 4 replies; 18+ messages in thread
From: Michael Meissner @ 2015-12-29 16:38 UTC (permalink / raw)
  To: gcc-patches, dje.gcc

[-- Attachment #1: Type: text/plain, Size: 5247 bytes --]

This patch enables support of the __float128 software emulation functions in
libgcc.  The patch is reworked from previous versions of this patch (listed as
patch #8).

This patch adds support for declaring emulation functions that either use the
software emulation functions from the soft-fp subdirectory converted for
PowerPC __float128 via sed, or by using the hardware instructions that will be
present in ISA 3.0 (power9).  Thus if you compile code for power7/power8 and
run it on a power9 system, it use the hardware support when running on power9.

I removed the old comparison functions that was in previous versions of this
patch, and instead went with the standard EQ, GE, LE, and UNORD software
emulation support (patch #10 changes the compiler to use these functions).

This patch adds support to use the hardware rounding modes and exceptions for
software emulation that was done by Steven Munroe and Tulio Magno.

The __float128 support is only enabled on 64-bit PowerPC Linux systems, where
the base compler targets at least power7.  On big endian systems, you can use
__float128 in 32-bit mode, but the support functions are not built on a purely
32-bit system.

At the moment, there is no support for converting between decimal types and
__float128, nor for the complex __float128 support.  These are being worked on,
and should be done in the GCC 7.x time frame.  However, it is important to add
the software emulation support in GCC 6.x now so that most users that want to
use IEEE 128-bit floating point can use it, and that we can work on the glibc
issues to fully support __float128 in the GCC 7.x time frame.  There might be
problems that need to be fixed, but without the libgcc changes, nobody can use
__float128.

I have done bootstraps on a big-endian power7 system and little-endian power8
system with no regressions.  I have also built a compiler on a SLES 11.3 system
to make sure that it builds on systems without the ISA 3.0 instructions (in
this case, the ifunc resolver always returns the software emulation function).
Is this ok to install in the tree along with IEEE patch #10?

2015-12-29  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-sw.c: New file to convert signed 128-bit
	integers to IEEE 128-bit floating point.

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

	* config/rs6000/fixkfti-sw.c: New file to convert IEEE 128-bit
	floating point to signed 128-bit integer.

	* 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/fixunskfti-sw.c: New file to convert IEEE 128-bit
	floating point to unsigned 128-bit integer.

	* config/rs6000/extendkftf2-sw.c: New file to convert IBM extended
	double to IEEE 128-bit floating point.

	* config/rs6000/floatuntikf-sw.c: New file to convert unsigned
	128-bit integer to IEEE 128-bit floating point.

	* config/rs6000/trunctfkf2-sw.c: New file to convert IEEE 128-bit
	floating point to IBM extended double.

	* config/rs6000/t-float128: New file to build IEEE 128-bit
	floating point emulator functions.

	* config/rs6000/t-float128-hw: New file to build IEEE 128-bit
	floating point emulator functions using ISA 3.0 hardware
	instructions.

	* 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.
	(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.

	* Makefile.in (EXTRA_CLEAN): Add extra files to be delete with
	make clean.
	(FLAGS_TO_PASS): Likewise.
	(clean rule): Likewise.

	* 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

[-- Attachment #2: ieee128-patch11b --]
[-- Type: text/plain, Size: 51490 bytes --]

Index: libgcc/config/rs6000/floattikf-sw.c
===================================================================
--- libgcc/config/rs6000/floattikf-sw.c	(.../svn+ssh://meissner@gcc.gnu.org/svn/gcc/trunk/libgcc)	(revision 0)
+++ libgcc/config/rs6000/floattikf-sw.c	(.../libgcc)	(revision 231985)
@@ -0,0 +1,51 @@
+/* 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_sw (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/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 231985)
@@ -0,0 +1,188 @@
+/* Automatic switching between software and hardware 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:
+	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 (__builtin_isunordered (a, b) || (a != b)) ? 1 : 0;
+}
+
+/* __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 (__builtin_isunordered (a, b))
+    return -2;
+
+  else if (a < b)
+    return -1;
+
+  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 (__builtin_isunordered (a, b))
+    return 2;
+
+  else if (a < b)
+    return -1;
+
+  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;
+}
+
Index: libgcc/config/rs6000/fixkfti-sw.c
===================================================================
--- libgcc/config/rs6000/fixkfti-sw.c	(.../svn+ssh://meissner@gcc.gnu.org/svn/gcc/trunk/libgcc)	(revision 0)
+++ libgcc/config/rs6000/fixkfti-sw.c	(.../libgcc)	(revision 231985)
@@ -0,0 +1,51 @@
+/* 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_sw (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/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 231985)
@@ -0,0 +1,341 @@
+/* Automatic switching between software and hardware 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:
+	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>
+#include <sys/auxv.h>
+
+#if defined(FLOAT128_HW_INSNS) && defined(AT_PLATFORM)
+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;
+
+      /* Use __builtin_cpu_supports once it is supported by the PowerPC.  */
+      if (p && p[0] == 'p' && p[1] == 'o' && p[2] == 'w' && p[3] == 'e'
+	  && p[4] == 'r')
+	{
+	  long n = 0;
+	  char ch;
+
+	  /* Don't use atoi/strtol/etc.  These require the normal environment
+	     to be setup to set errno to 0, and the ifunc resolvers run before
+	     the whole glibc environment is initialized.  */
+	  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.  */
+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 *__gekf2_resolve (void);
+static void *__lekf2_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);
+
+#ifdef _ARCH_PPC64
+static void *__fixkfti_resolve (void);
+static void *__fixunskfti_resolve (void);
+static void *__floattikf_resolve (void);
+static void *__floatuntikf_resolve (void);
+#endif	/* _ARCH_PPC64.  */
+
+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 *
+__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);
+}
+
+#ifdef _ARCH_PPC64
+/* For now, just use the emulator for 128-bit integer types.  */
+static void *
+__fixkfti_resolve (void)
+{
+  return (void *) __fixkfti_sw;
+}
+
+static void *
+__fixunskfti_resolve (void)
+{
+  return (void *) __fixunskfti_sw;
+}
+
+static void *
+__floattikf_resolve (void)
+{
+  return (void *) __floattikf_sw;
+}
+
+static void *
+__floatuntikf_resolve (void)
+{
+  return (void *) __floatuntikf_sw;
+}
+#endif	/* _ARCH_PPC64.  */
+
+\f
+/* 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 __gekf2 (TFtype, TFtype)
+  __attribute__ ((__ifunc__ ("__gekf2_resolve")));
+
+CMPtype __lekf2 (TFtype, TFtype)
+  __attribute__ ((__ifunc__ ("__lekf2_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")));
+
+#ifdef _ARCH_PPC64
+TItype_ppc __fixkfti (TFtype)
+  __attribute__ ((__ifunc__ ("__fixkfti_resolve")));
+
+UTItype_ppc __fixunskfti (TFtype)
+  __attribute__ ((__ifunc__ ("__fixunskfti_resolve")));
+
+TFtype __floattikf (TItype_ppc)
+  __attribute__ ((__ifunc__ ("__floattikf_resolve")));
+
+TFtype __floatuntikf (UTItype_ppc)
+  __attribute__ ((__ifunc__ ("__floatuntikf_resolve")));
+#endif
+
Index: libgcc/config/rs6000/fixunskfti-sw.c
===================================================================
--- libgcc/config/rs6000/fixunskfti-sw.c	(.../svn+ssh://meissner@gcc.gnu.org/svn/gcc/trunk/libgcc)	(revision 0)
+++ libgcc/config/rs6000/fixunskfti-sw.c	(.../libgcc)	(revision 231985)
@@ -0,0 +1,51 @@
+/* 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_sw (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/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 231985)
@@ -0,0 +1,63 @@
+/* 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:
+	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/floatuntikf-sw.c
===================================================================
--- libgcc/config/rs6000/floatuntikf-sw.c	(.../svn+ssh://meissner@gcc.gnu.org/svn/gcc/trunk/libgcc)	(revision 0)
+++ libgcc/config/rs6000/floatuntikf-sw.c	(.../libgcc)	(revision 231985)
@@ -0,0 +1,51 @@
+/* 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_sw (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/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 231985)
@@ -0,0 +1,71 @@
+/* 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:
+	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/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 231985)
@@ -0,0 +1,91 @@
+# 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-sw floatuntikf-sw fixkfti-sw fixunskfti-sw \
+			  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
+
+EXTRA_CLEAN		+= $(fp128_softfp_src)
+
+# 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) > $@
+
+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/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 231985)
@@ -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-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 231981)
@@ -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/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 231981)
@@ -0,0 +1,148 @@
+/* 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
+
+/* 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);
+
+#ifdef _ARCH_PPC64
+extern TItype_ppc __fixkfti_sw (TFtype);
+extern UTItype_ppc __fixunskfti_sw (TFtype);
+extern TFtype __floattikf_sw (TItype_ppc);
+extern TFtype __floatuntikf_sw (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);
+
+#ifdef _ARCH_PPC64
+extern TItype_ppc __fixkfti_hw (TFtype);
+extern UTItype_ppc __fixunskfti_hw (TFtype);
+extern TFtype __floattikf_hw (TItype_ppc);
+extern TFtype __floatuntikf_hw (UTItype_ppc);
+#endif
+
+/* 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 __gekf2 (TFtype, TFtype);
+extern CMPtype __lekf2 (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);
+
+#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/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 231981)
@@ -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/sfp-machine.h
===================================================================
--- libgcc/config/rs6000/sfp-machine.h	(.../svn+ssh://meissner@gcc.gnu.org/svn/gcc/trunk/libgcc)	(revision 231978)
+++ 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,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.host
===================================================================
--- libgcc/config.host	(.../svn+ssh://meissner@gcc.gnu.org/svn/gcc/trunk/libgcc)	(revision 231978)
+++ libgcc/config.host	(.../libgcc)	(working copy)
@@ -1063,6 +1063,15 @@ powerpc*-*-linux*)
 		exit 1
 		;;
 	esac
+
+	if test $libgcc_cv_powerpc_float128 = yes; then
+		tmake_file="${tmake_file} rs6000/t-float128"
+	fi
+
+	if test $libgcc_cv_powerpc_float128_hw = yes; then
+		tmake_file="${tmake_file} rs6000/t-float128-hw"
+	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	(.../svn+ssh://meissner@gcc.gnu.org/svn/gcc/trunk/libgcc)	(revision 231978)
+++ libgcc/Makefile.in	(.../libgcc)	(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	(.../svn+ssh://meissner@gcc.gnu.org/svn/gcc/trunk/libgcc)	(revision 231978)
+++ 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 231978)
+++ 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
 

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH], PowerPC IEEE 128-bit fp, #11 (enable libgcc conversions)
  2015-12-29 16:38 [PATCH], PowerPC IEEE 128-bit fp, #11 (enable libgcc conversions) Michael Meissner
@ 2015-12-29 16:53 ` Michael Meissner
  2015-12-29 20:26 ` David Edelsohn
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 18+ messages in thread
From: Michael Meissner @ 2015-12-29 16:53 UTC (permalink / raw)
  To: Michael Meissner, gcc-patches, dje.gcc

[-- Attachment #1: Type: text/plain, Size: 513 bytes --]

In my last patch (#11) on libgcc, I didn't submit the latest version of the
patch that allowed it to work on older systems that did not have the include
sys/auxv.h. This patch fixes that by moving the include of sys/auxv.h to within
the code protected by the define that says we have IEEE 128-bit floating point
hardware support and the include file sys/auxv.h.

-- 
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

[-- Attachment #2: ieee128-patch11b --]
[-- Type: text/plain, Size: 51463 bytes --]

Index: libgcc/config/rs6000/floattikf-sw.c
===================================================================
--- libgcc/config/rs6000/floattikf-sw.c	(.../svn+ssh://meissner@gcc.gnu.org/svn/gcc/trunk/libgcc)	(revision 0)
+++ libgcc/config/rs6000/floattikf-sw.c	(.../libgcc)	(revision 231985)
@@ -0,0 +1,51 @@
+/* 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_sw (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/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 231985)
@@ -0,0 +1,188 @@
+/* Automatic switching between software and hardware 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:
+	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 (__builtin_isunordered (a, b) || (a != b)) ? 1 : 0;
+}
+
+/* __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 (__builtin_isunordered (a, b))
+    return -2;
+
+  else if (a < b)
+    return -1;
+
+  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 (__builtin_isunordered (a, b))
+    return 2;
+
+  else if (a < b)
+    return -1;
+
+  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;
+}
+
Index: libgcc/config/rs6000/fixkfti-sw.c
===================================================================
--- libgcc/config/rs6000/fixkfti-sw.c	(.../svn+ssh://meissner@gcc.gnu.org/svn/gcc/trunk/libgcc)	(revision 0)
+++ libgcc/config/rs6000/fixkfti-sw.c	(.../libgcc)	(revision 231985)
@@ -0,0 +1,51 @@
+/* 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_sw (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/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 231995)
@@ -0,0 +1,342 @@
+/* Automatic switching between software and hardware 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:
+	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>
+
+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;
+
+      /* Use __builtin_cpu_supports once it is supported by the PowerPC.  */
+      if (p && p[0] == 'p' && p[1] == 'o' && p[2] == 'w' && p[3] == 'e'
+	  && p[4] == 'r')
+	{
+	  long n = 0;
+	  char ch;
+
+	  /* Don't use atoi/strtol/etc.  These require the normal environment
+	     to be setup to set errno to 0, and the ifunc resolvers run before
+	     the whole glibc environment is initialized.  */
+	  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.  */
+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 *__gekf2_resolve (void);
+static void *__lekf2_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);
+
+#ifdef _ARCH_PPC64
+static void *__fixkfti_resolve (void);
+static void *__fixunskfti_resolve (void);
+static void *__floattikf_resolve (void);
+static void *__floatuntikf_resolve (void);
+#endif	/* _ARCH_PPC64.  */
+
+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 *
+__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);
+}
+
+#ifdef _ARCH_PPC64
+/* For now, just use the emulator for 128-bit integer types.  */
+static void *
+__fixkfti_resolve (void)
+{
+  return (void *) __fixkfti_sw;
+}
+
+static void *
+__fixunskfti_resolve (void)
+{
+  return (void *) __fixunskfti_sw;
+}
+
+static void *
+__floattikf_resolve (void)
+{
+  return (void *) __floattikf_sw;
+}
+
+static void *
+__floatuntikf_resolve (void)
+{
+  return (void *) __floatuntikf_sw;
+}
+#endif	/* _ARCH_PPC64.  */
+
+\f
+/* 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 __gekf2 (TFtype, TFtype)
+  __attribute__ ((__ifunc__ ("__gekf2_resolve")));
+
+CMPtype __lekf2 (TFtype, TFtype)
+  __attribute__ ((__ifunc__ ("__lekf2_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")));
+
+#ifdef _ARCH_PPC64
+TItype_ppc __fixkfti (TFtype)
+  __attribute__ ((__ifunc__ ("__fixkfti_resolve")));
+
+UTItype_ppc __fixunskfti (TFtype)
+  __attribute__ ((__ifunc__ ("__fixunskfti_resolve")));
+
+TFtype __floattikf (TItype_ppc)
+  __attribute__ ((__ifunc__ ("__floattikf_resolve")));
+
+TFtype __floatuntikf (UTItype_ppc)
+  __attribute__ ((__ifunc__ ("__floatuntikf_resolve")));
+#endif
+
Index: libgcc/config/rs6000/fixunskfti-sw.c
===================================================================
--- libgcc/config/rs6000/fixunskfti-sw.c	(.../svn+ssh://meissner@gcc.gnu.org/svn/gcc/trunk/libgcc)	(revision 0)
+++ libgcc/config/rs6000/fixunskfti-sw.c	(.../libgcc)	(revision 231985)
@@ -0,0 +1,51 @@
+/* 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_sw (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/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 231985)
@@ -0,0 +1,63 @@
+/* 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:
+	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/floatuntikf-sw.c
===================================================================
--- libgcc/config/rs6000/floatuntikf-sw.c	(.../svn+ssh://meissner@gcc.gnu.org/svn/gcc/trunk/libgcc)	(revision 0)
+++ libgcc/config/rs6000/floatuntikf-sw.c	(.../libgcc)	(revision 231985)
@@ -0,0 +1,51 @@
+/* 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_sw (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/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 231985)
@@ -0,0 +1,71 @@
+/* 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:
+	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/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 231985)
@@ -0,0 +1,91 @@
+# 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-sw floatuntikf-sw fixkfti-sw fixunskfti-sw \
+			  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
+
+EXTRA_CLEAN		+= $(fp128_softfp_src)
+
+# 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) > $@
+
+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/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 231985)
@@ -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-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 231981)
@@ -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/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 231981)
@@ -0,0 +1,148 @@
+/* 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
+
+/* 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);
+
+#ifdef _ARCH_PPC64
+extern TItype_ppc __fixkfti_sw (TFtype);
+extern UTItype_ppc __fixunskfti_sw (TFtype);
+extern TFtype __floattikf_sw (TItype_ppc);
+extern TFtype __floatuntikf_sw (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);
+
+#ifdef _ARCH_PPC64
+extern TItype_ppc __fixkfti_hw (TFtype);
+extern UTItype_ppc __fixunskfti_hw (TFtype);
+extern TFtype __floattikf_hw (TItype_ppc);
+extern TFtype __floatuntikf_hw (UTItype_ppc);
+#endif
+
+/* 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 __gekf2 (TFtype, TFtype);
+extern CMPtype __lekf2 (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);
+
+#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/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 231981)
@@ -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/sfp-machine.h
===================================================================
--- libgcc/config/rs6000/sfp-machine.h	(.../svn+ssh://meissner@gcc.gnu.org/svn/gcc/trunk/libgcc)	(revision 231978)
+++ 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,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.host
===================================================================
--- libgcc/config.host	(.../svn+ssh://meissner@gcc.gnu.org/svn/gcc/trunk/libgcc)	(revision 231978)
+++ libgcc/config.host	(.../libgcc)	(working copy)
@@ -1063,6 +1063,15 @@ powerpc*-*-linux*)
 		exit 1
 		;;
 	esac
+
+	if test $libgcc_cv_powerpc_float128 = yes; then
+		tmake_file="${tmake_file} rs6000/t-float128"
+	fi
+
+	if test $libgcc_cv_powerpc_float128_hw = yes; then
+		tmake_file="${tmake_file} rs6000/t-float128-hw"
+	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	(.../svn+ssh://meissner@gcc.gnu.org/svn/gcc/trunk/libgcc)	(revision 231978)
+++ libgcc/Makefile.in	(.../libgcc)	(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	(.../svn+ssh://meissner@gcc.gnu.org/svn/gcc/trunk/libgcc)	(revision 231978)
+++ 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 231978)
+++ 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
 

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH], PowerPC IEEE 128-bit fp, #11 (enable libgcc conversions)
  2015-12-29 16:38 [PATCH], PowerPC IEEE 128-bit fp, #11 (enable libgcc conversions) Michael Meissner
  2015-12-29 16:53 ` Michael Meissner
@ 2015-12-29 20:26 ` David Edelsohn
  2015-12-31 20:30 ` Joseph Myers
  2016-01-06 22:48 ` [PATCH], PowerPC IEEE 128-bit fp, #11-rev2 " Michael Meissner
  3 siblings, 0 replies; 18+ messages in thread
From: David Edelsohn @ 2015-12-29 20:26 UTC (permalink / raw)
  To: Michael Meissner, GCC Patches, Joseph S. Myers

On Tue, Dec 29, 2015 at 11:38 AM, Michael Meissner
<meissner@linux.vnet.ibm.com> wrote:
> This patch enables support of the __float128 software emulation functions in
> libgcc.  The patch is reworked from previous versions of this patch (listed as
> patch #8).
>
> This patch adds support for declaring emulation functions that either use the
> software emulation functions from the soft-fp subdirectory converted for
> PowerPC __float128 via sed, or by using the hardware instructions that will be
> present in ISA 3.0 (power9).  Thus if you compile code for power7/power8 and
> run it on a power9 system, it use the hardware support when running on power9.
>
> I removed the old comparison functions that was in previous versions of this
> patch, and instead went with the standard EQ, GE, LE, and UNORD software
> emulation support (patch #10 changes the compiler to use these functions).
>
> This patch adds support to use the hardware rounding modes and exceptions for
> software emulation that was done by Steven Munroe and Tulio Magno.
>
> The __float128 support is only enabled on 64-bit PowerPC Linux systems, where
> the base compler targets at least power7.  On big endian systems, you can use
> __float128 in 32-bit mode, but the support functions are not built on a purely
> 32-bit system.
>
> At the moment, there is no support for converting between decimal types and
> __float128, nor for the complex __float128 support.  These are being worked on,
> and should be done in the GCC 7.x time frame.  However, it is important to add
> the software emulation support in GCC 6.x now so that most users that want to
> use IEEE 128-bit floating point can use it, and that we can work on the glibc
> issues to fully support __float128 in the GCC 7.x time frame.  There might be
> problems that need to be fixed, but without the libgcc changes, nobody can use
> __float128.
>
> I have done bootstraps on a big-endian power7 system and little-endian power8
> system with no regressions.  I have also built a compiler on a SLES 11.3 system
> to make sure that it builds on systems without the ISA 3.0 instructions (in
> this case, the ifunc resolver always returns the software emulation function).
> Is this ok to install in the tree along with IEEE patch #10?
>
> 2015-12-29  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-sw.c: New file to convert signed 128-bit
>         integers to IEEE 128-bit floating point.
>
>         * config/rs6000/float128-hw.c: New file for ISA 3.0 IEEE 128-bit
>         floating point hardware support.
>
>         * config/rs6000/fixkfti-sw.c: New file to convert IEEE 128-bit
>         floating point to signed 128-bit integer.
>
>         * 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/fixunskfti-sw.c: New file to convert IEEE 128-bit
>         floating point to unsigned 128-bit integer.
>
>         * config/rs6000/extendkftf2-sw.c: New file to convert IBM extended
>         double to IEEE 128-bit floating point.
>
>         * config/rs6000/floatuntikf-sw.c: New file to convert unsigned
>         128-bit integer to IEEE 128-bit floating point.
>
>         * config/rs6000/trunctfkf2-sw.c: New file to convert IEEE 128-bit
>         floating point to IBM extended double.
>
>         * config/rs6000/t-float128: New file to build IEEE 128-bit
>         floating point emulator functions.
>
>         * config/rs6000/t-float128-hw: New file to build IEEE 128-bit
>         floating point emulator functions using ISA 3.0 hardware
>         instructions.
>
>         * 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.
>         (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.
>
>         * Makefile.in (EXTRA_CLEAN): Add extra files to be delete with
>         make clean.
>         (FLAGS_TO_PASS): Likewise.
>         (clean rule): Likewise.
>
>         * configure.ac (powerpc*-*-linux*): Check whether the PowerPC
>         compiler can do __float128.
>         * configure: Regenerate.

The revised patch is okay with me in theory, but I would like Joseph
to check that this is the way he wants the solution addressed and
implemented.

Also, I cannot approve the Makefile.in change.

Thanks, David

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH], PowerPC IEEE 128-bit fp, #11 (enable libgcc conversions)
  2015-12-29 16:38 [PATCH], PowerPC IEEE 128-bit fp, #11 (enable libgcc conversions) Michael Meissner
  2015-12-29 16:53 ` Michael Meissner
  2015-12-29 20:26 ` David Edelsohn
@ 2015-12-31 20:30 ` Joseph Myers
  2016-01-04 22:11   ` Michael Meissner
  2016-01-06 22:48 ` [PATCH], PowerPC IEEE 128-bit fp, #11-rev2 " Michael Meissner
  3 siblings, 1 reply; 18+ messages in thread
From: Joseph Myers @ 2015-12-31 20:30 UTC (permalink / raw)
  To: Michael Meissner; +Cc: gcc-patches, dje.gcc

On Tue, 29 Dec 2015, Michael Meissner wrote:

> +/* __eqkf2 returns 0 if equal, or 1 if not equal or NaN.  */
> +CMPtype
> +__eqkf2_hw (TFtype a, TFtype b)
> +{
> +  return (__builtin_isunordered (a, b) || (a != b)) ? 1 : 0;

This is more complicated than necessary.  "return a != b;" will suffice.

> +/* __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 (__builtin_isunordered (a, b))
> +    return -2;
> +
> +  else if (a < b)
> +    return -1;

The __builtin_isunordered check should come after the < check, so that the 
"invalid" exception gets raised for quiet NaN arguments.

> +/* __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 (__builtin_isunordered (a, b))
> +    return 2;
> +
> +  else if (a < b)
> +    return -1;

Likewise.

> +      char *p = (char *) getauxval (AT_PLATFORM);

glibc deliberately exports __getauxval at a public symbol version, so you 
can do this in a namespace-clean way.

> +CMPtype __eqkf2 (TFtype, TFtype)
> +  __attribute__ ((__ifunc__ ("__eqkf2_resolve")));
> +
> +CMPtype __gekf2 (TFtype, TFtype)
> +  __attribute__ ((__ifunc__ ("__gekf2_resolve")));
> +
> +CMPtype __lekf2 (TFtype, TFtype)
> +  __attribute__ ((__ifunc__ ("__lekf2_resolve")));

Don't you need to arrange __nekf2, __gtkf2, __ltkf2 aliases to these 
resolvers (the semantics mean they don't need to be separate functions, 
but the entry points need to be there given the optabs the back end sets 
up)?

> +#ifdef _ARCH_PPC64
> +TItype_ppc __fixkfti (TFtype)
> +  __attribute__ ((__ifunc__ ("__fixkfti_resolve")));
> +
> +UTItype_ppc __fixunskfti (TFtype)
> +  __attribute__ ((__ifunc__ ("__fixunskfti_resolve")));
> +
> +TFtype __floattikf (TItype_ppc)
> +  __attribute__ ((__ifunc__ ("__floattikf_resolve")));
> +
> +TFtype __floatuntikf (UTItype_ppc)
> +  __attribute__ ((__ifunc__ ("__floatuntikf_resolve")));
> +#endif

I don't see the point of using ifuncs that just always return the software 
version.  You might as well just give the software version the appropriate 
function name directly, and add ifuncs later if adding a version using 
hardware arithmetic (e.g. doing something like the libgcc2.c functions 
with hardware conversions to/from DImode).

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

As far as I can see, my previous comment still applies: this part of the 
sfp-machine.h changes needs to be under some appropriate conditional so 
that it only applies when building the KFmode functions, not for 32-bit 
soft-float / e500 libgcc builds.

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH], PowerPC IEEE 128-bit fp, #11 (enable libgcc conversions)
  2015-12-31 20:30 ` Joseph Myers
@ 2016-01-04 22:11   ` Michael Meissner
  0 siblings, 0 replies; 18+ messages in thread
From: Michael Meissner @ 2016-01-04 22:11 UTC (permalink / raw)
  To: Joseph Myers; +Cc: Michael Meissner, gcc-patches, dje.gcc

On Thu, Dec 31, 2015 at 08:29:58PM +0000, Joseph Myers wrote:
> On Tue, 29 Dec 2015, Michael Meissner wrote:
> 
> > +/* __eqkf2 returns 0 if equal, or 1 if not equal or NaN.  */
> > +CMPtype
> > +__eqkf2_hw (TFtype a, TFtype b)
> > +{
> > +  return (__builtin_isunordered (a, b) || (a != b)) ? 1 : 0;
> 
> This is more complicated than necessary.  "return a != b;" will suffice.

Ok.  I will change this.

> > +/* __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 (__builtin_isunordered (a, b))
> > +    return -2;
> > +
> > +  else if (a < b)
> > +    return -1;
> 
> The __builtin_isunordered check should come after the < check, so that the 
> "invalid" exception gets raised for quiet NaN arguments.
> 
> > +/* __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 (__builtin_isunordered (a, b))
> > +    return 2;
> > +
> > +  else if (a < b)
> > +    return -1;
> 
> Likewise.

Ok.  I will change these.

> > +      char *p = (char *) getauxval (AT_PLATFORM);
> 
> glibc deliberately exports __getauxval at a public symbol version, so you 
> can do this in a namespace-clean way.

Ok.  I will change this.  The getauxval call by the way is only a temporary
measure until the support for __builtin_cpu_supports is added to the PowerPC.

> > +CMPtype __eqkf2 (TFtype, TFtype)
> > +  __attribute__ ((__ifunc__ ("__eqkf2_resolve")));
> > +
> > +CMPtype __gekf2 (TFtype, TFtype)
> > +  __attribute__ ((__ifunc__ ("__gekf2_resolve")));
> > +
> > +CMPtype __lekf2 (TFtype, TFtype)
> > +  __attribute__ ((__ifunc__ ("__lekf2_resolve")));
> 
> Don't you need to arrange __nekf2, __gtkf2, __ltkf2 aliases to these 
> resolvers (the semantics mean they don't need to be separate functions, 
> but the entry points need to be there given the optabs the back end sets 
> up)?

Because of default conversions we cannot allow the normal optab mechanism to be
used for IEEE 128-bit floating point emulation.  This is due to the fact that
if you have a __float128 comparison, the compiler will see if a larger type can
do the comparison, and in this case, the larger type is TFmode (i.e. IBM
extended double using the current defaults).

Instead rs6000_generate_compare generates the calls, and it does not use
the alternate names.  I can easily put in the resolver calls as well for the
alternate names just in case somebody hand crafts a call to __nekf3.

> 
> > +#ifdef _ARCH_PPC64
> > +TItype_ppc __fixkfti (TFtype)
> > +  __attribute__ ((__ifunc__ ("__fixkfti_resolve")));
> > +
> > +UTItype_ppc __fixunskfti (TFtype)
> > +  __attribute__ ((__ifunc__ ("__fixunskfti_resolve")));
> > +
> > +TFtype __floattikf (TItype_ppc)
> > +  __attribute__ ((__ifunc__ ("__floattikf_resolve")));
> > +
> > +TFtype __floatuntikf (UTItype_ppc)
> > +  __attribute__ ((__ifunc__ ("__floatuntikf_resolve")));
> > +#endif
> 
> I don't see the point of using ifuncs that just always return the software 
> version.  You might as well just give the software version the appropriate 
> function name directly, and add ifuncs later if adding a version using 
> hardware arithmetic (e.g. doing something like the libgcc2.c functions 
> with hardware conversions to/from DImode).

I'll think about it.  At some point, I was hoping to have implementations for
ISA 3.0.  However, there is not an ISA 3.0 instruction that converts from
128-bit integer to 128-bit floating point or vice versa.

> 
> > +#define ISA_BIT(x) (1 << (63 - x))
> 
> As far as I can see, my previous comment still applies: this part of the 
> sfp-machine.h changes needs to be under some appropriate conditional so 
> that it only applies when building the KFmode functions, not for 32-bit 
> soft-float / e500 libgcc builds.

Agreed.  I will fix this.

-- 
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

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH], PowerPC IEEE 128-bit fp, #11-rev2 (enable libgcc conversions)
  2015-12-29 16:38 [PATCH], PowerPC IEEE 128-bit fp, #11 (enable libgcc conversions) Michael Meissner
                   ` (2 preceding siblings ...)
  2015-12-31 20:30 ` Joseph Myers
@ 2016-01-06 22:48 ` Michael Meissner
  2016-01-07 21:55   ` Joseph Myers
  3 siblings, 1 reply; 18+ messages in thread
From: Michael Meissner @ 2016-01-06 22:48 UTC (permalink / raw)
  To: Michael Meissner, gcc-patches, dje.gcc
  Cc: Steven Munroe, Tulio Magno Quites Machado Filho

[-- Attachment #1: Type: text/plain, Size: 6838 bytes --]

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

[-- Attachment #2: ieee128-patch11b --]
[-- Type: text/plain, Size: 10354 bytes --]

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

[-- Attachment #3: ieee128-patch11c --]
[-- Type: text/plain, Size: 52814 bytes --]

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);
+}
+
+
+\f
+/* 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
 

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH], PowerPC IEEE 128-bit fp, #11-rev2 (enable libgcc conversions)
  2016-01-06 22:48 ` [PATCH], PowerPC IEEE 128-bit fp, #11-rev2 " Michael Meissner
@ 2016-01-07 21:55   ` Joseph Myers
  2016-01-11 18:56     ` [PATCH], PowerPC IEEE 128-bit fp, #11-rev3 " Michael Meissner
  0 siblings, 1 reply; 18+ messages in thread
From: Joseph Myers @ 2016-01-07 21:55 UTC (permalink / raw)
  To: Michael Meissner
  Cc: gcc-patches, dje.gcc, Steven Munroe, Tulio Magno Quites Machado Filho

On Wed, 6 Jan 2016, Michael Meissner wrote:

>     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).

I think this needs to be __NO_FPRS__ instead of _SOFT_FLOAT (since soft-fp 
is also built for e500).

Other than that my only comments on this version are some formatting / 
coding style comments:

> 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.
> + *

Normally we don't use the '*' at the start of each comment line.

> +TFtype
> +__floatsikf_hw (SItype_ppc a)
> +{
> +  return (TFtype)a;

Casts should have a space, "(TFtype) a".  Many more cases in this file.

> +/* __unordkf2 returns 1 if Nan or 0 otherwise.  */

NaN.

> +      __low = (double) (__value - (__float128)__high);			\

Again, space in cast.

> +      /* now renormalized move the high/low into canonical IBM long	\
> +	 double form.  */						\

Comments start with a capital letter.

> +  /* Handle the special cases of NAN and inifinity.  */			\

"infinity".

> +    RESULT = ((__float128)__high) + ((__float128)__low);		\

Spaces in casts.

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH], PowerPC IEEE 128-bit fp, #11-rev3 (enable libgcc conversions)
  2016-01-07 21:55   ` Joseph Myers
@ 2016-01-11 18:56     ` Michael Meissner
  2016-01-12  0:19       ` Joseph Myers
  0 siblings, 1 reply; 18+ messages in thread
From: Michael Meissner @ 2016-01-11 18:56 UTC (permalink / raw)
  To: Joseph Myers
  Cc: Michael Meissner, gcc-patches, dje.gcc, Steven Munroe,
	Tulio Magno Quites Machado Filho

[-- Attachment #1: Type: text/plain, Size: 4565 bytes --]

I fixed the #ifdef to use __NO_FPRS__ (thanks for the heads up on that).  I
also believe I fixed the various formatting issues.  These two patches build on
a big endian power7 host and little endian power8 host with no regressions in
the testsuite (the gcc patch is included here, but it hasn't changed since the
previous version of this patch).  Are they ok to be checked in?

[gcc]
2016-01-11  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-11  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/sfp-exceptions.c: New file to provide exception
	support for IEEE 128-bit floating point.

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

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

	* 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/quad-float128.h: New file to support IEEE 128-bit
	floating point.

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

	* 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.

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

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

-- 
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

[-- Attachment #2: ieee128-patch11b --]
[-- Type: text/plain, Size: 10354 bytes --]

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

[-- Attachment #3: ieee128-patch11c --]
[-- Type: text/plain, Size: 52813 bytes --]

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);
+}
+
+
+\f
+/* 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
 

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH], PowerPC IEEE 128-bit fp, #11-rev3 (enable libgcc conversions)
  2016-01-11 18:56     ` [PATCH], PowerPC IEEE 128-bit fp, #11-rev3 " Michael Meissner
@ 2016-01-12  0:19       ` Joseph Myers
  2016-01-12 18:31         ` Michael Meissner
  0 siblings, 1 reply; 18+ messages in thread
From: Joseph Myers @ 2016-01-12  0:19 UTC (permalink / raw)
  To: Michael Meissner
  Cc: gcc-patches, dje.gcc, Steven Munroe, Tulio Magno Quites Machado Filho

On Mon, 11 Jan 2016, Michael Meissner wrote:

> I fixed the #ifdef to use __NO_FPRS__ (thanks for the heads up on that).  I
> also believe I fixed the various formatting issues.  These two patches build on
> a big endian power7 host and little endian power8 host with no regressions in
> the testsuite (the gcc patch is included here, but it hasn't changed since the
> previous version of this patch).  Are they ok to be checked in?

Are you sure you sent the right patch version?  I don't see those fixes in 
this one.

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH], PowerPC IEEE 128-bit fp, #11-rev3 (enable libgcc conversions)
  2016-01-12  0:19       ` Joseph Myers
@ 2016-01-12 18:31         ` Michael Meissner
  2016-01-12 23:47           ` Joseph Myers
  0 siblings, 1 reply; 18+ messages in thread
From: Michael Meissner @ 2016-01-12 18:31 UTC (permalink / raw)
  To: Joseph Myers
  Cc: Michael Meissner, gcc-patches, dje.gcc, Steven Munroe,
	Tulio Magno Quites Machado Filho

[-- Attachment #1: Type: text/plain, Size: 4880 bytes --]

On Tue, Jan 12, 2016 at 12:18:55AM +0000, Joseph Myers wrote:
> On Mon, 11 Jan 2016, Michael Meissner wrote:
> 
> > I fixed the #ifdef to use __NO_FPRS__ (thanks for the heads up on that).  I
> > also believe I fixed the various formatting issues.  These two patches build on
> > a big endian power7 host and little endian power8 host with no regressions in
> > the testsuite (the gcc patch is included here, but it hasn't changed since the
> > previous version of this patch).  Are they ok to be checked in?
> 
> Are you sure you sent the right patch version?  I don't see those fixes in 
> this one.

You are right.  I did not update the patches from the changes I had made in the
branch.

[gcc]
2016-01-12  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-12  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/sfp-exceptions.c: New file to provide exception
	support for IEEE 128-bit floating point.

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

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

	* 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/quad-float128.h: New file to support IEEE 128-bit
	floating point.

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

	* 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.

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

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


-- 
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

[-- Attachment #2: ieee128-patch11b --]
[-- Type: text/plain, Size: 10354 bytes --]

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

[-- Attachment #3: ieee128-patch11c --]
[-- Type: text/plain, Size: 53486 bytes --]

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 232240)
@@ -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);
+}
+
+
+\f
+/* 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/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 232175)
@@ -0,0 +1,72 @@
+/* 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 __NO_FPRS__ 
+
+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	/* !__NO_FPRS__   */
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 232175)
@@ -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 232175)
@@ -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 232175)
@@ -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/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 232175)
@@ -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 232175)
@@ -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 232175)
@@ -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);			\
+      /* Renormalize low/high and move them 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 infinity.  */			\
+  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 232175)
@@ -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 232175)
@@ -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 232175)
@@ -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 232175)
@@ -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 232175)
@@ -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 232174)
+++ 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,54 @@ typedef int __gcc_CMPtype __attribute__ 
 # endif
 #endif
 
+/* Only provide exception support if we have hardware floating point using
+   floating point registers 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 ___NO_FPRS__
+#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	/* !__NO_FPRS__ */
 
 /* Define ALIASNAME as a strong alias for NAME.  */
 # define strong_alias(name, aliasname) _strong_alias(name, aliasname)
Index: libgcc/config.host
===================================================================
--- libgcc/config.host	(.../svn+ssh://meissner@gcc.gnu.org/svn/gcc/trunk/libgcc)	(revision 232174)
+++ libgcc/config.host	(.../libgcc)	(working copy)
@@ -1063,6 +1063,15 @@ powerpc*-*-linux*)
 		exit 1
 		;;
 	esac
+
+	if test $libgcc_cv_powerpc_float128 = yes; then
+		tmake_file="${tmake_file} rs6000/t-float128"
+	fi
+
+	if test $libgcc_cv_powerpc_float128_hw = yes; then
+		tmake_file="${tmake_file} rs6000/t-float128-hw"
+	fi
+
 	extra_parts="$extra_parts ecrti.o ecrtn.o ncrti.o ncrtn.o"
 	md_unwind_header=rs6000/linux-unwind.h
 	;;
Index: libgcc/configure.ac
===================================================================
--- libgcc/configure.ac	(.../svn+ssh://meissner@gcc.gnu.org/svn/gcc/trunk/libgcc)	(revision 232174)
+++ 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 232174)
+++ 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
 

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH], PowerPC IEEE 128-bit fp, #11-rev3 (enable libgcc conversions)
  2016-01-12 18:31         ` Michael Meissner
@ 2016-01-12 23:47           ` Joseph Myers
  2016-01-12 23:49             ` David Edelsohn
  0 siblings, 1 reply; 18+ messages in thread
From: Joseph Myers @ 2016-01-12 23:47 UTC (permalink / raw)
  To: Michael Meissner
  Cc: gcc-patches, dje.gcc, Steven Munroe, Tulio Magno Quites Machado Filho

On Tue, 12 Jan 2016, Michael Meissner wrote:

> On Tue, Jan 12, 2016 at 12:18:55AM +0000, Joseph Myers wrote:
> > On Mon, 11 Jan 2016, Michael Meissner wrote:
> > 
> > > I fixed the #ifdef to use __NO_FPRS__ (thanks for the heads up on that).  I
> > > also believe I fixed the various formatting issues.  These two patches build on
> > > a big endian power7 host and little endian power8 host with no regressions in
> > > the testsuite (the gcc patch is included here, but it hasn't changed since the
> > > previous version of this patch).  Are they ok to be checked in?
> > 
> > Are you sure you sent the right patch version?  I don't see those fixes in 
> > this one.
> 
> You are right.  I did not update the patches from the changes I had made in the
> branch.

I have no further comments on the patch.

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH], PowerPC IEEE 128-bit fp, #11-rev3 (enable libgcc conversions)
  2016-01-12 23:47           ` Joseph Myers
@ 2016-01-12 23:49             ` David Edelsohn
  2016-01-14 22:03               ` Michael Meissner
  0 siblings, 1 reply; 18+ messages in thread
From: David Edelsohn @ 2016-01-12 23:49 UTC (permalink / raw)
  To: Joseph Myers, Michael Meissner
  Cc: GCC Patches, Steven Munroe, Tulio Magno Quites Machado Filho

On Tue, Jan 12, 2016 at 6:47 PM, Joseph Myers <joseph@codesourcery.com> wrote:
> On Tue, 12 Jan 2016, Michael Meissner wrote:
>
>> On Tue, Jan 12, 2016 at 12:18:55AM +0000, Joseph Myers wrote:
>> > On Mon, 11 Jan 2016, Michael Meissner wrote:
>> >
>> > > I fixed the #ifdef to use __NO_FPRS__ (thanks for the heads up on that).  I
>> > > also believe I fixed the various formatting issues.  These two patches build on
>> > > a big endian power7 host and little endian power8 host with no regressions in
>> > > the testsuite (the gcc patch is included here, but it hasn't changed since the
>> > > previous version of this patch).  Are they ok to be checked in?
>> >
>> > Are you sure you sent the right patch version?  I don't see those fixes in
>> > this one.
>>
>> You are right.  I did not update the patches from the changes I had made in the
>> branch.
>
> I have no further comments on the patch.

If Joseph is satisfied, it's okay with me.

Thanks, David

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH], PowerPC IEEE 128-bit fp, #11-rev3 (enable libgcc conversions)
  2016-01-12 23:49             ` David Edelsohn
@ 2016-01-14 22:03               ` Michael Meissner
  2016-01-21  1:00                 ` [PATCH], PowerPC IEEE 128-bit fp, #11-rev4 " Michael Meissner
  0 siblings, 1 reply; 18+ messages in thread
From: Michael Meissner @ 2016-01-14 22:03 UTC (permalink / raw)
  To: David Edelsohn
  Cc: Joseph Myers, Michael Meissner, GCC Patches, Steven Munroe,
	Tulio Magno Quites Machado Filho

On Tue, Jan 12, 2016 at 06:48:58PM -0500, David Edelsohn wrote:
> On Tue, Jan 12, 2016 at 6:47 PM, Joseph Myers <joseph@codesourcery.com> wrote:
> > On Tue, 12 Jan 2016, Michael Meissner wrote:
> >
> >> On Tue, Jan 12, 2016 at 12:18:55AM +0000, Joseph Myers wrote:
> >> > On Mon, 11 Jan 2016, Michael Meissner wrote:
> >> >
> >> > > I fixed the #ifdef to use __NO_FPRS__ (thanks for the heads up on that).  I
> >> > > also believe I fixed the various formatting issues.  These two patches build on
> >> > > a big endian power7 host and little endian power8 host with no regressions in
> >> > > the testsuite (the gcc patch is included here, but it hasn't changed since the
> >> > > previous version of this patch).  Are they ok to be checked in?
> >> >
> >> > Are you sure you sent the right patch version?  I don't see those fixes in
> >> > this one.
> >>
> >> You are right.  I did not update the patches from the changes I had made in the
> >> branch.
> >
> > I have no further comments on the patch.
> 
> If Joseph is satisfied, it's okay with me.
> 
> Thanks, David

Because of the failures in my patch and the fact that I will be offline
for the next four days, I reverted my IEEE 128-bit libgcc patches.

I'm aware of the following breakages:

1) If you build the compiler without --enable-gnu-indirect-function, the
compiler is unable to set up the ifunc resolvers to use the IEEE 128-bit
hardware that is in ISA 3.0.  For this one, I will add code in the configure
test to see if we can do IFUNC as well as generate ISA 3.0 instructions.

2) The patch to gcc to add the __ibm128 unpack/pack function breaks the
bootstrap on AIX.

I will fix both problems and re-submit them on Tuesday when I return.

-- 
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

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH], PowerPC IEEE 128-bit fp, #11-rev4 (enable libgcc conversions)
  2016-01-14 22:03               ` Michael Meissner
@ 2016-01-21  1:00                 ` Michael Meissner
  2016-01-21 13:28                   ` David Edelsohn
  0 siblings, 1 reply; 18+ messages in thread
From: Michael Meissner @ 2016-01-21  1:00 UTC (permalink / raw)
  To: Michael Meissner, David Edelsohn, Joseph Myers, GCC Patches,
	Steven Munroe, Tulio Magno Quites Machado Filho

[-- Attachment #1: Type: text/plain, Size: 4457 bytes --]

This is revision 4 of the IEEE 128-bit floating point libgcc support.

Since revision 3, I have removed the gcc changes that broke AIX.  I rewrote the
IBM extended double pack/unpack support to not use the builtin functions, but
instead uses a union.  The libgcc code that I wrote tickles a bug in the pack
function.  While I would like to fix the pack function bug, I will need to make
sure I don't break AIX, so I didn't want to couple this library to getting
those bugs fixed.

I have also rewritten how the ifunc support is done, so that ifunc is only done
if the target assembler supports ISA 3.0 instructions AND the compiler supports
ifunc functions.  This is so that the compiler can build on 64-bit systems if
--enable-gnu-indirect-function is not specified without the ifunc functions
being flagged.

I have done bootstraps on both a big endian power7 system and a little endian
power8 with no regressions.  In addition, I have built a compiler explicitly
disabling ifunc support, and it built and ran the ieee 128-bit floating point
unit tests correctly.

Can I install this into libgcc?

Assuming I can install these changes, the one final change that I would like to
make is to enable float128 automatically on VSX powerpc Linux systems, but not
on other systems (AIX, *BSD, etc.) since those systems do not build float128
emulator functions.

2016-01-20  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/float128-sed: New files to convert TF names to KF
	names for PowerPC IEEE 128-bit floating point support.
	* config/rs6000/float128-sed-hw: 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/quad-float128.h: New file to support IEEE 128-bit
	floating point.

	* config/rs6000/extendkftf2-sw.c: New file, convert IEEE 128-bit
	floating point to IBM extended double.

	* config/rs6000/trunctfkf2-sw.c: New file, convert IBM extended
	double to IEEE 128-bit floating point.

	* 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/floattikf.c: New files for converting between IEEE
	128-bit floating point and signed/unsigned 128-bit integers.
	* config/rs6000/fixunskfti.c: Likewise.
	* config/rs6000/fixkfti.c: Likewise.
	* config/rs6000/floatuntikf.c: Likewise.

	* 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.  If the compiler can
	compile IEEE 128-bit floating point code with ISA 3.0 IEEE 128-bit
	floating point hardware instructions and it supports declaring
	functions with the ifunc attribute, enable ifunc functions to
	switch between software and hardware support.
	* configure.ac (powerpc*-*-linux*): Likewise.
	* 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

[-- Attachment #2: ieee128-patch11d --]
[-- Type: text/plain, Size: 55827 bytes --]

Index: libgcc/config/rs6000/float128-sed-hw
===================================================================
--- libgcc/config/rs6000/float128-sed-hw	(.../svn+ssh://meissner@gcc.gnu.org/svn/gcc/trunk/libgcc)	(revision 0)
+++ libgcc/config/rs6000/float128-sed-hw	(.../libgcc)	(revision 232635)
@@ -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/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 232635)
@@ -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_TYPE
+__extendkftf2_hw (TFtype value)
+{
+  IBM128_TYPE ret;
+
+  CVT_FLOAT128_TO_IBM128 (ret, value);
+  return ret;
+}
+
+/* Convert __ibm128 to __float128.  */
+TFtype
+__trunctfkf2_hw (IBM128_TYPE value)
+{
+  TFtype ret;
+
+  CVT_IBM128_TO_FLOAT128 (ret, value);
+  return ret;
+}
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 232635)
@@ -0,0 +1,362 @@
+/* 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>
+
+#ifndef FLOAT128_HW_INSNS
+#error "float128-ifunc.c needs access to ISA 3.0 instructions and ifunc"
+#endif
+
+#ifdef __FLOAT128_HARDWARE__
+#error "This module must not be compiled with IEEE 128-bit hardware support"
+#endif
+
+#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)
+
+/* 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);
+}
+
+
+\f
+/* 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_TYPE __extendkftf2 (TFtype)
+  __attribute__ ((__ifunc__ ("__extendkftf2_resolve")));
+
+TFtype __trunctfkf2 (IBM128_TYPE)
+  __attribute__ ((__ifunc__ ("__trunctfkf2_resolve")));
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 232635)
@@ -0,0 +1,213 @@
+/* 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>
+
+#ifdef __LONG_DOUBLE_IEEE128__
+#define IBM128_TYPE		__ibm128
+
+#else
+#define IBM128_TYPE		long double
+#endif
+
+/* 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_TYPE __extendkftf2_sw (TFtype);
+extern TFtype __trunctfkf2_sw (IBM128_TYPE);
+
+#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_TYPE __extendkftf2_hw (TFtype);
+extern TFtype __trunctfkf2_hw (IBM128_TYPE);
+
+/* 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_TYPE __extendkftf2 (TFtype);
+extern TFtype __trunctfkf2 (IBM128_TYPE);
+
+/* Implementation of conversions between __ibm128 and __float128, to allow the
+   same code to be used on systems with IEEE 128-bit emulation and with IEEE
+   128-bit hardware support.  */
+
+union ibm128_union {
+  IBM128_TYPE ibm128;
+  double dbl[2];
+};
+
+#define CVT_FLOAT128_TO_IBM128(RESULT, VALUE)				\
+{									\
+  double __high, __low;							\
+  __float128 __value = (VALUE);						\
+  union ibm128_union u;							\
+									\
+  __high = (double) __value;						\
+  if (__builtin_isnan (__high) || __builtin_isinf (__high))		\
+    __low = 0.0;							\
+									\
+  else									\
+    {									\
+      double __high_temp;						\
+									\
+      __low = (double) (__value - (__float128) __high);			\
+      /* Renormalize low/high and move them into canonical IBM long	\
+	 double form.  */						\
+      __high_temp = __high + __low;					\
+      __low = (__high - __high_temp) + __low;				\
+      __high = __high_temp;						\
+    }									\
+									\
+  u.dbl[0] = __high;							\
+  u.dbl[1] = __low;							\
+  RESULT = u.ibm128;							\
+}
+
+#define CVT_IBM128_TO_FLOAT128(RESULT, VALUE)				\
+{									\
+  union ibm128_union u;							\
+  double __high, __low;							\
+									\
+  u.ibm128 = (VALUE);							\
+  __high = u.dbl[0];							\
+  __low = u.dbl[1];							\
+									\
+  /* Handle the special cases of NAN and infinity.  */			\
+  if (__builtin_isnan (__high) || __builtin_isinf (__high))		\
+    RESULT = (__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 232635)
@@ -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_TYPE
+__extendkftf2_sw (__float128 value)
+{
+  IBM128_TYPE 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 232635)
@@ -0,0 +1,53 @@
+/* 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"
+
+#ifndef FLOAT128_HW_INSNS
+#define __trunctfkf2_sw __trunctfkf2
+#endif
+
+__float128
+__trunctfkf2_sw (IBM128_TYPE 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 232635)
@@ -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
+
+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_ifunc_funcs)
+
+fp128_src		= $(fp128_softfp_src) $(fp128_ppc_src) \
+			  $(fp128_hw_src) $(fp128_ifunc_src)
+
+fp128_obj		= $(fp128_softfp_obj) $(fp128_ppc_obj) \
+			  $(fp128_hw_obj) $(fp128_ifunc_obj)
+
+fp128_sed		= $(srcdir)/config/rs6000/float128-sed$(fp128_sed_hw)
+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 232635)
@@ -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/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 232635)
@@ -0,0 +1,35 @@
+# 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)
+
+fp128_ifunc_funcs	= float128-ifunc
+fp128_ifunc_src		= $(srcdir)/config/rs6000/float128-ifunc.c
+fp128_ifunc_static_obj	= float128-ifunc$(objext)
+fp128_ifunc_shared_obj	= float128-ifunc_s$(objext)
+fp128_ifunc_obj		= $(fp128_ifunc_static_obj) $(fp128_ifunc_shared_obj)
+
+# Add _sw suffix to names to allow ifunc support.
+fp128_sed_hw		= -hw
+
+# 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
+
+$(fp128_ifunc_obj)	 : INTERNAL_CFLAGS += $(FP128_CFLAGS_SW)
+$(fp128_ifunc_obj)	 : $(srcdir)/config/rs6000/t-float128-hw
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 232629)
@@ -0,0 +1,72 @@
+/* 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 __NO_FPRS__ 
+
+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	/* !__NO_FPRS__   */
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 232629)
@@ -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 232629)
@@ -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/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 232629)
@@ -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 232629)
@@ -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/sfp-machine.h
===================================================================
--- libgcc/config/rs6000/sfp-machine.h	(.../svn+ssh://meissner@gcc.gnu.org/svn/gcc/trunk/libgcc)	(revision 232629)
+++ 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,54 @@ typedef int __gcc_CMPtype __attribute__ 
 # endif
 #endif
 
+/* Only provide exception support if we have hardware floating point using
+   floating point registers 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 ___NO_FPRS__
+#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	/* !__NO_FPRS__ */
 
 /* Define ALIASNAME as a strong alias for NAME.  */
 # define strong_alias(name, aliasname) _strong_alias(name, aliasname)
Index: libgcc/config.host
===================================================================
--- libgcc/config.host	(.../svn+ssh://meissner@gcc.gnu.org/svn/gcc/trunk/libgcc)	(revision 232629)
+++ libgcc/config.host	(.../libgcc)	(working copy)
@@ -1063,6 +1063,15 @@ powerpc*-*-linux*)
 		exit 1
 		;;
 	esac
+
+	if test $libgcc_cv_powerpc_float128 = yes; then
+		tmake_file="${tmake_file} rs6000/t-float128"
+	fi
+
+	if test $libgcc_cv_powerpc_float128_hw = yes; then
+		tmake_file="${tmake_file} rs6000/t-float128-hw"
+	fi
+
 	extra_parts="$extra_parts ecrti.o ecrtn.o ncrti.o ncrtn.o"
 	md_unwind_header=rs6000/linux-unwind.h
 	;;
Index: libgcc/configure.ac
===================================================================
--- libgcc/configure.ac	(.../svn+ssh://meissner@gcc.gnu.org/svn/gcc/trunk/libgcc)	(revision 232629)
+++ libgcc/configure.ac	(.../libgcc)	(working copy)
@@ -373,6 +373,37 @@ 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>
+     #ifndef AT_PLATFORM
+     #error "AT_PLATFORM is not defined"
+     #endif
+     __float128 add (__float128 a, __float128 b)
+     {
+       __float128 ret;
+       __asm__ ("xsaddqp %0,%1,%2" : "=v" (ret) : "v" (a), "v" (b));
+       return ret;
+     }
+     void *add_resolver (void) { return (void *) add; }
+     __float128 add_ifunc (__float128, __float128)
+	__attribute__ ((__ifunc__ ("add_resolver")));],
+    [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 232629)
+++ libgcc/configure	(.../libgcc)	(working copy)
@@ -4766,6 +4766,61 @@ 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>
+     #ifndef AT_PLATFORM
+     #error "AT_PLATFORM is not defined"
+     #endif
+     __float128 add (__float128 a, __float128 b)
+     {
+       __float128 ret;
+       __asm__ ("xsaddqp %0,%1,%2" : "=v" (ret) : "v" (a), "v" (b));
+       return ret;
+     }
+     void *add_resolver (void) { return (void *) add; }
+     __float128 add_ifunc (__float128, __float128)
+	__attribute__ ((__ifunc__ ("add_resolver")));
+_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
 

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH], PowerPC IEEE 128-bit fp, #11-rev4 (enable libgcc conversions)
  2016-01-21  1:00                 ` [PATCH], PowerPC IEEE 128-bit fp, #11-rev4 " Michael Meissner
@ 2016-01-21 13:28                   ` David Edelsohn
  2016-01-21 17:35                     ` Michael Meissner
  2016-01-21 21:25                     ` [PATCH], PowerPC IEEE 128-bit fp, #12 (default -mfloat128 on PowerPC-Linux) Michael Meissner
  0 siblings, 2 replies; 18+ messages in thread
From: David Edelsohn @ 2016-01-21 13:28 UTC (permalink / raw)
  To: Michael Meissner, Joseph Myers, GCC Patches, Steven Munroe,
	Tulio Magno Quites Machado Filho

On Wed, Jan 20, 2016 at 8:00 PM, Michael Meissner
<meissner@linux.vnet.ibm.com> wrote:
> This is revision 4 of the IEEE 128-bit floating point libgcc support.
>
> Since revision 3, I have removed the gcc changes that broke AIX.  I rewrote the
> IBM extended double pack/unpack support to not use the builtin functions, but
> instead uses a union.  The libgcc code that I wrote tickles a bug in the pack
> function.  While I would like to fix the pack function bug, I will need to make
> sure I don't break AIX, so I didn't want to couple this library to getting
> those bugs fixed.
>
> I have also rewritten how the ifunc support is done, so that ifunc is only done
> if the target assembler supports ISA 3.0 instructions AND the compiler supports
> ifunc functions.  This is so that the compiler can build on 64-bit systems if
> --enable-gnu-indirect-function is not specified without the ifunc functions
> being flagged.
>
> I have done bootstraps on both a big endian power7 system and a little endian
> power8 with no regressions.  In addition, I have built a compiler explicitly
> disabling ifunc support, and it built and ran the ieee 128-bit floating point
> unit tests correctly.
>
> Can I install this into libgcc?
>
> Assuming I can install these changes, the one final change that I would like to
> make is to enable float128 automatically on VSX powerpc Linux systems, but not
> on other systems (AIX, *BSD, etc.) since those systems do not build float128
> emulator functions.

What does "enable" mean?

> 2016-01-20  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/float128-sed: New files to convert TF names to KF
>         names for PowerPC IEEE 128-bit floating point support.
>         * config/rs6000/float128-sed-hw: 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/quad-float128.h: New file to support IEEE 128-bit
>         floating point.
>
>         * config/rs6000/extendkftf2-sw.c: New file, convert IEEE 128-bit
>         floating point to IBM extended double.
>
>         * config/rs6000/trunctfkf2-sw.c: New file, convert IBM extended
>         double to IEEE 128-bit floating point.
>
>         * 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/floattikf.c: New files for converting between IEEE
>         128-bit floating point and signed/unsigned 128-bit integers.
>         * config/rs6000/fixunskfti.c: Likewise.
>         * config/rs6000/fixkfti.c: Likewise.
>         * config/rs6000/floatuntikf.c: Likewise.
>
>         * 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.  If the compiler can
>         compile IEEE 128-bit floating point code with ISA 3.0 IEEE 128-bit
>         floating point hardware instructions and it supports declaring
>         functions with the ifunc attribute, enable ifunc functions to
>         switch between software and hardware support.
>         * configure.ac (powerpc*-*-linux*): Likewise.
>         * configure: Regenerate.

Okay.

Thanks, David

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH], PowerPC IEEE 128-bit fp, #11-rev4 (enable libgcc conversions)
  2016-01-21 13:28                   ` David Edelsohn
@ 2016-01-21 17:35                     ` Michael Meissner
  2016-01-21 21:25                     ` [PATCH], PowerPC IEEE 128-bit fp, #12 (default -mfloat128 on PowerPC-Linux) Michael Meissner
  1 sibling, 0 replies; 18+ messages in thread
From: Michael Meissner @ 2016-01-21 17:35 UTC (permalink / raw)
  To: David Edelsohn
  Cc: Michael Meissner, Joseph Myers, GCC Patches, Steven Munroe,
	Tulio Magno Quites Machado Filho

On Thu, Jan 21, 2016 at 08:28:05AM -0500, David Edelsohn wrote:
> On Wed, Jan 20, 2016 at 8:00 PM, Michael Meissner
> <meissner@linux.vnet.ibm.com> wrote:
> > This is revision 4 of the IEEE 128-bit floating point libgcc support.
> >
> > Since revision 3, I have removed the gcc changes that broke AIX.  I rewrote the
> > IBM extended double pack/unpack support to not use the builtin functions, but
> > instead uses a union.  The libgcc code that I wrote tickles a bug in the pack
> > function.  While I would like to fix the pack function bug, I will need to make
> > sure I don't break AIX, so I didn't want to couple this library to getting
> > those bugs fixed.
> >
> > I have also rewritten how the ifunc support is done, so that ifunc is only done
> > if the target assembler supports ISA 3.0 instructions AND the compiler supports
> > ifunc functions.  This is so that the compiler can build on 64-bit systems if
> > --enable-gnu-indirect-function is not specified without the ifunc functions
> > being flagged.
> >
> > I have done bootstraps on both a big endian power7 system and a little endian
> > power8 with no regressions.  In addition, I have built a compiler explicitly
> > disabling ifunc support, and it built and ran the ieee 128-bit floating point
> > unit tests correctly.
> >
> > Can I install this into libgcc?
> >
> > Assuming I can install these changes, the one final change that I would like to
> > make is to enable float128 automatically on VSX powerpc Linux systems, but not
> > on other systems (AIX, *BSD, etc.) since those systems do not build float128
> > emulator functions.
> 
> What does "enable" mean?

I would prefer users being able to use __float128 without having to use the
-mfloat128 option on power7/power8/power9 systems.  Since we currently only
build the emulation for PowerPC Linux systems, I don't think we want to enable
it by default without enabling the emulation on those other systems.

This means, I probably don't want to put OPTION_MASK_FLOAT128 into
ISA_2_6_MASKS_SERVER in rs6000-cpus.def, but instead turn it on in the option
handling in rs6000.c if the switch was not done by the user, and we are
targetting a VSX Linux system.

If you want AIX support, in theory it should be doable. However, it has been a
long time since I used AIX, and I will need to refresh my memories on the
capabilities of the object file format currently used (in particular, does
ifunc and aliases work).

For *BSD, it may be more problematical.  We've had at least one query about
getting __float128 to work on non-VSX systems.  Obviously, it won't be in GCC
6, but it may come up in GCC 7.

-- 
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

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH], PowerPC IEEE 128-bit fp, #12 (default -mfloat128 on PowerPC-Linux)
  2016-01-21 13:28                   ` David Edelsohn
  2016-01-21 17:35                     ` Michael Meissner
@ 2016-01-21 21:25                     ` Michael Meissner
  2016-01-26 14:52                       ` David Edelsohn
  1 sibling, 1 reply; 18+ messages in thread
From: Michael Meissner @ 2016-01-21 21:25 UTC (permalink / raw)
  To: David Edelsohn
  Cc: Michael Meissner, Joseph Myers, GCC Patches, Steven Munroe,
	Tulio Magno Quites Machado Filho

[-- Attachment #1: Type: text/plain, Size: 1004 bytes --]

This is the final patch (at least so far) that turns on -mfloat128 by default
for PowerPC Linux systems where the VSX instruction set is enabled.  As I
mentioned in the last email, because we don't build the __float128 emulator on
other systems, I didn't think it would be useful to make it the default.

I did a boostrap build/check with no regressions on a little endian power8
system.  Are the patches ok to check in?

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

	* config/rs6000/rs6000.c (rs6000_option_override_internal): Enable
	-mfloat128 by default on PowerPC Linux systems with the VSX
	instruction enabled.

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

	* gcc.target/powerpc/float128-1.c: New test for IEEE 128-bit
	floating point support.
	* gcc.target/powerpc/float128-2.c: Likewise.

-- 
Michael Meissner, IBM
IBM, M/S 2506R, 550 King Street, Littleton, MA 01460-6245, USA
email: meissner@linux.vnet.ibm.com, phone: +1 (978) 899-4797

[-- Attachment #2: ieee128-patch12b --]
[-- Type: text/plain, Size: 8907 bytes --]

Index: gcc/config/rs6000/rs6000.c
===================================================================
--- gcc/config/rs6000/rs6000.c	(revision 232690)
+++ gcc/config/rs6000/rs6000.c	(working copy)
@@ -4236,6 +4236,15 @@ rs6000_option_override_internal (bool gl
 	}
     }
 
+  /* At present, we only build the __float128 emulator on PowerPC Linux.
+     Enable default __float128 support for PowerPC Linux systems, but not for
+     others.  */
+#ifdef POWERPC_LINUX
+  if (TARGET_VSX && !TARGET_FLOAT128
+      && (rs6000_isa_flags_explicit & OPTION_MASK_FLOAT128) == 0)
+    rs6000_isa_flags |= OPTION_MASK_FLOAT128;
+#endif
+
   /* __float128 requires VSX support.  */
   if (TARGET_FLOAT128 && !TARGET_VSX)
     {
Index: gcc/testsuite/gcc.target/powerpc/float128-1.c
===================================================================
--- gcc/testsuite/gcc.target/powerpc/float128-1.c	(revision 0)
+++ gcc/testsuite/gcc.target/powerpc/float128-1.c	(revision 0)
@@ -0,0 +1,147 @@
+/* { dg-do run { target { powerpc*-*-linux* } } } */
+/* { dg-require-effective-target ppc_float128_sw } */
+/* { dg-options "-mcpu=power7 -O2 -mfloat128 -static-libgcc" } */
+
+#ifdef DEBUG
+#include <stdio.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <inttypes.h>
+#endif
+
+#if !defined(__FLOAT128__) || !defined(_ARCH_PPC)
+static __float128
+pass_through (__float128 x)
+{
+  return x;
+}
+
+__float128 (*no_optimize) (__float128) = pass_through;
+#endif
+
+#ifdef DEBUG
+__attribute__((__noinline__))
+static void
+print_f128 (__float128 x)
+{
+  unsigned sign;
+  unsigned exponent;
+  uint64_t mantissa1;
+  uint64_t mantissa2;
+  uint64_t upper;
+  uint64_t lower;
+
+#if defined(_ARCH_PPC) && defined(__BIG_ENDIAN__)
+  struct ieee128 {
+    uint64_t upper;
+    uint64_t lower;
+  };
+
+#elif (defined(_ARCH_PPC) && defined(__LITTLE_ENDIAN__)) || defined(__x86_64__)
+  struct ieee128 {
+    uint64_t lower;
+    uint64_t upper;
+  };
+
+#else
+#error "Unknown system"
+#endif
+
+  union {
+    __float128 f128;
+    struct ieee128 s128;
+  } u;
+
+  u.f128 = x;
+  upper  = u.s128.upper;
+  lower  = u.s128.lower;
+
+  sign      = (unsigned)((upper >> 63) & 1);
+  exponent  = (unsigned)((upper >> 48) & ((((uint64_t)1) << 16) - 1));
+  mantissa1 = (upper & ((((uint64_t)1) << 48) - 1));
+  mantissa2 = lower;
+
+  printf ("%c 0x%.4x 0x%.12" PRIx64 " 0x%.16" PRIx64,
+	  sign ? '-' : '+',
+	  exponent,
+	  mantissa1,
+	  mantissa2);
+}
+#endif
+
+__attribute__((__noinline__))
+static void
+do_test (__float128 expected, __float128 got, const char *name)
+{
+  int equal_p = (expected == got);
+
+#ifdef DEBUG
+  printf ("Test %s, expected: ", name);
+  print_f128 (expected);
+  printf (" %5g, got: ", (double) expected);
+  print_f128 (got);
+  printf (" %5g, result %s\n",
+	  (double) got,
+	  (equal_p) ? "equal" : "not equal");
+#endif
+
+  if (!equal_p)
+    __builtin_abort ();
+}
+
+
+int
+main (void)
+{
+  __float128 one	= 1.0q;
+  __float128 two	= 2.0q;
+  __float128 three	= 3.0q;
+  __float128 four	= 4.0q;
+  __float128 five	= 5.0q;
+  __float128 add_result = (1.0q + 2.0q);
+  __float128 mul_result = ((1.0q + 2.0q) * 3.0q);
+  __float128 div_result = (((1.0q + 2.0q) * 3.0q) / 4.0q);
+  __float128 sub_result = ((((1.0q + 2.0q) * 3.0q) / 4.0q) - 5.0q);
+  __float128 neg_result = - sub_result;
+  __float128 add_xresult;
+  __float128 mul_xresult;
+  __float128 div_xresult;
+  __float128 sub_xresult;
+  __float128 neg_xresult;
+
+#if defined(__FLOAT128__) && defined(_ARCH_PPC)
+  __asm__ (" #prevent constant folding, %x0" : "+wa" (one));
+  __asm__ (" #prevent constant folding, %x0" : "+wa" (two));
+  __asm__ (" #prevent constant folding, %x0" : "+wa" (three));
+  __asm__ (" #prevent constant folding, %x0" : "+wa" (four));
+  __asm__ (" #prevent constant folding, %x0" : "+wa" (five));
+
+#else
+  one   = no_optimize (one);
+  two   = no_optimize (two);
+  three = no_optimize (three);
+  four  = no_optimize (four);
+  five  = no_optimize (five);
+#endif
+
+  add_xresult = (one + two);
+  do_test (add_result, add_xresult, "add");
+
+  mul_xresult = add_xresult * three;
+  do_test (mul_result, mul_xresult, "mul");
+
+  div_xresult = mul_xresult / four;
+  do_test (div_result, div_xresult, "div");
+
+  sub_xresult = div_xresult - five;
+  do_test (sub_result, sub_xresult, "sub");
+
+  neg_xresult = - sub_xresult;
+  do_test (neg_result, neg_xresult, "neg");
+
+#ifdef DEBUG
+  printf ("Passed\n");
+#endif
+
+  return 0;
+}
Index: gcc/testsuite/gcc.target/powerpc/float128-2.c
===================================================================
--- gcc/testsuite/gcc.target/powerpc/float128-2.c	(revision 0)
+++ gcc/testsuite/gcc.target/powerpc/float128-2.c	(revision 0)
@@ -0,0 +1,226 @@
+/* { dg-do run { target { powerpc*-*-linux* } } } */
+/* { dg-require-effective-target ppc_float128_sw } */
+/* { dg-options "-mcpu=power7 -O2 -mfloat128 -static-libgcc" } */
+
+/*
+ * Test program to make sure we are getting more precision than the 53 bits we
+ * get with IEEE double.
+ */
+
+#include <stdio.h>
+#include <math.h>
+#include <stdlib.h>
+#include <stddef.h>
+
+#ifndef TYPE
+#define TYPE __float128
+#endif
+
+#ifndef NO_INLINE
+#define NO_INLINE __attribute__((__noinline__))
+#endif
+
+static TYPE power_of_two (ssize_t) NO_INLINE;
+static TYPE calc1 (TYPE) NO_INLINE;
+static TYPE calc2 (TYPE) NO_INLINE;
+static TYPE calc3 (TYPE) NO_INLINE;
+
+#ifndef POWER2
+#define POWER2 60
+#endif
+
+\f
+/*
+ * Print TYPE in hex.
+ */
+
+
+#if defined(DEBUG) || defined(DEBUG2)
+static void print_hex (const char *prefix, TYPE, const char *suffix) NO_INLINE;
+
+#if defined (__i386__) || defined (__x86_64__) || defined (__LITTLE_ENDIAN__)
+#define ENDIAN_REVERSE(N, MAX)        ((MAX) - 1 - (N))
+
+#else
+#define ENDIAN_REVERSE(N, MAX)        (N)
+#endif
+
+static void
+print_hex (const char *prefix, TYPE value, const char *suffix)
+{
+  union {
+    TYPE f128;
+    unsigned char uc[sizeof (TYPE)];
+  } u;
+
+  size_t i;
+
+  u.f128 = value;
+  printf ("%s0x", prefix);
+  for (i = 0; i < sizeof (TYPE); i++)
+    printf ("%.2x", u.uc[ ENDIAN_REVERSE (i, sizeof (TYPE)) ]);
+
+  printf (", %24.2Lf%s", (long double)value, suffix);
+}
+#endif
+
+\f
+/*
+ * Return a power of two.
+ */
+
+static TYPE
+power_of_two (ssize_t num)
+{
+  TYPE ret = (TYPE) 1.0;
+  ssize_t i;
+
+  if (num >= 0)
+    {
+      for (i = 0; i < num; i++)
+	ret *= (TYPE) 2.0;
+    }
+  else
+    {
+      ssize_t num2 = -num;
+      for (i = 0; i < num2; i++)
+	ret /= (TYPE) 2.0;
+    }
+
+#ifdef DEBUG
+  printf ("power_of_two (%2ld)   = ", (long) num);
+  print_hex ("", ret, "\n");
+#endif
+
+  return ret;
+}
+
+\f
+#ifdef ADDSUB
+static TYPE add (TYPE a, TYPE b) NO_INLINE;
+static TYPE sub (TYPE a, TYPE b) NO_INLINE;
+
+static TYPE
+add (TYPE a, TYPE b)
+{
+  TYPE c;
+#ifdef DEBUG
+  print_hex ("add, arg1           = ", a, "\n");
+  print_hex ("add, arg2           = ", b, "\n");
+#endif
+  c = a + b;
+#ifdef DEBUG
+  print_hex ("add, result         = ", c, "\n");
+#endif
+  return c;
+}
+
+static TYPE
+sub (TYPE a, TYPE b)
+{
+  TYPE c;
+#ifdef DEBUG
+  print_hex ("sub, arg1           = ", a, "\n");
+  print_hex ("sub, arg2           = ", b, "\n");
+#endif
+  c = a - b;
+#ifdef DEBUG
+  print_hex ("sub, result         = ", c, "\n");
+#endif
+  return c;
+}
+
+#else
+#define add(x, y) ((x) + (y))
+#define sub(x, y) ((x) - (y))
+#endif
+
+/*
+ * Various calculations.  Add in 2**POWER2, and subtract 2**(POWER2-1) twice, and we should
+ * get the original value.
+ */
+
+static TYPE
+calc1 (TYPE num)
+{
+  TYPE num2 = add (power_of_two (POWER2), num);
+  TYPE ret;
+
+#ifdef DEBUG
+  print_hex ("calc1 (before call) = ", num2, "\n");
+#endif
+
+  ret = calc2 (num2);
+
+#ifdef DEBUG
+  print_hex ("calc1 (after call)  = ", ret, "\n");
+#endif
+
+  return ret;
+}
+
+static TYPE
+calc2 (TYPE num)
+{
+  TYPE num2 = sub (num, power_of_two (POWER2-1));
+  TYPE ret;
+
+#ifdef DEBUG
+  print_hex ("calc2 (before call) = ", num2, "\n");
+#endif
+
+  ret = calc3 (num2);
+
+#ifdef DEBUG
+  print_hex ("calc2 (after call)  = ", ret, "\n");
+#endif
+
+  return ret;
+}
+
+static TYPE
+calc3 (TYPE num)
+{
+  TYPE ret = sub (num, (((TYPE) 2.0) * power_of_two (POWER2-2)));
+
+#ifdef DEBUG
+  print_hex ("calc3               = ", ret, "\n");
+#endif
+
+  return ret;
+}
+
+\f
+int
+main (void)
+{
+  TYPE input, output;
+
+#ifdef DEBUG
+  printf ("Testing, %ld bytes\n", (long) sizeof (TYPE));
+#endif
+
+  input = power_of_two (-1);
+  if ((double)input != 0.5)
+    {
+#if defined(DEBUG) || defined(DEBUG2)
+      print_hex ("Input should be 0.5:  ", output, "\n");
+      return 1;
+#else
+      __builtin_abort ();
+#endif
+    }
+
+  output = calc1 (input);
+  if ((double)output != 0.5)
+    {
+#if defined(DEBUG) || defined(DEBUG2)
+      print_hex ("Output should be 0.5: ", output, "\n");
+      return 1;
+#else
+      __builtin_abort ();
+#endif
+    }
+
+  return 0;
+}

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH], PowerPC IEEE 128-bit fp, #12 (default -mfloat128 on PowerPC-Linux)
  2016-01-21 21:25                     ` [PATCH], PowerPC IEEE 128-bit fp, #12 (default -mfloat128 on PowerPC-Linux) Michael Meissner
@ 2016-01-26 14:52                       ` David Edelsohn
  0 siblings, 0 replies; 18+ messages in thread
From: David Edelsohn @ 2016-01-26 14:52 UTC (permalink / raw)
  To: Michael Meissner, Joseph Myers, GCC Patches, Steven Munroe,
	Tulio Magno Quites Machado Filho, William J. Schmidt

On Thu, Jan 21, 2016 at 4:25 PM, Michael Meissner
<meissner@linux.vnet.ibm.com> wrote:
> This is the final patch (at least so far) that turns on -mfloat128 by default
> for PowerPC Linux systems where the VSX instruction set is enabled.  As I
> mentioned in the last email, because we don't build the __float128 emulator on
> other systems, I didn't think it would be useful to make it the default.
>
> I did a boostrap build/check with no regressions on a little endian power8
> system.  Are the patches ok to check in?
>
> [gcc]
> 2016-01-21   Michael Meissner  <meissner@linux.vnet.ibm.com>
>
>         * config/rs6000/rs6000.c (rs6000_option_override_internal): Enable
>         -mfloat128 by default on PowerPC Linux systems with the VSX
>         instruction enabled.
>
> [gcc/testsuite]
> 2016-01-21   Michael Meissner  <meissner@linux.vnet.ibm.com>
>
>         * gcc.target/powerpc/float128-1.c: New test for IEEE 128-bit
>         floating point support.
>         * gcc.target/powerpc/float128-2.c: Likewise.

No.  This is too risky a change during Stage 4.

- David

^ permalink raw reply	[flat|nested] 18+ messages in thread

end of thread, other threads:[~2016-01-26 14:52 UTC | newest]

Thread overview: 18+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-12-29 16:38 [PATCH], PowerPC IEEE 128-bit fp, #11 (enable libgcc conversions) Michael Meissner
2015-12-29 16:53 ` Michael Meissner
2015-12-29 20:26 ` David Edelsohn
2015-12-31 20:30 ` Joseph Myers
2016-01-04 22:11   ` Michael Meissner
2016-01-06 22:48 ` [PATCH], PowerPC IEEE 128-bit fp, #11-rev2 " Michael Meissner
2016-01-07 21:55   ` Joseph Myers
2016-01-11 18:56     ` [PATCH], PowerPC IEEE 128-bit fp, #11-rev3 " Michael Meissner
2016-01-12  0:19       ` Joseph Myers
2016-01-12 18:31         ` Michael Meissner
2016-01-12 23:47           ` Joseph Myers
2016-01-12 23:49             ` David Edelsohn
2016-01-14 22:03               ` Michael Meissner
2016-01-21  1:00                 ` [PATCH], PowerPC IEEE 128-bit fp, #11-rev4 " Michael Meissner
2016-01-21 13:28                   ` David Edelsohn
2016-01-21 17:35                     ` Michael Meissner
2016-01-21 21:25                     ` [PATCH], PowerPC IEEE 128-bit fp, #12 (default -mfloat128 on PowerPC-Linux) Michael Meissner
2016-01-26 14:52                       ` David Edelsohn

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).