diff mbox

[v3,7/7] powerpc64le: Enable float128

Message ID 1498221206-26864-8-git-send-email-gftg@linux.vnet.ibm.com
State New
Headers show

Commit Message

Gabriel F. T. Gomes June 23, 2017, 12:33 p.m. UTC
From: "Paul E. Murphy" <murphyp@linux.vnet.ibm.com>

Changes since v2:

  - In the NEWS file, added mentions to strtof128_l and wcstof128_l and
    fixed some wording errors.
  - In sfp-machine.h, removed comment about 32-bits/64-bits detection,
    since the 32-bits part has been removed.
  - Removed the addition of the CFLAG $(libio-mtsafe) from the
    arch-specific Makefile.  It is added to the arch-independent
    sysdeps/ieee754/float128/Makefile by a previous, arch-independent
    commit.

Changes since v1:

  - In the NEWS file, mention the addition of HUGE_VAL_F128 and of the float128
    versions of the macros prefixed with M_.
  - In the NEWS file, clarify what float128 features are added.
  - Do not include libc-header-start.h in test-float128.h, strfromf128.c,
    strtof128_l.c, wcstof128.c, wcstof128_l.c.  Instead, include features.h in
    bits/floatn.h to get the definition of __GNUC_PREREQ.
  - When compiling C++, also define __HAVE_FLOAT128.
  - Use $(all-object-suffixes) in sysdeps/powerpc/powerpc64le/Makefile.
  - Remove blocks of code from sfp-machine.h that are irrelevant to
    powerpc64le.
  - In include/float.h, include libc-header-start.h to get the definition of
    __GLIBC_USE.

-- 8< --
This patch adds ULPs for the float128 type, updates the abilist for libc
and libm, and adds the files bits/floatn.h and float128-abi.h, in order to
enable the new type for powerpc64le.

This patch also adds the implementation of sqrtf128 for powerpc64le, since
it is not implemented in libgcc.  The sfp-machine.h header is taken from
libgcc.

Tested for powerpc64le (GCC 6.2 and GCC 7.1), powerpc64 and s390x.

	* NEWS: Mention the addition of float128 features for powerpc64le.
	* manual/math.texi (Mathematics): Mention the enabling of float128
	for powerpc64le.
	* sysdeps/powerpc/bits/floatn.h: New file.
	* sysdeps/powerpc/fpu/libm-test-ulps: Regenerated.
	* sysdeps/powerpc/fpu/math_private.h:
	(__ieee754_sqrtf128): New inline override.
	* sysdeps/powerpc/powerpc64le/Implies-before: New file.
	* sysdeps/powerpc/powerpc64le/Makefile: New file.
	* sysdeps/powerpc/powerpc64le/fpu/e_sqrtf128.c: New file.
	* sysdeps/powerpc/powerpc64le/fpu/sfp-machine.h: New file.
	* sysdeps/powerpc/powerpc64le/power9/fpu/e_sqrtf128.c: New file.
	* sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist:
	Updated.
	* sysdeps/unix/sysv/linux/powerpc/powerpc64/libm-le.abilist:
	Likewise.
	* sysdeps/unix/sysv/linux/powerpc/powerpc64le/float128-abi.h:
	New file.
---
 NEWS                                               |  94 ++++
 manual/math.texi                                   |   3 +-
 sysdeps/powerpc/bits/floatn.h                      |  92 ++++
 sysdeps/powerpc/fpu/libm-test-ulps                 | 578 +++++++++++++++++++++
 sysdeps/powerpc/fpu/math_private.h                 |  10 +
 sysdeps/powerpc/powerpc64le/Implies-before         |   1 +
 sysdeps/powerpc/powerpc64le/Makefile               |  45 ++
 sysdeps/powerpc/powerpc64le/fpu/e_sqrtf128.c       |  51 ++
 sysdeps/powerpc/powerpc64le/fpu/sfp-machine.h      | 115 ++++
 .../powerpc/powerpc64le/power9/fpu/e_sqrtf128.c    |  36 ++
 .../sysv/linux/powerpc/powerpc64/libc-le.abilist   |   7 +
 .../sysv/linux/powerpc/powerpc64/libm-le.abilist   | 138 +++++
 .../sysv/linux/powerpc/powerpc64le/float128-abi.h  |   2 +
 13 files changed, 1171 insertions(+), 1 deletion(-)
 create mode 100644 sysdeps/powerpc/bits/floatn.h
 create mode 100644 sysdeps/powerpc/powerpc64le/Implies-before
 create mode 100644 sysdeps/powerpc/powerpc64le/Makefile
 create mode 100644 sysdeps/powerpc/powerpc64le/fpu/e_sqrtf128.c
 create mode 100644 sysdeps/powerpc/powerpc64le/fpu/sfp-machine.h
 create mode 100644 sysdeps/powerpc/powerpc64le/power9/fpu/e_sqrtf128.c
 create mode 100644 sysdeps/unix/sysv/linux/powerpc/powerpc64le/float128-abi.h

Comments

Joseph Myers June 23, 2017, 1:18 p.m. UTC | #1
This is OK, subject to any fixes requested by powerpc maintainers.
Tulio Magno Quites Machado Filho June 26, 2017, 5:11 p.m. UTC | #2
"Gabriel F. T. Gomes" <gftg@linux.vnet.ibm.com> writes:

> This patch adds ULPs for the float128 type, updates the abilist for libc
> and libm, and adds the files bits/floatn.h and float128-abi.h, in order to
> enable the new type for powerpc64le.
>
> This patch also adds the implementation of sqrtf128 for powerpc64le, since
> it is not implemented in libgcc.  The sfp-machine.h header is taken from
> libgcc.
>
> Tested for powerpc64le (GCC 6.2 and GCC 7.1), powerpc64 and s390x.
>
> 	* NEWS: Mention the addition of float128 features for powerpc64le.
> 	* manual/math.texi (Mathematics): Mention the enabling of float128
> 	for powerpc64le.
> 	* sysdeps/powerpc/bits/floatn.h: New file.
> 	* sysdeps/powerpc/fpu/libm-test-ulps: Regenerated.
> 	* sysdeps/powerpc/fpu/math_private.h:
> 	(__ieee754_sqrtf128): New inline override.
> 	* sysdeps/powerpc/powerpc64le/Implies-before: New file.
> 	* sysdeps/powerpc/powerpc64le/Makefile: New file.
> 	* sysdeps/powerpc/powerpc64le/fpu/e_sqrtf128.c: New file.
> 	* sysdeps/powerpc/powerpc64le/fpu/sfp-machine.h: New file.
> 	* sysdeps/powerpc/powerpc64le/power9/fpu/e_sqrtf128.c: New file.
> 	* sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist:
> 	Updated.
> 	* sysdeps/unix/sysv/linux/powerpc/powerpc64/libm-le.abilist:
> 	Likewise.
> 	* sysdeps/unix/sysv/linux/powerpc/powerpc64le/float128-abi.h:
> 	New file.

Looks good to me.
Joseph Myers June 26, 2017, 11:02 p.m. UTC | #3
I'm seeing a testsuite regression for powerpc64le with 
build-many-glibcs.py with this patch (elf/check-localplt fails), did you 
not see that in your testing?

https://sourceware.org/ml/libc-testresults/2017-q2/msg00427.html

The failure is: "Extra PLT reference: libc.so: __getauxval".  As the 
__getauxval reference comes from have_ieee_hw_p in libgcc, presumably you 
need to allow that PLT reference in localplt.data with an appropriate 
comment, as it won't be readily possible to avoid it.
Alan Modra June 27, 2017, 3:28 a.m. UTC | #4
On Mon, Jun 26, 2017 at 11:02:04PM +0000, Joseph Myers wrote:
> I'm seeing a testsuite regression for powerpc64le with 
> build-many-glibcs.py with this patch (elf/check-localplt fails), did you 
> not see that in your testing?
> 
> https://sourceware.org/ml/libc-testresults/2017-q2/msg00427.html
> 
> The failure is: "Extra PLT reference: libc.so: __getauxval".  As the 
> __getauxval reference comes from have_ieee_hw_p in libgcc, presumably you 
> need to allow that PLT reference in localplt.data with an appropriate 
> comment, as it won't be readily possible to avoid it.

See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81193

I'm not sure the check-localplt fail should be swept under the rug.
Florian Weimer June 27, 2017, 7:05 a.m. UTC | #5
On 06/27/2017 01:02 AM, Joseph Myers wrote:
> I'm seeing a testsuite regression for powerpc64le with 
> build-many-glibcs.py with this patch (elf/check-localplt fails), did you 
> not see that in your testing?
> 
> https://sourceware.org/ml/libc-testresults/2017-q2/msg00427.html
> 
> The failure is: "Extra PLT reference: libc.so: __getauxval".  As the 
> __getauxval reference comes from have_ieee_hw_p in libgcc, presumably you 
> need to allow that PLT reference in localplt.data with an appropriate 
> comment, as it won't be readily possible to avoid it.

The __getauxval call happens from IFUNC resolvers and violates current
guidelines regarding what can be done from IFUNC resolvers.  This is
another reason to get rid of the PLT reference.

My IFUNC resolver enhancements are not ready for 2.26, and I plan to
wait for DJ's dl-minimal malloc improvements to land, rather than
rolling my own memory allocator to back the IFUNC resolver queue.

Thanks,
Florian
Andreas Schwab June 27, 2017, 7:19 a.m. UTC | #6
On Jun 23 2017, "Gabriel F. T. Gomes" <gftg@linux.vnet.ibm.com> wrote:

> +* Support is added, on powerpc64le, for interfaces supporting the _Float128
> +  type from ISO/IEC TS 18661-3:2015.  Most of the interfaces are taken from
> +  TS 18661-3.  The type-generic macros in <math.h> support this type, but
> +  those in <tgmath.h> do not.  The GNU C Library now requires GCC 6.2 or
> +  later to build for powerpc64le.  When used with GCC versions before GCC
> +  7, these interfaces may be used with the type under the non-standard name
> +  __float128.

You also need to check that the compiler actually supports float128.

Andreas.
Andreas Schwab June 27, 2017, 9:24 a.m. UTC | #7
On Jun 23 2017, "Gabriel F. T. Gomes" <gftg@linux.vnet.ibm.com> wrote:

> diff --git a/sysdeps/powerpc/powerpc64le/Makefile b/sysdeps/powerpc/powerpc64le/Makefile
> new file mode 100644
> index 0000000..bd8a82d
> --- /dev/null
> +++ b/sysdeps/powerpc/powerpc64le/Makefile
> @@ -0,0 +1,45 @@
> +# When building float128 we need to ensure -mfloat128 is
> +# passed to all such object files.
> +
> +ifeq ($(subdir),math)
> +# sqrtf128 requires emulation before POWER9.
> +CPPFLAGS += -I../soft-fp
> +
> +# float128 requires adding a handful of extra flags.
> +$(foreach suf,$(all-object-suffixes),%f128$(suf)): CFLAGS += -mfloat128
> +$(foreach suf,$(all-object-suffixes),%f128_r$(suf)): CFLAGS += -mfloat128
> +$(objpfx)test-float128%.o $(objpfx)test-float128%.os: CFLAGS += -mfloat128
> +$(objpfx)test-ifloat128%.o $(objpfx)test-ifloat128%.os: CFLAGS += -mfloat128
> +CFLAGS-libm-test-support-float128.c += -mfloat128
> +endif
> +
> +# Append flags to string <-> _Float128 routines.
> +ifneq ($(filter $(subdir),wcsmbs stdlib),)
> +%f128.o %f128.os %f128_l.o %f128_l.os %f128_nan.o %f128_nan.os %float1282mpn.o %float1282mpn.os %mpn2float128.o %mpn2float128.os: CFLAGS += -mfloat128

You need to iterate over all object suffixes.

Andreas.
Andreas Schwab June 27, 2017, 1:15 p.m. UTC | #8
On Jun 23 2017, "Gabriel F. T. Gomes" <gftg@linux.vnet.ibm.com> wrote:

> +# Append flags to string <-> _Float128 routines.
> +ifneq ($(filter $(subdir),wcsmbs stdlib),)
> +%f128.o %f128.os %f128_l.o %f128_l.os %f128_nan.o %f128_nan.os %float1282mpn.o %float1282mpn.os %mpn2float128.o %mpn2float128.os: CFLAGS += -mfloat128
> +CFLAGS-bug-strtod.c += -mfloat128
> +CFLAGS-bug-strtod2.c += -mfloat128
> +CFLAGS-tst-strtod-round.c += -mfloat128
> +CFLAGS-tst-wcstod-round.c += -mfloat128
> +CFLAGS-tst-strtod6.c += -mfloat128
> +CFLAGS-tst-strfrom.c += -mfloat128
> +CFLAGS-tst-strfrom-locale.c += -mfloat128
> +CFLAGS-strfrom-skeleton.c += -mfloat128
> +
> +# When building glibc with support for _Float128, the powers of ten tables in
> +# fpioconst.c and in the string conversion functions must be extended.
> +sysdep-CFLAGS += $(sysdep-CFLAGS-$(<F))
> +sysdep-CFLAGS-fpioconst.c += -mfloat128
> +sysdep-CFLAGS-strtod_l.c += -mfloat128
> +sysdep-CFLAGS-strtof_l.c += -mfloat128
> +sysdep-CFLAGS-strtold_l.c += -mfloat128
> +sysdep-CFLAGS-wcstod_l.c += -mfloat128
> +sysdep-CFLAGS-wcstof_l.c += -mfloat128
> +sysdep-CFLAGS-wcstold_l.c += -mfloat128

Why sysdep-CFLAGS-* and not CFLAGS-*?

Wouldn't it make sense to always pass -mfloat128?

Andreas.
Peter Bergner June 27, 2017, 3 p.m. UTC | #9
On 6/27/17 2:05 AM, Florian Weimer wrote:
> On 06/27/2017 01:02 AM, Joseph Myers wrote:
>> I'm seeing a testsuite regression for powerpc64le with 
>> build-many-glibcs.py with this patch (elf/check-localplt fails), did you 
>> not see that in your testing?
>>
>> https://sourceware.org/ml/libc-testresults/2017-q2/msg00427.html
>>
>> The failure is: "Extra PLT reference: libc.so: __getauxval".  As the 
>> __getauxval reference comes from have_ieee_hw_p in libgcc, presumably you 
>> need to allow that PLT reference in localplt.data with an appropriate 
>> comment, as it won't be readily possible to avoid it.
> 
> The __getauxval call happens from IFUNC resolvers and violates current
> guidelines regarding what can be done from IFUNC resolvers.  This is
> another reason to get rid of the PLT reference.
> 
> My IFUNC resolver enhancements are not ready for 2.26, and I plan to
> wait for DJ's dl-minimal malloc improvements to land, rather than
> rolling my own memory allocator to back the IFUNC resolver queue.

