[31/31] RFC: powerpc64le: Enable support for IEEE long double

Message ID 20191015190529.11559-32-gabriel@inconstante.net.br
State Superseded
Headers

Commit Message

Gabriel F. T. Gomes Oct. 15, 2019, 7:05 p.m. UTC
  From: "Gabriel F. T. Gomes" <gabrielftg@linux.ibm.com>

DO NOT COMMIT!

On platforms where long double may have two different formats, i.e.: the
same format as double (64-bits) or something else (128-bits), building
with -mlong-double-128 is the default and function calls in the user
program match the name of the function in Glibc.  When building with
-mlong-double-64, Glibc installed headers redirect such calls to the
appropriate function.

This patch adds similar redirections to be used by user code builds in
IEEE long double mode (-mabi=ieeelongdouble).  It also skips some uses
of libc_hidden_proto in internal headers, because they also produce
redirections, causing a redirection conflict.

PS: Missing NEWS entry.
---
 argp/argp.h                                   |   4 +-
 include/stdlib.h                              |   4 +
 include/wchar.h                               |   4 +
 libio/bits/stdio-ldbl.h                       |  46 +++++---
 libio/stdio.h                                 |  19 +++-
 misc/bits/syslog-ldbl.h                       |   4 +-
 misc/err.h                                    |   4 +-
 misc/error.h                                  |   7 +-
 misc/sys/cdefs.h                              |  41 ++++++-
 misc/sys/syslog.h                             |   5 +-
 stdio-common/printf.h                         |   4 +-
 stdlib/bits/stdlib-ldbl.h                     |  22 ++++
 stdlib/monetary.h                             |   4 +-
 stdlib/stdlib.h                               |   5 +-
 .../ldbl-128ibm-compat/bits/long-double.h     |  25 +++++
 sysdeps/powerpc/powerpc64/le/Implies-before   |   1 +
 .../linux/powerpc/powerpc64/le/libc.abilist   |  93 ++++++++++++++++
 .../linux/powerpc/powerpc64/le/libm.abilist   | 104 ++++++++++++++++++
 wcsmbs/bits/wchar-ldbl.h                      |  36 +++++-
 wcsmbs/wchar.h                                |  17 ++-
 20 files changed, 406 insertions(+), 43 deletions(-)
 create mode 100644 sysdeps/ieee754/ldbl-128ibm-compat/bits/long-double.h
  

Patch

diff --git a/argp/argp.h b/argp/argp.h
index 07adec1895..e6eb77085f 100644
--- a/argp/argp.h
+++ b/argp/argp.h
@@ -554,7 +554,9 @@  __NTH (__option_is_end (const struct argp_option *__opt))
 # endif
 #endif /* Use extern inlines.  */
 
-#ifdef __LDBL_COMPAT
+#include <bits/floatn.h>
+#if defined __LDBL_COMPAT || (defined __LONG_DOUBLE_USES_FLOAT128 \
+			      && __LONG_DOUBLE_USES_FLOAT128 == 1)
 # include <bits/argp-ldbl.h>
 #endif
 
diff --git a/include/stdlib.h b/include/stdlib.h
index 089607dbf9..130ca84201 100644
--- a/include/stdlib.h
+++ b/include/stdlib.h
@@ -202,9 +202,13 @@  libc_hidden_proto (____strtoll_l_internal)
 libc_hidden_proto (____strtoul_l_internal)
 libc_hidden_proto (____strtoull_l_internal)
 
+#include <bits/floatn.h>
 libc_hidden_proto (strtof)
 libc_hidden_proto (strtod)
+#if !defined __LONG_DOUBLE_USES_FLOAT128 \
+    || __LONG_DOUBLE_USES_FLOAT128 == 0
 libc_hidden_proto (strtold)
+#endif
 libc_hidden_proto (strtol)
 libc_hidden_proto (strtoll)
 libc_hidden_proto (strtoul)