We have a __builtin_cpu_supports() version that can test for float128, so
why can't we use the following?  On older systems (ie, older glibcs),
the builtin will expand to false, which is conservatively correct.

Peter


-/* 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)
+#define SW_OR_HW(SW, HW) (__builtin_cpu_supports ("ieee128") ? HW : SW)
Gabriel F. T. Gomes June 27, 2017, 5:46 p.m. UTC | #10
On Mon, 26 Jun 2017 23:02:04 +0000
Joseph Myers <joseph@codesourcery.com> wrote:

> I'm seeing a testsuite regression for powerpc64le with 
> build-many-glibcs.py with this patch (elf/check-localplt fails), did you 
> not see that in your testing?

Not with GCCs built by myself (GCC 6.2 and 7.1 (release tags) and GCC 8
(248932)), which is what I used in the tests.  None of them produced a
libc.so that contained have_ieee_hw_p.

I'm still trying to understand what's the difference between my compilers
and those from build-many-glibcs.py, but one of our suspects is that the
assembler on my machine does not have support for POWER9.
Florian Weimer June 27, 2017, 6:42 p.m. UTC | #11
On 06/27/2017 05:00 PM, Peter Bergner wrote:
> We have a __builtin_cpu_supports() version that can test for float128, so
> why can't we use the following?  On older systems (ie, older glibcs),
> the builtin will expand to false, which is conservatively correct.

> +#define SW_OR_HW(SW, HW) (__builtin_cpu_supports ("ieee128") ? HW : SW)

How is that implemented?  Does it call into the kernel or glibc, too?

Thanks,
Florian
Peter Bergner June 27, 2017, 6:51 p.m. UTC | #12
On 6/27/17 1:42 PM, Florian Weimer wrote:
> On 06/27/2017 05:00 PM, Peter Bergner wrote:
>> We have a __builtin_cpu_supports() version that can test for float128, so
>> why can't we use the following?  On older systems (ie, older glibcs),
>> the builtin will expand to false, which is conservatively correct.
> 
>> +#define SW_OR_HW(SW, HW) (__builtin_cpu_supports ("ieee128") ? HW : SW)
> 
> How is that implemented?  Does it call into the kernel or glibc, too?

No.  It reads a bit mask stored in the TCB which glibc has initialized
for us long before main() is called:

  https://sourceware.org/ml/libc-alpha/2015-12/msg00041.html

..so all that is generated is a load followed by a masking operation:

bergner@pike:~$ cat float128.c
int
float128 (void)
{
  return __builtin_cpu_supports ("ieee128");
}
bergner@pike:~$ gcc -O2 -S float128.c
bergner@pike:~$ cat float128.s
	[snip]
float128:
	lwz 3,-28776(13)
	rldicl 3,3,42,63
	blr

Peter
Florian Weimer June 27, 2017, 7:17 p.m. UTC | #13
* Peter Bergner:

> On 6/27/17 1:42 PM, Florian Weimer wrote:
>> On 06/27/2017 05:00 PM, Peter Bergner wrote:
>>> We have a __builtin_cpu_supports() version that can test for float128, so
>>> why can't we use the following?  On older systems (ie, older glibcs),
>>> the builtin will expand to false, which is conservatively correct.
>> 
>>> +#define SW_OR_HW(SW, HW) (__builtin_cpu_supports ("ieee128") ? HW : SW)
>> 
>> How is that implemented?  Does it call into the kernel or glibc, too?
>
> No.  It reads a bit mask stored in the TCB which glibc has initialized
> for us long before main() is called:
>
>   https://sourceware.org/ml/libc-alpha/2015-12/msg00041.html
>
> ..so all that is generated is a load followed by a masking operation:
>
> bergner@pike:~$ cat float128.c
> int
> float128 (void)
> {
>   return __builtin_cpu_supports ("ieee128");
> }
> bergner@pike:~$ gcc -O2 -S float128.c
> bergner@pike:~$ cat float128.s
> 	[snip]
> float128:
> 	lwz 3,-28776(13)
> 	rldicl 3,3,42,63
> 	blr

Nice.  I guess the next question is: what would ensure that this code
only runs on a glibc which sets up the TCB in the expected way?  Is
there a symbol reference which prevents that?

__parse_hwcap_and_convert_at_platform isn't that symbol, as far as I
can tell.
cseo June 27, 2017, 7:33 p.m. UTC | #14
Nice.  I guess the next question is: what would ensure that this code
    only runs on a glibc which sets up the TCB in the expected way?  Is
    there a symbol reference which prevents that?
    
    __parse_hwcap_and_convert_at_platform isn't that symbol, as far as I
    can tell.
    
  

Actually, it is. It’s versioned at glibc-2.23. I added that in sysdeps/powerpc/Versions when I did the change. This is what we agreed with O’Donell and the others that discussed that patch.


--
Carlos Eduardo Seo
Software Engineer - Linux on Power Toolchain
cseo@linux.vnet.ibm.com
Peter Bergner June 27, 2017, 7:34 p.m. UTC | #15
On 6/27/17 2:17 PM, Florian Weimer wrote:
> * Peter Bergner:
>> bergner@pike:~$ cat float128.c
>> int
>> float128 (void)
>> {
>>   return __builtin_cpu_supports ("ieee128");
>> }
>> bergner@pike:~$ gcc -O2 -S float128.c
>> bergner@pike:~$ cat float128.s
>> 	[snip]
>> float128:
>> 	lwz 3,-28776(13)
>> 	rldicl 3,3,42,63
>> 	blr
> 
> Nice.  I guess the next question is: what would ensure that this code
> only runs on a glibc which sets up the TCB in the expected way?  Is
> there a symbol reference which prevents that?
> 
> __parse_hwcap_and_convert_at_platform isn't that symbol, as far as I
> can tell.

Yes, we emit a symbol only defined by libcs that support this and
yes, __parse_hwcap_and_convert_at_platform is that symbol:

  if (cpu_builtin_p)
    {
      /* We have expanded a CPU builtin, so we need to emit a reference to
         the special symbol that LIBC uses to declare it supports the
         AT_PLATFORM and AT_HWCAP/AT_HWCAP2 in the TCB feature.  */
      switch_to_section (data_section);
      fprintf (asm_out_file, "\t.align %u\n", TARGET_32BIT ? 2 : 3);
      fprintf (asm_out_file, "\t%s %s\n",
               TARGET_32BIT ? ".long" : ".quad", tcb_verification_symbol);
    }

Why do you think that isn't the symbol we're using?

Peter
Florian Weimer June 27, 2017, 9:41 p.m. UTC | #16
* Peter Bergner:

> On 6/27/17 2:17 PM, Florian Weimer wrote:
>> * Peter Bergner:
>>> bergner@pike:~$ cat float128.c
>>> int
>>> float128 (void)
>>> {
>>>   return __builtin_cpu_supports ("ieee128");
>>> }
>>> bergner@pike:~$ gcc -O2 -S float128.c
>>> bergner@pike:~$ cat float128.s
>>> 	[snip]
>>> float128:
>>> 	lwz 3,-28776(13)
>>> 	rldicl 3,3,42,63
>>> 	blr
>> 
>> Nice.  I guess the next question is: what would ensure that this code
>> only runs on a glibc which sets up the TCB in the expected way?  Is
>> there a symbol reference which prevents that?
>> 
>> __parse_hwcap_and_convert_at_platform isn't that symbol, as far as I
>> can tell.
>
> Yes, we emit a symbol only defined by libcs that support this and
> yes, __parse_hwcap_and_convert_at_platform is that symbol:
>
>   if (cpu_builtin_p)
>     {
>       /* We have expanded a CPU builtin, so we need to emit a reference to
>          the special symbol that LIBC uses to declare it supports the
>          AT_PLATFORM and AT_HWCAP/AT_HWCAP2 in the TCB feature.  */
>       switch_to_section (data_section);
>       fprintf (asm_out_file, "\t.align %u\n", TARGET_32BIT ? 2 : 3);
>       fprintf (asm_out_file, "\t%s %s\n",
>                TARGET_32BIT ? ".long" : ".quad", tcb_verification_symbol);
>     }

I see, so everything is fine.  Nice!
Szabolcs Nagy June 28, 2017, 4:30 p.m. UTC | #17
On 27/06/17 22:41, Florian Weimer wrote:
> * Peter Bergner:
> 
>> On 6/27/17 2:17 PM, Florian Weimer wrote:
>>> * Peter Bergner:
>>>> bergner@pike:~$ cat float128.c
>>>> int
>>>> float128 (void)
>>>> {
>>>>   return __builtin_cpu_supports ("ieee128");
>>>> }
>>>> bergner@pike:~$ gcc -O2 -S float128.c
>>>> bergner@pike:~$ cat float128.s
>>>> 	[snip]
>>>> float128:
>>>> 	lwz 3,-28776(13)
>>>> 	rldicl 3,3,42,63
>>>> 	blr
>>>
>>> Nice.  I guess the next question is: what would ensure that this code
>>> only runs on a glibc which sets up the TCB in the expected way?  Is
>>> there a symbol reference which prevents that?
>>>
>>> __parse_hwcap_and_convert_at_platform isn't that symbol, as far as I
>>> can tell.
>>
>> Yes, we emit a symbol only defined by libcs that support this and
>> yes, __parse_hwcap_and_convert_at_platform is that symbol:
>>
>>   if (cpu_builtin_p)
>>     {
>>       /* We have expanded a CPU builtin, so we need to emit a reference to
>>          the special symbol that LIBC uses to declare it supports the
>>          AT_PLATFORM and AT_HWCAP/AT_HWCAP2 in the TCB feature.  */
>>       switch_to_section (data_section);
>>       fprintf (asm_out_file, "\t.align %u\n", TARGET_32BIT ? 2 : 3);
>>       fprintf (asm_out_file, "\t%s %s\n",
>>                TARGET_32BIT ? ".long" : ".quad", tcb_verification_symbol);
>>     }
> 
> I see, so everything is fine.  Nice!
> 

well using the new builtin means glibc build will fail with old gcc.
Peter Bergner June 28, 2017, 5:08 p.m. UTC | #18
On 6/28/17 11:30 AM, Szabolcs Nagy wrote:
> On 27/06/17 22:41, Florian Weimer wrote:
>> * Peter Bergner:
>>> Yes, we emit a symbol only defined by libcs that support this and
>>> yes, __parse_hwcap_and_convert_at_platform is that symbol:
>>>
>>>   if (cpu_builtin_p)
>>>     {
>>>       /* We have expanded a CPU builtin, so we need to emit a reference to
>>>          the special symbol that LIBC uses to declare it supports the
>>>          AT_PLATFORM and AT_HWCAP/AT_HWCAP2 in the TCB feature.  */
>>>       switch_to_section (data_section);
>>>       fprintf (asm_out_file, "\t.align %u\n", TARGET_32BIT ? 2 : 3);
>>>       fprintf (asm_out_file, "\t%s %s\n",
>>>                TARGET_32BIT ? ".long" : ".quad", tcb_verification_symbol);
>>>     }
>>
>> I see, so everything is fine.  Nice!
>>
> 
> well using the new builtin means glibc build will fail with old gcc.

How so?  The usage of __builtin_cpu_supports() we're talking about is in
libgcc's float128-ifunc.c source file, so it's not part of GLIBC's build.

Peter
Szabolcs Nagy June 28, 2017, 5:15 p.m. UTC | #19
On 28/06/17 18:08, Peter Bergner wrote:
> On 6/28/17 11:30 AM, Szabolcs Nagy wrote:
>> On 27/06/17 22:41, Florian Weimer wrote:
>>> * Peter Bergner:
>>>> Yes, we emit a symbol only defined by libcs that support this and
>>>> yes, __parse_hwcap_and_convert_at_platform is that symbol:
>>>>
>>>>   if (cpu_builtin_p)
>>>>     {
>>>>       /* We have expanded a CPU builtin, so we need to emit a reference to
>>>>          the special symbol that LIBC uses to declare it supports the
>>>>          AT_PLATFORM and AT_HWCAP/AT_HWCAP2 in the TCB feature.  */
>>>>       switch_to_section (data_section);
>>>>       fprintf (asm_out_file, "\t.align %u\n", TARGET_32BIT ? 2 : 3);
>>>>       fprintf (asm_out_file, "\t%s %s\n",
>>>>                TARGET_32BIT ? ".long" : ".quad", tcb_verification_symbol);
>>>>     }
>>>
>>> I see, so everything is fine.  Nice!
>>>
>>
>> well using the new builtin means glibc build will fail with old gcc.
> 
> How so?  The usage of __builtin_cpu_supports() we're talking about is in
> libgcc's float128-ifunc.c source file, so it's not part of GLIBC's build.

ah sorry then don't mind me.
Florian Weimer July 4, 2017, 6:37 a.m. UTC | #20
On 06/27/2017 09:05 AM, Florian Weimer wrote:
> On 06/27/2017 01:02 AM, Joseph Myers wrote:
>> I'm seeing a testsuite regression for powerpc64le with 
>> build-many-glibcs.py with this patch (elf/check-localplt fails), did you 
>> not see that in your testing?
>>
>> https://sourceware.org/ml/libc-testresults/2017-q2/msg00427.html
>>
>> The failure is: "Extra PLT reference: libc.so: __getauxval".  As the 
>> __getauxval reference comes from have_ieee_hw_p in libgcc, presumably you 
>> need to allow that PLT reference in localplt.data with an appropriate 
>> comment, as it won't be readily possible to avoid it.
> 
> The __getauxval call happens from IFUNC resolvers and violates current
> guidelines regarding what can be done from IFUNC resolvers.  This is
> another reason to get rid of the PLT reference.
> 
> My IFUNC resolver enhancements are not ready for 2.26, and I plan to
> wait for DJ's dl-minimal malloc improvements to land, rather than
> rolling my own memory allocator to back the IFUNC resolver queue.

The above isn't correct because even if you can call getauxval, it
doesn't have the data to return meaningful results during relocation.
This currently breaks --enable-bind-now builds on pcp64le:

  https://sourceware.org/bugzilla/show_bug.cgi?id=21707

For the time being, we just disable --enable-bind-now, but I'd prefer a
proper fix, perhaps the one suggested here:

  https://sourceware.org/ml/libc-alpha/2017-06/msg01383.html

Thanks,
Florian
Peter Bergner July 7, 2017, 10:19 p.m. UTC | #21
On 7/4/17 1:37 AM, Florian Weimer wrote:
> For the time being, we just disable --enable-bind-now, but I'd prefer a
> proper fix, perhaps the one suggested here:
> 
>   https://sourceware.org/ml/libc-alpha/2017-06/msg01383.html

I just committed this to GCC trunk today.  I still need to bootstrap
and regtest the backports to GCC 7 and GCC 6.

Peter
Peter Bergner July 10, 2017, 7:59 p.m. UTC | #22
On 7/7/17 5:19 PM, Peter Bergner wrote:
> On 7/4/17 1:37 AM, Florian Weimer wrote:
>> For the time being, we just disable --enable-bind-now, but I'd prefer a
>> proper fix, perhaps the one suggested here:
>>
>>   https://sourceware.org/ml/libc-alpha/2017-06/msg01383.html
> 
> I just committed this to GCC trunk today.  I still need to bootstrap
> and regtest the backports to GCC 7 and GCC 6.

The trunk patch applied to GCC 7 and GCC 6 cleanly/no fuzz and it
bootstrapped and regtested with no regressions on powerpc64le-linux
as well as on powerpc64-linux and running the testsuite in both 32-bit
and 64-bit modes.

The backports were approved today, but I am leaving on vacation today,
returning on the 19th, so I will not commit the backports until I
return.  If there is a large need to have the backports committed before
I return, please work with Tulio to find someone on our GCC team to
commit the patch and watch for fallout.

Peter
Peter Bergner July 20, 2017, 2:48 p.m. UTC | #23
On 7/10/17 2:59 PM, Peter Bergner wrote:
> On 7/7/17 5:19 PM, Peter Bergner wrote:
>> On 7/4/17 1:37 AM, Florian Weimer wrote:
>>> For the time being, we just disable --enable-bind-now, but I'd prefer a
>>> proper fix, perhaps the one suggested here:
>>>
>>>   https://sourceware.org/ml/libc-alpha/2017-06/msg01383.html
>>
>> I just committed this to GCC trunk today.  I still need to bootstrap
>> and regtest the backports to GCC 7 and GCC 6.
> 
> The trunk patch applied to GCC 7 and GCC 6 cleanly/no fuzz and it
> bootstrapped and regtested with no regressions on powerpc64le-linux
> as well as on powerpc64-linux and running the testsuite in both 32-bit
> and 64-bit modes.
> 
> The backports were approved today, but I am leaving on vacation today,
> returning on the 19th, so I will not commit the backports until I
> return.  If there is a large need to have the backports committed before
> I return, please work with Tulio to find someone on our GCC team to
> commit the patch and watch for fallout.

Backports to GCC 7 and GCC 6 release branches have now been committed.

Peter
diff mbox

Patch

diff --git a/NEWS b/NEWS
index e8546e1..027f09b 100644
--- a/NEWS
+++ b/NEWS
@@ -121,6 +121,100 @@  Version 2.26
   C Library is GCC 4.9.  Older GCC versions, and non-GNU compilers, can
   still be used to compile programs using the GNU C Library.
 
+* Support is added, on powerpc64le, for interfaces supporting the _Float128
+  type from ISO/IEC TS 18661-3:2015.  Most of the interfaces are taken from
+  TS 18661-3.  The type-generic macros in <math.h> support this type, but
+  those in <tgmath.h> do not.  The GNU C Library now requires GCC 6.2 or
+  later to build for powerpc64le.  When used with GCC versions before GCC
+  7, these interfaces may be used with the type under the non-standard name
+  __float128.
+
+  New <stdlib.h> functions from ISO/IEC TS 18661-3:
+
+    - String Conversion Functions: strfromf128 and strtof128.
+
+  New <math.h> features from ISO/IEC TS 18661-3:
+
+    - Very Large Number macro: HUGE_VAL_F128.
+
+    - Signaling NaN macro: SNANF128.
+
+    - Trigonometric Functions: acosf128, asinf128, atanf128, atan2f128,
+      cosf128, sinf128, tanf128.
+
+    - Hyperbolic Functions: acoshf128, asinhf128, atanhf128, coshf128,
+      sinhf128, tanhf128.
+
+    - Exponential and Logarithmic Functions: expf128, exp2f128, expm1f128,
+      frexpf128, ilogbf128, ldexpf128, llogbf128, logf128, log10f128,
+      log1pf128, log2f128, logbf128, modff128, scalbnf128, scalblnf128.
+
+    - Power and Absolute Functions: cbrtf128, fabsf128, hypotf128, powf128,
+      sqrtf128.
+
+    - Error and Gamma Functions: erff128, erfcf128, lgammaf128, tgammaf128.
+
+    - Nearest Integer Functions: ceilf128, floorf128, nearbyintf128,
+      rintf128, lrintf128, llrintf128, roundf128, lroundf128, llroundf128,
+      roundevenf128, truncf128, fromfpf128, ufromfpf128, fromfpxf128,
+      ufromfpxf128.
+
+    - Remainder Functions: fmodf128, remainderf128, remquof128.
+
+    - Manipulation Functions: copysignf128, nanf128, nextafterf128,
+      nextupf128, nextdownf128, canonicalizef128.
+
+    - Minimum, Maximum, and Positive Difference Functions: fdimf128,
+      fmaxf128, fminf128, fmaxmagf128, fminmagf128.
+
+    - Floating Multiply-Add Function: fmaf128.
+
+    - Total Order Functions: totalorderf128, totalordermagf128.
+
+    - Payload Functions: getpayloadf128, setpayloadf128, setpayloadsigf128.
+
+  New <complex.h> functions from ISO/IEC TS 18661-3:
+
+    - Trigonometric Functions: cacosf128, casinf128, catanf128, ccosf128,
+      csinf128, ctanf128.
+
+    - Hyperbolic Functions: cacoshf128, casinhf128, catanhf128, ccoshf128,
+      csinhf128, ctanhf128.
+
+    - Exponential and Logarithmic Functions: cexpf128, clogf128.
+
+    - Power and Absolute Functions: cabsf128, cpowf128, csqrtf128.
+
+    - Manipulation Functions: cargf128, cimagf128, CMPLXF128, conjf128,
+      cprojf128, crealf128.
+
+  The following <wchar.h> functions are added as GNU extensions:
+
+    - Wide String Conversion Functions: wsctof128, wcstof128_l.
+
+  The following <stdlib.h> function is added as a GNU extension:
+
+    - String Conversion Function: strtof128_l.
+
+  The following <math.h> features are added as GNU extensions:
+
+    - Predefined Mathematical Constants: M_Ef128, M_LOG2Ef128,
+      M_LOG10Ef128, M_LN2f128, M_LN10f128, M_PIf128, M_PI_2f128,
+      M_PI_4f128, M_1_PIf128, M_2_PIf128, M_2_SQRTPIf128, M_SQRT2f128,
+      M_SQRT1_2f128.
+
+    - Trigonometric Function: sincosf128.
+
+    - Exponential and Logarithmic Function: exp10f128.
+
+    - Error and Gamma Function: lgammaf128_r.
+
+    - Bessel Functions: j0f128, j1f128, jnf128, y0f128, y1f128, ynf128.
+
+  The following <complex.h> function is added as a GNU extension:
+
+    - Exponential and Logarithmic Function: clog10f128.
+
 Security related changes:
 
 * The DNS stub resolver limits the advertised UDP buffer size to 1200 bytes,
diff --git a/manual/math.texi b/manual/math.texi
index 5bd3341..01bd812 100644
--- a/manual/math.texi
+++ b/manual/math.texi
@@ -66,7 +66,8 @@  these functions are described along with the @code{double},
 @w{ISO/IEC TS 18661-3}, unless explicitly stated otherwise.
 
 Currently, support for @code{_Float@var{N}} or @code{_Float@var{N}x}
-types is not provided for any machine.
+types is only provided for @code{_Float128} on powerpc64le (PowerPC
+64-bits little-endian).
 
 @menu
 * Mathematical Constants::      Precise numeric values for often-used
diff --git a/sysdeps/powerpc/bits/floatn.h b/sysdeps/powerpc/bits/floatn.h
new file mode 100644
index 0000000..be57e70
--- /dev/null
+++ b/sysdeps/powerpc/bits/floatn.h
@@ -0,0 +1,92 @@ 
+/* Macros to control TS 18661-3 glibc features on powerpc.
+   Copyright (C) 2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   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.
+
+   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/>.  */
+
+#ifndef _BITS_FLOATN_H
+#define _BITS_FLOATN_H
+
+#include <features.h>
+
+/* Defined to 1 if the current compiler invocation provides a
+   floating-point type with the IEEE 754 binary128 format, and this glibc
+   includes corresponding *f128 interfaces for it.  */
+#if defined _ARCH_PWR8 && defined __LITTLE_ENDIAN__ && (_CALL_ELF == 2) \
+    && defined __FLOAT128__
+# define __HAVE_FLOAT128 1
+#else
+# define __HAVE_FLOAT128 0
+#endif
+
+/* Defined to 1 if __HAVE_FLOAT128 is 1 and the type is ABI-distinct
+   from the default float, double and long double types in this glibc.  */
+#if __HAVE_FLOAT128
+# define __HAVE_DISTINCT_FLOAT128 1
+#else
+# define __HAVE_DISTINCT_FLOAT128 0
+#endif
+
+/* Defined to concatenate the literal suffix to be used with _Float128
+   types, if __HAVE_FLOAT128 is 1. */
+#if __HAVE_FLOAT128
+# if !__GNUC_PREREQ (7, 0) || defined __cplusplus
+/* The literal suffix (f128) exist for powerpc only since GCC 7.0.  */
+#  define __f128(x) x##q
+# else
+#  define __f128(x) x##f128
+# endif
+#endif
+
+/* Defined to a complex binary128 type if __HAVE_FLOAT128 is 1.  */
+#if __HAVE_FLOAT128
+# if !__GNUC_PREREQ (7, 0) || defined __cplusplus
+/* Add a typedef for older GCC compilers which don't natively support
+   _Complex _Float128.  */
+typedef _Complex float __cfloat128 __attribute__ ((__mode__ (__KC__)));
+#  define __CFLOAT128 __cfloat128
+# else
+#  define __CFLOAT128 _Complex _Float128
+# endif
+#endif
+
+/* The remaining of this file provides support for older compilers.  */
+#if __HAVE_FLOAT128
+
+/* The type _Float128 exist for powerpc only since GCC 7.0.  */
+# if !__GNUC_PREREQ (7, 0) || defined __cplusplus
+typedef __float128 _Float128;
+# endif
+
+/* Builtin __builtin_huge_valf128 doesn't exist before GCC 7.0.  */
+# if !__GNUC_PREREQ (7, 0)
+#  define __builtin_huge_valf128() ((_Float128) __builtin_huge_val ())
+# endif
+
+/* The following builtins (suffixed with 'q') are available in GCC >= 6.2,
+   which is the minimum version required for float128 support on powerpc64le.
+   Since GCC 7.0 the builtins suffixed with f128 are also available, then
+   there is no need to redefined them.  */
+# if !__GNUC_PREREQ (7, 0)
+#  define __builtin_copysignf128 __builtin_copysignq
+#  define __builtin_fabsf128 __builtin_fabsq
+#  define __builtin_inff128 __builtin_infq
+#  define __builtin_nanf128 __builtin_nanq
+#  define __builtin_nansf128 __builtin_nansq
+# endif
+
+#endif
+
+#endif /* _BITS_FLOATN_H */
diff --git a/sysdeps/powerpc/fpu/libm-test-ulps b/sysdeps/powerpc/fpu/libm-test-ulps
index 72eb2b1..7fb6744 100644
--- a/sysdeps/powerpc/fpu/libm-test-ulps
+++ b/sysdeps/powerpc/fpu/libm-test-ulps
@@ -3,1583 +3,1985 @@ 
 # Maximal error of functions:
 Function: "acos":
 float: 1
+float128: 1
 ifloat: 1
+ifloat128: 1
 ildouble: 1
 ldouble: 1
 
 Function: "acos_downward":
 double: 1
 float: 1
+float128: 1
 idouble: 1
 ifloat: 1
+ifloat128: 1
 ildouble: 3
 ldouble: 3
 
 Function: "acos_towardzero":
 double: 1
 float: 1
+float128: 1
 idouble: 1
 ifloat: 1
+ifloat128: 1
 ildouble: 3
 ldouble: 3
 
 Function: "acos_upward":
 double: 1
 float: 1
+float128: 1
 idouble: 1
 ifloat: 1
+ifloat128: 1
 ildouble: 2
 ldouble: 2
 
 Function: "acosh":
 double: 2
 float: 2
+float128: 2
 idouble: 2
 ifloat: 2
+ifloat128: 2
 ildouble: 2
 ldouble: 2
 
 Function: "acosh_downward":
 double: 2
 float: 2
+float128: 3
 idouble: 2
 ifloat: 2
+ifloat128: 3
 ildouble: 3
 ldouble: 3
 
 Function: "acosh_towardzero":
 double: 2
 float: 2
+float128: 2
 idouble: 2
 ifloat: 2
+ifloat128: 2
 ildouble: 4
 ldouble: 4
 
 Function: "acosh_upward":
 double: 2
 float: 2
+float128: 2
 idouble: 2
 ifloat: 2
+ifloat128: 2
 ildouble: 3
 ldouble: 4
 
 Function: "asin":
 float: 1
+float128: 1
 ifloat: 1
+ifloat128: 1
 ildouble: 2
 ldouble: 2
 
 Function: "asin_downward":
 double: 1
 float: 1
+float128: 2
 idouble: 1
 ifloat: 1
+ifloat128: 2
 ildouble: 2
 ldouble: 2
 
 Function: "asin_towardzero":
 double: 1
 float: 1
+float128: 1
 idouble: 1
 ifloat: 1
+ifloat128: 1
 ildouble: 1
 ldouble: 1
 
 Function: "asin_upward":
 double: 1
 float: 1
+float128: 2
 idouble: 1
 ifloat: 1
+ifloat128: 2
 ildouble: 2
 ldouble: 2
 
 Function: "asinh":
 double: 1
 float: 1
+float128: 3
 idouble: 1
 ifloat: 1
+ifloat128: 3
 ildouble: 2
 ldouble: 2
 
 Function: "asinh_downward":
 double: 3
 float: 3