diff --git a/include/wchar.h b/include/wchar.h
index 4875c9e84c..653a080373 100644
--- a/include/wchar.h
+++ b/include/wchar.h
@@ -55,6 +55,7 @@  extern unsigned long long int __wcstoull_internal (const wchar_t *
 extern unsigned long long int ____wcstoull_l_internal (const wchar_t *,
 						       wchar_t **, int, int,
 						       locale_t);
+#include <bits/floatn.h>
 libc_hidden_proto (__wcstof_internal)
 libc_hidden_proto (__wcstod_internal)
 libc_hidden_proto (__wcstold_internal)
@@ -64,7 +65,10 @@  libc_hidden_proto (__wcstoul_internal)
 libc_hidden_proto (__wcstoull_internal)
 libc_hidden_proto (wcstof)
 libc_hidden_proto (wcstod)
+#if !defined __LONG_DOUBLE_USES_FLOAT128 \
+    || __LONG_DOUBLE_USES_FLOAT128 == 0
 libc_hidden_proto (wcstold)
+#endif
 libc_hidden_proto (wcstol)
 libc_hidden_proto (wcstoll)
 libc_hidden_proto (wcstoul)
diff --git a/libio/bits/stdio-ldbl.h b/libio/bits/stdio-ldbl.h
index 2f01a98384..bfa65e87dc 100644
--- a/libio/bits/stdio-ldbl.h
+++ b/libio/bits/stdio-ldbl.h
@@ -27,9 +27,17 @@  __LDBL_REDIR_DECL (vfprintf)
 __LDBL_REDIR_DECL (vprintf)
 __LDBL_REDIR_DECL (vsprintf)
 #if !__GLIBC_USE (DEPRECATED_SCANF)
+# if defined __LDBL_COMPAT
 __LDBL_REDIR1_DECL (fscanf, __nldbl___isoc99_fscanf)
 __LDBL_REDIR1_DECL (scanf, __nldbl___isoc99_scanf)
 __LDBL_REDIR1_DECL (sscanf, __nldbl___isoc99_sscanf)
+# elif defined __LONG_DOUBLE_USES_FLOAT128 && __LONG_DOUBLE_USES_FLOAT128 == 1
+__LDBL_REDIR1_DECL (fscanf, __isoc99_fscanfieee128)
+__LDBL_REDIR1_DECL (scanf, __isoc99_scanfieee128)
+__LDBL_REDIR1_DECL (sscanf, __isoc99_sscanfieee128)
+# else
+#  error bits/stdlib-ldbl.h included when no ldbl redirections are required.
+# endif
 #else
 __LDBL_REDIR_DECL (fscanf)
 __LDBL_REDIR_DECL (scanf)
@@ -43,9 +51,17 @@  __LDBL_REDIR_DECL (vsnprintf)
 
 #ifdef	__USE_ISOC99
 # if !__GLIBC_USE (DEPRECATED_SCANF)
+#  if defined __LDBL_COMPAT
 __LDBL_REDIR1_DECL (vfscanf, __nldbl___isoc99_vfscanf)
 __LDBL_REDIR1_DECL (vscanf, __nldbl___isoc99_vscanf)
 __LDBL_REDIR1_DECL (vsscanf, __nldbl___isoc99_vsscanf)
+#  elif defined __LONG_DOUBLE_USES_FLOAT128 && __LONG_DOUBLE_USES_FLOAT128 == 1
+__LDBL_REDIR1_DECL (vfscanf, __isoc99_vfscanfieee128)
+__LDBL_REDIR1_DECL (vscanf, __isoc99_vscanfieee128)
+__LDBL_REDIR1_DECL (vsscanf, __isoc99_vsscanfieee128)
+#  else
+#   error bits/stdlib-ldbl.h included when no ldbl redirections are required.
+#  endif
 # else
 __LDBL_REDIR_DECL (vfscanf)
 __LDBL_REDIR_DECL (vsscanf)
@@ -60,33 +76,33 @@  __LDBL_REDIR_DECL (dprintf)
 
 #ifdef __USE_GNU
 __LDBL_REDIR_DECL (vasprintf)
-__LDBL_REDIR_DECL (__asprintf)
+__LDBL_REDIR2_DECL (asprintf)
 __LDBL_REDIR_DECL (asprintf)
 __LDBL_REDIR_DECL (obstack_printf)
 __LDBL_REDIR_DECL (obstack_vprintf)
 #endif
 
 #if __USE_FORTIFY_LEVEL > 0 && defined __fortify_function
-__LDBL_REDIR_DECL (__sprintf_chk)
-__LDBL_REDIR_DECL (__vsprintf_chk)
+__LDBL_REDIR2_DECL (sprintf_chk)
+__LDBL_REDIR2_DECL (vsprintf_chk)
 # if defined __USE_ISOC99 || defined __USE_UNIX98
-__LDBL_REDIR_DECL (__snprintf_chk)
-__LDBL_REDIR_DECL (__vsnprintf_chk)
+__LDBL_REDIR2_DECL (snprintf_chk)
+__LDBL_REDIR2_DECL (vsnprintf_chk)
 # endif
 # if __USE_FORTIFY_LEVEL > 1
-__LDBL_REDIR_DECL (__fprintf_chk)
-__LDBL_REDIR_DECL (__printf_chk)
-__LDBL_REDIR_DECL (__vfprintf_chk)
-__LDBL_REDIR_DECL (__vprintf_chk)
+__LDBL_REDIR2_DECL (fprintf_chk)
+__LDBL_REDIR2_DECL (printf_chk)
+__LDBL_REDIR2_DECL (vfprintf_chk)
+__LDBL_REDIR2_DECL (vprintf_chk)
 #  ifdef __USE_XOPEN2K8
-__LDBL_REDIR_DECL (__dprintf_chk)
-__LDBL_REDIR_DECL (__vdprintf_chk)
+__LDBL_REDIR2_DECL (dprintf_chk)
+__LDBL_REDIR2_DECL (vdprintf_chk)
 #  endif
 #  ifdef __USE_GNU
-__LDBL_REDIR_DECL (__asprintf_chk)
-__LDBL_REDIR_DECL (__vasprintf_chk)
-__LDBL_REDIR_DECL (__obstack_printf_chk)
-__LDBL_REDIR_DECL (__obstack_vprintf_chk)
+__LDBL_REDIR2_DECL (asprintf_chk)
+__LDBL_REDIR2_DECL (vasprintf_chk)
+__LDBL_REDIR2_DECL (obstack_printf_chk)
+__LDBL_REDIR2_DECL (obstack_vprintf_chk)
 #  endif
 # endif
 #endif
diff --git a/libio/stdio.h b/libio/stdio.h
index 1abce9b3f1..7bbec4b60b 100644
--- a/libio/stdio.h
+++ b/libio/stdio.h
@@ -400,9 +400,13 @@  extern int sscanf (const char *__restrict __s,
 		   const char *__restrict __format, ...) __THROW;
 
 /* For historical reasons, the C99-compliant versions of the scanf
-   functions are at alternative names.  When __LDBL_COMPAT is in
-   effect, this is handled in bits/stdio-ldbl.h.  */
-#if !__GLIBC_USE (DEPRECATED_SCANF) && !defined __LDBL_COMPAT
+   functions are at alternative names.  When __LDBL_COMPAT or
+   __LONG_DOUBLE_USES_FLOAT128 are in effect, this is handled in
+   bits/stdio-ldbl.h.  */
+#include <bits/floatn.h>
+#if !__GLIBC_USE (DEPRECATED_SCANF) && !defined __LDBL_COMPAT \
+    && (!defined __LONG_DOUBLE_USES_FLOAT128 \
+	|| __LONG_DOUBLE_USES_FLOAT128 == 0)
 # ifdef __REDIRECT
 extern int __REDIRECT (fscanf, (FILE *__restrict __stream,
 				const char *__restrict __format, ...),
@@ -447,7 +451,9 @@  extern int vsscanf (const char *__restrict __s,
 
 /* Same redirection as above for the v*scanf family.  */
 # if !__GLIBC_USE (DEPRECATED_SCANF)
-#  if defined __REDIRECT && !defined __LDBL_COMPAT
+#  if defined __REDIRECT && !defined __LDBL_COMPAT \
+      && (!defined __LONG_DOUBLE_USES_FLOAT128 \
+	  || __LONG_DOUBLE_USES_FLOAT128 == 0)
 extern int __REDIRECT (vfscanf,
 		       (FILE *__restrict __s,
 			const char *__restrict __format, __gnuc_va_list __arg),
@@ -866,7 +872,10 @@  extern int __overflow (FILE *, int);
 #if __USE_FORTIFY_LEVEL > 0 && defined __fortify_function
 # include <bits/stdio2.h>
 #endif
-#ifdef __LDBL_COMPAT
+
+#include <bits/floatn.h>
+#if defined __LDBL_COMPAT || (defined __LONG_DOUBLE_USES_FLOAT128 \
+			      && __LONG_DOUBLE_USES_FLOAT128 == 1)
 # include <bits/stdio-ldbl.h>
 #endif
 
diff --git a/misc/bits/syslog-ldbl.h b/misc/bits/syslog-ldbl.h
index 8d60fb8e44..5075e50379 100644
--- a/misc/bits/syslog-ldbl.h
+++ b/misc/bits/syslog-ldbl.h
@@ -27,9 +27,9 @@  __LDBL_REDIR_DECL (vsyslog)
 #endif
 
 #if __USE_FORTIFY_LEVEL > 0 && defined __fortify_function
-__LDBL_REDIR_DECL (__syslog_chk)
+__LDBL_REDIR2_DECL (syslog_chk)
 
 # ifdef __USE_MISC
-__LDBL_REDIR_DECL (__vsyslog_chk)
+__LDBL_REDIR2_DECL (vsyslog_chk)
 # endif
 #endif
diff --git a/misc/err.h b/misc/err.h
index a71b3fafe0..6ba1c7804f 100644
--- a/misc/err.h
+++ b/misc/err.h
@@ -52,7 +52,9 @@  extern void errx (int __status, const char *__format, ...)
 extern void verrx (int __status, const char *, __gnuc_va_list)
      __attribute__ ((__noreturn__, __format__ (__printf__, 2, 0)));
 
-#ifdef __LDBL_COMPAT
+#include <bits/floatn.h>
+#if defined __LDBL_COMPAT || (defined __LONG_DOUBLE_USES_FLOAT128 \
+			      && __LONG_DOUBLE_USES_FLOAT128 == 1)
 # include <bits/err-ldbl.h>
 #endif
 
diff --git a/misc/error.h b/misc/error.h
index 79840bf0f7..69a284ea52 100644
--- a/misc/error.h
+++ b/misc/error.h
@@ -47,11 +47,14 @@  extern unsigned int error_message_count;
    variable controls whether this mode is selected or not.  */
 extern int error_one_per_line;
 
-#ifdef __LDBL_COMPAT
+#include <bits/floatn.h>
+#if defined __LDBL_COMPAT || (defined __LONG_DOUBLE_USES_FLOAT128 \
+			      && __LONG_DOUBLE_USES_FLOAT128 == 1)
 # include <bits/error-ldbl.h>
 #else
 /* Do not inline error and error_at_line when long double has the same
-   size of double, because that would invalidate the redirections to the
+   size of double, nor when long double reuses the float128
+   implementation, because that would invalidate the redirections to the
    compatibility functions.  */
 # if defined __extern_always_inline && defined __va_arg_pack
 #  include <bits/error.h>
diff --git a/misc/sys/cdefs.h b/misc/sys/cdefs.h
index abcb0d5e3c..f48f89f078 100644
--- a/misc/sys/cdefs.h
+++ b/misc/sys/cdefs.h
@@ -460,7 +460,38 @@ 
 #include <bits/wordsize.h>
 #include <bits/long-double.h>
 
-#if defined __LONG_DOUBLE_MATH_OPTIONAL && defined __NO_LONG_DOUBLE_MATH
+#if defined __LONG_DOUBLE_USES_FLOAT128 \
+    && __LONG_DOUBLE_USES_FLOAT128 == 1
+# ifdef __REDIRECT
+
+/* Alias name defined automatically.  */
+#  define __LDBL_REDIR(name, proto) ... unused__ldbl_redir
+#  define __LDBL_REDIR_DECL(name) \
+  extern __typeof (name) name __asm (__ASMNAME ("__" #name "ieee128"));
+
+/* Alias name defined automatically, with leading underscores.  */
+#  define __LDBL_REDIR2_DECL(name) \
+  extern __typeof (__##name) __##name \
+    __asm (__ASMNAME ("__" #name "ieee128"));
+
+/* Alias name defined manually.  */
+#  define __LDBL_REDIR1(name, proto, alias) ... unused__ldbl_redir1
+#  define __LDBL_REDIR1_DECL(name, alias) \
+  extern __typeof (name) name __asm (__ASMNAME (#alias));
+
+#  define __LDBL_REDIR1_NTH(name, proto, alias) \
+  __REDIRECT_NTH (name, proto, alias)
+#  define __REDIRECT_NTH_LDBL(name, proto, alias) \
+  __LDBL_REDIR1_NTH (name, proto, __##alias##ieee128)
+
+/* Unused.  */
+#  define __REDIRECT_LDBL(name, proto, alias) ... unused__redirect_ldbl
+#  define __LDBL_REDIR_NTH(name, proto) ... unused__ldbl_redir_nth
+
+# else
+_Static_assert (0, "IEEE 128-bits long double requires redirection on this platform");
+# endif
+#elif defined __LONG_DOUBLE_MATH_OPTIONAL && defined __NO_LONG_DOUBLE_MATH
 # define __LDBL_COMPAT 1
 # ifdef __REDIRECT
 #  define __LDBL_REDIR1(name, proto, alias) __REDIRECT (name, proto, alias)
@@ -469,6 +500,8 @@ 
 #  define __LDBL_REDIR1_NTH(name, proto, alias) __REDIRECT_NTH (name, proto, alias)
 #  define __LDBL_REDIR_NTH(name, proto) \
   __LDBL_REDIR1_NTH (name, proto, __nldbl_##name)
+#  define __LDBL_REDIR2_DECL(name) \
+  extern __typeof (__##name) __##name __asm (__ASMNAME ("__nldbl___" #name));
 #  define __LDBL_REDIR1_DECL(name, alias) \
   extern __typeof (name) name __asm (__ASMNAME (#alias));
 #  define __LDBL_REDIR_DECL(name) \
@@ -479,11 +512,15 @@ 
   __LDBL_REDIR1_NTH (name, proto, __nldbl_##alias)
 # endif
 #endif
-#if !defined __LDBL_COMPAT || !defined __REDIRECT
+#if (!defined __LDBL_COMPAT \
+     && (!defined __LONG_DOUBLE_USES_FLOAT128 \
+	 || __LONG_DOUBLE_USES_FLOAT128 == 0)) \
+    || !defined __REDIRECT
 # define __LDBL_REDIR1(name, proto, alias) name proto
 # define __LDBL_REDIR(name, proto) name proto
 # define __LDBL_REDIR1_NTH(name, proto, alias) name proto __THROW
 # define __LDBL_REDIR_NTH(name, proto) name proto __THROW
+# define __LDBL_REDIR2_DECL(name)
 # define __LDBL_REDIR_DECL(name)
 # ifdef __REDIRECT
 #  define __REDIRECT_LDBL(name, proto, alias) __REDIRECT (name, proto, alias)
diff --git a/misc/sys/syslog.h b/misc/sys/syslog.h
index ee01478c4b..56d3ce416c 100644
--- a/misc/sys/syslog.h
+++ b/misc/sys/syslog.h
@@ -206,7 +206,10 @@  extern void vsyslog (int __pri, const char *__fmt, __gnuc_va_list __ap)
 #if __USE_FORTIFY_LEVEL > 0 && defined __fortify_function
 # include <bits/syslog.h>
 #endif
-#ifdef __LDBL_COMPAT
+
+#include <bits/floatn.h>
+#if defined __LDBL_COMPAT || (defined __LONG_DOUBLE_USES_FLOAT128 \
+			      && __LONG_DOUBLE_USES_FLOAT128 == 1)
 # include <bits/syslog-ldbl.h>
 #endif
 
diff --git a/stdio-common/printf.h b/stdio-common/printf.h
index 2eb0b51382..ad1024572d 100644
--- a/stdio-common/printf.h
+++ b/stdio-common/printf.h
@@ -182,7 +182,9 @@  extern int printf_size_info (const struct printf_info *__restrict
 			     __info, size_t __n, int *__restrict __argtypes)
      __THROW;
 
-#ifdef __LDBL_COMPAT
+#include <bits/floatn.h>
+#if defined __LDBL_COMPAT || (defined __LONG_DOUBLE_USES_FLOAT128 \
+			      && __LONG_DOUBLE_USES_FLOAT128 == 1)
 # include <bits/printf-ldbl.h>
 #endif
 
diff --git a/stdlib/bits/stdlib-ldbl.h b/stdlib/bits/stdlib-ldbl.h
index dcbf74a6dd..5b81394424 100644
--- a/stdlib/bits/stdlib-ldbl.h
+++ b/stdlib/bits/stdlib-ldbl.h
@@ -21,21 +21,43 @@ 
 #endif
 
 #ifdef	__USE_ISOC99
+# ifdef __LDBL_COMPAT
 __LDBL_REDIR1_DECL (strtold, strtod)
+# else
+__LDBL_REDIR1_DECL (strtold, __strtoieee128)
+# endif
 #endif
 
 #ifdef __USE_GNU
+# ifdef __LDBL_COMPAT
 __LDBL_REDIR1_DECL (strtold_l, strtod_l)
+# else
+__LDBL_REDIR1_DECL (strtold_l, __strtoieee128_l)
+# endif
 #endif
 
 #if __GLIBC_USE (IEC_60559_BFP_EXT_C2X)
+# ifdef __LDBL_COMPAT
 __LDBL_REDIR1_DECL (strfroml, strfromd)
+# else
+__LDBL_REDIR1_DECL (strfroml, __strfromieee128)
+# endif
 #endif
 
 #ifdef __USE_MISC
+# if defined __LDBL_COMPAT
 __LDBL_REDIR1_DECL (qecvt, ecvt)
 __LDBL_REDIR1_DECL (qfcvt, fcvt)
 __LDBL_REDIR1_DECL (qgcvt, gcvt)
 __LDBL_REDIR1_DECL (qecvt_r, ecvt_r)
 __LDBL_REDIR1_DECL (qfcvt_r, fcvt_r)
+# elif defined __LONG_DOUBLE_USES_FLOAT128 && __LONG_DOUBLE_USES_FLOAT128 == 1
+__LDBL_REDIR1_DECL (qecvt, __qecvtieee128)
+__LDBL_REDIR1_DECL (qfcvt, __qfcvtieee128)
+__LDBL_REDIR1_DECL (qgcvt, __qgcvtieee128)
+__LDBL_REDIR1_DECL (qecvt_r, __qecvtieee128_r)
+__LDBL_REDIR1_DECL (qfcvt_r, __qfcvtieee128_r)
+# else
+#  error bits/stdlib-ldbl.h included when no ldbl redirections are required.
+# endif
 #endif
diff --git a/stdlib/monetary.h b/stdlib/monetary.h
index 40d3128b90..164e3a729b 100644
--- a/stdlib/monetary.h
+++ b/stdlib/monetary.h
@@ -50,7 +50,9 @@  extern ssize_t strfmon_l (char *__restrict __s, size_t __maxsize,
      __THROW __attribute_format_strfmon__ (4, 5);
 #endif
 
-#ifdef __LDBL_COMPAT
+#include <bits/floatn.h>
+#if defined __LDBL_COMPAT || (defined __LONG_DOUBLE_USES_FLOAT128 \
+			      && __LONG_DOUBLE_USES_FLOAT128 == 1)
 # include <bits/monetary-ldbl.h>
 #endif
 
diff --git a/stdlib/stdlib.h b/stdlib/stdlib.h
index 4bd86ec84d..85046fb8fe 100644
--- a/stdlib/stdlib.h
+++ b/stdlib/stdlib.h
@@ -1016,7 +1016,10 @@  extern int ttyslot (void) __THROW;
 #if __USE_FORTIFY_LEVEL > 0 && defined __fortify_function
 # include <bits/stdlib.h>
 #endif
-#ifdef __LDBL_COMPAT
+
+#include <bits/floatn.h>
+#if defined __LDBL_COMPAT || (defined __LONG_DOUBLE_USES_FLOAT128 \
+			      && __LONG_DOUBLE_USES_FLOAT128 == 1)
 # include <bits/stdlib-ldbl.h>
 #endif
 
diff --git a/sysdeps/ieee754/ldbl-128ibm-compat/bits/long-double.h b/sysdeps/ieee754/ldbl-128ibm-compat/bits/long-double.h
new file mode 100644
index 0000000000..32452b672d
--- /dev/null
+++ b/sysdeps/ieee754/ldbl-128ibm-compat/bits/long-double.h
@@ -0,0 +1,25 @@ 
+/* Properties of long double type.  ldbl-opt version.
+   Copyright (C) 2016-2018 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  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 __NO_LONG_DOUBLE_MATH
+# define __LONG_DOUBLE_MATH_OPTIONAL	1
+# ifndef __LONG_DOUBLE_128__
+#  define __NO_LONG_DOUBLE_MATH		1
+# endif
+#endif
+#define __LONG_DOUBLE_USES_FLOAT128 (__LDBL_MANT_DIG__ == 113)
diff --git a/sysdeps/powerpc/powerpc64/le/Implies-before b/sysdeps/powerpc/powerpc64/le/Implies-before
index 7c20db4e97..2139f4dae8 100644
--- a/sysdeps/powerpc/powerpc64/le/Implies-before
+++ b/sysdeps/powerpc/powerpc64/le/Implies-before
@@ -1,4 +1,5 @@ 
 # On PowerPC we use the IBM extended long double format.
+ieee754/ldbl-128ibm-compat
 ieee754/ldbl-128ibm
 ieee754/ldbl-opt
 ieee754/dbl-64
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist
index 2229a1dcc0..737c7c33e4 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist
@@ -2247,3 +2247,96 @@  GLIBC_2.30 getdents64 F
 GLIBC_2.30 gettid F
 GLIBC_2.30 tgkill F
 GLIBC_2.30 twalk_r F
+GLIBC_2.31 __argp_errorieee128 F
+GLIBC_2.31 __argp_failureieee128 F
+GLIBC_2.31 __asprintf_chkieee128 F
+GLIBC_2.31 __asprintfieee128 F
+GLIBC_2.31 __dprintf_chkieee128 F
+GLIBC_2.31 __dprintfieee128 F
+GLIBC_2.31 __errieee128 F
+GLIBC_2.31 __error_at_lineieee128 F
+GLIBC_2.31 __errorieee128 F
+GLIBC_2.31 __errxieee128 F
+GLIBC_2.31 __fprintf_chkieee128 F
+GLIBC_2.31 __fprintfieee128 F
+GLIBC_2.31 __fscanfieee128 F
+GLIBC_2.31 __fwprintf_chkieee128 F
+GLIBC_2.31 __fwprintfieee128 F
+GLIBC_2.31 __fwscanfieee128 F
+GLIBC_2.31 __isoc99_fscanfieee128 F
+GLIBC_2.31 __isoc99_fwscanfieee128 F
+GLIBC_2.31 __isoc99_scanfieee128 F
+GLIBC_2.31 __isoc99_sscanfieee128 F
+GLIBC_2.31 __isoc99_swscanfieee128 F
+GLIBC_2.31 __isoc99_vfscanfieee128 F
+GLIBC_2.31 __isoc99_vfwscanfieee128 F
+GLIBC_2.31 __isoc99_vscanfieee128 F
+GLIBC_2.31 __isoc99_vsscanfieee128 F
+GLIBC_2.31 __isoc99_vswscanfieee128 F
+GLIBC_2.31 __isoc99_vwscanfieee128 F
+GLIBC_2.31 __isoc99_wscanfieee128 F
+GLIBC_2.31 __obstack_printf_chkieee128 F
+GLIBC_2.31 __obstack_printfieee128 F
+GLIBC_2.31 __obstack_vprintf_chkieee128 F
+GLIBC_2.31 __obstack_vprintfieee128 F
+GLIBC_2.31 __printf_chkieee128 F
+GLIBC_2.31 __printf_sizeieee128 F
+GLIBC_2.31 __printfieee128 F
+GLIBC_2.31 __qecvtieee128 F
+GLIBC_2.31 __qecvtieee128_r F
+GLIBC_2.31 __qfcvtieee128 F
+GLIBC_2.31 __qfcvtieee128_r F
+GLIBC_2.31 __qgcvtieee128 F
+GLIBC_2.31 __scanfieee128 F
+GLIBC_2.31 __snprintf_chkieee128 F
+GLIBC_2.31 __snprintfieee128 F
+GLIBC_2.31 __sprintf_chkieee128 F
+GLIBC_2.31 __sprintfieee128 F
+GLIBC_2.31 __sscanfieee128 F
+GLIBC_2.31 __strfmon_lieee128 F
+GLIBC_2.31 __strfmonieee128 F
+GLIBC_2.31 __strfromieee128 F
+GLIBC_2.31 __strtoieee128 F
+GLIBC_2.31 __strtoieee128_l F
+GLIBC_2.31 __swprintf_chkieee128 F
+GLIBC_2.31 __swprintfieee128 F
+GLIBC_2.31 __swscanfieee128 F
+GLIBC_2.31 __syslog_chkieee128 F
+GLIBC_2.31 __syslogieee128 F
+GLIBC_2.31 __vasprintf_chkieee128 F
+GLIBC_2.31 __vasprintfieee128 F
+GLIBC_2.31 __vdprintf_chkieee128 F
+GLIBC_2.31 __vdprintfieee128 F
+GLIBC_2.31 __verrieee128 F
+GLIBC_2.31 __verrxieee128 F
+GLIBC_2.31 __vfprintf_chkieee128 F
+GLIBC_2.31 __vfprintfieee128 F
+GLIBC_2.31 __vfscanfieee128 F
+GLIBC_2.31 __vfwprintf_chkieee128 F
+GLIBC_2.31 __vfwprintfieee128 F
+GLIBC_2.31 __vfwscanfieee128 F
+GLIBC_2.31 __vprintf_chkieee128 F
+GLIBC_2.31 __vprintfieee128 F
+GLIBC_2.31 __vscanfieee128 F
+GLIBC_2.31 __vsnprintf_chkieee128 F
+GLIBC_2.31 __vsnprintfieee128 F
+GLIBC_2.31 __vsprintf_chkieee128 F
+GLIBC_2.31 __vsprintfieee128 F
+GLIBC_2.31 __vsscanfieee128 F
+GLIBC_2.31 __vswprintf_chkieee128 F
+GLIBC_2.31 __vswprintfieee128 F
+GLIBC_2.31 __vswscanfieee128 F
+GLIBC_2.31 __vsyslog_chkieee128 F
+GLIBC_2.31 __vsyslogieee128 F
+GLIBC_2.31 __vwarnieee128 F
+GLIBC_2.31 __vwarnxieee128 F
+GLIBC_2.31 __vwprintf_chkieee128 F
+GLIBC_2.31 __vwprintfieee128 F
+GLIBC_2.31 __vwscanfieee128 F
+GLIBC_2.31 __warnieee128 F
+GLIBC_2.31 __warnxieee128 F
+GLIBC_2.31 __wcstoieee128 F
+GLIBC_2.31 __wcstoieee128_l F
+GLIBC_2.31 __wprintf_chkieee128 F
+GLIBC_2.31 __wprintfieee128 F
+GLIBC_2.31 __wscanfieee128 F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libm.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libm.abilist
index d479a64fca..60658729d0 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libm.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libm.abilist
@@ -1081,6 +1081,110 @@  GLIBC_2.29 exp2 F
 GLIBC_2.29 log F
 GLIBC_2.29 log2 F
 GLIBC_2.29 pow F
+GLIBC_2.31 __acoshieee128 F
+GLIBC_2.31 __acosieee128 F
+GLIBC_2.31 __asinhieee128 F
+GLIBC_2.31 __asinieee128 F
+GLIBC_2.31 __atan2ieee128 F
+GLIBC_2.31 __atanhieee128 F
+GLIBC_2.31 __atanieee128 F
+GLIBC_2.31 __cabsieee128 F
+GLIBC_2.31 __cacoshieee128 F
+GLIBC_2.31 __cacosieee128 F
+GLIBC_2.31 __canonicalizeieee128 F
+GLIBC_2.31 __cargieee128 F
+GLIBC_2.31 __casinhieee128 F
+GLIBC_2.31 __casinieee128 F
+GLIBC_2.31 __catanhieee128 F
+GLIBC_2.31 __catanieee128 F
+GLIBC_2.31 __cbrtieee128 F
+GLIBC_2.31 __ccoshieee128 F
+GLIBC_2.31 __ccosieee128 F
+GLIBC_2.31 __ceilieee128 F
+GLIBC_2.31 __cexpieee128 F
+GLIBC_2.31 __cimagieee128 F
+GLIBC_2.31 __clog10ieee128 F
+GLIBC_2.31 __clogieee128 F
+GLIBC_2.31 __conjieee128 F
+GLIBC_2.31 __copysignieee128 F
+GLIBC_2.31 __coshieee128 F
+GLIBC_2.31 __cosieee128 F
+GLIBC_2.31 __cpowieee128 F
+GLIBC_2.31 __cprojieee128 F
+GLIBC_2.31 __crealieee128 F
+GLIBC_2.31 __csinhieee128 F
+GLIBC_2.31 __csinieee128 F
+GLIBC_2.31 __csqrtieee128 F
+GLIBC_2.31 __ctanhieee128 F
+GLIBC_2.31 __ctanieee128 F
+GLIBC_2.31 __erfcieee128 F
+GLIBC_2.31 __erfieee128 F
+GLIBC_2.31 __exp10ieee128 F
+GLIBC_2.31 __exp2ieee128 F
+GLIBC_2.31 __expieee128 F
+GLIBC_2.31 __expm1ieee128 F
+GLIBC_2.31 __fabsieee128 F
+GLIBC_2.31 __fdimieee128 F
+GLIBC_2.31 __floorieee128 F
+GLIBC_2.31 __fmaieee128 F
+GLIBC_2.31 __fmaxieee128 F
+GLIBC_2.31 __fmaxmagieee128 F
+GLIBC_2.31 __fminieee128 F
+GLIBC_2.31 __fminmagieee128 F
+GLIBC_2.31 __fmodieee128 F
+GLIBC_2.31 __frexpieee128 F
+GLIBC_2.31 __fromfpieee128 F
+GLIBC_2.31 __fromfpxieee128 F
+GLIBC_2.31 __getpayloadieee128 F
+GLIBC_2.31 __hypotieee128 F
+GLIBC_2.31 __ilogbieee128 F
+GLIBC_2.31 __j0ieee128 F
+GLIBC_2.31 __j1ieee128 F
+GLIBC_2.31 __jnieee128 F
+GLIBC_2.31 __ldexpieee128 F
+GLIBC_2.31 __lgammaieee128 F
+GLIBC_2.31 __lgammaieee128_r F
+GLIBC_2.31 __llogbieee128 F
+GLIBC_2.31 __llrintieee128 F
+GLIBC_2.31 __llroundieee128 F
+GLIBC_2.31 __log10ieee128 F
+GLIBC_2.31 __log1pieee128 F
+GLIBC_2.31 __log2ieee128 F
+GLIBC_2.31 __logbieee128 F
+GLIBC_2.31 __logieee128 F
+GLIBC_2.31 __lrintieee128 F
+GLIBC_2.31 __lroundieee128 F
+GLIBC_2.31 __modfieee128 F
+GLIBC_2.31 __nanieee128 F
+GLIBC_2.31 __nearbyintieee128 F
+GLIBC_2.31 __nextafterieee128 F
+GLIBC_2.31 __nextdownieee128 F
+GLIBC_2.31 __nextupieee128 F
+GLIBC_2.31 __powieee128 F
+GLIBC_2.31 __remainderieee128 F
+GLIBC_2.31 __remquoieee128 F
+GLIBC_2.31 __rintieee128 F
+GLIBC_2.31 __roundevenieee128 F
+GLIBC_2.31 __roundieee128 F
+GLIBC_2.31 __scalblnieee128 F
+GLIBC_2.31 __scalbnieee128 F
+GLIBC_2.31 __setpayloadieee128 F
+GLIBC_2.31 __setpayloadsigieee128 F
+GLIBC_2.31 __sincosieee128 F
+GLIBC_2.31 __sinhieee128 F
+GLIBC_2.31 __sinieee128 F
+GLIBC_2.31 __sqrtieee128 F
+GLIBC_2.31 __tanhieee128 F
+GLIBC_2.31 __tanieee128 F
+GLIBC_2.31 __tgammaieee128 F
+GLIBC_2.31 __totalorderieee128 F
+GLIBC_2.31 __totalordermagieee128 F
+GLIBC_2.31 __truncieee128 F
+GLIBC_2.31 __ufromfpieee128 F
+GLIBC_2.31 __ufromfpxieee128 F
+GLIBC_2.31 __y0ieee128 F
+GLIBC_2.31 __y1ieee128 F
+GLIBC_2.31 __ynieee128 F
 GLIBC_2.31 totalorder F
 GLIBC_2.31 totalorderf F
 GLIBC_2.31 totalorderf128 F
diff --git a/wcsmbs/bits/wchar-ldbl.h b/wcsmbs/bits/wchar-ldbl.h
index ae8f09800f..79df111c10 100644
--- a/wcsmbs/bits/wchar-ldbl.h
+++ b/wcsmbs/bits/wchar-ldbl.h
@@ -28,9 +28,17 @@  __LDBL_REDIR_DECL (vfwprintf);
 __LDBL_REDIR_DECL (vwprintf);
 __LDBL_REDIR_DECL (vswprintf);
 # if !__GLIBC_USE (DEPRECATED_SCANF)
+#  if defined __LDBL_COMPAT
 __LDBL_REDIR1_DECL (fwscanf, __nldbl___isoc99_fwscanf)
 __LDBL_REDIR1_DECL (wscanf, __nldbl___isoc99_wscanf)
 __LDBL_REDIR1_DECL (swscanf, __nldbl___isoc99_swscanf)
+#  elif defined __LONG_DOUBLE_USES_FLOAT128 && __LONG_DOUBLE_USES_FLOAT128 == 1
+__LDBL_REDIR1_DECL (fwscanf, __isoc99_fwscanfieee128)
+__LDBL_REDIR1_DECL (wscanf, __isoc99_wscanfieee128)
+__LDBL_REDIR1_DECL (swscanf, __isoc99_swscanfieee128)
+#  else
+#   error bits/stdlib-ldbl.h included when no ldbl redirections are required.
+#  endif
 # else
 __LDBL_REDIR_DECL (fwscanf);
 __LDBL_REDIR_DECL (wscanf);
@@ -39,11 +47,23 @@  __LDBL_REDIR_DECL (swscanf);
 #endif
 
 #ifdef __USE_ISOC99
+# ifdef __LDBL_COMPAT
 __LDBL_REDIR1_DECL (wcstold, wcstod);
+# else
+__LDBL_REDIR1_DECL (wcstold, __wcstoieee128)
+# endif
 # if !__GLIBC_USE (DEPRECATED_SCANF)
+#  if defined __LDBL_COMPAT
 __LDBL_REDIR1_DECL (vfwscanf, __nldbl___isoc99_vfwscanf)
 __LDBL_REDIR1_DECL (vwscanf, __nldbl___isoc99_vwscanf)
 __LDBL_REDIR1_DECL (vswscanf, __nldbl___isoc99_vswscanf)
+#  elif defined __LONG_DOUBLE_USES_FLOAT128 && __LONG_DOUBLE_USES_FLOAT128 == 1
+__LDBL_REDIR1_DECL (vfwscanf, __isoc99_vfwscanfieee128)
+__LDBL_REDIR1_DECL (vwscanf, __isoc99_vwscanfieee128)
+__LDBL_REDIR1_DECL (vswscanf, __isoc99_vswscanfieee128)
+#  else
+#   error bits/stdlib-ldbl.h included when no ldbl redirections are required.
+#  endif
 # else
 __LDBL_REDIR_DECL (vfwscanf);
 __LDBL_REDIR_DECL (vwscanf);
@@ -52,16 +72,20 @@  __LDBL_REDIR_DECL (vswscanf);
 #endif
 
 #ifdef __USE_GNU
+# ifdef __LDBL_COMPAT
 __LDBL_REDIR1_DECL (wcstold_l, wcstod_l);
+# else
+__LDBL_REDIR1_DECL (wcstold_l, __wcstoieee128_l)
+# endif
 #endif
 
 #if __USE_FORTIFY_LEVEL > 0 && defined __fortify_function
-__LDBL_REDIR_DECL (__swprintf_chk)
-__LDBL_REDIR_DECL (__vswprintf_chk)
+__LDBL_REDIR2_DECL (swprintf_chk)
+__LDBL_REDIR2_DECL (vswprintf_chk)
 # if __USE_FORTIFY_LEVEL > 1
-__LDBL_REDIR_DECL (__fwprintf_chk)
-__LDBL_REDIR_DECL (__wprintf_chk)
-__LDBL_REDIR_DECL (__vfwprintf_chk)
-__LDBL_REDIR_DECL (__vwprintf_chk)
+__LDBL_REDIR2_DECL (fwprintf_chk)
+__LDBL_REDIR2_DECL (wprintf_chk)
+__LDBL_REDIR2_DECL (vfwprintf_chk)
+__LDBL_REDIR2_DECL (vwprintf_chk)
 # endif
 #endif
diff --git a/wcsmbs/wchar.h b/wcsmbs/wchar.h
index 4b731ebb51..c131d6a8c4 100644
--- a/wcsmbs/wchar.h
+++ b/wcsmbs/wchar.h
@@ -633,9 +633,12 @@  extern int swscanf (const wchar_t *__restrict __s,
      __THROW /* __attribute__ ((__format__ (__wscanf__, 2, 3))) */;
 
 /* For historical reasons, the C99-compliant versions of the scanf
-   functions are at alternative names.  When __LDBL_COMPAT is in
-   effect, this is handled in bits/wchar-ldbl.h.  */
-#if !__GLIBC_USE (DEPRECATED_SCANF) && !defined __LDBL_COMPAT
+   functions are at alternative names.  When __LDBL_COMPAT or
+   __LONG_DOUBLE_USES_FLOAT128 are in effect, this is handled in
+   bits/wchar-ldbl.h.  */
+#if !__GLIBC_USE (DEPRECATED_SCANF) && !defined __LDBL_COMPAT \
+     && (!defined __LONG_DOUBLE_USES_FLOAT128 \
+	 || __LONG_DOUBLE_USES_FLOAT128 == 0)
 #  ifdef __REDIRECT
 extern int __REDIRECT (fwscanf, (__FILE *__restrict __stream,
 				 const wchar_t *__restrict __format, ...),
@@ -687,7 +690,9 @@  extern int vswscanf (const wchar_t *__restrict __s,
 
 # if !defined __USE_GNU \
      && (!defined __LDBL_COMPAT || !defined __REDIRECT) \
-     && (defined __STRICT_ANSI__ || defined __USE_XOPEN2K)
+     && (defined __STRICT_ANSI__ || defined __USE_XOPEN2K) \
+     && (!defined __LONG_DOUBLE_USES_FLOAT128 \
+	 || __LONG_DOUBLE_USES_FLOAT128 == 0)
 #  ifdef __REDIRECT
 extern int __REDIRECT (vfwscanf, (__FILE *__restrict __s,
 				  const wchar_t *__restrict __format,
@@ -848,7 +853,9 @@  extern size_t wcsftime_l (wchar_t *__restrict __s, size_t __maxsize,
 # include <bits/wchar2.h>
 #endif
 
-#ifdef __LDBL_COMPAT
+#include <bits/floatn.h>
+#if defined __LDBL_COMPAT || (defined __LONG_DOUBLE_USES_FLOAT128 \
+			      && __LONG_DOUBLE_USES_FLOAT128 == 1)
 # include <bits/wchar-ldbl.h>
 #endif