+float128: 4
 idouble: 3
 ifloat: 3
+ifloat128: 4
 ildouble: 5
 ldouble: 5
 
 Function: "asinh_towardzero":
 double: 2
 float: 2
+float128: 2
 idouble: 2
 ifloat: 2
+ifloat128: 2
 ildouble: 5
 ldouble: 5
 
 Function: "asinh_upward":
 double: 3
 float: 3
+float128: 4
 idouble: 3
 ifloat: 3
+ifloat128: 4
 ildouble: 7
 ldouble: 7
 
 Function: "atan":
 double: 1
 float: 1
+float128: 1
 idouble: 1
 ifloat: 1
+ifloat128: 1
 ildouble: 1
 ldouble: 1
 
 Function: "atan2":
 float: 1
+float128: 1
 ifloat: 1
+ifloat128: 1
 ildouble: 2
 ldouble: 2
 
 Function: "atan2_downward":
 double: 1
 float: 2
+float128: 2
 idouble: 1
 ifloat: 2
+ifloat128: 2
 ildouble: 5
 ldouble: 5
 
 Function: "atan2_towardzero":
 double: 1
 float: 2
+float128: 3
 idouble: 1
 ifloat: 2
+ifloat128: 3
 ildouble: 6
 ldouble: 6
 
 Function: "atan2_upward":
 double: 1
 float: 1
+float128: 2
 idouble: 1
 ifloat: 1
+ifloat128: 2
 ildouble: 3
 ldouble: 3
 
 Function: "atan_downward":
 double: 1
 float: 2
+float128: 2
 idouble: 1
 ifloat: 2
+ifloat128: 2
 ildouble: 1
 ldouble: 1
 
 Function: "atan_towardzero":
 double: 1
 float: 1
+float128: 1
 idouble: 1
 ifloat: 1
+ifloat128: 1
 ildouble: 1
 ldouble: 1
 
 Function: "atan_upward":
 double: 1
 float: 2
+float128: 2
 idouble: 1
 ifloat: 2
+ifloat128: 2
 ildouble: 2
 ldouble: 2
 
 Function: "atanh":
 double: 2
 float: 2
+float128: 3
 idouble: 2
 ifloat: 2
+ifloat128: 3
 ildouble: 2
 ldouble: 2
 
 Function: "atanh_downward":
 double: 3
 float: 3
+float128: 4
 idouble: 3
 ifloat: 3
+ifloat128: 4
 ildouble: 3
 ldouble: 3
 
 Function: "atanh_towardzero":
 double: 2
 float: 2
+float128: 2
 idouble: 2
 ifloat: 2
+ifloat128: 2
 ildouble: 2
 ldouble: 2
 
 Function: "atanh_upward":
 double: 3
 float: 3
+float128: 4
 idouble: 3
 ifloat: 3
+ifloat128: 4
 ildouble: 4
 ldouble: 4
 
 Function: "cabs":
 double: 1
+float128: 1
 idouble: 1
+ifloat128: 1
 ildouble: 1
 ldouble: 1
 
 Function: "cabs_downward":
 double: 1
+float128: 1
 idouble: 1
+ifloat128: 1
 ildouble: 1
 ldouble: 1
 
 Function: "cabs_towardzero":
 double: 1
+float128: 1
 idouble: 1
+ifloat128: 1
 ildouble: 1
 ldouble: 1
 
 Function: "cabs_upward":
 double: 1
+float128: 1
 idouble: 1
+ifloat128: 1
 ildouble: 2
 ldouble: 2
 
 Function: Real part of "cacos":
 double: 1
 float: 2
+float128: 2
 idouble: 1
 ifloat: 2
+ifloat128: 2
 ildouble: 1
 ldouble: 1
 
 Function: Imaginary part of "cacos":
 double: 2
 float: 2
+float128: 2
 idouble: 2
 ifloat: 2
+ifloat128: 2
 ildouble: 2
 ldouble: 2
 
 Function: Real part of "cacos_downward":
 double: 3
 float: 2
+float128: 3
 idouble: 3
 ifloat: 2
+ifloat128: 3
 ildouble: 6
 ldouble: 6
 
 Function: Imaginary part of "cacos_downward":
 double: 5
 float: 3
+float128: 6
 idouble: 5
 ifloat: 3
+ifloat128: 6
 ildouble: 8
 ldouble: 8
 
 Function: Real part of "cacos_towardzero":
 double: 3
 float: 2
+float128: 3
 idouble: 3
 ifloat: 2
+ifloat128: 3
 ildouble: 7
 ldouble: 7
 
 Function: Imaginary part of "cacos_towardzero":
 double: 5
 float: 3
+float128: 5
 idouble: 5
 ifloat: 3
+ifloat128: 5
 ildouble: 8
 ldouble: 8
 
 Function: Real part of "cacos_upward":
 double: 2
 float: 2
+float128: 3
 idouble: 2
 ifloat: 2
+ifloat128: 3
 ildouble: 7
 ldouble: 7
 
 Function: Imaginary part of "cacos_upward":
 double: 5
 float: 5
+float128: 7
 idouble: 5
 ifloat: 5
+ifloat128: 7
 ildouble: 13
 ldouble: 13
 
 Function: Real part of "cacosh":
 double: 2
 float: 2
+float128: 2
 idouble: 2
 ifloat: 2
+ifloat128: 2
 ildouble: 2
 ldouble: 2
 
 Function: Imaginary part of "cacosh":
 double: 1
 float: 2
+float128: 2
 idouble: 1
 ifloat: 2
+ifloat128: 2
 ildouble: 1
 ldouble: 1
 
 Function: Real part of "cacosh_downward":
 double: 5
 float: 3
+float128: 5
 idouble: 5
 ifloat: 3
+ifloat128: 5
 ildouble: 8
 ldouble: 8
 
 Function: Imaginary part of "cacosh_downward":
 double: 3
 float: 3
+float128: 4
 idouble: 3
 ifloat: 3
+ifloat128: 4
 ildouble: 6
 ldouble: 6
 
 Function: Real part of "cacosh_towardzero":
 double: 5
 float: 3
+float128: 5
 idouble: 5
 ifloat: 3
+ifloat128: 5
 ildouble: 8
 ldouble: 8
 
 Function: Imaginary part of "cacosh_towardzero":
 double: 3
 float: 2
+float128: 3
 idouble: 3
 ifloat: 2
+ifloat128: 3
 ildouble: 7
 ldouble: 7
 
 Function: Real part of "cacosh_upward":
 double: 4
 float: 4
+float128: 6
 idouble: 4
 ifloat: 4
+ifloat128: 6
 ildouble: 12
 ldouble: 12
 
 Function: Imaginary part of "cacosh_upward":
 double: 3
 float: 2
+float128: 4
 idouble: 3
 ifloat: 2
+ifloat128: 4
 ildouble: 8
 ldouble: 8
 
 Function: "carg":
 double: 1
 float: 1
+float128: 2
 idouble: 1
 ifloat: 1
+ifloat128: 2
 ildouble: 2
 ldouble: 2
 
 Function: "carg_downward":
 double: 1
 float: 2
+float128: 2
 idouble: 1
 ifloat: 2
+ifloat128: 2
 ildouble: 5
 ldouble: 5
 
 Function: "carg_towardzero":
 double: 1
 float: 2
+float128: 3
 idouble: 1
 ifloat: 2
+ifloat128: 3
 ildouble: 6
 ldouble: 6
 
 Function: "carg_upward":
 double: 1
 float: 1
+float128: 2
 idouble: 1
 ifloat: 1
+ifloat128: 2
 ildouble: 3
 ldouble: 3
 
 Function: Real part of "casin":
 double: 1
 float: 1
+float128: 2
 idouble: 1
 ifloat: 1
+ifloat128: 2
 ildouble: 1
 ldouble: 1
 
 Function: Imaginary part of "casin":
 double: 2
 float: 2
+float128: 2
 idouble: 2
 ifloat: 2
+ifloat128: 2
 ildouble: 2
 ldouble: 2
 
 Function: Real part of "casin_downward":
 double: 3
 float: 2
+float128: 3
 idouble: 3
 ifloat: 2
+ifloat128: 3
 ildouble: 4
 ldouble: 4
 
 Function: Imaginary part of "casin_downward":
 double: 5
 float: 3
+float128: 6
 idouble: 5
 ifloat: 3
+ifloat128: 6
 ildouble: 8
 ldouble: 8
 
 Function: Real part of "casin_towardzero":
 double: 3
 float: 1
+float128: 3
 idouble: 3
 ifloat: 1
+ifloat128: 3
 ildouble: 5
 ldouble: 5
 
 Function: Imaginary part of "casin_towardzero":
 double: 5
 float: 3
+float128: 5
 idouble: 5
 ifloat: 3
+ifloat128: 5
 ildouble: 8
 ldouble: 8
 
 Function: Real part of "casin_upward":
 double: 3
 float: 2
+float128: 3
 idouble: 3
 ifloat: 2
+ifloat128: 3
 ildouble: 6
 ldouble: 6
 
 Function: Imaginary part of "casin_upward":
 double: 5
 float: 5
+float128: 7
 idouble: 5
 ifloat: 5
+ifloat128: 7
 ildouble: 13
 ldouble: 13
 
 Function: Real part of "casinh":
 double: 2
 float: 2
+float128: 2
 idouble: 2
 ifloat: 2
+ifloat128: 2
 ildouble: 2
 ldouble: 2
 
 Function: Imaginary part of "casinh":
 double: 1
 float: 1
+float128: 2
 idouble: 1
 ifloat: 1
+ifloat128: 2
 ildouble: 1
 ldouble: 1
 
 Function: Real part of "casinh_downward":
 double: 5
 float: 3
+float128: 6
 idouble: 5
 ifloat: 3
+ifloat128: 6
 ildouble: 8
 ldouble: 8
 
 Function: Imaginary part of "casinh_downward":
 double: 3
 float: 2
+float128: 3
 idouble: 3
 ifloat: 2
+ifloat128: 3
 ildouble: 4
 ldouble: 4
 
 Function: Real part of "casinh_towardzero":
 double: 5
 float: 3
+float128: 5
 idouble: 5
 ifloat: 3
+ifloat128: 5
 ildouble: 8
 ldouble: 8
 
 Function: Imaginary part of "casinh_towardzero":
 double: 3
 float: 1
+float128: 3
 idouble: 3
 ifloat: 1
+ifloat128: 3
 ildouble: 5
 ldouble: 5
 
 Function: Real part of "casinh_upward":
 double: 5
 float: 5
+float128: 7
 idouble: 5
 ifloat: 5
+ifloat128: 7
 ildouble: 13
 ldouble: 13
 
 Function: Imaginary part of "casinh_upward":
 double: 3
 float: 2
+float128: 3
 idouble: 3
 ifloat: 2
+ifloat128: 3
 ildouble: 6
 ldouble: 6
 
 Function: Real part of "catan":
 double: 1
 float: 1
+float128: 1
 idouble: 1
 ifloat: 1
+ifloat128: 1
 ildouble: 3
 ldouble: 3
 
 Function: Imaginary part of "catan":
 double: 1
 float: 1
+float128: 1
 idouble: 1
 ifloat: 1
+ifloat128: 1
 ildouble: 2
 ldouble: 2
 
 Function: Real part of "catan_downward":
 double: 1
 float: 2
+float128: 2
 idouble: 1
 ifloat: 2
+ifloat128: 2
 ildouble: 6
 ldouble: 6
 
 Function: Imaginary part of "catan_downward":
 double: 2
 float: 2
+float128: 2
 idouble: 2
 ifloat: 2
+ifloat128: 2
 ildouble: 7
 ldouble: 7
 
 Function: Real part of "catan_towardzero":
 double: 1
 float: 2
+float128: 2
 idouble: 1
 ifloat: 2
+ifloat128: 2
 ildouble: 7
 ldouble: 7
 
 Function: Imaginary part of "catan_towardzero":
 double: 2
 float: 2
+float128: 2
 idouble: 2
 ifloat: 2
+ifloat128: 2
 ildouble: 3
 ldouble: 3
 
 Function: Real part of "catan_upward":
 double: 1
 float: 1
+float128: 2
 idouble: 1
 ifloat: 1
+ifloat128: 2
 ildouble: 6
 ldouble: 6
 
 Function: Imaginary part of "catan_upward":
 double: 3
 float: 3
+float128: 3
 idouble: 3
 ifloat: 3
+ifloat128: 3
 ildouble: 8
 ldouble: 8
 
 Function: Real part of "catanh":
 double: 1
 float: 1
+float128: 1
 idouble: 1
 ifloat: 1
+ifloat128: 1
 ildouble: 2
 ldouble: 2
 
 Function: Imaginary part of "catanh":
 double: 1
 float: 1
+float128: 1
 idouble: 1
 ifloat: 1
+ifloat128: 1
 ildouble: 3
 ldouble: 3
 
 Function: Real part of "catanh_downward":
 double: 2
 float: 2
+float128: 2
 idouble: 2
 ifloat: 2
+ifloat128: 2
 ildouble: 5
 ldouble: 5
 
 Function: Imaginary part of "catanh_downward":
 double: 1
 float: 2
+float128: 2
 idouble: 1
 ifloat: 2
+ifloat128: 2
 ildouble: 6
 ldouble: 6
 
 Function: Real part of "catanh_towardzero":
 double: 2
 float: 2
+float128: 2
 idouble: 2
 ifloat: 2
+ifloat128: 2
 ildouble: 3
 ldouble: 3
 
 Function: Imaginary part of "catanh_towardzero":
 double: 1
 float: 2
+float128: 2
 idouble: 1
 ifloat: 2
+ifloat128: 2
 ildouble: 7
 ldouble: 7
 
 Function: Real part of "catanh_upward":
 double: 4
 float: 4
+float128: 4
 idouble: 4
 ifloat: 4
+ifloat128: 4
 ildouble: 8
 ldouble: 8
 
 Function: Imaginary part of "catanh_upward":
 double: 1
 float: 1
+float128: 2
 idouble: 1
 ifloat: 1
+ifloat128: 2
 ildouble: 6
 ldouble: 6
 
 Function: "cbrt":
 double: 3
 float: 1
+float128: 1
 idouble: 3
 ifloat: 1
+ifloat128: 1
 ildouble: 1
 ldouble: 1
 
 Function: "cbrt_downward":
 double: 4
 float: 1
+float128: 1
 idouble: 4
 ifloat: 1
+ifloat128: 1
 ildouble: 5
 ldouble: 5
 
 Function: "cbrt_towardzero":
 double: 3
 float: 1
+float128: 1
 idouble: 3
 ifloat: 1
+ifloat128: 1
 ildouble: 3
 ldouble: 3
 
 Function: "cbrt_upward":
 double: 5
 float: 1
+float128: 1
 idouble: 5
 ifloat: 1
+ifloat128: 1
 ildouble: 2
 ldouble: 2
 
 Function: Real part of "ccos":
 double: 1
 float: 1
+float128: 1
 idouble: 1
 ifloat: 1
+ifloat128: 1
 ildouble: 1
 ldouble: 1
 
 Function: Imaginary part of "ccos":
 double: 1
 float: 1
+float128: 1
 idouble: 1
 ifloat: 1
+ifloat128: 1
 ildouble: 2
 ldouble: 2
 
 Function: Real part of "ccos_downward":
 double: 1
 float: 1
+float128: 2
 idouble: 1
 ifloat: 1
+ifloat128: 2
 ildouble: 6
 ldouble: 6
 
 Function: Imaginary part of "ccos_downward":
 double: 2
 float: 3
+float128: 2
 idouble: 2
 ifloat: 3
+ifloat128: 2
 ildouble: 6
 ldouble: 6
 
 Function: Real part of "ccos_towardzero":
 double: 1
 float: 2
+float128: 2
 idouble: 1
 ifloat: 2
+ifloat128: 2
 ildouble: 6
 ldouble: 6
 
 Function: Imaginary part of "ccos_towardzero":
 double: 2
 float: 3
+float128: 2
 idouble: 2
 ifloat: 3
+ifloat128: 2
 ildouble: 6
 ldouble: 6
 
 Function: Real part of "ccos_upward":
 double: 1
 float: 2
+float128: 3
 idouble: 1
 ifloat: 2
+ifloat128: 3
 ildouble: 3
 ldouble: 3
 
 Function: Imaginary part of "ccos_upward":
 double: 2
 float: 2
+float128: 2
 idouble: 2
 ifloat: 2
+ifloat128: 2
 ildouble: 4
 ldouble: 4
 
 Function: Real part of "ccosh":
 double: 1
 float: 1
+float128: 1
 idouble: 1
 ifloat: 1
+ifloat128: 1
 ildouble: 1
 ldouble: 1
 
 Function: Imaginary part of "ccosh":
 double: 1
 float: 1
+float128: 1
 idouble: 1
 ifloat: 1
+ifloat128: 1
 ildouble: 2
 ldouble: 2
 
 Function: Real part of "ccosh_downward":
 double: 1
 float: 3
+float128: 2
 idouble: 1
 ifloat: 3
+ifloat128: 2
 ildouble: 6
 ldouble: 6
 
 Function: Imaginary part of "ccosh_downward":
 double: 2
 float: 3
+float128: 2
 idouble: 2
 ifloat: 3
+ifloat128: 2
 ildouble: 6
 ldouble: 6
 
 Function: Real part of "ccosh_towardzero":
 double: 1
 float: 3
+float128: 2
 idouble: 1
 ifloat: 3
+ifloat128: 2
 ildouble: 6
 ldouble: 6
 
 Function: Imaginary part of "ccosh_towardzero":
 double: 2
 float: 3
+float128: 2
 idouble: 2
 ifloat: 3
+ifloat128: 2
 ildouble: 6
 ldouble: 6
 
 Function: Real part of "ccosh_upward":
 double: 1
 float: 2
+float128: 3
 idouble: 1
 ifloat: 2
+ifloat128: 3
 ildouble: 3
 ldouble: 3
 
 Function: Imaginary part of "ccosh_upward":
 double: 2
 float: 2
+float128: 2
 idouble: 2
 ifloat: 2
+ifloat128: 2
 ildouble: 4
 ldouble: 4
 
 Function: Real part of "cexp":
 double: 2
 float: 1
+float128: 1
 idouble: 2
 ifloat: 1
+ifloat128: 1
 ildouble: 2
 ldouble: 2
 
 Function: Imaginary part of "cexp":
 double: 1
 float: 2
+float128: 1
 idouble: 1
 ifloat: 2
+ifloat128: 1
 ildouble: 2
 ldouble: 2
 
 Function: Real part of "cexp_downward":
 double: 1
 float: 2
+float128: 2
 idouble: 1
 ifloat: 2
+ifloat128: 2
 ildouble: 11
 ldouble: 11
 
 Function: Imaginary part of "cexp_downward":
 double: 1
 float: 3
+float128: 2
 idouble: 1
 ifloat: 3
+ifloat128: 2
 ildouble: 11
 ldouble: 11
 
 Function: Real part of "cexp_towardzero":
 double: 1
 float: 2
+float128: 2
 idouble: 1
 ifloat: 2
+ifloat128: 2
 ildouble: 11
 ldouble: 11
 
 Function: Imaginary part of "cexp_towardzero":
 double: 1
 float: 3
+float128: 2
 idouble: 1
 ifloat: 3
+ifloat128: 2
 ildouble: 11
 ldouble: 11
 
 Function: Real part of "cexp_upward":
 double: 1
 float: 2
+float128: 3
 idouble: 1
 ifloat: 2
+ifloat128: 3
 ildouble: 3
 ldouble: 3
 
 Function: Imaginary part of "cexp_upward":
 double: 1
 float: 2
+float128: 3
 idouble: 1
 ifloat: 2
+ifloat128: 3
 ildouble: 3
 ldouble: 3
 
 Function: Real part of "clog":
 double: 3
 float: 3
+float128: 2
 idouble: 3
 ifloat: 3
+ifloat128: 2
 ildouble: 5
 ldouble: 5
 
 Function: Imaginary part of "clog":
 double: 1
 float: 1
+float128: 1
 idouble: 1
 ifloat: 1
+ifloat128: 1
 ildouble: 2
 ldouble: 2
 
 Function: Real part of "clog10":
 double: 3
 float: 4
+float128: 2
 idouble: 3
 ifloat: 4
+ifloat128: 2
 ildouble: 3
 ldouble: 3
 
 Function: Imaginary part of "clog10":
 double: 2
 float: 2
+float128: 2
 idouble: 2
 ifloat: 2
+ifloat128: 2
 ildouble: 2
 ldouble: 2
 
 Function: Real part of "clog10_downward":
 double: 6
 float: 6
+float128: 3
 idouble: 6
 ifloat: 6
+ifloat128: 3
 ildouble: 10
 ldouble: 10
 
 Function: Imaginary part of "clog10_downward":
 double: 2
 float: 4
+float128: 3
 idouble: 2
 ifloat: 4
+ifloat128: 3
 ildouble: 7
 ldouble: 7
 
 Function: Real part of "clog10_towardzero":
 double: 5
 float: 5
+float128: 4
 idouble: 5
 ifloat: 5
+ifloat128: 4
 ildouble: 9
 ldouble: 9
 
 Function: Imaginary part of "clog10_towardzero":
 double: 2
 float: 4
+float128: 3
 idouble: 2
 ifloat: 4
+ifloat128: 3
 ildouble: 8
 ldouble: 8
 
 Function: Real part of "clog10_upward":
 double: 8
 float: 5
+float128: 4
 idouble: 8
 ifloat: 5
+ifloat128: 4
 ildouble: 10
 ldouble: 10
 
 Function: Imaginary part of "clog10_upward":
 double: 2
 float: 4
+float128: 3
 idouble: 2
 ifloat: 4
+ifloat128: 3
 ildouble: 7
 ldouble: 7
 
 Function: Real part of "clog_downward":
 double: 7
 float: 5
+float128: 3
 idouble: 7
 ifloat: 5
+ifloat128: 3
 ildouble: 11
 ldouble: 11
 
 Function: Imaginary part of "clog_downward":
 double: 1
 float: 2
+float128: 2
 idouble: 1
 ifloat: 2
+ifloat128: 2
 ildouble: 5
 ldouble: 5
 
 Function: Real part of "clog_towardzero":
 double: 7
 float: 5
+float128: 3
 idouble: 7
 ifloat: 5
+ifloat128: 3
 ildouble: 10
 ldouble: 10
 
 Function: Imaginary part of "clog_towardzero":
 double: 1
 float: 3
+float128: 2
 idouble: 1
 ifloat: 3
+ifloat128: 2
 ildouble: 7
 ldouble: 7
 
 Function: Real part of "clog_upward":
 double: 8
 float: 5
+float128: 4
 idouble: 8
 ifloat: 5
+ifloat128: 4
 ildouble: 10
 ldouble: 10
 
 Function: Imaginary part of "clog_upward":
 double: 1
 float: 2
+float128: 2
 idouble: 1
 ifloat: 2
+ifloat128: 2
 ildouble: 4
 ldouble: 4
 
 Function: "cos":
 float: 3
+float128: 1
 ifloat: 3
+ifloat128: 1
 ildouble: 4
 ldouble: 4
 
 Function: "cos_downward":
 double: 1
 float: 4
+float128: 3
 idouble: 1
 ifloat: 4
+ifloat128: 3
 ildouble: 5
 ldouble: 5
 
 Function: "cos_towardzero":
 double: 1
 float: 3
+float128: 1
 idouble: 1
 ifloat: 3
+ifloat128: 1
 ildouble: 4
 ldouble: 4
 
 Function: "cos_upward":
 double: 1
 float: 3
+float128: 2
 idouble: 1
 ifloat: 3
+ifloat128: 2
 ildouble: 5
 ldouble: 5
 
 Function: "cosh":
 double: 1
 float: 1
+float128: 1
 idouble: 1
 ifloat: 1
+ifloat128: 1
 ildouble: 3
 ldouble: 3
 
 Function: "cosh_downward":
 double: 1
 float: 1
+float128: 2
 idouble: 1
 ifloat: 1
+ifloat128: 1
 ildouble: 2
 ldouble: 2
 
 Function: "cosh_towardzero":
 double: 1
 float: 1
+float128: 2
 idouble: 1
 ifloat: 1
+ifloat128: 1
 ildouble: 2
 ldouble: 2
 
 Function: "cosh_upward":
 double: 1
 float: 2
+float128: 3
 idouble: 1
 ifloat: 2
+ifloat128: 1
 ildouble: 2
 ldouble: 2
 
 Function: Real part of "cpow":
 double: 2
 float: 5
+float128: 4
 idouble: 2
 ifloat: 5
+ifloat128: 4
 ildouble: 4
 ldouble: 4
 
 Function: Imaginary part of "cpow":
 float: 2
+float128: 9
 ifloat: 2
+ifloat128: 9
 ildouble: 2
 ldouble: 2
 
 Function: Real part of "cpow_downward":
 double: 4
 float: 8
+float128: 6
 idouble: 4
 ifloat: 8
+ifloat128: 6
 ildouble: 7
 ldouble: 7
 
 Function: Imaginary part of "cpow_downward":
 double: 1
 float: 2
+float128: 2
 idouble: 1
 ifloat: 2
+ifloat128: 2
 ildouble: 4
 ldouble: 4
 
 Function: Real part of "cpow_towardzero":
 double: 4
 float: 8
+float128: 6
 idouble: 4
 ifloat: 8
+ifloat128: 6
 ildouble: 8
 ldouble: 8
 
 Function: Imaginary part of "cpow_towardzero":
 double: 1
 float: 2
+float128: 2
 idouble: 1
 ifloat: 2
+ifloat128: 2
 ildouble: 4
 ldouble: 4
 
 Function: Real part of "cpow_upward":
 double: 4
 float: 1
+float128: 3
 idouble: 4
 ifloat: 1
+ifloat128: 3
 ildouble: 3
 ldouble: 3
 
 Function: Imaginary part of "cpow_upward":
 double: 1
 float: 2
+float128: 2
 idouble: 1
 ifloat: 2
+ifloat128: 2
 ildouble: 3
 ldouble: 3
 
 Function: Real part of "csin":
 double: 1
 float: 1
+float128: 1
 idouble: 1
 ifloat: 1
+ifloat128: 1
 ildouble: 2
 ldouble: 2
 
 Function: Imaginary part of "csin":
+float128: 1
+ifloat128: 1
 ildouble: 1
 ldouble: 1
 
 Function: Real part of "csin_downward":
 double: 2
 float: 3
+float128: 2
 idouble: 2
 ifloat: 3
+ifloat128: 2
 ildouble: 6
 ldouble: 6
 
 Function: Imaginary part of "csin_downward":
 double: 1
 float: 1
+float128: 2
 idouble: 1
 ifloat: 1
+ifloat128: 2
 ildouble: 6
 ldouble: 6
 
 Function: Real part of "csin_towardzero":
 double: 2
 float: 3
+float128: 2
 idouble: 2
 ifloat: 3
+ifloat128: 2
 ildouble: 6
 ldouble: 6
 
 Function: Imaginary part of "csin_towardzero":
 double: 1
 float: 1
+float128: 2
 idouble: 1
 ifloat: 1
+ifloat128: 2
 ildouble: 6
 ldouble: 6
 
 Function: Real part of "csin_upward":
 double: 2
 float: 2
+float128: 2
 idouble: 2
 ifloat: 2
+ifloat128: 2
 ildouble: 3
 ldouble: 3
 
 Function: Imaginary part of "csin_upward":
 double: 1
 float: 2
+float128: 3
 idouble: 1
 ifloat: 2
+ifloat128: 3
 ildouble: 3
 ldouble: 3
 
 Function: Real part of "csinh":
 float: 1
+float128: 1
 ifloat: 1
+ifloat128: 1
 ildouble: 1
 ldouble: 1
 
 Function: Imaginary part of "csinh":
 double: 1
 float: 1
+float128: 1
 idouble: 1
 ifloat: 1
+ifloat128: 1
 ildouble: 2
 ldouble: 2
 
 Function: Real part of "csinh_downward":
 double: 2
 float: 2
+float128: 2
 idouble: 2
 ifloat: 2
+ifloat128: 2
 ildouble: 6
 ldouble: 6
 
 Function: Imaginary part of "csinh_downward":
 double: 2
 float: 3
+float128: 2
 idouble: 2
 ifloat: 3
+ifloat128: 2
 ildouble: 6
 ldouble: 6
 
 Function: Real part of "csinh_towardzero":
 double: 2
 float: 2
+float128: 2
 idouble: 2
 ifloat: 2
+ifloat128: 2
 ildouble: 6
 ldouble: 6
 
 Function: Imaginary part of "csinh_towardzero":
 double: 2
 float: 3
+float128: 2
 idouble: 2
 ifloat: 3
+ifloat128: 2
 ildouble: 6
 ldouble: 6
 
 Function: Real part of "csinh_upward":
 double: 1
 float: 2
+float128: 3
 idouble: 1
 ifloat: 2
+ifloat128: 3
 ildouble: 3
 ldouble: 3
 
 Function: Imaginary part of "csinh_upward":
 double: 2
 float: 2
+float128: 2
 idouble: 2
 ifloat: 2
+ifloat128: 2
 ildouble: 3
 ldouble: 3
 
 Function: Real part of "csqrt":
 double: 2
 float: 2
+float128: 2
 idouble: 2
 ifloat: 2
+ifloat128: 2
 ildouble: 1
 ldouble: 1
 
 Function: Imaginary part of "csqrt":
 double: 2
 float: 2
+float128: 2
 idouble: 2
 ifloat: 2
+ifloat128: 2
 ildouble: 1
 ldouble: 1
 
 Function: Real part of "csqrt_downward":
 double: 5
 float: 4
+float128: 4
 idouble: 5
 ifloat: 4
+ifloat128: 4
 ildouble: 4
 ldouble: 4
 
 Function: Imaginary part of "csqrt_downward":
 double: 4
 float: 3
+float128: 3
 idouble: 4
 ifloat: 3
+ifloat128: 3
 ildouble: 5
 ldouble: 5
 
 Function: Real part of "csqrt_towardzero":
 double: 4
 float: 3
+float128: 3
 idouble: 4
 ifloat: 3
+ifloat128: 3
 ildouble: 5
 ldouble: 5
 
 Function: Imaginary part of "csqrt_towardzero":
 double: 4
 float: 3
+float128: 3
 idouble: 4
 ifloat: 3
+ifloat128: 3
 ildouble: 5
 ldouble: 5
 
 Function: Real part of "csqrt_upward":
 double: 5
 float: 4
+float128: 4
 idouble: 5
 ifloat: 4
+ifloat128: 4
 ildouble: 12
 ldouble: 12
 
 Function: Imaginary part of "csqrt_upward":
 double: 3
 float: 3
+float128: 3
 idouble: 3
 ifloat: 3
+ifloat128: 3
 ildouble: 8
 ldouble: 8
 
 Function: Real part of "ctan":
 double: 1
 float: 1
+float128: 3
 idouble: 1
 ifloat: 1
+ifloat128: 3
 ildouble: 3
 ldouble: 3
 
 Function: Imaginary part of "ctan":
 double: 2
 float: 1
+float128: 3
 idouble: 2
 ifloat: 1
+ifloat128: 3
 ildouble: 2
 ldouble: 2
 
 Function: Real part of "ctan_downward":
 double: 6
 float: 5
+float128: 4
 idouble: 6
 ifloat: 5
+ifloat128: 4
 ildouble: 6
 ldouble: 6
 
 Function: Imaginary part of "ctan_downward":
 double: 2
 float: 1
+float128: 5
 idouble: 2
 ifloat: 1
+ifloat128: 5
 ildouble: 9
 ldouble: 9
 
 Function: Real part of "ctan_towardzero":
 double: 5
 float: 3
+float128: 4
 idouble: 5
 ifloat: 3
+ifloat128: 4
 ildouble: 6
 ldouble: 6
 
 Function: Imaginary part of "ctan_towardzero":
 double: 2
 float: 2
+float128: 5
 idouble: 2
 ifloat: 2
+ifloat128: 5
 ildouble: 13
 ldouble: 13
 
 Function: Real part of "ctan_upward":
 double: 2
 float: 3
+float128: 5
 idouble: 2
 ifloat: 3
+ifloat128: 5
 ildouble: 7
 ldouble: 7
 
 Function: Imaginary part of "ctan_upward":
 double: 2
 float: 3
+float128: 5
 idouble: 2
 ifloat: 3
+ifloat128: 5
 ildouble: 10
 ldouble: 10
 
 Function: Real part of "ctanh":
 double: 2
 float: 2
+float128: 3
 idouble: 2
 ifloat: 2
+ifloat128: 3
 ildouble: 3
 ldouble: 3
 
 Function: Imaginary part of "ctanh":
 double: 2
 float: 1
+float128: 3
 idouble: 2
 ifloat: 1
+ifloat128: 3
 ildouble: 3
 ldouble: 3
 
 Function: Real part of "ctanh_downward":
 double: 4
 float: 1
+float128: 5
 idouble: 4
 ifloat: 1
+ifloat128: 5
 ildouble: 9
 ldouble: 9
 
 Function: Imaginary part of "ctanh_downward":
 double: 6
 float: 5
+float128: 4
 idouble: 6
 ifloat: 5
+ifloat128: 4
 ildouble: 6
 ldouble: 6
 
 Function: Real part of "ctanh_towardzero":
 double: 2
 float: 2
+float128: 5
 idouble: 2
 ifloat: 2
+ifloat128: 5
 ildouble: 13
 ldouble: 13
 
 Function: Imaginary part of "ctanh_towardzero":
 double: 5
 float: 2
+float128: 3
 idouble: 5
 ifloat: 2
+ifloat128: 3
 ildouble: 10
 ldouble: 10
 
 Function: Real part of "ctanh_upward":
 double: 2
 float: 3
+float128: 5
 idouble: 2
 ifloat: 3
+ifloat128: 5
 ildouble: 10
 ldouble: 10
 
 Function: Imaginary part of "ctanh_upward":
 double: 2
 float: 3
+float128: 5
 idouble: 2
 ifloat: 3
+ifloat128: 5
 ildouble: 10
 ldouble: 10
 
 Function: "erf":
 double: 1
 float: 1
+float128: 1
 idouble: 1
 ifloat: 1
+ifloat128: 1
 ildouble: 1
 ldouble: 1
 
 Function: "erf_downward":
 double: 1
 float: 1
+float128: 2
 idouble: 1
 ifloat: 1
+ifloat128: 2
 ildouble: 2
 ldouble: 2
 
 Function: "erf_towardzero":
 double: 1
 float: 1
+float128: 1
 idouble: 1
 ifloat: 1
+ifloat128: 1
 ildouble: 2
 ldouble: 2
 
 Function: "erf_upward":
 double: 1
 float: 1
+float128: 2
 idouble: 1
 ifloat: 1
+ifloat128: 2
 ildouble: 3
 ldouble: 3
 
 Function: "erfc":
 double: 2
 float: 2
+float128: 2
 idouble: 2
 ifloat: 2
+ifloat128: 2
 ildouble: 3
 ldouble: 3
 
 Function: "erfc_downward":
 double: 3
 float: 4
+float128: 5
 idouble: 3
 ifloat: 4
+ifloat128: 5
 ildouble: 10
 ldouble: 10
 
 Function: "erfc_towardzero":
 double: 3
 float: 3
+float128: 4
 idouble: 3
 ifloat: 3
+ifloat128: 4
 ildouble: 9
 ldouble: 9
 
 Function: "erfc_upward":
 double: 3
 float: 4
+float128: 5
 idouble: 3
 ifloat: 4
+ifloat128: 5
 ildouble: 7
 ldouble: 7
 
 Function: "exp":
 double: 1
 float: 1
+float128: 1
 idouble: 1
 ifloat: 1
+ifloat128: 1
 ildouble: 1
 ldouble: 1
 
 Function: "exp10":
 double: 2
+float128: 2
 idouble: 2
+ifloat128: 2
 ildouble: 1
 ldouble: 1
 
 Function: "exp10_downward":
 double: 2
 float: 1
+float128: 3
 idouble: 2
 ifloat: 1
+ifloat128: 3
 ildouble: 9
 ldouble: 9
 
 Function: "exp10_towardzero":
 double: 2
 float: 1
+float128: 3
 idouble: 2
 ifloat: 1
+ifloat128: 3
 ildouble: 9
 ldouble: 9
 
 Function: "exp10_upward":
 double: 2
 float: 1
+float128: 3
 idouble: 2
 ifloat: 1
+ifloat128: 3
 ildouble: 4
 ldouble: 4
 
 Function: "exp2":
 double: 1
 float: 1
+float128: 1
 idouble: 1
 ifloat: 1
+ifloat128: 1
 ildouble: 2
 ldouble: 2
 
 Function: "exp2_downward":
 double: 1
 float: 1
+float128: 1
 idouble: 1
 ifloat: 1
+ifloat128: 1
 ildouble: 1
 ldouble: 1
 
 Function: "exp2_towardzero":
 double: 1
 float: 1
+float128: 1
 idouble: 1
 ifloat: 1
+ifloat128: 1
 ildouble: 2
 ldouble: 2
 
 Function: "exp2_upward":
 double: 1
 float: 1
+float128: 2
 idouble: 1
 ifloat: 1
+ifloat128: 2
 ildouble: 2
 ldouble: 2
 
@@ -1606,32 +2008,40 @@  ldouble: 1
 Function: "expm1":
 double: 1
 float: 1
+float128: 1
 idouble: 1
 ifloat: 1
+ifloat128: 1
 ildouble: 1
 ldouble: 1
 
 Function: "expm1_downward":
 double: 1
 float: 1
+float128: 2
 idouble: 1
 ifloat: 1
+ifloat128: 2
 ildouble: 3
 ldouble: 3
 
 Function: "expm1_towardzero":
 double: 1
 float: 2
+float128: 4
 idouble: 1
 ifloat: 2
+ifloat128: 4
 ildouble: 5
 ldouble: 5
 
 Function: "expm1_upward":
 double: 1
 float: 1
+float128: 3
 idouble: 1
 ifloat: 1
+ifloat128: 3
 ildouble: 6
 ldouble: 6
 
@@ -1670,306 +2080,386 @@  ldouble: 1
 Function: "gamma":
 double: 3
 float: 4
+float128: 9
 idouble: 3
 ifloat: 4
+ifloat128: 9
 ildouble: 3
 ldouble: 3
 
 Function: "gamma_downward":
 double: 4
 float: 4
+float128: 9
 idouble: 4
 ifloat: 4
+ifloat128: 9
 ildouble: 15
 ldouble: 15
 
 Function: "gamma_towardzero":
 double: 4
 float: 3
+float128: 9
 idouble: 4
 ifloat: 3
+ifloat128: 9
 ildouble: 16
 ldouble: 16
 
 Function: "gamma_upward":
 double: 4
 float: 5
+float128: 9
 idouble: 4
 ifloat: 5
+ifloat128: 9
 ildouble: 11
 ldouble: 11
 
 Function: "hypot":
 double: 1
+float128: 1
 idouble: 1
+ifloat128: 1
 ildouble: 1
 ldouble: 1
 
 Function: "hypot_downward":
 double: 1
+float128: 1
 idouble: 1
+ifloat128: 1
 ildouble: 2
 ldouble: 2
 
 Function: "hypot_towardzero":
 double: 1
+float128: 1
 idouble: 1
+ifloat128: 1
 ildouble: 2
 ldouble: 2
 
 Function: "hypot_upward":
 double: 1
+float128: 1
 idouble: 1
+ifloat128: 1
 ildouble: 3
 ldouble: 3
 
 Function: "j0":
 double: 2
 float: 2
+float128: 2
 idouble: 2
 ifloat: 2
+ifloat128: 2
 ildouble: 2
 ldouble: 2
 
 Function: "j0_downward":
 double: 2
 float: 3
+float128: 4
 idouble: 2
 ifloat: 3
+ifloat128: 4
 ildouble: 11
 ldouble: 11
 
 Function: "j0_towardzero":
 double: 2
 float: 1
+float128: 2
 idouble: 2
 ifloat: 1
+ifloat128: 2
 ildouble: 8
 ldouble: 8
 
 Function: "j0_upward":
 double: 3
 float: 2
+float128: 5
 idouble: 3
 ifloat: 2
+ifloat128: 5
 ildouble: 6
 ldouble: 6
 
 Function: "j1":
 double: 1
 float: 2
+float128: 4
 idouble: 1
 ifloat: 2
+ifloat128: 4
 ildouble: 2
 ldouble: 2
 
 Function: "j1_downward":
 double: 3
 float: 2
+float128: 4
 idouble: 3
 ifloat: 2
+ifloat128: 4
 ildouble: 7
 ldouble: 7
 
 Function: "j1_towardzero":
 double: 3
 float: 2
+float128: 4
 idouble: 3
 ifloat: 2
+ifloat128: 4
 ildouble: 7
 ldouble: 7
 
 Function: "j1_upward":
 double: 3
 float: 4
+float128: 3
 idouble: 3
 ifloat: 4
+ifloat128: 3
 ildouble: 6
 ldouble: 6
 
 Function: "jn":
 double: 4
 float: 4
+float128: 7
 idouble: 4
 ifloat: 4
+ifloat128: 7
 ildouble: 4
 ldouble: 4
 
 Function: "jn_downward":
 double: 4
 float: 5
+float128: 8
 idouble: 4
 ifloat: 5
+ifloat128: 8
 ildouble: 7
 ldouble: 7
 
 Function: "jn_towardzero":
 double: 4
 float: 5
+float128: 8
 idouble: 4
 ifloat: 5
+ifloat128: 8
 ildouble: 7
 ldouble: 7
 
 Function: "jn_upward":
 double: 5
 float: 4
+float128: 7
 idouble: 5
 ifloat: 4
+ifloat128: 7
 ildouble: 5
 ldouble: 5
 
 Function: "lgamma":
 double: 3
 float: 4
+float128: 9
 idouble: 3
 ifloat: 4
+ifloat128: 9
 ildouble: 3
 ldouble: 3
 
 Function: "lgamma_downward":
 double: 4
 float: 4
+float128: 9
 idouble: 4
 ifloat: 4
+ifloat128: 9
 ildouble: 15
 ldouble: 15
 
 Function: "lgamma_towardzero":
 double: 4
 float: 3
+float128: 9
 idouble: 4
 ifloat: 3
+ifloat128: 9
 ildouble: 16
 ldouble: 16
 
 Function: "lgamma_upward":
 double: 4
 float: 5
+float128: 9
 idouble: 4
 ifloat: 5
+ifloat128: 9
 ildouble: 11
 ldouble: 11
 
 Function: "log":
 float: 1
+float128: 1
 ifloat: 1
+ifloat128: 1
 ildouble: 1
 ldouble: 1
 
 Function: "log10":
 double: 2
 float: 2
+float128: 1
 idouble: 2
 ifloat: 2
+ifloat128: 1
 ildouble: 1
 ldouble: 1
 
 Function: "log10_downward":
 double: 2
 float: 3
+float128: 1
 idouble: 2
 ifloat: 3
+ifloat128: 1
 ildouble: 1
 ldouble: 1
 
 Function: "log10_towardzero":
 double: 2
 float: 2
+float128: 1
 idouble: 2
 ifloat: 2
+ifloat128: 1
 ildouble: 2
 ldouble: 2
 
 Function: "log10_upward":
 double: 2
 float: 2
+float128: 1
 idouble: 2
 ifloat: 2
+ifloat128: 1
 ildouble: 1
 ldouble: 1
 
 Function: "log1p":
 double: 1
 float: 1
+float128: 2
 idouble: 1
 ifloat: 1
+ifloat128: 2
 ildouble: 2
 ldouble: 2
 
 Function: "log1p_downward":
 double: 1
 float: 2
+float128: 3
 idouble: 1
 ifloat: 2
+ifloat128: 3
 ildouble: 2
 ldouble: 2
 
 Function: "log1p_towardzero":
 double: 2
 float: 2
+float128: 3
 idouble: 2
 ifloat: 2
+ifloat128: 3
 ildouble: 3
 ldouble: 3
 
 Function: "log1p_upward":
 double: 2
 float: 2
+float128: 2
 idouble: 2
 ifloat: 2
+ifloat128: 2
 ildouble: 3
 ldouble: 3
 
 Function: "log2":
 double: 1
 float: 1
+float128: 2
 idouble: 1
 ifloat: 1
+ifloat128: 2
 ildouble: 1
 ldouble: 1
 
 Function: "log2_downward":
 double: 3
 float: 3
+float128: 3
 idouble: 3
 ifloat: 3
+ifloat128: 3
 ildouble: 2
 ldouble: 2
 
 Function: "log2_towardzero":
 double: 2
 float: 2
+float128: 1
 idouble: 2
 ifloat: 2
+ifloat128: 1
 ildouble: 4
 ldouble: 4
 
 Function: "log2_upward":
 double: 3
 float: 3
+float128: 1
 idouble: 3
 ifloat: 3
+ifloat128: 1
 ildouble: 4
 ldouble: 4
 
 Function: "log_downward":
 float: 2
+float128: 1
 ifloat: 2
+ifloat128: 1
 ildouble: 1
 ldouble: 1
 
 Function: "log_towardzero":
 float: 2
+float128: 2
 ifloat: 2
+ifloat128: 2
 ildouble: 2
 ldouble: 2
 
 Function: "log_upward":
 double: 1
 float: 2
+float128: 1
 idouble: 1
 ifloat: 2
+ifloat128: 1
 ildouble: 1
 ldouble: 1
 
@@ -1983,153 +2473,193 @@  ldouble: 1
 
 Function: "pow":
 float: 1
+float128: 2
 ifloat: 1
+ifloat128: 2
 ildouble: 1
 ldouble: 1
 
 Function: "pow10":
 double: 2
+float128: 2
 idouble: 2
+ifloat128: 2
 ildouble: 1
 ldouble: 1
 
 Function: "pow10_downward":
 double: 2
 float: 1
+float128: 3
 idouble: 2
 ifloat: 1
+ifloat128: 3
 ildouble: 9
 ldouble: 9
 
 Function: "pow10_towardzero":
 double: 2
 float: 1
+float128: 3
 idouble: 2
 ifloat: 1
+ifloat128: 3
 ildouble: 9
 ldouble: 9
 
 Function: "pow10_upward":
 double: 2
 float: 1
+float128: 3
 idouble: 2
 ifloat: 1
+ifloat128: 3
 ildouble: 4
 ldouble: 4
 
 Function: "pow_downward":
 double: 1
 float: 1
+float128: 2
 idouble: 1
 ifloat: 1
+ifloat128: 2
 ildouble: 1
 ldouble: 1
 
 Function: "pow_towardzero":
 double: 1
 float: 1
+float128: 2
 idouble: 1
 ifloat: 1
+ifloat128: 2
 ildouble: 1
 ldouble: 1
 
 Function: "pow_upward":
 double: 1
 float: 1
+float128: 2
 idouble: 1
 ifloat: 1
+ifloat128: 2
 ildouble: 1
 ldouble: 1
 
 Function: "sin":
 float: 1
+float128: 1
 ifloat: 1
+ifloat128: 1
 ildouble: 1
 ldouble: 1
 
 Function: "sin_downward":
 double: 1
 float: 2
+float128: 3
 idouble: 1
 ifloat: 2
+ifloat128: 3
 ildouble: 4
 ldouble: 4
 
 Function: "sin_towardzero":
 double: 1
 float: 1
+float128: 2
 idouble: 1
 ifloat: 1
+ifloat128: 2
 ildouble: 4
 ldouble: 4
 
 Function: "sin_upward":
 double: 1
 float: 2
+float128: 3
 idouble: 1
 ifloat: 2
+ifloat128: 3
 ildouble: 5
 ldouble: 5
 
 Function: "sincos":
 float: 1
+float128: 1
 ifloat: 1
+ifloat128: 1
 ildouble: 1
 ldouble: 1
 
 Function: "sincos_downward":
 double: 1
 float: 2
+float128: 3
 idouble: 1
 ifloat: 2
+ifloat128: 3
 ildouble: 4
 ldouble: 4
 
 Function: "sincos_towardzero":
 double: 1
 float: 1
+float128: 2
 idouble: 1
 ifloat: 1
+ifloat128: 2
 ildouble: 7
 ldouble: 7
 
 Function: "sincos_upward":
 double: 1
 float: 2
+float128: 3
 idouble: 1
 ifloat: 2
+ifloat128: 3
 ildouble: 7
 ldouble: 7
 
 Function: "sinh":
 double: 2
 float: 2
+float128: 2
 idouble: 2
 ifloat: 2
+ifloat128: 2
 ildouble: 3
 ldouble: 3
 
 Function: "sinh_downward":
 double: 3
 float: 3
+float128: 3
 idouble: 3
 ifloat: 3
+ifloat128: 3
 ildouble: 6
 ldouble: 6
 
 Function: "sinh_towardzero":
 double: 2
 float: 2
+float128: 3
 idouble: 2
 ifloat: 2
+ifloat128: 3
 ildouble: 6
 ldouble: 6
 
 Function: "sinh_upward":
 double: 3
 float: 3
+float128: 4
 idouble: 3
 ifloat: 3
+ifloat128: 4
 ildouble: 6
 ldouble: 6
 
@@ -2151,191 +2681,239 @@  ldouble: 1
 
 Function: "tan":
 float: 3
+float128: 1
 ifloat: 3
+ifloat128: 1
 ildouble: 2
 ldouble: 2
 
 Function: "tan_downward":
 double: 1
 float: 3
+float128: 1
 idouble: 1
 ifloat: 3
+ifloat128: 1
 ildouble: 3
 ldouble: 3
 
 Function: "tan_towardzero":
 double: 1
 float: 3
+float128: 1
 idouble: 1
 ifloat: 3
+ifloat128: 1
 ildouble: 2
 ldouble: 2
 
 Function: "tan_upward":
 double: 1
 float: 3
+float128: 1
 idouble: 1
 ifloat: 3
+ifloat128: 1
 ildouble: 3
 ldouble: 3
 
 Function: "tanh":
 double: 2
 float: 2
+float128: 2
 idouble: 2
 ifloat: 2
+ifloat128: 2
 ildouble: 1
 ldouble: 1
 
 Function: "tanh_downward":
 double: 3
 float: 3
+float128: 4
 idouble: 3
 ifloat: 3
+ifloat128: 4
 ildouble: 4
 ldouble: 4
 
 Function: "tanh_towardzero":
 double: 2
 float: 2
+float128: 3
 idouble: 2
 ifloat: 2
+ifloat128: 3
 ildouble: 4
 ldouble: 4
 
 Function: "tanh_upward":
 double: 3
 float: 3
+float128: 3
 idouble: 3
 ifloat: 3
+ifloat128: 3
 ildouble: 6
 ldouble: 6
 
 Function: "tgamma":
 double: 5
 float: 4
+float128: 4
 idouble: 5
 ifloat: 4
+ifloat128: 4
 ildouble: 5
 ldouble: 5
 
 Function: "tgamma_downward":
 double: 5
 float: 5
+float128: 5
 idouble: 5
 ifloat: 5
+ifloat128: 5
 ildouble: 6
 ldouble: 6
 
 Function: "tgamma_towardzero":
 double: 5
 float: 4
+float128: 5
 idouble: 5
 ifloat: 4
+ifloat128: 5
 ildouble: 5
 ldouble: 5
 
 Function: "tgamma_upward":
 double: 4
 float: 4
+float128: 4
 idouble: 4
 ifloat: 4
+ifloat128: 4
 ildouble: 5
 ldouble: 5
 
 Function: "y0":
 double: 2
 float: 1
+float128: 3
 idouble: 2
 ifloat: 1
+ifloat128: 3
 ildouble: 1
 ldouble: 1
 
 Function: "y0_downward":
 double: 3
 float: 2
+float128: 4
 idouble: 3
 ifloat: 2
+ifloat128: 4
 ildouble: 10
 ldouble: 10
 
 Function: "y0_towardzero":
 double: 3
 float: 3
+float128: 3
 idouble: 3
 ifloat: 3
+ifloat128: 3
 ildouble: 8
 ldouble: 8
 
 Function: "y0_upward":
 double: 2
 float: 3
+float128: 3
 idouble: 2
 ifloat: 3
+ifloat128: 3
 ildouble: 9
 ldouble: 9
 
 Function: "y1":
 double: 3
 float: 2
+float128: 2
 idouble: 3
 ifloat: 2
+ifloat128: 2
 ildouble: 2
 ldouble: 2
 
 Function: "y1_downward":
 double: 3
 float: 2
+float128: 4
 idouble: 3
 ifloat: 2
+ifloat128: 4
 ildouble: 7
 ldouble: 7
 
 Function: "y1_towardzero":
 double: 3
 float: 2
+float128: 2
 idouble: 3
 ifloat: 2
+ifloat128: 2
 ildouble: 9
 ldouble: 9
 
 Function: "y1_upward":
 double: 5
 float: 2
+float128: 5
 idouble: 5
 ifloat: 2
+ifloat128: 5
 ildouble: 9
 ldouble: 9
 
 Function: "yn":
 double: 3
 float: 2
+float128: 5
 idouble: 3
 ifloat: 2
+ifloat128: 5
 ildouble: 2
 ldouble: 2
 
 Function: "yn_downward":
 double: 3
 float: 2
+float128: 5
 idouble: 3
 ifloat: 2
+ifloat128: 5
 ildouble: 10
 ldouble: 10
 
 Function: "yn_towardzero":
 double: 3
 float: 3
+float128: 5
 idouble: 3
 ifloat: 3
+ifloat128: 5
 ildouble: 8
 ldouble: 8
 
 Function: "yn_upward":
 double: 4
 float: 3
+float128: 5
 idouble: 4
 ifloat: 3
+ifloat128: 5
 ildouble: 9
 ldouble: 9
 
diff --git a/sysdeps/powerpc/fpu/math_private.h b/sysdeps/powerpc/fpu/math_private.h
index 3c71275..d8fd492 100644
--- a/sysdeps/powerpc/fpu/math_private.h
+++ b/sysdeps/powerpc/fpu/math_private.h
@@ -25,6 +25,16 @@ 
 #include <fenv_private.h>
 #include_next <math_private.h>
 
+#if defined _ARCH_PWR9 && __HAVE_DISTINCT_FLOAT128
+extern __always_inline _Float128
+__ieee754_sqrtf128 (_Float128 __x)
+{
+  _Float128 __z;
+  asm ("xssqrtqp %0,%1" : "=wq" (__z) : "wq" (__x));
+  return __z;
+}
+#endif
+
 extern double __slow_ieee754_sqrt (double);
 extern __always_inline double
 __ieee754_sqrt (double __x)
diff --git a/sysdeps/powerpc/powerpc64le/Implies-before b/sysdeps/powerpc/powerpc64le/Implies-before
new file mode 100644
index 0000000..4806514
--- /dev/null
+++ b/sysdeps/powerpc/powerpc64le/Implies-before
@@ -0,0 +1 @@ 
+ieee754/float128
diff --git a/sysdeps/powerpc/powerpc64le/Makefile b/sysdeps/powerpc/powerpc64le/Makefile
new file mode 100644
index 0000000..bd8a82d
--- /dev/null
+++ b/sysdeps/powerpc/powerpc64le/Makefile
@@ -0,0 +1,45 @@ 
+# When building float128 we need to ensure -mfloat128 is
+# passed to all such object files.
+
+ifeq ($(subdir),math)
+# sqrtf128 requires emulation before POWER9.
+CPPFLAGS += -I../soft-fp
+
+# float128 requires adding a handful of extra flags.
+$(foreach suf,$(all-object-suffixes),%f128$(suf)): CFLAGS += -mfloat128
+$(foreach suf,$(all-object-suffixes),%f128_r$(suf)): CFLAGS += -mfloat128
+$(objpfx)test-float128%.o $(objpfx)test-float128%.os: CFLAGS += -mfloat128
+$(objpfx)test-ifloat128%.o $(objpfx)test-ifloat128%.os: CFLAGS += -mfloat128
+CFLAGS-libm-test-support-float128.c += -mfloat128
+endif
+
+# Append flags to string <-> _Float128 routines.
+ifneq ($(filter $(subdir),wcsmbs stdlib),)
+%f128.o %f128.os %f128_l.o %f128_l.os %f128_nan.o %f128_nan.os %float1282mpn.o %float1282mpn.os %mpn2float128.o %mpn2float128.os: CFLAGS += -mfloat128
+CFLAGS-bug-strtod.c += -mfloat128
+CFLAGS-bug-strtod2.c += -mfloat128
+CFLAGS-tst-strtod-round.c += -mfloat128
+CFLAGS-tst-wcstod-round.c += -mfloat128
+CFLAGS-tst-strtod6.c += -mfloat128
+CFLAGS-tst-strfrom.c += -mfloat128
+CFLAGS-tst-strfrom-locale.c += -mfloat128
+CFLAGS-strfrom-skeleton.c += -mfloat128
+
+# When building glibc with support for _Float128, the powers of ten tables in
+# fpioconst.c and in the string conversion functions must be extended.
+sysdep-CFLAGS += $(sysdep-CFLAGS-$(<F))
+sysdep-CFLAGS-fpioconst.c += -mfloat128
+sysdep-CFLAGS-strtod_l.c += -mfloat128
+sysdep-CFLAGS-strtof_l.c += -mfloat128
+sysdep-CFLAGS-strtold_l.c += -mfloat128
+sysdep-CFLAGS-wcstod_l.c += -mfloat128
+sysdep-CFLAGS-wcstof_l.c += -mfloat128
+sysdep-CFLAGS-wcstold_l.c += -mfloat128
+endif
+
+# Append flags to printf routines.
+ifeq ($(subdir),stdio-common)
+CFLAGS-printf_fp.c = -mfloat128
+CFLAGS-printf_fphex.c = -mfloat128
+CFLAGS-printf_size.c = -mfloat128
+endif
diff --git a/sysdeps/powerpc/powerpc64le/fpu/e_sqrtf128.c b/sysdeps/powerpc/powerpc64le/fpu/e_sqrtf128.c
new file mode 100644
index 0000000..4dcc363
--- /dev/null
+++ b/sysdeps/powerpc/powerpc64le/fpu/e_sqrtf128.c
@@ -0,0 +1,51 @@ 
+/* soft-fp sqrt for _Float128
+   Return sqrt(a)
+   Copyright (C) 2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   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/>.  */
+
+/* Unavoidable hacks since TFmode is assumed to be binary128. */
+#define TFtype KFtype
+#define TF KF
+
+#include <soft-fp.h>
+#include <quad.h>
+
+__float128
+__ieee754_sqrtf128 (__float128 a)
+{
+  FP_DECL_EX;
+  FP_DECL_Q (A);
+  FP_DECL_Q (R);
+  __float128 r;
+
+  FP_INIT_ROUNDMODE;
+  FP_UNPACK_Q (A, a);
+  FP_SQRT_Q (R, A);
+  FP_PACK_Q (r, R);
+  FP_HANDLE_EXCEPTIONS;
+  return r;
+}
+strong_alias (__ieee754_sqrtf128, __sqrtf128_finite)
diff --git a/sysdeps/powerpc/powerpc64le/fpu/sfp-machine.h b/sysdeps/powerpc/powerpc64le/fpu/sfp-machine.h
new file mode 100644
index 0000000..fac5dd0
--- /dev/null
+++ b/sysdeps/powerpc/powerpc64le/fpu/sfp-machine.h
@@ -0,0 +1,115 @@ 
+#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
+
+typedef int TItype __attribute__ ((mode (TI)));
+typedef unsigned int UTItype __attribute__ ((mode (TI)));
+
+#define TI_BITS (__CHAR_BIT__ * (int)sizeof(TItype))
+
+/* The type of the result of a floating point comparison.  This must
+   match `__libgcc_cmp_return__' in GCC for the target.  */
+typedef int __gcc_CMPtype __attribute__ ((mode (__libgcc_cmp_return__)));
+#define CMPtype __gcc_CMPtype
+
+#define _FP_MUL_MEAT_S(R,X,Y)				\
+  _FP_MUL_MEAT_1_wide(_FP_WFRACBITS_S,R,X,Y,umul_ppmm)
+
+#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)
+
+#define _FP_DIV_MEAT_S(R,X,Y)	_FP_DIV_MEAT_1_loop(S,R,X,Y)
+
+#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)
+
+#define _FP_NANFRAC_S		((_FP_QNANBIT_S << 1) - 1)
+
+#define _FP_NANFRAC_D		((_FP_QNANBIT_D << 1) - 1)
+#define _FP_NANFRAC_Q		((_FP_QNANBIT_Q << 1) - 1), -1
+
+#define _FP_NANSIGN_S		0
+#define _FP_NANSIGN_D		0
+#define _FP_NANSIGN_Q		0
+
+#define _FP_KEEPNANFRACP 1
+#define _FP_QNANNEGATEDP 0
+
+/* Someone please check this.  */
+#define _FP_CHOOSENAN(fs, wc, R, X, Y, OP)			\
+  do {								\
+    if ((_FP_FRAC_HIGH_RAW_##fs(X) & _FP_QNANBIT_##fs)		\
+	&& !(_FP_FRAC_HIGH_RAW_##fs(Y) & _FP_QNANBIT_##fs))	\
+      {								\
+	R##_s = Y##_s;						\
+	_FP_FRAC_COPY_##wc(R,Y);				\
+      }								\
+    else							\
+      {								\
+	R##_s = X##_s;						\
+	_FP_FRAC_COPY_##wc(R,X);				\
+      }								\
+    R##_c = FP_CLS_NAN;						\
+  } while (0)
+
+#define _FP_TININESS_AFTER_ROUNDING 0
+
+#define	__LITTLE_ENDIAN	1234
+#define	__BIG_ENDIAN	4321
+#define	__BYTE_ORDER	__LITTLE_ENDIAN
+
+/* 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.  */
+
+#ifdef __FLOAT128__
+#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);
+
+/* The FP_EX_* bits track whether the exception has occurred.  This macro
+   must set the FP_EX_* bits of those exceptions which are configured to
+   trap.  The FPSCR bit which indicates this is 22 ISA bits above the
+   respective FP_EX_* bit.  Note, the ISA labels bits from msb to lsb,
+   so 22 ISA bits above is 22 bits below when counted from the lsb.  */
+# define FP_TRAPPING_EXCEPTIONS ((_fpscr.i << 22) & FP_EX_ALL)
+
+# 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 \
+  union { unsigned long long i; double d; } _fpscr __attribute__ ((unused)) = \
+	{ .i = FP_RND_NEAREST }
+
+#define FP_INIT_ROUNDMODE			\
+  do {						\
+    __asm__ __volatile__ ("mffs %0"		\
+			  : "=f" (_fpscr.d));	\
+  } while (0)
+
+# define FP_ROUNDMODE	(_fpscr.i & FP_RND_MASK)
+#endif	/* !__FLOAT128__ */
diff --git a/sysdeps/powerpc/powerpc64le/power9/fpu/e_sqrtf128.c b/sysdeps/powerpc/powerpc64le/power9/fpu/e_sqrtf128.c
new file mode 100644
index 0000000..769d3f8
--- /dev/null
+++ b/sysdeps/powerpc/powerpc64le/power9/fpu/e_sqrtf128.c
@@ -0,0 +1,36 @@ 
+/* POWER9 sqrt for _Float128
+   Return sqrt(a)
+   Copyright (C) 2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   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/>.  */
+
+__float128
+__ieee754_sqrtf128 (__float128 a)
+{
+  __float128 z;
+  asm ("xssqrtqp %0,%1" : "=wq" (z) : "wq" (a));
+  return z;
+}
+strong_alias (__ieee754_sqrtf128, __sqrtf128_finite)
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist
index 443d89f..51a8d19 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist
@@ -2186,8 +2186,15 @@  GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
 GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 __strtof128_internal F
+GLIBC_2.26 __wcstof128_internal F
 GLIBC_2.26 preadv2 F
 GLIBC_2.26 preadv64v2 F
 GLIBC_2.26 pwritev2 F
 GLIBC_2.26 pwritev64v2 F
 GLIBC_2.26 reallocarray F
+GLIBC_2.26 strfromf128 F
+GLIBC_2.26 strtof128 F
+GLIBC_2.26 strtof128_l F
+GLIBC_2.26 wcstof128 F
+GLIBC_2.26 wcstof128_l F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libm-le.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libm-le.abilist
index 9658ded..d79cb99 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libm-le.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libm-le.abilist
@@ -467,3 +467,141 @@  GLIBC_2.25 ufromfpl F
 GLIBC_2.25 ufromfpx F
 GLIBC_2.25 ufromfpxf F
 GLIBC_2.25 ufromfpxl F
+GLIBC_2.26 GLIBC_2.26 A
+GLIBC_2.26 __acosf128_finite F
+GLIBC_2.26 __acoshf128_finite F
+GLIBC_2.26 __asinf128_finite F
+GLIBC_2.26 __atan2f128_finite F
+GLIBC_2.26 __atanhf128_finite F
+GLIBC_2.26 __coshf128_finite F
+GLIBC_2.26 __exp10f128_finite F
+GLIBC_2.26 __exp2f128_finite F
+GLIBC_2.26 __expf128_finite F
+GLIBC_2.26 __finitef128 F
+GLIBC_2.26 __fmodf128_finite F
+GLIBC_2.26 __fpclassifyf128 F
+GLIBC_2.26 __gammaf128_r_finite F
+GLIBC_2.26 __hypotf128_finite F
+GLIBC_2.26 __iseqsigf128 F
+GLIBC_2.26 __isinff128 F
+GLIBC_2.26 __isnanf128 F
+GLIBC_2.26 __issignalingf128 F
+GLIBC_2.26 __j0f128_finite F
+GLIBC_2.26 __j1f128_finite F
+GLIBC_2.26 __jnf128_finite F
+GLIBC_2.26 __lgammaf128_r_finite F
+GLIBC_2.26 __log10f128_finite F
+GLIBC_2.26 __log2f128_finite F
+GLIBC_2.26 __logf128_finite F
+GLIBC_2.26 __powf128_finite F
+GLIBC_2.26 __remainderf128_finite F
+GLIBC_2.26 __signbitf128 F
+GLIBC_2.26 __sinhf128_finite F
+GLIBC_2.26 __sqrtf128_finite F
+GLIBC_2.26 __y0f128_finite F
+GLIBC_2.26 __y1f128_finite F
+GLIBC_2.26 __ynf128_finite F
+GLIBC_2.26 acosf128 F
+GLIBC_2.26 acoshf128 F
+GLIBC_2.26 asinf128 F
+GLIBC_2.26 asinhf128 F
+GLIBC_2.26 atan2f128 F
+GLIBC_2.26 atanf128 F
+GLIBC_2.26 atanhf128 F
+GLIBC_2.26 cabsf128 F
+GLIBC_2.26 cacosf128 F
+GLIBC_2.26 cacoshf128 F
+GLIBC_2.26 canonicalizef128 F
+GLIBC_2.26 cargf128 F
+GLIBC_2.26 casinf128 F
+GLIBC_2.26 casinhf128 F
+GLIBC_2.26 catanf128 F
+GLIBC_2.26 catanhf128 F
+GLIBC_2.26 cbrtf128 F
+GLIBC_2.26 ccosf128 F
+GLIBC_2.26 ccoshf128 F
+GLIBC_2.26 ceilf128 F
+GLIBC_2.26 cexpf128 F
+GLIBC_2.26 cimagf128 F
+GLIBC_2.26 clog10f128 F
+GLIBC_2.26 clogf128 F
+GLIBC_2.26 conjf128 F
+GLIBC_2.26 copysignf128 F
+GLIBC_2.26 cosf128 F
+GLIBC_2.26 coshf128 F
+GLIBC_2.26 cpowf128 F
+GLIBC_2.26 cprojf128 F
+GLIBC_2.26 crealf128 F
+GLIBC_2.26 csinf128 F
+GLIBC_2.26 csinhf128 F
+GLIBC_2.26 csqrtf128 F
+GLIBC_2.26 ctanf128 F
+GLIBC_2.26 ctanhf128 F
+GLIBC_2.26 erfcf128 F
+GLIBC_2.26 erff128 F
+GLIBC_2.26 exp10f128 F
+GLIBC_2.26 exp2f128 F
+GLIBC_2.26 expf128 F
+GLIBC_2.26 expm1f128 F
+GLIBC_2.26 fabsf128 F
+GLIBC_2.26 fdimf128 F
+GLIBC_2.26 floorf128 F
+GLIBC_2.26 fmaf128 F
+GLIBC_2.26 fmaxf128 F
+GLIBC_2.26 fmaxmagf128 F
+GLIBC_2.26 fminf128 F
+GLIBC_2.26 fminmagf128 F
+GLIBC_2.26 fmodf128 F
+GLIBC_2.26 frexpf128 F
+GLIBC_2.26 fromfpf128 F
+GLIBC_2.26 fromfpxf128 F
+GLIBC_2.26 getpayloadf128 F
+GLIBC_2.26 hypotf128 F
+GLIBC_2.26 ilogbf128 F
+GLIBC_2.26 j0f128 F
+GLIBC_2.26 j1f128 F
+GLIBC_2.26 jnf128 F
+GLIBC_2.26 ldexpf128 F
+GLIBC_2.26 lgammaf128 F
+GLIBC_2.26 lgammaf128_r F
+GLIBC_2.26 llogbf128 F
+GLIBC_2.26 llrintf128 F
+GLIBC_2.26 llroundf128 F
+GLIBC_2.26 log10f128 F
+GLIBC_2.26 log1pf128 F
+GLIBC_2.26 log2f128 F
+GLIBC_2.26 logbf128 F
+GLIBC_2.26 logf128 F
+GLIBC_2.26 lrintf128 F
+GLIBC_2.26 lroundf128 F
+GLIBC_2.26 modff128 F
+GLIBC_2.26 nanf128 F
+GLIBC_2.26 nearbyintf128 F
+GLIBC_2.26 nextafterf128 F
+GLIBC_2.26 nextdownf128 F
+GLIBC_2.26 nextupf128 F
+GLIBC_2.26 powf128 F
+GLIBC_2.26 remainderf128 F
+GLIBC_2.26 remquof128 F
+GLIBC_2.26 rintf128 F
+GLIBC_2.26 roundevenf128 F
+GLIBC_2.26 roundf128 F
+GLIBC_2.26 scalblnf128 F
+GLIBC_2.26 scalbnf128 F
+GLIBC_2.26 setpayloadf128 F
+GLIBC_2.26 setpayloadsigf128 F
+GLIBC_2.26 sincosf128 F
+GLIBC_2.26 sinf128 F
+GLIBC_2.26 sinhf128 F
+GLIBC_2.26 sqrtf128 F
+GLIBC_2.26 tanf128 F
+GLIBC_2.26 tanhf128 F
+GLIBC_2.26 tgammaf128 F
+GLIBC_2.26 totalorderf128 F
+GLIBC_2.26 totalordermagf128 F
+GLIBC_2.26 truncf128 F
+GLIBC_2.26 ufromfpf128 F
+GLIBC_2.26 ufromfpxf128 F
+GLIBC_2.26 y0f128 F
+GLIBC_2.26 y1f128 F
+GLIBC_2.26 ynf128 F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64le/float128-abi.h b/sysdeps/unix/sysv/linux/powerpc/powerpc64le/float128-abi.h
new file mode 100644
index 0000000..6b954cc
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64le/float128-abi.h
@@ -0,0 +1,2 @@ 
+/* ABI version for _Float128 ABI introduction.  */
+#define FLOAT128_VERSION GLIBC_2.26