This is the mail archive of the glibc-cvs@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

GNU C Library master sources branch ibm/2.18/master created. glibc-2.18-147-g2626829


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "GNU C Library master sources".

The branch, ibm/2.18/master has been created
        at  2626829973991772450bfac94e77a8af62af4222 (commit)

- Log -----------------------------------------------------------------
http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=2626829973991772450bfac94e77a8af62af4222

commit 2626829973991772450bfac94e77a8af62af4222
Author: Adhemerval Zanella <azanella@linux.vnet.ibm.com>
Date:   Thu May 22 14:48:38 2014 -0500

    PowerPC: Remove 64 bits instructions in PPC32 code
    
    This patch replaces the insrdi by insrwi in powerpc32 assembly.
    
    It is a backport of d298c41635ce7f2dc7c3eccc842fe3aa754c0c8e.
    
    Conflicts:
    	ChangeLog

diff --git a/ChangeLog b/ChangeLog
index 26910d9..ad9df0f 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,15 @@
+2014-05-26  Adhemerval Zanella  <azanella@linux.vnet.ibm.com>
+
+	* sysdeps/powerpc/powerpc32/power4/memset.S (memset): Replace insrdi
+	by insrwi.
+	* sysdeps/powerpc/powerpc32/power6/memset.S (memset): Likewise.
+	* sysdeps/powerpc/powerpc32/power7/memset.S (memset): Likewise.
+	* sysdeps/powerpc/powerpc32/power7/memchr.S (memchr): Likewise.
+	* sysdeps/powerpc/powerpc32/power7/memrchr.S (memrchr): Likewise.
+	* sysdeps/powerpc/powerpc32/power7/rawmemchr.S (rawmemchr): Likewise.
+	* sysdeps/powerpc/powerpc32/power7/strchr.S (strchr): Likewise.
+	* sysdeps/powerpc/powerpc32/power7/strchrnul.S (strchrnul): Likewise.
+
 2014-11-19  Carlos O'Donell  <carlos@redhat.com>
 	    Florian Weimer  <fweimer@redhat.com>
 	    Joseph Myers  <joseph@codesourcery.com>
diff --git a/sysdeps/powerpc/powerpc32/power4/memset.S b/sysdeps/powerpc/powerpc32/power4/memset.S
index 4fd9d8c..9129c12 100644
--- a/sysdeps/powerpc/powerpc32/power4/memset.S
+++ b/sysdeps/powerpc/powerpc32/power4/memset.S
@@ -50,7 +50,7 @@ L(_memset):
 
 /* Align to word boundary.  */
 	cmplwi	cr5, rLEN, 31
-	insrdi	rCHR, rCHR, 8, 48     /* Replicate byte to halfword.  */
+	insrwi	rCHR, rCHR, 8, 16     /* Replicate byte to halfword.  */
 	beq+	L(aligned)
 	mtcrf	0x01, rMEMP0
 	subfic	rALIGN, rALIGN, 4
@@ -65,7 +65,7 @@ L(g0):
 /* Handle the case of size < 31.  */
 L(aligned):
 	mtcrf	0x01, rLEN
-	insrdi	rCHR, rCHR, 16, 32    /* Replicate halfword to word.  */
+	insrwi	rCHR, rCHR, 16, 0    /* Replicate halfword to word.  */
 	ble	cr5, L(medium)
 /* Align to 32-byte boundary.  */
 	andi.	rALIGN, rMEMP, 0x1C
diff --git a/sysdeps/powerpc/powerpc32/power6/memset.S b/sysdeps/powerpc/powerpc32/power6/memset.S
index 508d560..78ce1a5 100644
--- a/sysdeps/powerpc/powerpc32/power6/memset.S
+++ b/sysdeps/powerpc/powerpc32/power6/memset.S
@@ -48,7 +48,7 @@ L(_memset):
 	ble-	cr1, L(small)
 /* Align to word boundary.  */
 	cmplwi	cr5, rLEN, 31
-	insrdi	rCHR, rCHR, 8, 48	/* Replicate byte to halfword.  */
+	insrwi	rCHR, rCHR, 8, 16	/* Replicate byte to halfword.  */
 	beq+	L(aligned)
 	mtcrf	0x01, rMEMP0
 	subfic	rALIGN, rALIGN, 4
@@ -64,7 +64,7 @@ L(g0):
 /* Handle the case of size < 31.  */
 L(aligned):
 	mtcrf	0x01, rLEN
-	insrdi	rCHR, rCHR, 16, 32	/* Replicate halfword to word.  */
+	insrwi	rCHR, rCHR, 16, 0	/* Replicate halfword to word.  */
 	ble	cr5, L(medium)
 /* Align to 32-byte boundary.  */
 	andi.	rALIGN, rMEMP, 0x1C
diff --git a/sysdeps/powerpc/powerpc32/power7/memchr.S b/sysdeps/powerpc/powerpc32/power7/memchr.S
index 85754f3..bd15db8 100644
--- a/sysdeps/powerpc/powerpc32/power7/memchr.S
+++ b/sysdeps/powerpc/powerpc32/power7/memchr.S
@@ -25,9 +25,9 @@ ENTRY (__memchr)
 	CALL_MCOUNT
 	dcbt	0,r3
 	clrrwi  r8,r3,2
-	insrdi	r4,r4,8,48
+	insrwi	r4,r4,8,16    /* Replicate byte to word.  */
 	add	r7,r3,r5      /* Calculate the last acceptable address.  */
-	insrdi	r4,r4,16,32
+	insrwi	r4,r4,16,0
 	cmplwi	r5,16
 	li	r9, -1
 	rlwinm	r6,r3,3,27,28 /* Calculate padding.  */
diff --git a/sysdeps/powerpc/powerpc32/power7/memrchr.S b/sysdeps/powerpc/powerpc32/power7/memrchr.S
index 9601aa7..3dd1c87 100644
--- a/sysdeps/powerpc/powerpc32/power7/memrchr.S
+++ b/sysdeps/powerpc/powerpc32/power7/memrchr.S
@@ -32,8 +32,8 @@ ENTRY (__memrchr)
 	dcbt	r9,r6,16      /* Stream hint, decreasing addresses.  */
 
 	/* Replicate BYTE to word.  */
-	rldimi	r4,r4,8,48
-	rldimi	r4,r4,16,32
+	insrwi	r4,r4,8,16
+	insrwi	r4,r4,16,0
 	li	r6,-4
 	li	r9,-1
 	rlwinm	r0,r0,3,27,28 /* Calculate padding.  */
diff --git a/sysdeps/powerpc/powerpc32/power7/memset.S b/sysdeps/powerpc/powerpc32/power7/memset.S
index aadda25..0e86d83 100644
--- a/sysdeps/powerpc/powerpc32/power7/memset.S
+++ b/sysdeps/powerpc/powerpc32/power7/memset.S
@@ -35,8 +35,8 @@ L(_memset):
 	cfi_offset(31,-8)
 
 	/* Replicate byte to word.  */
-	insrdi	4,4,8,48
-	insrdi	4,4,16,32
+	insrwi	4,4,8,16
+	insrwi	4,4,16,0
 
 	ble	cr6,L(small)	/* If length <= 8, use short copy code.  */
 
diff --git a/sysdeps/powerpc/powerpc32/power7/rawmemchr.S b/sysdeps/powerpc/powerpc32/power7/rawmemchr.S
index c2d8c4b..8a4b29a 100644
--- a/sysdeps/powerpc/powerpc32/power7/rawmemchr.S
+++ b/sysdeps/powerpc/powerpc32/power7/rawmemchr.S
@@ -27,8 +27,8 @@ ENTRY (__rawmemchr)
 	clrrwi	r8,r3,2	      /* Align the address to word boundary.  */
 
 	/* Replicate byte to word.  */
-	rldimi	r4,r4,8,48
-	rldimi	r4,r4,16,32
+	insrwi	r4,r4,8,16
+	insrwi	r4,r4,16,0
 
 	/* Now r4 has a word of c bytes.  */
 
diff --git a/sysdeps/powerpc/powerpc32/power7/strchr.S b/sysdeps/powerpc/powerpc32/power7/strchr.S
index b662659..f24b078 100644
--- a/sysdeps/powerpc/powerpc32/power7/strchr.S
+++ b/sysdeps/powerpc/powerpc32/power7/strchr.S
@@ -35,8 +35,8 @@ ENTRY (strchr)
 	beq	cr7,L(null_match)
 
 	/* Replicate byte to word.  */
-	insrdi	r4,r4,8,48
-	insrdi	r4,r4,16,32
+	insrwi	r4,r4,8,16
+	insrwi	r4,r4,16,0
 
 	/* Now r4 has a word of c bytes and r0 has
 	   a word of null bytes.  */
diff --git a/sysdeps/powerpc/powerpc32/power7/strchrnul.S b/sysdeps/powerpc/powerpc32/power7/strchrnul.S
index f5d24d4..8e8d0b6 100644
--- a/sysdeps/powerpc/powerpc32/power7/strchrnul.S
+++ b/sysdeps/powerpc/powerpc32/power7/strchrnul.S
@@ -27,8 +27,8 @@ ENTRY (__strchrnul)
 	clrrwi	r8,r3,2	      /* Align the address to word boundary.  */
 
 	/* Replicate byte to word.  */
-	insrdi	r4,r4,8,48
-	insrdi	r4,r4,16,32
+	insrwi  r4,r4,8,16
+	insrwi  r4,r4,16,0
 
 	rlwinm	r6,r3,3,27,28 /* Calculate padding.  */
 	lwz	r12,0(r8)     /* Load word from memory.  */

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=eff063ac3c96a29e4fb9bab0ab0385eac49525d5

commit eff063ac3c96a29e4fb9bab0ab0385eac49525d5
Author: Carlos O'Donell <carlos@redhat.com>
Date:   Wed Nov 19 11:44:12 2014 -0500

    CVE-2014-7817: wordexp fails to honour WRDE_NOCMD.
    
    The function wordexp() fails to properly handle the WRDE_NOCMD
    flag when processing arithmetic inputs in the form of "$((... ``))"
    where "..." can be anything valid. The backticks in the arithmetic
    epxression are evaluated by in a shell even if WRDE_NOCMD forbade
    command substitution. This allows an attacker to attempt to pass
    dangerous commands via constructs of the above form, and bypass
    the WRDE_NOCMD flag. This patch fixes this by checking for WRDE_NOCMD
    in exec_comm(), the only place that can execute a shell. All other
    checks for WRDE_NOCMD are superfluous and removed.
    
    We expand the testsuite and add 3 new regression tests of roughly
    the same form but with a couple of nested levels.
    
    On top of the 3 new tests we add fork validation to the WRDE_NOCMD
    testing. If any forks are detected during the execution of a wordexp()
    call with WRDE_NOCMD, the test is marked as failed. This is slightly
    heuristic since vfork might be used in the future, but it provides a
    higher level of assurance that no shells were executed as part of
    command substitution with WRDE_NOCMD in effect. In addition it doesn't
    require libpthread or libdl, instead we use the public implementation
    namespace function __register_atfork (already part of the public ABI
    for libpthread).
    
    Tested on x86_64 with no regressions.

diff --git a/ChangeLog b/ChangeLog
index ff8da28..26910d9 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,25 @@
+2014-11-19  Carlos O'Donell  <carlos@redhat.com>
+	    Florian Weimer  <fweimer@redhat.com>
+	    Joseph Myers  <joseph@codesourcery.com>
+	    Adam Conrad  <adconrad@0c3.net>
+	    Andreas Schwab  <schwab@suse.de>
+	    Brooks  <bmoses@google.com>
+
+	[BZ #17625]
+	* wordexp-test.c (__dso_handle): Add prototype.
+	(__register_atfork): Likewise.
+	(__app_register_atfork): New function.
+	(registered_forks): New global.
+	(register_fork): New function.
+	(test_case): Add 3 new tests for WRDE_CMDSUB.
+	(main): Call __app_register_atfork.
+	(testit): If WRDE_NOCMD set registered_forks to zero, run test, and if
+	fork count is non-zero fail the test.
+	* posix/wordexp.c (exec_comm): Return WRDE_CMDSUB if WRDE_NOCMD flag
+	is set.
+	(parse_dollars): Remove check for WRDE_NOCMD.
+	(parse_dquote): Likewise.
+
 2014-12-16  Florian Weimer  <fweimer@redhat.com>
 
 	[BZ #17630]
diff --git a/NEWS b/NEWS
index d65c0e2..1c9acf3 100644
--- a/NEWS
+++ b/NEWS
@@ -11,10 +11,16 @@ Version 2.18.1
 
   14143, 14155, 14547, 14699, 15532, 15427, 15522, 15680, 15723, 15734,
   15735, 15797, 15892, 15895, 15909, 15915, 15917, 15996, 16072, 16150,
-  16414, 16430, 16431, 16617, 17048, 17137, 17187, 17325, 17630.
+  16414, 16430, 16431, 16617, 17048, 17137, 17187, 17325, 17625, 17630.
 
 * Support for powerpc64le has been added.
 
+* CVE-2104-7817 The wordexp function could ignore the WRDE_NOCMD flag
+  under certain input conditions resulting in the execution of a shell for
+  command substitution when the applicaiton did not request it. The
+  implementation now checks WRDE_NOCMD immediately before executing the
+  shell and returns the error WRDE_CMDSUB as expected.
+
 * CVE-2012-3406 printf-style functions could run into a stack overflow when
   processing format strings with a large number of format specifiers.
 
diff --git a/posix/wordexp-test.c b/posix/wordexp-test.c
index 8032029..c3c2c7d 100644
--- a/posix/wordexp-test.c
+++ b/posix/wordexp-test.c
@@ -27,6 +27,25 @@
 
 #define IFS " \n\t"
 
+extern void *__dso_handle __attribute__ ((__weak__, __visibility__ ("hidden")));
+extern int __register_atfork (void (*) (void), void (*) (void), void (*) (void), void *);
+
+static int __app_register_atfork (void (*prepare) (void), void (*parent) (void), void (*child) (void))
+{
+  return __register_atfork (prepare, parent, child,
+			    &__dso_handle == NULL ? NULL : __dso_handle);
+}
+
+/* Number of forks seen.  */
+static int registered_forks;
+
+/* For each fork increment the fork count.  */
+static void
+register_fork (void)
+{
+  registered_forks++;
+}
+
 struct test_case_struct
 {
   int retval;
@@ -206,6 +225,12 @@ struct test_case_struct
     { WRDE_SYNTAX, NULL, "$((2+))", 0, 0, { NULL, }, IFS },
     { WRDE_SYNTAX, NULL, "`", 0, 0, { NULL, }, IFS },
     { WRDE_SYNTAX, NULL, "$((010+4+))", 0, 0, { NULL }, IFS },
+    /* Test for CVE-2014-7817. We test 3 combinations of command
+       substitution inside an arithmetic expression to make sure that
+       no commands are executed and error is returned.  */
+    { WRDE_CMDSUB, NULL, "$((`echo 1`))", WRDE_NOCMD, 0, { NULL, }, IFS },
+    { WRDE_CMDSUB, NULL, "$((1+`echo 1`))", WRDE_NOCMD, 0, { NULL, }, IFS },
+    { WRDE_CMDSUB, NULL, "$((1+$((`echo 1`))))", WRDE_NOCMD, 0, { NULL, }, IFS },
 
     { -1, NULL, NULL, 0, 0, { NULL, }, IFS },
   };
@@ -258,6 +283,15 @@ main (int argc, char *argv[])
 	  return -1;
     }
 
+  /* If we are not allowed to do command substitution, we install
+     fork handlers to verify that no forks happened.  No forks should
+     happen at all if command substitution is disabled.  */
+  if (__app_register_atfork (register_fork, NULL, NULL) != 0)
+    {
+      printf ("Failed to register fork handler.\n");
+      return -1;
+    }
+
   for (test = 0; test_case[test].retval != -1; test++)
     if (testit (&test_case[test]))
       ++fail;
@@ -367,6 +401,9 @@ testit (struct test_case_struct *tc)
 
   printf ("Test %d (%s): ", ++tests, tc->words);
 
+  if (tc->flags & WRDE_NOCMD)
+    registered_forks = 0;
+
   if (tc->flags & WRDE_APPEND)
     {
       /* initial wordexp() call, to be appended to */
@@ -378,6 +415,13 @@ testit (struct test_case_struct *tc)
     }
   retval = wordexp (tc->words, &we, tc->flags);
 
+  if ((tc->flags & WRDE_NOCMD)
+      && (registered_forks > 0))
+    {
+	  printf ("FAILED fork called for WRDE_NOCMD\n");
+	  return 1;
+    }
+
   if (tc->flags & WRDE_DOOFFS)
       start_offs = sav_we.we_offs;
 
diff --git a/posix/wordexp.c b/posix/wordexp.c
index 96ce8a4..a88a92e 100644
--- a/posix/wordexp.c
+++ b/posix/wordexp.c
@@ -893,6 +893,10 @@ exec_comm (char *comm, char **word, size_t *word_length, size_t *max_length,
   pid_t pid;
   int noexec = 0;
 
+  /* Do nothing if command substitution should not succeed.  */
+  if (flags & WRDE_NOCMD)
+    return WRDE_CMDSUB;
+
   /* Don't fork() unless necessary */
   if (!comm || !*comm)
     return 0;
@@ -2082,9 +2086,6 @@ parse_dollars (char **word, size_t *word_length, size_t *max_length,
 	    }
 	}
 
-      if (flags & WRDE_NOCMD)
-	return WRDE_CMDSUB;
-
       (*offset) += 2;
       return parse_comm (word, word_length, max_length, words, offset, flags,
 			 quoted? NULL : pwordexp, ifs, ifs_white);
@@ -2196,9 +2197,6 @@ parse_dquote (char **word, size_t *word_length, size_t *max_length,
 	  break;
 
 	case '`':
-	  if (flags & WRDE_NOCMD)
-	    return WRDE_CMDSUB;
-
 	  ++(*offset);
 	  error = parse_backtick (word, word_length, max_length, words,
 				  offset, flags, NULL, NULL, NULL);
@@ -2357,12 +2355,6 @@ wordexp (const char *words, wordexp_t *pwordexp, int flags)
 	break;
 
       case '`':
-	if (flags & WRDE_NOCMD)
-	  {
-	    error = WRDE_CMDSUB;
-	    goto do_error;
-	  }
-
 	++words_offset;
 	error = parse_backtick (&word, &word_length, &max_length, words,
 				&words_offset, flags, pwordexp, ifs,

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=93f407ae2e4dedf66fe93c7e0512445c8bca898a

commit 93f407ae2e4dedf66fe93c7e0512445c8bca898a
Author: Allan McRae <allan@archlinux.org>
Date:   Thu Dec 18 11:01:43 2014 +1000

    Label CVE-2014-9402 in NEWS

diff --git a/NEWS b/NEWS
index e4c4244..d65c0e2 100644
--- a/NEWS
+++ b/NEWS
@@ -18,8 +18,9 @@ Version 2.18.1
 * CVE-2012-3406 printf-style functions could run into a stack overflow when
   processing format strings with a large number of format specifiers.
 
-* The nss_dns implementation of getnetbyname could run into an infinite loop
-  if the DNS response contained a PTR record of an unexpected format.
+* CVE-2014-9402 The nss_dns implementation of getnetbyname could run into an
+  infinite loop if the DNS response contained a PTR record of an unexpected
+  format.
 
 * CVE-2014-4043 The posix_spawn_file_actions_addopen implementation did not
   copy the path argument.  This allowed programs to cause posix_spawn to

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=612b11da56d9cd77a7125e4de984127ee7b52de6

commit 612b11da56d9cd77a7125e4de984127ee7b52de6
Author: Florian Weimer <fweimer@redhat.com>
Date:   Mon Dec 15 17:41:13 2014 +0100

    Avoid infinite loop in nss_dns getnetbyname [BZ #17630]

diff --git a/ChangeLog b/ChangeLog
index a89142a..ff8da28 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2014-12-16  Florian Weimer  <fweimer@redhat.com>
+
+	[BZ #17630]
+	* resolv/nss_dns/dns-network.c (getanswer_r): Iterate over alias
+	names.
+
 2014-12-15  Jeff Law  <law@redhat.com>
 
 	[BZ #16617]
diff --git a/NEWS b/NEWS
index 42697f7..e4c4244 100644
--- a/NEWS
+++ b/NEWS
@@ -11,13 +11,16 @@ Version 2.18.1
 
   14143, 14155, 14547, 14699, 15532, 15427, 15522, 15680, 15723, 15734,
   15735, 15797, 15892, 15895, 15909, 15915, 15917, 15996, 16072, 16150,
-  16414, 16430, 16431, 16617, 17048, 17137, 17187, 17325.
+  16414, 16430, 16431, 16617, 17048, 17137, 17187, 17325, 17630.
 
 * Support for powerpc64le has been added.
 
 * CVE-2012-3406 printf-style functions could run into a stack overflow when
   processing format strings with a large number of format specifiers.
 
+* The nss_dns implementation of getnetbyname could run into an infinite loop
+  if the DNS response contained a PTR record of an unexpected format.
+
 * CVE-2014-4043 The posix_spawn_file_actions_addopen implementation did not
   copy the path argument.  This allowed programs to cause posix_spawn to
   deference a dangling pointer, or use an unexpected pathname argument if
diff --git a/resolv/nss_dns/dns-network.c b/resolv/nss_dns/dns-network.c
index 3c4db7e..7507f8c 100644
--- a/resolv/nss_dns/dns-network.c
+++ b/resolv/nss_dns/dns-network.c
@@ -398,8 +398,8 @@ getanswer_r (const querybuf *answer, int anslen, struct netent *result,
 
 	case BYNAME:
 	  {
-	    char **ap = result->n_aliases++;
-	    while (*ap != NULL)
+	    char **ap;
+	    for (ap = result->n_aliases; *ap != NULL; ++ap)
 	      {
 		/* Check each alias name for being of the forms:
 		   4.3.2.1.in-addr.arpa		= net 1.2.3.4

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=955edb2d28e14fd86d57a2877cde15094a882932

commit 955edb2d28e14fd86d57a2877cde15094a882932
Author: Jeff Law <law@redhat.com>
Date:   Mon Dec 15 10:09:32 2014 +0100

    CVE-2012-3406: Stack overflow in vfprintf [BZ #16617]
    
    A larger number of format specifiers coudld cause a stack overflow,
    potentially allowing to bypass _FORTIFY_SOURCE format string
    protection.

diff --git a/ChangeLog b/ChangeLog
index 3a38309..a89142a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+2014-12-15  Jeff Law  <law@redhat.com>
+
+	[BZ #16617]
+	* stdio-common/vfprintf.c (vfprintf): Allocate large specs array
+	on the heap.  (CVE-2012-3406)
+	* stdio-common/bug23-2.c, stdio-common/bug23-3.c: New file.
+	* stdio-common/bug23-4.c: New file.  Test case by Joseph Myers.
+	* stdio-common/Makefile (tests): Add bug23-2, bug23-3, bug23-4.
+
 2014-06-21  Allan McRae  <allan@archlinux.org>
 
 	* NEWS: Mention CVE-2014-4043.
diff --git a/NEWS b/NEWS
index 8fc3cf8..42697f7 100644
--- a/NEWS
+++ b/NEWS
@@ -11,10 +11,13 @@ Version 2.18.1
 
   14143, 14155, 14547, 14699, 15532, 15427, 15522, 15680, 15723, 15734,
   15735, 15797, 15892, 15895, 15909, 15915, 15917, 15996, 16072, 16150,
-  16414, 16430, 16431, 17048, 17137, 17187, 17325.
+  16414, 16430, 16431, 16617, 17048, 17137, 17187, 17325.
 
 * Support for powerpc64le has been added.
 
+* CVE-2012-3406 printf-style functions could run into a stack overflow when
+  processing format strings with a large number of format specifiers.
+
 * CVE-2014-4043 The posix_spawn_file_actions_addopen implementation did not
   copy the path argument.  This allowed programs to cause posix_spawn to
   deference a dangling pointer, or use an unexpected pathname argument if
diff --git a/stdio-common/Makefile b/stdio-common/Makefile
index 658804b..b1a4216 100644
--- a/stdio-common/Makefile
+++ b/stdio-common/Makefile
@@ -57,7 +57,7 @@ tests := tstscanf test_rdwr test-popen tstgetln test-fseek \
 	 bug19 bug19a tst-popen2 scanf13 scanf14 scanf15 bug20 bug21 bug22 \
 	 scanf16 scanf17 tst-setvbuf1 tst-grouping bug23 bug24 \
 	 bug-vfprintf-nargs tst-long-dbl-fphex tst-fphex-wide tst-sprintf3 \
-	 bug25 tst-printf-round bug26
+	 bug25 tst-printf-round bug23-2 bug23-3 bug23-4
 
 test-srcs = tst-unbputc tst-printf
 
diff --git a/stdio-common/bug23-2.c b/stdio-common/bug23-2.c
new file mode 100644
index 0000000..9e0cfe6
--- /dev/null
+++ b/stdio-common/bug23-2.c
@@ -0,0 +1,70 @@
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+static const char expected[] = "\
+\n\
+a\n\
+abbcd55\
+\n\
+a\n\
+abbcd55\
+\n\
+a\n\
+abbcd55\
+\n\
+a\n\
+abbcd55\
+\n\
+a\n\
+abbcd55\
+\n\
+a\n\
+abbcd55\
+\n\
+a\n\
+abbcd55\
+\n\
+a\n\
+abbcd55\
+\n\
+a\n\
+abbcd55\
+\n\
+a\n\
+abbcd55\
+\n\
+a\n\
+abbcd55\
+\n\
+a\n\
+abbcd55\
+\n\
+a\n\
+abbcd55%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
+
+static int
+do_test (void)
+{
+  char *buf = malloc (strlen (expected) + 1);
+  snprintf (buf, strlen (expected) + 1,
+	    "\n%1$s\n" "%1$s" "%2$s" "%2$s" "%3$s" "%4$s" "%5$d" "%5$d"
+	    "\n%1$s\n" "%1$s" "%2$s" "%2$s" "%3$s" "%4$s" "%5$d" "%5$d"
+	    "\n%1$s\n" "%1$s" "%2$s" "%2$s" "%3$s" "%4$s" "%5$d" "%5$d"
+	    "\n%1$s\n" "%1$s" "%2$s" "%2$s" "%3$s" "%4$s" "%5$d" "%5$d"
+	    "\n%1$s\n" "%1$s" "%2$s" "%2$s" "%3$s" "%4$s" "%5$d" "%5$d"
+	    "\n%1$s\n" "%1$s" "%2$s" "%2$s" "%3$s" "%4$s" "%5$d" "%5$d"
+	    "\n%1$s\n" "%1$s" "%2$s" "%2$s" "%3$s" "%4$s" "%5$d" "%5$d"
+	    "\n%1$s\n" "%1$s" "%2$s" "%2$s" "%3$s" "%4$s" "%5$d" "%5$d"
+	    "\n%1$s\n" "%1$s" "%2$s" "%2$s" "%3$s" "%4$s" "%5$d" "%5$d"
+	    "\n%1$s\n" "%1$s" "%2$s" "%2$s" "%3$s" "%4$s" "%5$d" "%5$d"
+	    "\n%1$s\n" "%1$s" "%2$s" "%2$s" "%3$s" "%4$s" "%5$d" "%5$d"
+	    "\n%1$s\n" "%1$s" "%2$s" "%2$s" "%3$s" "%4$s" "%5$d" "%5$d"
+	    "\n%1$s\n" "%1$s" "%2$s" "%2$s" "%3$s" "%4$s" "%5$d" "%5$d"
+	    "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n",
+	    "a", "b", "c", "d", 5);
+  return strcmp (buf, expected) != 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/stdio-common/bug23-3.c b/stdio-common/bug23-3.c
new file mode 100644
index 0000000..57c8cef
--- /dev/null
+++ b/stdio-common/bug23-3.c
@@ -0,0 +1,50 @@
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+int
+do_test (void)
+{
+  size_t instances = 16384;
+#define X0 "\n%1$s\n" "%1$s" "%2$s" "%2$s" "%3$s" "%4$s" "%5$d" "%5$d"
+  const char *item = "\na\nabbcd55";
+#define X3 X0 X0 X0 X0 X0 X0 X0 X0
+#define X6 X3 X3 X3 X3 X3 X3 X3 X3
+#define X9 X6 X6 X6 X6 X6 X6 X6 X6
+#define X12 X9 X9 X9 X9 X9 X9 X9 X9
+#define X14 X12 X12 X12 X12
+#define TRAILER "%%%%%%%%%%%%%%%%%%%%%%%%%%"
+#define TRAILER2 TRAILER TRAILER
+  size_t length = instances * strlen (item) + strlen (TRAILER) + 1;
+
+  char *buf = malloc (length + 1);
+  snprintf (buf, length + 1,
+	    X14 TRAILER2 "\n",
+	    "a", "b", "c", "d", 5);
+
+  const char *p = buf;
+  size_t i;
+  for (i = 0; i < instances; ++i)
+    {
+      const char *expected;
+      for (expected = item; *expected; ++expected)
+	{
+	  if (*p != *expected)
+	    {
+	      printf ("mismatch at offset %zu (%zu): expected %d, got %d\n",
+		      (size_t) (p - buf), i, *expected & 0xFF, *p & 0xFF);
+	      return 1;
+	    }
+	  ++p;
+	}
+    }
+  if (strcmp (p, TRAILER "\n") != 0)
+    {
+      printf ("mismatch at trailer: [%s]\n", p);
+      return 1;
+    }
+  free (buf);
+  return 0;
+}
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/stdio-common/bug23-4.c b/stdio-common/bug23-4.c
new file mode 100644
index 0000000..a478564
--- /dev/null
+++ b/stdio-common/bug23-4.c
@@ -0,0 +1,31 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/resource.h>
+
+#define LIMIT 1000000
+
+int
+main (void)
+{
+  struct rlimit lim;
+  getrlimit (RLIMIT_STACK, &lim);
+  lim.rlim_cur = 1048576;
+  setrlimit (RLIMIT_STACK, &lim);
+  char *fmtstr = malloc (4 * LIMIT + 1);
+  if (fmtstr == NULL)
+    abort ();
+  char *output = malloc (LIMIT + 1);
+  if (output == NULL)
+    abort ();
+  for (size_t i = 0; i < LIMIT; i++)
+    memcpy (fmtstr + 4 * i, "%1$d", 4);
+  fmtstr[4 * LIMIT] = '\0';
+  int ret = snprintf (output, LIMIT + 1, fmtstr, 0);
+  if (ret != LIMIT)
+    abort ();
+  for (size_t i = 0; i < LIMIT; i++)
+    if (output[i] != '0')
+      abort ();
+  return 0;
+}
diff --git a/stdio-common/vfprintf.c b/stdio-common/vfprintf.c
index fb22f69..030a5ba 100644
--- a/stdio-common/vfprintf.c
+++ b/stdio-common/vfprintf.c
@@ -263,6 +263,12 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
   /* For the argument descriptions, which may be allocated on the heap.  */
   void *args_malloced = NULL;
 
+  /* For positional argument handling.  */
+  struct printf_spec *specs;
+
+  /* Track if we malloced the SPECS array and thus must free it.  */
+  bool specs_malloced = false;
+
   /* This table maps a character into a number representing a
      class.  In each step there is a destination label for each
      class.  */
@@ -1672,8 +1678,8 @@ do_positional:
     size_t nspecs = 0;
     /* A more or less arbitrary start value.  */
     size_t nspecs_size = 32 * sizeof (struct printf_spec);
-    struct printf_spec *specs = alloca (nspecs_size);
 
+    specs = alloca (nspecs_size);
     /* The number of arguments the format string requests.  This will
        determine the size of the array needed to store the argument
        attributes.  */
@@ -1714,11 +1720,39 @@ do_positional:
 	if (nspecs * sizeof (*specs) >= nspecs_size)
 	  {
 	    /* Extend the array of format specifiers.  */
+	    if (nspecs_size * 2 < nspecs_size)
+	      {
+		__set_errno (ENOMEM);
+		done = -1;
+		goto all_done;
+	      }
 	    struct printf_spec *old = specs;
-	    specs = extend_alloca (specs, nspecs_size, 2 * nspecs_size);
+	    if (__libc_use_alloca (2 * nspecs_size))
+	      specs = extend_alloca (specs, nspecs_size, 2 * nspecs_size);
+	    else
+	      {
+		nspecs_size *= 2;
+		specs = malloc (nspecs_size);
+		if (specs == NULL)
+		  {
+		    __set_errno (ENOMEM);
+		    specs = old;
+		    done = -1;
+		    goto all_done;
+		  }
+	      }
 
 	    /* Copy the old array's elements to the new space.  */
 	    memmove (specs, old, nspecs * sizeof (*specs));
+
+	    /* If we had previously malloc'd space for SPECS, then
+	       release it after the copy is complete.  */
+	    if (specs_malloced)
+	      free (old);
+
+	    /* Now set SPECS_MALLOCED if needed.  */
+	    if (!__libc_use_alloca (nspecs_size))
+	      specs_malloced = true;
 	  }
 
 	/* Parse the format specifier.  */
@@ -2039,6 +2073,8 @@ do_positional:
   }
 
 all_done:
+  if (specs_malloced)
+    free (specs);
   if (__glibc_unlikely (args_malloced != NULL))
     free (args_malloced);
   if (__glibc_unlikely (workstart != NULL))

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=6b2bd5d9607d2ea6e18e8bf32695322e5ae0ebb4

commit 6b2bd5d9607d2ea6e18e8bf32695322e5ae0ebb4
Author: Allan McRae <allan@archlinux.org>
Date:   Sat Jun 21 17:23:55 2014 +1000

    Mention CVE-2014-4043 in NEWS

diff --git a/ChangeLog b/ChangeLog
index e24271c..3a38309 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
+2014-06-21  Allan McRae  <allan@archlinux.org>
+
+	* NEWS: Mention CVE-2014-4043.
+
 2014-06-11  Florian Weimer  <fweimer@redhat.com>
 
 	[BZ #17048]
diff --git a/NEWS b/NEWS
index fa6caeb..8fc3cf8 100644
--- a/NEWS
+++ b/NEWS
@@ -15,6 +15,12 @@ Version 2.18.1
 
 * Support for powerpc64le has been added.
 
+* CVE-2014-4043 The posix_spawn_file_actions_addopen implementation did not
+  copy the path argument.  This allowed programs to cause posix_spawn to
+  deference a dangling pointer, or use an unexpected pathname argument if
+  the string was modified after the posix_spawn_file_actions_addopen
+  invocation.
+
 * Locale names, including those obtained from environment variables (LANG
   and the LC_* variables), are more tightly checked for proper syntax.
   setlocale will now fail (with EINVAL) for locale names that are overly

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=12565bd6138d6d5c0f6f615c55a2609d000e5ed0

commit 12565bd6138d6d5c0f6f615c55a2609d000e5ed0
Author: Florian Weimer <fweimer@redhat.com>
Date:   Wed Jun 11 23:12:52 2014 +0200

    posix_spawn_file_actions_addopen needs to copy the path argument (BZ 17048)
    
    POSIX requires that we make a copy, so we allocate a new string
    and free it in posix_spawn_file_actions_destroy.
    
    Reported by David Reid, Alex Gaynor, and Glyph Lefkowitz.  This bug
    may have security implications.

diff --git a/ChangeLog b/ChangeLog
index d23e631..e24271c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,16 @@
+2014-06-11  Florian Weimer  <fweimer@redhat.com>
+
+	[BZ #17048]
+	* posix/spawn_int.h (struct __spawn_action): Make the path string
+	non-const to support deallocation.
+	* posix/spawn_faction_addopen.c
+	(posix_spawn_file_actions_addopen): Make a copy of the pathname.
+	* posix/spawn_faction_destroy.c
+	(posix_spawn_file_actions_destroy): Adjust comment.  Deallocate
+	path in all spawn_do_open actions.
+	* posix/tst-spawn.c (do_test): Exercise the copy operation in
+	posix_spawn_file_actions_addopen.
+
 2014-08-26  Florian Weimer  <fweimer@redhat.com>
 
 	[BZ #17187]
diff --git a/NEWS b/NEWS
index 3832c7c..fa6caeb 100644
--- a/NEWS
+++ b/NEWS
@@ -11,7 +11,7 @@ Version 2.18.1
 
   14143, 14155, 14547, 14699, 15532, 15427, 15522, 15680, 15723, 15734,
   15735, 15797, 15892, 15895, 15909, 15915, 15917, 15996, 16072, 16150,
-  16414, 16430, 16431, 17137, 17187, 17325.
+  16414, 16430, 16431, 17048, 17137, 17187, 17325.
 
 * Support for powerpc64le has been added.
 
diff --git a/posix/spawn_faction_addopen.c b/posix/spawn_faction_addopen.c
index 93065b3..3ff6eb2 100644
--- a/posix/spawn_faction_addopen.c
+++ b/posix/spawn_faction_addopen.c
@@ -35,17 +35,24 @@ posix_spawn_file_actions_addopen (posix_spawn_file_actions_t *file_actions,
   if (fd < 0 || fd >= maxfd)
     return EBADF;
 
+  char *path_copy = strdup (path);
+  if (path_copy == NULL)
+    return ENOMEM;
+
   /* Allocate more memory if needed.  */
   if (file_actions->__used == file_actions->__allocated
       && __posix_spawn_file_actions_realloc (file_actions) != 0)
-    /* This can only mean we ran out of memory.  */
-    return ENOMEM;
+    {
+      /* This can only mean we ran out of memory.  */
+      free (path_copy);
+      return ENOMEM;
+    }
 
   /* Add the new value.  */
   rec = &file_actions->__actions[file_actions->__used];
   rec->tag = spawn_do_open;
   rec->action.open_action.fd = fd;
-  rec->action.open_action.path = path;
+  rec->action.open_action.path = path_copy;
   rec->action.open_action.oflag = oflag;
   rec->action.open_action.mode = mode;
 
diff --git a/posix/spawn_faction_destroy.c b/posix/spawn_faction_destroy.c
index cc1d824..b59e619 100644
--- a/posix/spawn_faction_destroy.c
+++ b/posix/spawn_faction_destroy.c
@@ -18,11 +18,29 @@
 #include <spawn.h>
 #include <stdlib.h>
 
-/* Initialize data structure for file attribute for `spawn' call.  */
+#include "spawn_int.h"
+
+/* Deallocate the file actions.  */
 int
 posix_spawn_file_actions_destroy (posix_spawn_file_actions_t *file_actions)
 {
-  /* Free the memory allocated.  */
+  /* Free the paths in the open actions.  */
+  for (int i = 0; i < file_actions->__used; ++i)
+    {
+      struct __spawn_action *sa = &file_actions->__actions[i];
+      switch (sa->tag)
+	{
+	case spawn_do_open:
+	  free (sa->action.open_action.path);
+	  break;
+	case spawn_do_close:
+	case spawn_do_dup2:
+	  /* No cleanup required.  */
+	  break;
+	}
+    }
+
+  /* Free the array of actions.  */
   free (file_actions->__actions);
   return 0;
 }
diff --git a/posix/spawn_int.h b/posix/spawn_int.h
index 5609e58..861e3b4 100644
--- a/posix/spawn_int.h
+++ b/posix/spawn_int.h
@@ -22,7 +22,7 @@ struct __spawn_action
     struct
     {
       int fd;
-      const char *path;
+      char *path;
       int oflag;
       mode_t mode;
     } open_action;
diff --git a/posix/tst-spawn.c b/posix/tst-spawn.c
index 66fd26b..36c3c12 100644
--- a/posix/tst-spawn.c
+++ b/posix/tst-spawn.c
@@ -168,6 +168,7 @@ do_test (int argc, char *argv[])
   char fd2name[18];
   char fd3name[18];
   char fd4name[18];
+  char *name3_copy;
   char *spargv[12];
   int i;
 
@@ -222,9 +223,15 @@ do_test (int argc, char *argv[])
    if (posix_spawn_file_actions_addclose (&actions, fd1) != 0)
      error (EXIT_FAILURE, errno, "posix_spawn_file_actions_addclose");
    /* We want to open the third file.  */
-   if (posix_spawn_file_actions_addopen (&actions, fd3, name3,
+   name3_copy = strdup (name3);
+   if (name3_copy == NULL)
+     error (EXIT_FAILURE, errno, "strdup");
+   if (posix_spawn_file_actions_addopen (&actions, fd3, name3_copy,
 					 O_RDONLY, 0666) != 0)
      error (EXIT_FAILURE, errno, "posix_spawn_file_actions_addopen");
+   /* Overwrite the name to check that a copy has been made.  */
+   memset (name3_copy, 'X', strlen (name3_copy));
+
    /* We dup the second descriptor.  */
    fd4 = MAX (2, MAX (fd1, MAX (fd2, fd3))) + 1;
    if (posix_spawn_file_actions_adddup2 (&actions, fd2, fd4) != 0)
@@ -253,6 +260,7 @@ do_test (int argc, char *argv[])
    /* Cleanup.  */
    if (posix_spawn_file_actions_destroy (&actions) != 0)
      error (EXIT_FAILURE, errno, "posix_spawn_file_actions_destroy");
+   free (name3_copy);
 
   /* Wait for the child.  */
   if (waitpid (pid, &status, 0) != pid)

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=4b8d4de03832e1975ece4faf4e84ade4db7f2d51

commit 4b8d4de03832e1975ece4faf4e84ade4db7f2d51
Author: Florian Weimer <fweimer@redhat.com>
Date:   Mon May 12 15:24:12 2014 +0200

    _nl_find_locale: Improve handling of crafted locale names [BZ #17137]
    
    Prevent directory traversal in locale-related environment variables
    (CVE-2014-0475).

diff --git a/NEWS b/NEWS
index 9cc2ce5..3832c7c 100644
--- a/NEWS
+++ b/NEWS
@@ -11,10 +11,19 @@ Version 2.18.1
 
   14143, 14155, 14547, 14699, 15532, 15427, 15522, 15680, 15723, 15734,
   15735, 15797, 15892, 15895, 15909, 15915, 15917, 15996, 16072, 16150,
-  16414, 16430, 16431, 17187, 17325.
+  16414, 16430, 16431, 17137, 17187, 17325.
 
 * Support for powerpc64le has been added.
 
+* Locale names, including those obtained from environment variables (LANG
+  and the LC_* variables), are more tightly checked for proper syntax.
+  setlocale will now fail (with EINVAL) for locale names that are overly
+  long, contain slashes without starting with a slash, or contain ".." path
+  components. (CVE-2014-0475)  Previously, some valid locale names were
+  silently replaced with the "C" locale when running in AT_SECURE mode
+  (e.g., in a SUID program).  This is no longer necessary because of the
+  additional checks.
+
 * Support for loadable gconv transliteration modules has been removed.
   The support for transliteration modules has been non-functional for
   over a decade, and the removal is prompted by security defects.  The
diff --git a/locale/findlocale.c b/locale/findlocale.c
index 3c04aa8..30055ad 100644
--- a/locale/findlocale.c
+++ b/locale/findlocale.c
@@ -17,6 +17,7 @@
    <http://www.gnu.org/licenses/>.  */
 
 #include <assert.h>
+#include <errno.h>
 #include <locale.h>
 #include <stdlib.h>
 #include <string.h>
@@ -57,6 +58,45 @@ struct loaded_l10nfile *_nl_locale_file_list[__LC_LAST];
 
 const char _nl_default_locale_path[] attribute_hidden = LOCALEDIR;
 
+/* Checks if the name is actually present, that is, not NULL and not
+   empty.  */
+static inline int
+name_present (const char *name)
+{
+  return name != NULL && name[0] != '\0';
+}
+
+/* Checks that the locale name neither extremely long, nor contains a
+   ".." path component (to prevent directory traversal).  */
+static inline int
+valid_locale_name (const char *name)
+{
+  /* Not set.  */
+  size_t namelen = strlen (name);
+  /* Name too long.  The limit is arbitrary and prevents stack overflow
+     issues later.  */
+  if (__glibc_unlikely (namelen > 255))
+    return 0;
+  /* Directory traversal attempt.  */
+  static const char slashdot[4] = {'/', '.', '.', '/'};
+  if (__glibc_unlikely (memmem (name, namelen,
+				slashdot, sizeof (slashdot)) != NULL))
+    return 0;
+  if (namelen == 2 && __glibc_unlikely (name[0] == '.' && name [1] == '.'))
+    return 0;
+  if (namelen >= 3
+      && __glibc_unlikely (((name[0] == '.'
+			     && name[1] == '.'
+			     && name[2] == '/')
+			    || (name[namelen - 3] == '/'
+				&& name[namelen - 2] == '.'
+				&& name[namelen - 1] == '.'))))
+    return 0;
+  /* If there is a slash in the name, it must start with one.  */
+  if (__glibc_unlikely (memchr (name, '/', namelen) != NULL) && name[0] != '/')
+    return 0;
+  return 1;
+}
 
 struct __locale_data *
 internal_function
@@ -65,7 +105,7 @@ _nl_find_locale (const char *locale_path, size_t locale_path_len,
 {
   int mask;
   /* Name of the locale for this category.  */
-  char *loc_name;
+  char *loc_name = (char *) *name;
   const char *language;
   const char *modifier;
   const char *territory;
@@ -73,31 +113,39 @@ _nl_find_locale (const char *locale_path, size_t locale_path_len,
   const char *normalized_codeset;
   struct loaded_l10nfile *locale_file;
 
-  if ((*name)[0] == '\0')
+  if (loc_name[0] == '\0')
     {
       /* The user decides which locale to use by setting environment
 	 variables.  */
-      *name = getenv ("LC_ALL");
-      if (*name == NULL || (*name)[0] == '\0')
-	*name = getenv (_nl_category_names.str
+      loc_name = getenv ("LC_ALL");
+      if (!name_present (loc_name))
+	loc_name = getenv (_nl_category_names.str
 			+ _nl_category_name_idxs[category]);
-      if (*name == NULL || (*name)[0] == '\0')
-	*name = getenv ("LANG");
+      if (!name_present (loc_name))
+	loc_name = getenv ("LANG");
+      if (!name_present (loc_name))
+	loc_name = (char *) _nl_C_name;
     }
 
-  if (*name == NULL || (*name)[0] == '\0'
-      || (__builtin_expect (__libc_enable_secure, 0)
-	  && strchr (*name, '/') != NULL))
-    *name = (char *) _nl_C_name;
+  /* We used to fall back to the C locale if the name contains a slash
+     character '/', but we now check for directory traversal in
+     valid_locale_name, so this is no longer necessary.  */
 
-  if (__builtin_expect (strcmp (*name, _nl_C_name), 1) == 0
-      || __builtin_expect (strcmp (*name, _nl_POSIX_name), 1) == 0)
+  if (__builtin_expect (strcmp (loc_name, _nl_C_name), 1) == 0
+      || __builtin_expect (strcmp (loc_name, _nl_POSIX_name), 1) == 0)
     {
       /* We need not load anything.  The needed data is contained in
 	 the library itself.  */
       *name = (char *) _nl_C_name;
       return _nl_C[category];
     }
+  else if (!valid_locale_name (loc_name))
+    {
+      __set_errno (EINVAL);
+      return NULL;
+    }
+
+  *name = loc_name;
 
   /* We really have to load some data.  First we try the archive,
      but only if there was no LOCPATH environment variable specified.  */
diff --git a/localedata/ChangeLog b/localedata/ChangeLog
index 3bc2fcf..71df86b 100644
--- a/localedata/ChangeLog
+++ b/localedata/ChangeLog
@@ -1,3 +1,9 @@
+2014-07-02  Florian Weimer  <fweimer@redhat.com>
+
+	* tst-setlocale3.c: New file.
+	* Makefile (tests): Add tst-setlocale3.
+	(tst-setlocale3-ENV): New variable.
+
 2013-06-13  Johan Heikkila  <johan.heikkila@gmail.com>
 
 	[BZ#15432]
diff --git a/localedata/Makefile b/localedata/Makefile
index 52c39b3..98c1c21 100644
--- a/localedata/Makefile
+++ b/localedata/Makefile
@@ -77,7 +77,7 @@ locale_test_suite := tst_iswalnum tst_iswalpha tst_iswcntrl            \
 
 tests = $(locale_test_suite) tst-digits tst-setlocale bug-iconv-trans \
 	tst-leaks tst-mbswcs6 tst-xlocale1 tst-xlocale2 bug-usesetlocale \
-	tst-strfmon1 tst-sscanf bug-setlocale1 tst-setlocale2
+	tst-strfmon1 tst-sscanf bug-setlocale1 tst-setlocale2 tst-setlocale3
 tests-static = bug-setlocale1-static
 tests += $(tests-static)
 ifeq (yes,$(build-shared))
diff --git a/localedata/tst-setlocale3.c b/localedata/tst-setlocale3.c
new file mode 100644
index 0000000..e3b21a9
--- /dev/null
+++ b/localedata/tst-setlocale3.c
@@ -0,0 +1,203 @@
+/* Regression test for setlocale invalid environment variable handling.
+   Copyright (C) 2014 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/>.  */
+
+#include <locale.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+/* The result of setlocale may be overwritten by subsequent calls, so
+   this wrapper makes a copy.  */
+static char *
+setlocale_copy (int category, const char *locale)
+{
+  const char *result = setlocale (category, locale);
+  if (result == NULL)
+    return NULL;
+  return strdup (result);
+}
+
+static char *de_locale;
+
+static void
+setlocale_fail (const char *envstring)
+{
+  setenv ("LC_CTYPE", envstring, 1);
+  if (setlocale (LC_CTYPE, "") != NULL)
+    {
+      printf ("unexpected setlocale success for \"%s\" locale\n", envstring);
+      exit (1);
+    }
+  const char *newloc = setlocale (LC_CTYPE, NULL);
+  if (strcmp (newloc, de_locale) != 0)
+    {
+      printf ("failed setlocale call \"%s\" changed locale to \"%s\"\n",
+	      envstring, newloc);
+      exit (1);
+    }
+}
+
+static void
+setlocale_success (const char *envstring)
+{
+  setenv ("LC_CTYPE", envstring, 1);
+  char *newloc = setlocale_copy (LC_CTYPE, "");
+  if (newloc == NULL)
+    {
+      printf ("setlocale for \"%s\": %m\n", envstring);
+      exit (1);
+    }
+  if (strcmp (newloc, de_locale) == 0)
+    {
+      printf ("setlocale with LC_CTYPE=\"%s\" left locale at \"%s\"\n",
+	      envstring, de_locale);
+      exit (1);
+    }
+  if (setlocale (LC_CTYPE, de_locale) == NULL)
+    {
+      printf ("restoring locale \"%s\" with LC_CTYPE=\"%s\": %m\n",
+	      de_locale, envstring);
+      exit (1);
+    }
+  char *newloc2 = setlocale_copy (LC_CTYPE, newloc);
+  if (newloc2 == NULL)
+    {
+      printf ("restoring locale \"%s\" following \"%s\": %m\n",
+	      newloc, envstring);
+      exit (1);
+    }
+  if (strcmp (newloc, newloc2) != 0)
+    {
+      printf ("representation of locale \"%s\" changed from \"%s\" to \"%s\"",
+	      envstring, newloc, newloc2);
+      exit (1);
+    }
+  free (newloc);
+  free (newloc2);
+
+  if (setlocale (LC_CTYPE, de_locale) == NULL)
+    {
+      printf ("restoring locale \"%s\" with LC_CTYPE=\"%s\": %m\n",
+	      de_locale, envstring);
+      exit (1);
+    }
+}
+
+/* Checks that a known-good locale still works if LC_ALL contains a
+   value which should be ignored.  */
+static void
+setlocale_ignore (const char *to_ignore)
+{
+  const char *fr_locale = "fr_FR.UTF-8";
+  setenv ("LC_CTYPE", fr_locale, 1);
+  char *expected_locale = setlocale_copy (LC_CTYPE, "");
+  if (expected_locale == NULL)
+    {
+      printf ("setlocale with LC_CTYPE=\"%s\" failed: %m\n", fr_locale);
+      exit (1);
+    }
+  if (setlocale (LC_CTYPE, de_locale) == NULL)
+    {
+      printf ("failed to restore locale: %m\n");
+      exit (1);
+    }
+  unsetenv ("LC_CTYPE");
+
+  setenv ("LC_ALL", to_ignore, 1);
+  setenv ("LC_CTYPE", fr_locale, 1);
+  const char *actual_locale = setlocale (LC_CTYPE, "");
+  if (actual_locale == NULL)
+    {
+      printf ("setlocale with LC_ALL, LC_CTYPE=\"%s\" failed: %m\n",
+	      fr_locale);
+      exit (1);
+    }
+  if (strcmp (actual_locale, expected_locale) != 0)
+    {
+      printf ("setlocale under LC_ALL failed: got \"%s\", expected \"%s\"\n",
+	      actual_locale, expected_locale);
+      exit (1);
+    }
+  unsetenv ("LC_CTYPE");
+  setlocale_success (fr_locale);
+  unsetenv ("LC_ALL");
+  free (expected_locale);
+}
+
+static int
+do_test (void)
+{
+  /* The glibc test harness sets this environment variable
+     uncondionally.  */
+  unsetenv ("LC_ALL");
+
+  de_locale = setlocale_copy (LC_CTYPE, "de_DE.UTF-8");
+  if (de_locale == NULL)
+    {
+      printf ("setlocale (LC_CTYPE, \"de_DE.UTF-8\"): %m\n");
+      return 1;
+    }
+  setlocale_success ("C");
+  setlocale_success ("en_US.UTF-8");
+  setlocale_success ("/en_US.UTF-8");
+  setlocale_success ("//en_US.UTF-8");
+  setlocale_ignore ("");
+
+  setlocale_fail ("does-not-exist");
+  setlocale_fail ("/");
+  setlocale_fail ("/../localedata/en_US.UTF-8");
+  setlocale_fail ("en_US.UTF-8/");
+  setlocale_fail ("en_US.UTF-8/..");
+  setlocale_fail ("en_US.UTF-8/../en_US.UTF-8");
+  setlocale_fail ("../localedata/en_US.UTF-8");
+  {
+    size_t large_length = 1024;
+    char *large_name = malloc (large_length + 1);
+    if (large_name == NULL)
+      {
+	puts ("malloc failure");
+	return 1;
+      }
+    memset (large_name, '/', large_length);
+    const char *suffix = "en_US.UTF-8";
+    strcpy (large_name + large_length - strlen (suffix), suffix);
+    setlocale_fail (large_name);
+    free (large_name);
+  }
+  {
+    size_t huge_length = 64 * 1024 * 1024;
+    char *huge_name = malloc (huge_length + 1);
+    if (huge_name == NULL)
+      {
+	puts ("malloc failure");
+	return 1;
+      }
+    memset (huge_name, 'X', huge_length);
+    huge_name[huge_length] = '\0';
+    /* Construct a composite locale specification. */
+    const char *prefix = "LC_CTYPE=de_DE.UTF-8;LC_TIME=";
+    memcpy (huge_name, prefix, strlen (prefix));
+    setlocale_fail (huge_name);
+    free (huge_name);
+  }
+
+  return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=02d327633bf0184f9a2e8814f5614ecec1e1229e

commit 02d327633bf0184f9a2e8814f5614ecec1e1229e
Author: Florian Weimer <fweimer@redhat.com>
Date:   Tue Aug 26 19:38:59 2014 +0200

    __gconv_translit_find: Disable function [BZ #17187]
    
    This functionality has never worked correctly, and the implementation
    contained a security vulnerability (CVE-2014-5119).

diff --git a/ChangeLog b/ChangeLog
index ccdfddf..d23e631 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2014-08-26  Florian Weimer  <fweimer@redhat.com>
+
+	[BZ #17187]
+	* iconv/gconv_trans.c (struct known_trans, search_tree, lock,
+	trans_compare, open_translit, __gconv_translit_find):
+	Remove module loading code.
+
 2014-09-03  Florian Weimer  <fweimer@redhat.com>
 
 	[BZ #17325]
diff --git a/NEWS b/NEWS
index 8029dab..9cc2ce5 100644
--- a/NEWS
+++ b/NEWS
@@ -11,10 +11,17 @@ Version 2.18.1
 
   14143, 14155, 14547, 14699, 15532, 15427, 15522, 15680, 15723, 15734,
   15735, 15797, 15892, 15895, 15909, 15915, 15917, 15996, 16072, 16150,
-  16414, 16430, 16431, 17325.
+  16414, 16430, 16431, 17187, 17325.
 
 * Support for powerpc64le has been added.
 
+* Support for loadable gconv transliteration modules has been removed.
+  The support for transliteration modules has been non-functional for
+  over a decade, and the removal is prompted by security defects.  The
+  normal gconv conversion modules are still supported.  Transliteration
+  with //TRANSLIT is still possible, and the //IGNORE specifier
+  continues to be  supported. (CVE-2014-5119)
+
 * Decoding a crafted input sequence in the character sets IBM933, IBM935,
   IBM937, IBM939, IBM1364 could result in an out-of-bounds array read,
   resulting a denial-of-service security vulnerability in applications which
diff --git a/iconv/gconv_trans.c b/iconv/gconv_trans.c
index 41b021a..5e91af2 100644
--- a/iconv/gconv_trans.c
+++ b/iconv/gconv_trans.c
@@ -238,181 +238,12 @@ __gconv_transliterate (struct __gconv_step *step,
   return __GCONV_ILLEGAL_INPUT;
 }
 
-
-/* Structure to represent results of found (or not) transliteration
-   modules.  */
-struct known_trans
-{
-  /* This structure must remain the first member.  */
-  struct trans_struct info;
-
-  char *fname;
-  void *handle;
-  int open_count;
-};
-
-
-/* Tree with results of previous calls to __gconv_translit_find.  */
-static void *search_tree;
-
-/* We modify global data.   */
-__libc_lock_define_initialized (static, lock);
-
-
-/* Compare two transliteration entries.  */
-static int
-trans_compare (const void *p1, const void *p2)
-{
-  const struct known_trans *s1 = (const struct known_trans *) p1;
-  const struct known_trans *s2 = (const struct known_trans *) p2;
-
-  return strcmp (s1->info.name, s2->info.name);
-}
-
-
-/* Open (maybe reopen) the module named in the struct.  Get the function
-   and data structure pointers we need.  */
-static int
-open_translit (struct known_trans *trans)
-{
-  __gconv_trans_query_fct queryfct;
-
-  trans->handle = __libc_dlopen (trans->fname);
-  if (trans->handle == NULL)
-    /* Not available.  */
-    return 1;
-
-  /* Find the required symbol.  */
-  queryfct = __libc_dlsym (trans->handle, "gconv_trans_context");
-  if (queryfct == NULL)
-    {
-      /* We cannot live with that.  */
-    close_and_out:
-      __libc_dlclose (trans->handle);
-      trans->handle = NULL;
-      return 1;
-    }
-
-  /* Get the context.  */
-  if (queryfct (trans->info.name, &trans->info.csnames, &trans->info.ncsnames)
-      != 0)
-    goto close_and_out;
-
-  /* Of course we also have to have the actual function.  */
-  trans->info.trans_fct = __libc_dlsym (trans->handle, "gconv_trans");
-  if (trans->info.trans_fct == NULL)
-    goto close_and_out;
-
-  /* Now the optional functions.  */
-  trans->info.trans_init_fct =
-    __libc_dlsym (trans->handle, "gconv_trans_init");
-  trans->info.trans_context_fct =
-    __libc_dlsym (trans->handle, "gconv_trans_context");
-  trans->info.trans_end_fct =
-    __libc_dlsym (trans->handle, "gconv_trans_end");
-
-  trans->open_count = 1;
-
-  return 0;
-}
-
-
 int
 internal_function
 __gconv_translit_find (struct trans_struct *trans)
 {
-  struct known_trans **found;
-  const struct path_elem *runp;
-  int res = 1;
-
-  /* We have to have a name.  */
-  assert (trans->name != NULL);
-
-  /* Acquire the lock.  */
-  __libc_lock_lock (lock);
-
-  /* See whether we know this module already.  */
-  found = __tfind (trans, &search_tree, trans_compare);
-  if (found != NULL)
-    {
-      /* Is this module available?  */
-      if ((*found)->handle != NULL)
-	{
-	  /* Maybe we have to reopen the file.  */
-	  if ((*found)->handle != (void *) -1)
-	    /* The object is not unloaded.  */
-	    res = 0;
-	  else if (open_translit (*found) == 0)
-	    {
-	      /* Copy the data.  */
-	      *trans = (*found)->info;
-	      (*found)->open_count++;
-	      res = 0;
-	    }
-	}
-    }
-  else
-    {
-      size_t name_len = strlen (trans->name) + 1;
-      int need_so = 0;
-      struct known_trans *newp;
-
-      /* We have to continue looking for the module.  */
-      if (__gconv_path_elem == NULL)
-	__gconv_get_path ();
-
-      /* See whether we have to append .so.  */
-      if (name_len <= 4 || memcmp (&trans->name[name_len - 4], ".so", 3) != 0)
-	need_so = 1;
-
-      /* Create a new entry.  */
-      newp = (struct known_trans *) malloc (sizeof (struct known_trans)
-					    + (__gconv_max_path_elem_len
-					       + name_len + 3)
-					    + name_len);
-      if (newp != NULL)
-	{
-	  char *cp;
-
-	  /* Clear the struct.  */
-	  memset (newp, '\0', sizeof (struct known_trans));
-
-	  /* Store a copy of the module name.  */
-	  newp->info.name = cp = (char *) (newp + 1);
-	  cp = __mempcpy (cp, trans->name, name_len);
-
-	  newp->fname = cp;
-
-	  /* Search in all the directories.  */
-	  for (runp = __gconv_path_elem; runp->name != NULL; ++runp)
-	    {
-	      cp = __mempcpy (__stpcpy ((char *) newp->fname, runp->name),
-			      trans->name, name_len);
-	      if (need_so)
-		memcpy (cp, ".so", sizeof (".so"));
-
-	      if (open_translit (newp) == 0)
-		{
-		  /* We found a module.  */
-		  res = 0;
-		  break;
-		}
-	    }
-
-	  if (res)
-	    newp->fname = NULL;
-
-	  /* In any case we'll add the entry to our search tree.  */
-	  if (__tsearch (newp, &search_tree, trans_compare) == NULL)
-	    {
-	      /* Yickes, this should not happen.  Unload the object.  */
-	      res = 1;
-	      /* XXX unload here.  */
-	    }
-	}
-    }
-
-  __libc_lock_unlock (lock);
-
-  return res;
+  /* Transliteration module loading has been removed because it never
+     worked as intended and suffered from a security vulnerability.
+     Consequently, this function always fails.  */
+  return 1;
 }

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=3e36f1f5391c49e0024d5001e8097aeb49fda824

commit 3e36f1f5391c49e0024d5001e8097aeb49fda824
Author: Florian Weimer <fweimer@redhat.com>
Date:   Wed Sep 3 19:45:43 2014 +0200

    CVE-2014-6040: Crashes on invalid input in IBM gconv modules [BZ #17325]
    
    These changes are based on the fix for BZ #14134 in commit
    6e230d11837f3ae7b375ea69d7905f0d18eb79e5.

diff --git a/ChangeLog b/ChangeLog
index 14760a2..ccdfddf 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,20 @@
+2014-09-03  Florian Weimer  <fweimer@redhat.com>
+
+	[BZ #17325]
+	* iconvdata/ibm1364.c (BODY): Fix check for sentinel.
+	* iconvdata/ibm932.c (BODY): Replace invalid sentinel check with
+	assert.
+	* iconvdata/ibm933.c (BODY): Fix check for sentinel.
+	* iconvdata/ibm935.c (BODY): Likewise.
+	* iconvdata/ibm937.c (BODY): Likewise.
+	* iconvdata/ibm939.c (BODY): Likewise.
+	* iconvdata/ibm943.c (BODY): Replace invalid sentinel check with
+	assert.
+	* iconvdata/Makefile (iconv-test.out): Pass module list to test
+	script.
+	* iconvdata/run-iconv-test.sh: New test loop for checking for
+	decoder crashers.
+
 2014-02-18  Brooks Moses  <bmoses@google.com>
 
 	[BZ #15915]
diff --git a/NEWS b/NEWS
index e2931f1..8029dab 100644
--- a/NEWS
+++ b/NEWS
@@ -11,10 +11,15 @@ Version 2.18.1
 
   14143, 14155, 14547, 14699, 15532, 15427, 15522, 15680, 15723, 15734,
   15735, 15797, 15892, 15895, 15909, 15915, 15917, 15996, 16072, 16150,
-  16414, 16430, 16431.
+  16414, 16430, 16431, 17325.
 
 * Support for powerpc64le has been added.
 
+* Decoding a crafted input sequence in the character sets IBM933, IBM935,
+  IBM937, IBM939, IBM1364 could result in an out-of-bounds array read,
+  resulting a denial-of-service security vulnerability in applications which
+  use functions related to iconv. (CVE-2014-6040)
+
 * CVE-2013-4237 The readdir_r function could write more than NAME_MAX bytes
   to the d_name member of struct dirent, or omit the terminating NUL
   character.  (Bugzilla #14699).
diff --git a/iconvdata/Makefile b/iconvdata/Makefile
index 7752013..a8c43bd 100644
--- a/iconvdata/Makefile
+++ b/iconvdata/Makefile
@@ -299,7 +299,10 @@ $(objpfx)tst-iconv7.out: $(objpfx)gconv-modules \
 $(objpfx)iconv-test.out: run-iconv-test.sh $(objpfx)gconv-modules \
 			 $(addprefix $(objpfx),$(modules.so)) \
 			 $(common-objdir)/iconv/iconv_prog TESTS
-	$(SHELL) $< $(common-objdir) '$(test-wrapper)' > $@
+	iconv_modules="$(modules)" \
+	$(SHELL) $< $(common-objdir) '$(test-wrapper-env)' \
+		 '$(run-program-env)' > $@; \
+	$(evaluate-test)
 
 $(objpfx)tst-tables.out: tst-tables.sh $(objpfx)gconv-modules \
 			 $(addprefix $(objpfx),$(modules.so)) \
diff --git a/iconvdata/ibm1364.c b/iconvdata/ibm1364.c
index 0dfa250..569fdc1 100644
--- a/iconvdata/ibm1364.c
+++ b/iconvdata/ibm1364.c
@@ -220,7 +220,8 @@ enum
 	  ++rp2;							      \
 									      \
 	uint32_t res;							      \
-	if (__builtin_expect (ch < rp2->start, 0)			      \
+	if (__builtin_expect (rp2->start == 0xffff, 0)			      \
+	    || __builtin_expect (ch < rp2->start, 0)			      \
 	    || (res = DB_TO_UCS4[ch + rp2->idx],			      \
 		__builtin_expect (res, L'\1') == L'\0' && ch != '\0'))	      \
 	  {								      \
diff --git a/iconvdata/ibm932.c b/iconvdata/ibm932.c
index 0764fb2..cbdaad3 100644
--- a/iconvdata/ibm932.c
+++ b/iconvdata/ibm932.c
@@ -73,11 +73,12 @@
 	  }								      \
 									      \
 	ch = (ch * 0x100) + inptr[1];					      \
+	/* ch was less than 0xfd.  */					      \
+	assert (ch < 0xfd00);						      \
 	while (ch > rp2->end)						      \
 	  ++rp2;							      \
 									      \
-	if (__builtin_expect (rp2 == NULL, 0)				      \
-	    || __builtin_expect (ch < rp2->start, 0)			      \
+	if (__builtin_expect (ch < rp2->start, 0)			      \
 	    || (res = __ibm932db_to_ucs4[ch + rp2->idx],		      \
 	    __builtin_expect (res, '\1') == 0 && ch !=0))		      \
 	  {								      \
diff --git a/iconvdata/ibm933.c b/iconvdata/ibm933.c
index 145d12f..b56a68d 100644
--- a/iconvdata/ibm933.c
+++ b/iconvdata/ibm933.c
@@ -161,7 +161,7 @@ enum
 	while (ch > rp2->end)						      \
 	  ++rp2;							      \
 									      \
-	if (__builtin_expect (rp2 == NULL, 0)				      \
+	if (__builtin_expect (rp2->start == 0xffff, 0)			      \
 	    || __builtin_expect (ch < rp2->start, 0)			      \
 	    || (res = __ibm933db_to_ucs4[ch + rp2->idx],		      \
 		__builtin_expect (res, L'\1') == L'\0' && ch != '\0'))	      \
diff --git a/iconvdata/ibm935.c b/iconvdata/ibm935.c
index 7d5628b..4d111b0 100644
--- a/iconvdata/ibm935.c
+++ b/iconvdata/ibm935.c
@@ -161,7 +161,7 @@ enum
 	while (ch > rp2->end)						      \
 	  ++rp2;							      \
 									      \
-	if (__builtin_expect (rp2 == NULL, 0)				      \
+	if (__builtin_expect (rp2->start == 0xffff, 0)			      \
 	    || __builtin_expect (ch < rp2->start, 0)			      \
 	    || (res = __ibm935db_to_ucs4[ch + rp2->idx],		      \
 		__builtin_expect (res, L'\1') == L'\0' && ch != '\0'))	      \
diff --git a/iconvdata/ibm937.c b/iconvdata/ibm937.c
index b913cbb..dcedcd4 100644
--- a/iconvdata/ibm937.c
+++ b/iconvdata/ibm937.c
@@ -161,7 +161,7 @@ enum
 	while (ch > rp2->end)						      \
 	  ++rp2;							      \
 									      \
-	if (__builtin_expect (rp2 == NULL, 0)				      \
+	if (__builtin_expect (rp2->start == 0xffff, 0)			      \
 	    || __builtin_expect (ch < rp2->start, 0)			      \
 	    || (res = __ibm937db_to_ucs4[ch + rp2->idx],		      \
 		__builtin_expect (res, L'\1') == L'\0' && ch != '\0'))	      \
diff --git a/iconvdata/ibm939.c b/iconvdata/ibm939.c
index d42b98c..4727288 100644
--- a/iconvdata/ibm939.c
+++ b/iconvdata/ibm939.c
@@ -161,7 +161,7 @@ enum
 	while (ch > rp2->end)						      \
 	  ++rp2;							      \
 									      \
-	if (__builtin_expect (rp2 == NULL, 0)				      \
+	if (__builtin_expect (rp2->start == 0xffff, 0)			      \
 	    || __builtin_expect (ch < rp2->start, 0)			      \
 	    || (res = __ibm939db_to_ucs4[ch + rp2->idx],		      \
 		__builtin_expect (res, L'\1') == L'\0' && ch != '\0'))	      \
diff --git a/iconvdata/ibm943.c b/iconvdata/ibm943.c
index b3a6555..53eb2fc 100644
--- a/iconvdata/ibm943.c
+++ b/iconvdata/ibm943.c
@@ -74,11 +74,12 @@
 	  }								      \
 									      \
 	ch = (ch * 0x100) + inptr[1];					      \
+	/* ch was less than 0xfd.  */					      \
+	assert (ch < 0xfd00);						      \
 	while (ch > rp2->end)						      \
 	  ++rp2;							      \
 									      \
-	if (__builtin_expect (rp2 == NULL, 0)				      \
-	    || __builtin_expect (ch < rp2->start, 0)			      \
+	if (__builtin_expect (ch < rp2->start, 0)			      \
 	    || (res = __ibm943db_to_ucs4[ch + rp2->idx],		      \
 	    __builtin_expect (res, '\1') == 0 && ch !=0))		      \
 	  {								      \
diff --git a/iconvdata/run-iconv-test.sh b/iconvdata/run-iconv-test.sh
index 107ded0..8afece9 100755
--- a/iconvdata/run-iconv-test.sh
+++ b/iconvdata/run-iconv-test.sh
@@ -188,6 +188,24 @@ while read utf8 from filename; do
 
 done < TESTS2
 
+# Check for crashes in decoders.
+printf '\016\377\377\377\377\377\377\377' > $temp1
+for from in $iconv_modules ; do
+    echo $ac_n "test decoder $from $ac_c"
+    PROG=`eval echo $ICONV`
+    if $PROG < $temp1 >/dev/null 2>&1 ; then
+	: # fall through
+    else
+	status=$?
+	if test $status -gt 1 ; then
+	    echo "/FAILED"
+	    failed=1
+	    continue
+	fi
+    fi
+    echo "OK"
+done
+
 exit $failed
 # Local Variables:
 #  mode:shell-script

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=301e0d6f9a2218f2d1943860c2d14046b917e846

commit 301e0d6f9a2218f2d1943860c2d14046b917e846
Author: Will Newton <will.newton@linaro.org>
Date:   Fri Sep 13 09:26:02 2013 +0100

    Add CVE-2013-4332 to NEWS.

diff --git a/NEWS b/NEWS
index 96df7a9..e2931f1 100644
--- a/NEWS
+++ b/NEWS
@@ -22,6 +22,11 @@ Version 2.18.1
 * CVE-2013-4458 Stack overflow in getaddrinfo with large number of results
   for AF_INET6 has been fixed (Bugzilla #16072).
 
+* CVE-2013-4332 The pvalloc, valloc, memalign, posix_memalign and
+  aligned_alloc functions could allocate too few bytes or corrupt the
+  heap when passed very large allocation size values (Bugzilla #15855,
+  #15856, #15857).
+
 * CVE-2012-4424 The strcoll implementation uses malloc to cache indices and
   rules for large collation sequences to optimize multiple passes and falls
   back to alloca if malloc fails, resulting in a possible stack overflow.

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=9c77803abebe02a99a5329e28627e1ad6d074cfe

commit 9c77803abebe02a99a5329e28627e1ad6d074cfe
Author: Will Newton <will.newton@linaro.org>
Date:   Fri Aug 16 12:54:29 2013 +0100

    malloc: Check for integer overflow in memalign.
    
    A large bytes parameter to memalign could cause an integer overflow
    and corrupt allocator internals. Check the overflow does not occur
    before continuing with the allocation.
    
    ChangeLog:
    
    2013-09-11  Will Newton  <will.newton@linaro.org>
    
    	[BZ #15857]
    	* malloc/malloc.c (__libc_memalign): Check the value of bytes
    	does not overflow.

diff --git a/ChangeLog b/ChangeLog
index 2c9dc89..14760a2 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -337,6 +337,12 @@
 
 2013-09-11  Will Newton  <will.newton@linaro.org>
 
+	[BZ #15857]
+	* malloc/malloc.c (__libc_memalign): Check the value of bytes
+	does not overflow.
+
+2013-09-11  Will Newton  <will.newton@linaro.org>
+
 	[BZ #15856]
 	* malloc/malloc.c (__libc_valloc): Check the value of bytes
 	does not overflow.

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=71d84750188dc6e1d45a9d05e40b00c430dc5637

commit 71d84750188dc6e1d45a9d05e40b00c430dc5637
Author: Will Newton <will.newton@linaro.org>
Date:   Fri Aug 16 11:59:37 2013 +0100

    malloc: Check for integer overflow in valloc.
    
    A large bytes parameter to valloc could cause an integer overflow
    and corrupt allocator internals. Check the overflow does not occur
    before continuing with the allocation.
    
    ChangeLog:
    
    2013-09-11  Will Newton  <will.newton@linaro.org>
    
    	[BZ #15856]
    	* malloc/malloc.c (__libc_valloc): Check the value of bytes
    	does not overflow.

diff --git a/ChangeLog b/ChangeLog
index c448dda..2c9dc89 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -337,6 +337,12 @@
 
 2013-09-11  Will Newton  <will.newton@linaro.org>
 
+	[BZ #15856]
+	* malloc/malloc.c (__libc_valloc): Check the value of bytes
+	does not overflow.
+
+2013-09-11  Will Newton  <will.newton@linaro.org>
+
 	[BZ #15855]
 	* malloc/malloc.c (__libc_pvalloc): Check the value of bytes
 	does not overflow.

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=052b65bfeee78d8ba82f070f9f10f79bb0de5376

commit 052b65bfeee78d8ba82f070f9f10f79bb0de5376
Author: Brooks Moses <bmoses@google.com>
Date:   Tue Feb 18 11:18:44 2014 -0600

    Fix erroneous (and circular) implied pattern rule for linkobj/libc.so.
    
    [BZ #15915] As described in the bug, the pattern rule for lib%.so files
    in Makerules includes linkobj/libc.so as a dependency.  However, the
    explicit rule for linkobj/libc.so is in the top-level Makefile.
    
    Thus, the subdirectory makefiles that include Makerules end up with an
    erroneous makefile pattern rule for linkobj/libc.so that includes
    itself as a dependency.  The result is make warnings whenever rules
    for other .so files are resolved -- and, on occasion, actual makefile
    failures when a race condition causes the implicit rule to actually be
    used.
    
    This patch moves the explicit rules for linkobj/libc.so into Makerules
    to clear up this problem.  It also elaborates a couple of comments
    that I'd initially found confusing.
    
    Backport of 5f855e3598a576c35e54623a13b256f3e87fcd4d

diff --git a/ChangeLog b/ChangeLog
index 0afa5ca..c448dda 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2014-02-18  Brooks Moses  <bmoses@google.com>
+
+	[BZ #15915]
+	* Makefile (linkobj/libc_pic.a, linkobj/libc.so): Move rules to...
+	* Makerules: ...here, and adjust associated comments.
+
 2014-02-06  Adhemerval Zanella  <azanella@linux.vnet.ibm.com>
 
 	* sysdeps/powerpc/powerpc64/power5/Implies: Remove inexistent
diff --git a/Makefile b/Makefile
index 7d8eccf..00e4394 100644
--- a/Makefile
+++ b/Makefile
@@ -123,30 +123,7 @@ lib-noranlib: subdir_lib
 
 ifeq (yes,$(build-shared))
 # Build the shared object from the PIC object library.
-lib: $(common-objpfx)libc.so
-
-lib: $(common-objpfx)linkobj/libc.so
-
-# Do not filter ld.so out of libc.so link.
-$(common-objpfx)linkobj/libc.so: link-libc-deps = # empty
-
-$(common-objpfx)linkobj/libc.so: $(elfobjdir)/soinit.os \
-				 $(common-objpfx)linkobj/libc_pic.a \
-				 $(elfobjdir)/sofini.os \
-				 $(elfobjdir)/interp.os \
-				 $(elfobjdir)/ld.so \
-				 $(shlib-lds)
-	$(build-shlib)
-
-$(common-objpfx)linkobj/libc_pic.a: $(common-objpfx)libc_pic.a \
-				    $(common-objpfx)sunrpc/librpc_compat_pic.a
-	$(..)./scripts/mkinstalldirs $(common-objpfx)linkobj
-	(cd $(common-objpfx)linkobj; \
-	 $(AR) x ../libc_pic.a; \
-	 rm $$($(AR) t ../sunrpc/librpc_compat_pic.a | sed 's/^compat-//'); \
-	 $(AR) x ../sunrpc/librpc_compat_pic.a; \
-	 $(AR) cr libc_pic.a *.os; \
-	 rm *.os)
+lib: $(common-objpfx)libc.so $(common-objpfx)linkobj/libc.so
 endif
 
 
diff --git a/Makerules b/Makerules
index bd8642a..8ed458f 100644
--- a/Makerules
+++ b/Makerules
@@ -565,16 +565,47 @@ generated += libc_pic.opts libc_pic.os.clean
 libc_pic_clean := .clean
 endif
 
-# Do not filter ld.so out of libc.so link.
+# Build a possibly-modified version of libc_pic.a for use in building
+# linkobj/libc.so.
+ifeq (,$(filter sunrpc,$(subdirs)))
+$(common-objpfx)linkobj/libc_pic.a: $(common-objpfx)libc_pic.a
+	$(make-target-directory)
+	ln -f $< $@
+else
+$(common-objpfx)linkobj/libc_pic.a: $(common-objpfx)libc_pic.a \
+				    $(common-objpfx)sunrpc/librpc_compat_pic.a
+	$(make-target-directory)
+	(cd $(common-objpfx)linkobj; \
+	 $(AR) x ../libc_pic.a; \
+	 rm $$($(AR) t ../sunrpc/librpc_compat_pic.a | sed 's/^compat-//'); \
+	 $(AR) x ../sunrpc/librpc_compat_pic.a; \
+	 $(AR) cr libc_pic.a *.os; \
+	 rm *.os)
+endif # $(subdirs) contains sunrpc
+
+# Clear link-libc-deps for the libc.so libraries so build-shlibs does not
+# filter ld.so out of the list of linked objects.
 $(common-objpfx)libc.so: link-libc-deps = # empty
+$(common-objpfx)linkobj/libc.so: link-libc-deps = # empty
 
-# Use our own special initializer and finalizer files for libc.so.
+# Use our own special initializer and finalizer files for the libc.so
+# libraries.
 $(common-objpfx)libc.so: $(elfobjdir)/soinit.os \
 			 $(common-objpfx)libc_pic.os$(libc_pic_clean) \
 			 $(elfobjdir)/sofini.os \
-			 $(elfobjdir)/interp.os $(elfobjdir)/ld.so \
+			 $(elfobjdir)/interp.os \
+			 $(elfobjdir)/ld.so \
+			 $(shlib-lds)
+	$(build-shlib)
+
+$(common-objpfx)linkobj/libc.so: $(elfobjdir)/soinit.os \
+			 $(common-objpfx)linkobj/libc_pic.a \
+			 $(elfobjdir)/sofini.os \
+			 $(elfobjdir)/interp.os \
+			 $(elfobjdir)/ld.so \
 			 $(shlib-lds)
 	$(build-shlib)
+
 ifeq ($(versioning),yes)
 $(common-objpfx)libc.so: $(common-objpfx)libc.map
 endif
diff --git a/NEWS b/NEWS
index 5c2f07a..96df7a9 100644
--- a/NEWS
+++ b/NEWS
@@ -10,8 +10,8 @@ Version 2.18.1
 * The following bugs are resolved with this release:
 
   14143, 14155, 14547, 14699, 15532, 15427, 15522, 15680, 15723, 15734,
-  15735, 15797, 15892, 15895, 15909, 15917, 15996, 16072, 16150, 16414,
-  16430, 16431.
+  15735, 15797, 15892, 15895, 15909, 15915, 15917, 15996, 16072, 16150,
+  16414, 16430, 16431.
 
 * Support for powerpc64le has been added.
 

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=7d000197af0d94220c665c5a655c8575fa348e47

commit 7d000197af0d94220c665c5a655c8575fa348e47
Author: Adhemerval Zanella <azanella@linux.vnet.ibm.com>
Date:   Thu Feb 6 12:10:25 2014 -0600

    PowerPC: Remove inexistent paths in sysdeps dirs
    
    This patch removes inexistent paths when building with --with-cpu=power5
    or newer.

diff --git a/ChangeLog b/ChangeLog
index 7835d36..0afa5ca 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,10 @@
 2014-02-06  Adhemerval Zanella  <azanella@linux.vnet.ibm.com>
 
+	* sysdeps/powerpc/powerpc64/power5/Implies: Remove inexistent
+	paths.
+
+2014-02-06  Adhemerval Zanella  <azanella@linux.vnet.ibm.com>
+
 	* elf/get-dynamic-info.h (elf_get_dynamic_info): Fix remove of
 	assert.
 
diff --git a/sysdeps/powerpc/powerpc64/power5/Implies b/sysdeps/powerpc/powerpc64/power5/Implies
index b36831e..bedb20b 100644
--- a/sysdeps/powerpc/powerpc64/power5/Implies
+++ b/sysdeps/powerpc/powerpc64/power5/Implies
@@ -1,4 +1,2 @@
-powerpc/power5/fpu
-powerpc/power5
 powerpc/powerpc64/power4/fpu
 powerpc/powerpc64/power4

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=c93dc5f0d2811b971a8cf124818fff22d1c74e52

commit c93dc5f0d2811b971a8cf124818fff22d1c74e52
Author: Adhemerval Zanella <azanella@linux.vnet.ibm.com>
Date:   Thu Feb 6 12:10:00 2014 -0600

    Fix assert() remove for DT_RUNPATH and DT_RPATH
    
    This patch fixes a wrong merge of d19762a5fd946ef86fb2922eb5710aac8000ab25

diff --git a/ChangeLog b/ChangeLog
index 01518f8..7835d36 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2014-02-06  Adhemerval Zanella  <azanella@linux.vnet.ibm.com>
+
+	* elf/get-dynamic-info.h (elf_get_dynamic_info): Fix remove of
+	assert.
+
 2014-02-04  Adhemerval Zanella  <azanella@linux.vnet.ibm.com>
 
 	* Versions.def (libm): Add GLIBC_2.3.
diff --git a/elf/get-dynamic-info.h b/elf/get-dynamic-info.h
index 1c30c44..57cf964 100644
--- a/elf/get-dynamic-info.h
+++ b/elf/get-dynamic-info.h
@@ -130,8 +130,8 @@ elf_get_dynamic_info (struct link_map *l, ElfW(Dyn) *temp)
   assert (info[DT_FLAGS] == NULL
 	  || (info[DT_FLAGS]->d_un.d_val & ~DF_BIND_NOW) == 0);
   /* Flags must not be set for ld.so.  */
-  info[DT_RUNPATH] == NULL;
-  info[DT_RPATH] == NULL;
+  info[DT_RUNPATH] = NULL;
+  info[DT_RPATH] = NULL;
 #else
   if (info[DT_FLAGS] != NULL)
     {

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=8e6ea3948c217401a84cd1115ca0291bdf2be90c

commit 8e6ea3948c217401a84cd1115ca0291bdf2be90c
Author: Adhemerval Zanella <azanella@linux.vnet.ibm.com>
Date:   Wed Feb 5 15:29:39 2014 -0600

    Fix wrong ChangeLog merge

diff --git a/ChangeLog b/ChangeLog
index 9a0f195..01518f8 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -386,7 +386,12 @@
 
 2013-10-25  Siddhesh Poyarekar  <siddhesh@redhat.com>
 
-<<<<<<< HEAD
+	[BZ #16072]
+	* sysdeps/posix/getaddrinfo.c (gethosts): Allocate tmpbuf on
+	heap for large requests.
+
+2013-10-10  Joseph Myers  <joseph@codsourcery.com>
+
 	* sysdeps/ieee754/ldbl-128ibm/e_acosl.c (__ieee754_acosl): Check
 	for NaNs before doing comparisons on argument.
 	* sysdeps/ieee754/ldbl-128ibm/e_asinl.c (__ieee754_asinl):
@@ -877,11 +882,6 @@
 
 	* sysdeps/unix/sysv/linux/tst-fanotify.c: New test.
 	* sysdeps/unix/sysv/linux/Makefile (tests): Add tst-fanotify.
-=======
-	[BZ #16072]
-	* sysdeps/posix/getaddrinfo.c (gethosts): Allocate tmpbuf on
-	heap for large requests.
->>>>>>> 6f95434... Fix stack overflow due to large AF_INET6 requests
 
 2013-09-02  Joseph Myers  <joseph@codesourcery.com>
 

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=fcb59062b1e2dcd9952dbf508c3fee7efcc329be

commit fcb59062b1e2dcd9952dbf508c3fee7efcc329be
Author: Adhemerval Zanella <azanella@linux.vnet.ibm.com>
Date:   Wed Feb 5 15:28:57 2014 -0600

    Add GLIBC_2.3 to libm in Versions.def
    
    This patch adds GLIBC_2.3 mark on libm so it is always
    define in abi-versions.h. This fixes a build issue with
    fe_nomask.c in PPC64 LE where GLIBC_2_3 are no defined
    for SHLIB_COMPAT, resulting in a wrong evaluation in the macro.

diff --git a/ChangeLog b/ChangeLog
index b190338..9a0f195 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,9 @@
 2014-02-04  Adhemerval Zanella  <azanella@linux.vnet.ibm.com>
 
+	* Versions.def (libm): Add GLIBC_2.3.
+
+2014-02-04  Adhemerval Zanella  <azanella@linux.vnet.ibm.com>
+
 	* nptl/shlib-versions: Change powerpc*le start to 2.17.
 	* shlib-versions: Likewise.
 
diff --git a/Versions.def b/Versions.def
index 0854e6e..d8ef91b 100644
--- a/Versions.def
+++ b/Versions.def
@@ -55,6 +55,7 @@ libm {
   GLIBC_2.1
   GLIBC_2.2
   GLIBC_2.2.3
+  GLIBC_2.3
   GLIBC_2.3.4
   GLIBC_2.4
   GLIBC_2.15

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=96c5bbf7030c2b5e483485f8301f4b367e89db67

commit 96c5bbf7030c2b5e483485f8301f4b367e89db67
Author: Adhemerval Zanella <azanella@linux.vnet.ibm.com>
Date:   Tue Feb 4 10:18:26 2014 -0600

    PowerPC: powerpc64le abilist for 2.17
    
    This patch is the abifiles for powerpc64le based on GLIBC 2.17.

diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/ld-le.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/ld-le.abilist
index 0f745f2..3530fb4 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/ld-le.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/ld-le.abilist
@@ -1,5 +1,5 @@
-GLIBC_2.18
- GLIBC_2.18 A
+GLIBC_2.17
+ GLIBC_2.17 A
  __libc_memalign F
  __libc_stack_end D 0x8
  __tls_get_addr F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libBrokenLocale-le.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libBrokenLocale-le.abilist
index 0ca5b6f..92c43d9 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libBrokenLocale-le.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libBrokenLocale-le.abilist
@@ -1,3 +1,3 @@
-GLIBC_2.18
- GLIBC_2.18 A
+GLIBC_2.17
+ GLIBC_2.17 A
  __ctype_get_mb_cur_max F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libanl-le.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libanl-le.abilist
index c25a1ab..0d32f2e 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libanl-le.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libanl-le.abilist
@@ -1,5 +1,5 @@
-GLIBC_2.18
- GLIBC_2.18 A
+GLIBC_2.17
+ GLIBC_2.17 A
  gai_cancel F
  gai_error F
  gai_suspend F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libc-le.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libc-le.abilist
index 691c8c0..20eac4e 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libc-le.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libc-le.abilist
@@ -1,5 +1,5 @@
-GLIBC_2.18
- GLIBC_2.18 A
+GLIBC_2.17
+ GLIBC_2.17 A
  _Exit F
  _IO_2_1_stderr_ D 0xe0
  _IO_2_1_stdin_ D 0xe0
@@ -161,7 +161,6 @@ GLIBC_2.18
  __cxa_at_quick_exit F
  __cxa_atexit F
  __cxa_finalize F
- __cxa_thread_atexit_impl F
  __cyg_profile_func_enter F
  __cyg_profile_func_exit F
  __daylight D 0x4
@@ -2167,3 +2166,6 @@ GLIBC_2.18
  xencrypt F
  xprt_register F
  xprt_unregister F
+GLIBC_2.18
+ GLIBC_2.18 A
+ __cxa_thread_atexit_impl F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libcrypt-le.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libcrypt-le.abilist
index 0ac28c5..177c536 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libcrypt-le.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libcrypt-le.abilist
@@ -1,5 +1,5 @@
-GLIBC_2.18
- GLIBC_2.18 A
+GLIBC_2.17
+ GLIBC_2.17 A
  crypt F
  crypt_r F
  encrypt F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libdl-le.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libdl-le.abilist
index aa89245..6caff88 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libdl-le.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libdl-le.abilist
@@ -1,5 +1,5 @@
-GLIBC_2.18
- GLIBC_2.18 A
+GLIBC_2.17
+ GLIBC_2.17 A
  dladdr F
  dladdr1 F
  dlclose F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libm-le.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libm-le.abilist
index 9bb4cbf..a820074 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libm-le.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libm-le.abilist
@@ -1,5 +1,5 @@
-GLIBC_2.18
- GLIBC_2.18 A
+GLIBC_2.17
+ GLIBC_2.17 A
  _LIB_VERSION D 0x4
  __acos_finite F
  __acosf_finite F
@@ -50,9 +50,6 @@ GLIBC_2.18
  __hypot_finite F
  __hypotf_finite F
  __hypotl_finite F
- __issignaling F
- __issignalingf F
- __issignalingl F
  __j0_finite F
  __j0f_finite F
  __j0l_finite F
@@ -403,3 +400,8 @@ GLIBC_2.18
  yn F
  ynf F
  ynl F
+GLIBC_2.18
+ GLIBC_2.18 A
+ __issignaling F
+ __issignalingf F
+ __issignalingl F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libnsl-le.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libnsl-le.abilist
index a476875..763b8dc 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libnsl-le.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libnsl-le.abilist
@@ -1,5 +1,5 @@
-GLIBC_2.18
- GLIBC_2.18 A
+GLIBC_2.17
+ GLIBC_2.17 A
  __free_fdresult F
  __nis_default_access F
  __nis_default_group F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libpthread-le.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libpthread-le.abilist
index f25407d..5520312 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libpthread-le.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libpthread-le.abilist
@@ -1,5 +1,5 @@
-GLIBC_2.18
- GLIBC_2.18 A
+GLIBC_2.17
+ GLIBC_2.17 A
  _IO_flockfile F
  _IO_ftrylockfile F
  _IO_funlockfile F
@@ -120,7 +120,6 @@ GLIBC_2.18
  pthread_equal F
  pthread_exit F
  pthread_getaffinity_np F
- pthread_getattr_default_np F
  pthread_getattr_np F
  pthread_getconcurrency F
  pthread_getcpuclockid F
@@ -176,7 +175,6 @@ GLIBC_2.18
  pthread_rwlockattr_setpshared F
  pthread_self F
  pthread_setaffinity_np F
- pthread_setattr_default_np F
  pthread_setcancelstate F
  pthread_setcanceltype F
  pthread_setconcurrency F
@@ -224,3 +222,7 @@ GLIBC_2.18
  wait F
  waitpid F
  write F
+GLIBC_2.18
+ GLIBC_2.18 A
+ pthread_getattr_default_np F
+ pthread_setattr_default_np F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libresolv-le.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libresolv-le.abilist
index 4dd7cd0..ed312c0 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libresolv-le.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libresolv-le.abilist
@@ -1,5 +1,5 @@
-GLIBC_2.18
- GLIBC_2.18 A
+GLIBC_2.17
+ GLIBC_2.17 A
  __b64_ntop F
  __b64_pton F
  __dn_comp F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/librt-le.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/librt-le.abilist
index 211e046..f89f83e 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/librt-le.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/librt-le.abilist
@@ -1,5 +1,5 @@
-GLIBC_2.18
- GLIBC_2.18 A
+GLIBC_2.17
+ GLIBC_2.17 A
  __mq_open_2 F
  aio_cancel F
  aio_cancel64 F
@@ -16,11 +16,6 @@ GLIBC_2.18
  aio_suspend64 F
  aio_write F
  aio_write64 F
- clock_getcpuclockid F
- clock_getres F
- clock_gettime F
- clock_nanosleep F
- clock_settime F
  lio_listio F
  lio_listio64 F
  mq_close F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libthread_db-le.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libthread_db-le.abilist
index 61d736a..52f8d07 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libthread_db-le.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libthread_db-le.abilist
@@ -1,5 +1,5 @@
-GLIBC_2.18
- GLIBC_2.18 A
+GLIBC_2.17
+ GLIBC_2.17 A
  td_init F
  td_log F
  td_symbol_list F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libutil-le.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libutil-le.abilist
index 5563672..7e75bb2 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libutil-le.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libutil-le.abilist
@@ -1,5 +1,5 @@
-GLIBC_2.18
- GLIBC_2.18 A
+GLIBC_2.17
+ GLIBC_2.17 A
  forkpty F
  login F
  login_tty F

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=fe14043608be64ddf458b8fa49819b22406a5f5c

commit fe14043608be64ddf458b8fa49819b22406a5f5c
Author: Adhemerval Zanella <azanella@linux.vnet.ibm.com>
Date:   Tue Feb 4 10:07:36 2014 -0600

    PowerPC: Change powerpc64le start ABI to 2.17.
    
    Backport of 0ff8246327401ae8779e2697d5c7348611cdbf8a.

diff --git a/ChangeLog b/ChangeLog
index 0575323..b190338 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2014-02-04  Adhemerval Zanella  <azanella@linux.vnet.ibm.com>
+
+	* nptl/shlib-versions: Change powerpc*le start to 2.17.
+	* shlib-versions: Likewise.
+
 2014-02-04  Roland McGrath  <roland@hack.frob.com>
 	    Adhemerval Zanella  <azanella@linux.vnet.ibm.com>
 
diff --git a/nptl/shlib-versions b/nptl/shlib-versions
index 495b240..f6b9b9a 100644
--- a/nptl/shlib-versions
+++ b/nptl/shlib-versions
@@ -2,5 +2,5 @@ sparc64.*-.*-linux.*	libpthread=0		GLIBC_2.2
 sh.*-.*-linux.*		libpthread=0		GLIBC_2.2
 s390x-.*-linux.*	libpthread=0		GLIBC_2.2
 powerpc64-.*-linux.*	libpthread=0		GLIBC_2.3
-powerpc.*le-.*-linux.*	libpthread=0		GLIBC_2.18
+powerpc.*le-.*-linux.*	libpthread=0		GLIBC_2.17
 .*-.*-linux.*		libpthread=0
diff --git a/shlib-versions b/shlib-versions
index 51f5327..78b0ad7 100644
--- a/shlib-versions
+++ b/shlib-versions
@@ -23,7 +23,7 @@
 
 s390x-.*-linux.*        DEFAULT			GLIBC_2.2
 powerpc64-.*-linux.*	DEFAULT			GLIBC_2.3
-powerpc.*le-.*-linux.*	DEFAULT			GLIBC_2.18
+powerpc.*le-.*-linux.*	DEFAULT			GLIBC_2.17
 .*-.*-gnu-gnu.*		DEFAULT			GLIBC_2.2.6
 
 # Configuration		ABI			Identifier for ABI data files

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=ceca4209347d0639a7ed726822a21c33891ca15b

commit ceca4209347d0639a7ed726822a21c33891ca15b
Author: Adhemerval Zanella <azanella@linux.vnet.ibm.com>
Date:   Tue Feb 4 10:06:41 2014 -0600

    abilist-pattern configurability
    
    This patch creates implicit rules to match the abifiles if
    abilist-pattern is defined in the architecture Makefile. This allows
    machine specific Makefiles to define different abifiles names
    (for instance *-le.abilist for powerpc64le).

diff --git a/ChangeLog b/ChangeLog
index ac1a76a..0575323 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+2014-02-04  Roland McGrath  <roland@hack.frob.com>
+	    Adhemerval Zanella  <azanella@linux.vnet.ibm.com>
+
+	* sysdeps/powerpc/Makefile [$(config-machine) ends with 'le']
+	(abilist-pattern): New variable, set to %-le.abilist.
+
+	* Makerules (abilist-pattern): New variable.
+	(vpath): Use $(abilist-pattern) in place of %.abilist.
+	(check-abi-% pattern rule): Likewise.
+	(check-abi, update-abi): Likewise.
+
 2014-01-23  Adhemerval Zanella  <azanella@linux.vnet.ibm.com>
 
 	[BZ#16431]
diff --git a/Makerules b/Makerules
index 7d0bc1b..bd8642a 100644
--- a/Makerules
+++ b/Makerules
@@ -1144,11 +1144,15 @@ ifeq ($(versioning),yes)
 	LC_ALL=C $(OBJDUMP) --dynamic-syms $< > $@T
 	mv -f $@T $@
 
-ifndef abilist
-abilist=.abilist
+# A sysdeps/.../Makefile can set abilist-pattern to something like
+# %-foo.abilist to look for libc-foo.abilist instead of libc.abilist.
+# This makes sense if multiple ABIs can be most cleanly supported by a
+# configuration without using separate sysdeps directories for each.
+ifdef abilist-pattern
+vpath $(abilist-pattern) $(+sysdep_dirs)
 endif
 
-vpath %$(abilist) $(+sysdep_dirs)
+vpath %.abilist $(+sysdep_dirs)
 
 # The .PRECIOUS rule prevents the files built by an implicit rule whose
 # target pattern is %.symlist from being considered "intermediate files"
@@ -1157,24 +1161,48 @@ vpath %$(abilist) $(+sysdep_dirs)
 .PRECIOUS: %.symlist
 generated += $(extra-libs:=.symlist)
 
-check-abi-%: $(common-objpfx)config.make %$(abilist) $(objpfx)%.symlist
+ifdef abilist-pattern
+check-abi-%: $(common-objpfx)config.make $(abilist-pattern) $(objpfx)%.symlist
+	$(check-abi-pattern)
+check-abi-%: $(common-objpfx)config.make $(abilist-pattern) \
+	     $(common-objpfx)%.symlist
+	$(check-abi-pattern)
+endif
+check-abi-%: $(common-objpfx)config.make %.abilist $(objpfx)%.symlist
 	$(check-abi)
-check-abi-%: $(common-objpfx)config.make %$(abilist) $(common-objpfx)%.symlist
+check-abi-%: $(common-objpfx)config.make %.abilist $(common-objpfx)%.symlist
 	$(check-abi)
+define check-abi-pattern
+	diff -p -U 0 $(filter $(abilist-pattern),$^) $(filter %.symlist,$^)
+endef
 define check-abi
-	diff -p -U 0 $(filter %$(abilist),$^) $(filter %.symlist,$^)
+	diff -p -U 0 $(filter %.abilist,$^) $(filter %.symlist,$^)
 endef
 
-update-abi-%: $(objpfx)%.symlist %$(abilist)
+ifdef abilist-pattern
+update-abi-%: $(objpfx)%.symlist $(abilist-pattern)
+	$(update-abi-pattern)
+update-abi-%: $(common-objpfx)%.symlist $(abilist-pattern)
+	$(update-abi-pattern)
+endif
+update-abi-%: $(objpfx)%.symlist %.abilist
 	$(update-abi)
-update-abi-%: $(common-objpfx)%.symlist %$(abilist)
+update-abi-%: $(common-objpfx)%.symlist %.abilist
 	$(update-abi)
+define update-abi-pattern
+@if cmp -s $^ 2> /dev/null; \
+ then \
+      echo '+++ $(filter $(abilist-pattern),$^) is unchanged'; \
+ else cp -f $^; \
+      echo '*** Now check $(filter $(abilist-pattern),$^) changes for correctness ***'; \
+ fi
+endef
 define update-abi
 @if cmp -s $^ 2> /dev/null; \
  then \
-      echo '+++ $(filter %$(abilist),$^) is unchanged'; \
+      echo '+++ $(filter %.abilist,$^) is unchanged'; \
  else cp -f $^; \
-      echo '*** Now check $(filter %$(abilist),$^) changes for correctness ***'; \
+      echo '*** Now check $(filter %.abilist,$^) changes for correctness ***'; \
  fi
 endef
 
diff --git a/sysdeps/powerpc/Makefile b/sysdeps/powerpc/Makefile
index f75e625..b11edd7 100644
--- a/sysdeps/powerpc/Makefile
+++ b/sysdeps/powerpc/Makefile
@@ -27,3 +27,7 @@ ifeq ($(subdir),misc)
 sysdep_headers += sys/platform/ppc.h
 tests += test-gettimebase
 endif
+
+ifneq (,$(filter %le,$(config-machine)))
+abilist-pattern = %-le.abilist
+endif

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=01d6218aead2f93e81223097ad134a2999d84e2c

commit 01d6218aead2f93e81223097ad134a2999d84e2c
Author: Adhemerval Zanella <azanella@linux.vnet.ibm.com>
Date:   Thu Jan 23 11:07:47 2014 -0600

    PowerPC: Fix gettimeofday ifunc selection
    
    The IFUNC selector for gettimeofday runs before _libc_vdso_platform_setup where
    __vdso_gettimeofday is set. The selector then sets __gettimeofday (the internal
    version used within GLIBC) to use the system call version instead of the vDSO one.
    This patch changes the check if vDSO is available to get its value directly
    instead of rely on __vdso_gettimeofday.
    
    This patch changes it by getting the vDSO value directly.
    
    It fixes BZ#16431.

diff --git a/ChangeLog b/ChangeLog
index 47607ed..ac1a76a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,12 @@
 2014-01-23  Adhemerval Zanella  <azanella@linux.vnet.ibm.com>
 
+	[BZ#16431]
+	* sysdeps/unix/sysv/linux/powerpc/gettimeofday.c (__gettimeofday):
+	Adjust the vDSO correctly for internal calls.
+	* sysdeps/unix/sysv/linux/powerpc/time.c (time): Likewise.
+
+2014-01-23  Adhemerval Zanella  <azanella@linux.vnet.ibm.com>
+
 	[BZ #16414]
 	* sysdeps/powerpc/powerpc64/fpu/s_truncl.S: Remove wrong
 	implementation.
diff --git a/NEWS b/NEWS
index 4190e85..5c2f07a 100644
--- a/NEWS
+++ b/NEWS
@@ -11,7 +11,7 @@ Version 2.18.1
 
   14143, 14155, 14547, 14699, 15532, 15427, 15522, 15680, 15723, 15734,
   15735, 15797, 15892, 15895, 15909, 15917, 15996, 16072, 16150, 16414,
-  16430.
+  16430, 16431.
 
 * Support for powerpc64le has been added.
 
diff --git a/sysdeps/unix/sysv/linux/powerpc/gettimeofday.c b/sysdeps/unix/sysv/linux/powerpc/gettimeofday.c
index 3ee063d..0313874 100644
--- a/sysdeps/unix/sysv/linux/powerpc/gettimeofday.c
+++ b/sysdeps/unix/sysv/linux/powerpc/gettimeofday.c
@@ -35,9 +35,12 @@ __gettimeofday_syscall (struct timeval *tv, struct timezone *tz)
 void *
 gettimeofday_ifunc (void)
 {
+  PREPARE_VERSION (linux2615, "LINUX_2.6.15", 123718565);
+
   /* If the vDSO is not available we fall back syscall.  */
-  return (__vdso_gettimeofday ? VDSO_IFUNC_RET (__vdso_gettimeofday)
-	  : __gettimeofday_syscall);
+  void *vdso_gettimeofday = _dl_vdso_vsym ("__kernel_gettimeofday", &linux2615);
+  return (vdso_gettimeofday ? VDSO_IFUNC_RET (vdso_gettimeofday)
+	  : (void*)__gettimeofday_syscall);
 }
 asm (".type __gettimeofday, %gnu_indirect_function");
 
diff --git a/sysdeps/unix/sysv/linux/powerpc/time.c b/sysdeps/unix/sysv/linux/powerpc/time.c
index 85cc20e..cd40a29 100644
--- a/sysdeps/unix/sysv/linux/powerpc/time.c
+++ b/sysdeps/unix/sysv/linux/powerpc/time.c
@@ -45,9 +45,12 @@ time_syscall (time_t *t)
 void *
 time_ifunc (void)
 {
+  PREPARE_VERSION (linux2615, "LINUX_2.6.15", 123718565);
+
   /* If the vDSO is not available we fall back to the syscall.  */
-  return (__vdso_time ? VDSO_IFUNC_RET (__vdso_time)
-	  : time_syscall);
+  void *vdso_time = _dl_vdso_vsym ("__kernel_time", &linux2615);
+  return (vdso_time ? VDSO_IFUNC_RET (vdso_time)
+	  : (void*)time_syscall);
 }
 asm (".type time, %gnu_indirect_function");
 

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=a21742a515c18de4b46070b5eff5eedf43f9c7c5

commit a21742a515c18de4b46070b5eff5eedf43f9c7c5
Author: Adhemerval Zanella <azanella@linux.vnet.ibm.com>
Date:   Thu Jan 23 11:06:58 2014 -0600

    PowerPC: remove wrong truncl implementation for PowerPC64
    
    The truncl assembly implementation (sysdeps/powerpc/powerpc64/fpu/s_truncl.S)
    returns wrong results for some inputs where first double is a exact integer
    and the precision is determined by second long double.
    
    Checking on implementation comments and history, I am very confident the
    assembly implementation was based on a version before commit
    5c68d401698a58cf7da150d9cce769fa6679ba5f that fixes BZ#2423 (Errors in
    long double (ldbl-128ibm) rounding functions in glibc-2.4).
    
    By just removing the implementation and make the build select
    sysdeps/ieee754/ldbl-128ibm/s_truncl.c instead it fixes tgammal
    issues regarding wrong result sign.

diff --git a/ChangeLog b/ChangeLog
index d839367..47607ed 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,12 @@
 2014-01-23  Adhemerval Zanella  <azanella@linux.vnet.ibm.com>
 
+	[BZ #16414]
+	* sysdeps/powerpc/powerpc64/fpu/s_truncl.S: Remove wrong
+	implementation.
+	* sysdeps/ieee754/ldbl-128ibm/s_truncl.c: Remove bogus comment.
+
+2014-01-23  Adhemerval Zanella  <azanella@linux.vnet.ibm.com>
+
 	[BZ #14143]
 	* sysdeps/powerpc/bits/fenv.h (__fe_nomask_env): Remove declaration.
 	(__fe_mask_env): Likewise.
diff --git a/NEWS b/NEWS
index 28b7755..4190e85 100644
--- a/NEWS
+++ b/NEWS
@@ -10,7 +10,8 @@ Version 2.18.1
 * The following bugs are resolved with this release:
 
   14143, 14155, 14547, 14699, 15532, 15427, 15522, 15680, 15723, 15734,
-  15735, 15797, 15892, 15895, 15909, 15917, 15996, 16072, 16150, 16430.
+  15735, 15797, 15892, 15895, 15909, 15917, 15996, 16072, 16150, 16414,
+  16430.
 
 * Support for powerpc64le has been added.
 
diff --git a/sysdeps/ieee754/ldbl-128ibm/s_truncl.c b/sysdeps/ieee754/ldbl-128ibm/s_truncl.c
index 2765b63..02bfc49 100644
--- a/sysdeps/ieee754/ldbl-128ibm/s_truncl.c
+++ b/sysdeps/ieee754/ldbl-128ibm/s_truncl.c
@@ -17,9 +17,6 @@
    License along with the GNU C Library; if not, see
    <http://www.gnu.org/licenses/>.  */
 
-/* This has been coded in assembler because GCC makes such a mess of it
-   when it's coded in C.  */
-
 #include <math.h>
 #include <math_ldbl_opt.h>
 #include <float.h>
diff --git a/sysdeps/powerpc/powerpc64/fpu/s_truncl.S b/sysdeps/powerpc/powerpc64/fpu/s_truncl.S
deleted file mode 100644
index 06fd7db..0000000
--- a/sysdeps/powerpc/powerpc64/fpu/s_truncl.S
+++ /dev/null
@@ -1,120 +0,0 @@
-/* long double trunc function.
-   IBM extended format long double version.
-   Copyright (C) 2004-2013 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/>.  */
-
-#include <sysdep.h>
-#include <math_ldbl_opt.h>
-
-	.section	".toc","aw"
-.LC0:	/* 2**52 */
-	.tc FD_43300000_0[TC],0x4330000000000000
-.LC1:	/* 0.5 */
-	.tc FD_3fe00000_0[TC],0x3fe0000000000000
-	.section	".text"
-
-/* long double [fp1,fp2] truncl (long double x [fp1,fp2])  */
-
-ENTRY (__truncl)
-	mffs	fp11		/* Save current FPU rounding mode.  */
-	lfd	fp13,.LC0@toc(2)
-	fabs	fp0,fp1
-	fabs	fp9,fp2
-	fsub	fp12,fp13,fp13	/* generate 0.0  */
-	fcmpu	cr7,fp0,fp13	/* if (fabs(x) > TWO52)  */
-	fcmpu	cr6,fp1,fp12	/* if (x > 0.0)  */
-	bnl-	cr7,.L2
-	mtfsfi	7,1		/* Set rounding mode toward 0.  */
-	ble-	cr6,.L1
-	fneg	fp2,fp12
-	fadd	fp1,fp1,fp13	/* x+= TWO52;  */
-	fsub	fp1,fp1,fp13	/* x-= TWO52;  */
-	fabs	fp1,fp1		/* if (x == 0.0) x = 0.0;  */
-.L0:
-	mtfsf	0x01,fp11	/* restore previous rounding mode.  */
-	blr
-.L1:
-	fneg	fp2,fp12
-	bge-	cr6,.L0		/* if (x < 0.0)  */
-	fsub	fp1,fp1,fp13	/* x-= TWO52;  */
-	fadd	fp1,fp1,fp13	/* x+= TWO52;  */
-	fnabs	fp1,fp1		/* if (x == 0.0) x = -0.0;  */
-	mtfsf	0x01,fp11	/* restore previous rounding mode.  */
-	blr
-
-/* The high double is > TWO52 so we need to round the low double and
-   perhaps the high double.  In this case we have to round the low
-   double and handle any adjustment to the high double that may be
-   caused by rounding (up).  This is complicated by the fact that the
-   high double may already be rounded and the low double may have the
-   opposite sign to compensate.This gets a bit tricky so we use the
-   following algorithm:
-
-   tau = floor(x_high/TWO52);
-   x0 = x_high - tau;
-   x1 = x_low + tau;
-   r1 = rint(x1);
-   y_high = x0 + r1;
-   y_low = x0 - y_high + r1;
-   return y;  */
-.L2:
-	fcmpu	cr7,fp9,fp13	/* if (|x_low| > TWO52)  */
-	fcmpu	cr0,fp9,fp12	/* || (|x_low| == 0.0)  */
-	fcmpu	cr5,fp2,fp12	/* if (x_low > 0.0)  */
-	bgelr-	cr7		/*   return x;	*/
-	beqlr-  cr0
-	mtfsfi	7,1		/* Set rounding mode toward 0.  */
-	fdiv	fp8,fp1,fp13	/* x_high/TWO52  */
-
-	bng-	cr6,.L6		/* if (x > 0.0)  */
-	fctidz	fp0,fp8
-	fcfid	fp8,fp0		/* tau = floor(x_high/TWO52);  */
-	fadd	fp8,fp8,fp8	/* tau++; Make tau even  */
-	bng	cr5,.L4		/* if (x_low > 0.0)  */
-	fmr	fp3,fp1
-	fmr	fp4,fp2
-	b	.L5
-.L4:				/* if (x_low < 0.0)  */
-	fsub	fp3,fp1,fp8	/* x0 = x_high - tau;  */
-	fadd	fp4,fp2,fp8	/* x1 = x_low + tau;  */
-.L5:
-	fadd	fp5,fp4,fp13	/* r1 = r1 + TWO52;  */
-	fsub	fp5,fp5,fp13	/* r1 = r1 - TWO52;  */
-	b	.L9
-.L6:				/* if (x < 0.0)  */
-	fctidz	fp0,fp8
-	fcfid	fp8,fp0		/* tau = floor(x_high/TWO52);  */
-	fadd	fp8,fp8,fp8	/* tau++; Make tau even  */
-	bnl	cr5,.L7		/* if (x_low < 0.0)  */
-	fmr	fp3,fp1
-	fmr	fp4,fp2
-	b	.L8
-.L7:				/* if (x_low > 0.0)  */
-	fsub	fp3,fp1,fp8	/* x0 = x_high - tau;  */
-	fadd	fp4,fp2,fp8	/* x1 = x_low + tau;  */
-.L8:
-	fsub	fp5,fp4,fp13	/* r1-= TWO52;  */
-	fadd	fp5,fp5,fp13	/* r1+= TWO52;  */
-.L9:
-	mtfsf	0x01,fp11	/* restore previous rounding mode.  */
-	fadd	fp1,fp3,fp5	/* y_high = x0 + r1;  */
-	fsub	fp2,fp3,fp1	/* y_low = x0 - y_high + r1;  */
-	fadd	fp2,fp2,fp5
-	blr
-END (__truncl)
-
-long_double_symbol (libm, __truncl, truncl)

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=4af3a9fb312d9fbbc5050f4a8cf70c70a86a050f

commit 4af3a9fb312d9fbbc5050f4a8cf70c70a86a050f
Author: Adhemerval Zanella <azanella@linux.vnet.ibm.com>
Date:   Thu Jan 23 11:04:51 2014 -0600

    PowerPC: Fix __fe_mask_env export
    
    This patch does not export __fe_mask_env anymore, only providing a
    compatibility symbol. It fixes BZ#14143.

diff --git a/ChangeLog b/ChangeLog
index 0992488..d839367 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,18 @@
+2014-01-23  Adhemerval Zanella  <azanella@linux.vnet.ibm.com>
+
+	[BZ #14143]
+	* sysdeps/powerpc/bits/fenv.h (__fe_nomask_env): Remove declaration.
+	(__fe_mask_env): Likewise.
+	* sysdeps/powerpc/fpu/fenv_libc.h (__fe_nomask_env): Remove
+	libm_hidden_proto and add function prototype.
+	(__fe_mask_env): Add function prototype.
+	* sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/fe_nomask.c
+	(__fe_nomask_env): Add compat symbol for GLIBC_2.1.
+	* sysdeps/unix/sysv/linux/powerpc/powerpc64/fpu/fe_mask.c
+	(__fe_mask_env): Remove compiler warnings regarding ununsed variables.
+	* sysdeps/unix/sysv/linux/powerpc/powerpc64/fpu/fe_nomask.c
+	(__fe_nomask_env): Add compat symbol for GLIBC_2.3.
+
 2014-01-16  Adhemerval Zanella  <azanella@linux.vnet.ibm.com>
 
 	[BZ#16430]
diff --git a/NEWS b/NEWS
index db471a4..28b7755 100644
--- a/NEWS
+++ b/NEWS
@@ -9,8 +9,8 @@ Version 2.18.1
 
 * The following bugs are resolved with this release:
 
-  14155, 14547, 14699, 15532, 15427, 15522, 15680, 15723, 15734, 15735,
-  15797, 15892, 15895, 15909, 15917, 15996, 16072, 16150, 16430.
+  14143, 14155, 14547, 14699, 15532, 15427, 15522, 15680, 15723, 15734,
+  15735, 15797, 15892, 15895, 15909, 15917, 15996, 16072, 16150, 16430.
 
 * Support for powerpc64le has been added.
 
diff --git a/sysdeps/powerpc/bits/fenv.h b/sysdeps/powerpc/bits/fenv.h
index 122edd3..86bf94e 100644
--- a/sysdeps/powerpc/bits/fenv.h
+++ b/sysdeps/powerpc/bits/fenv.h
@@ -153,15 +153,12 @@ extern const fenv_t __fe_enabled_env;
 extern const fenv_t __fe_nonieee_env;
 # define FE_NONIEEE_ENV	(&__fe_nonieee_env)
 
-__BEGIN_DECLS
-
 /* Floating-point environment with all exceptions enabled.  Note that
    just evaluating this value does not change the processor exception mode.
    Passing this mask to fesetenv will result in a prctl syscall to change
    the MSR FE0/FE1 bits to "Precise Mode".  On some processors this will
    result in slower floating point execution.  This will last until an
    fenv or exception mask is installed that disables all FP exceptions.  */
-extern const fenv_t *__fe_nomask_env (void);
 # define FE_NOMASK_ENV	FE_ENABLED_ENV
 
 /* Floating-point environment with all exceptions disabled.  Note that
@@ -169,9 +166,6 @@ extern const fenv_t *__fe_nomask_env (void);
    Passing this mask to fesetenv will result in a prctl syscall to change
    the MSR FE0/FE1 bits to "Ignore Exceptions Mode".  On most processors
    this allows the fastest possible floating point execution.*/
-extern const fenv_t *__fe_mask_env (void);
 # define FE_MASK_ENV	FE_DFL_ENV
 
-__END_DECLS
-
 #endif
diff --git a/sysdeps/powerpc/fpu/fenv_libc.h b/sysdeps/powerpc/fpu/fenv_libc.h
index baa2a7d..cb15c1c 100644
--- a/sysdeps/powerpc/fpu/fenv_libc.h
+++ b/sysdeps/powerpc/fpu/fenv_libc.h
@@ -23,7 +23,9 @@
 #include <ldsodefs.h>
 #include <sysdep.h>
 
-libm_hidden_proto (__fe_nomask_env)
+extern const fenv_t *__fe_nomask_env (void);
+
+extern const fenv_t *__fe_mask_env (void);
 
 /* The sticky bits in the FPSCR indicating exceptions have occurred.  */
 #define FPSCR_STICKY_BITS ((FE_ALL_EXCEPT | FE_ALL_INVALID) & ~FE_INVALID)
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/fe_nomask.c b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/fe_nomask.c
index 94db79f..dd3ec46 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/fe_nomask.c
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/fe_nomask.c
@@ -23,6 +23,7 @@
 #include <sysdep.h>
 #include <sys/prctl.h>
 #include <kernel-features.h>
+#include <shlib-compat.h>
 
 const fenv_t *
 __fe_nomask_env (void)
@@ -32,4 +33,6 @@ __fe_nomask_env (void)
 
   return FE_ENABLED_ENV;
 }
-libm_hidden_def (__fe_nomask_env)
+#if SHLIB_COMPAT (libm, GLIBC_2_1, GLIBC_2_18)
+compat_symbol (libm, __fe_nomask_env, __fe_nomask_env, GLIBC_2_1);
+#endif
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/fpu/fe_mask.c b/sysdeps/unix/sysv/linux/powerpc/powerpc64/fpu/fe_mask.c
index 2ab5855..1d579bf 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/fpu/fe_mask.c
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/fpu/fe_mask.c
@@ -27,9 +27,8 @@ const fenv_t *
 __fe_mask_env (void)
 {
 #if defined PR_SET_FPEXC && defined PR_FP_EXC_DISABLED
-  int result;
   INTERNAL_SYSCALL_DECL (err);
-  result = INTERNAL_SYSCALL (prctl, err, 2, PR_SET_FPEXC, PR_FP_EXC_DISABLED);
+  INTERNAL_SYSCALL (prctl, err, 2, PR_SET_FPEXC, PR_FP_EXC_DISABLED);
 #else
   __set_errno (ENOSYS);
 #endif
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/fpu/fe_nomask.c b/sysdeps/unix/sysv/linux/powerpc/powerpc64/fpu/fe_nomask.c
index fd2ffb1..5172f65 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/fpu/fe_nomask.c
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/fpu/fe_nomask.c
@@ -22,17 +22,19 @@
 #include <sys/syscall.h>
 #include <sys/prctl.h>
 #include <kernel-features.h>
+#include <shlib-compat.h>
 
 const fenv_t *
 __fe_nomask_env (void)
 {
 #if defined PR_SET_FPEXC && defined PR_FP_EXC_PRECISE
-  int result;
   INTERNAL_SYSCALL_DECL (err);
-  result = INTERNAL_SYSCALL (prctl, err, 2, PR_SET_FPEXC, PR_FP_EXC_PRECISE);
+  INTERNAL_SYSCALL (prctl, err, 2, PR_SET_FPEXC, PR_FP_EXC_PRECISE);
 #else
   __set_errno (ENOSYS);
 #endif
   return FE_ENABLED_ENV;
 }
-libm_hidden_def (__fe_nomask_env)
+#if SHLIB_COMPAT (libm, GLIBC_2_3, GLIBC_2_18)
+compat_symbol (libm, __fe_nomask_env, __fe_nomask_env, GLIBC_2_3);
+#endif

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=a1db67c6c7fafc3d2ebd391d64837d54a994e5b9

commit a1db67c6c7fafc3d2ebd391d64837d54a994e5b9
Author: Adhemerval Zanella <azanella@linux.vnet.ibm.com>
Date:   Thu Jan 16 13:01:55 2014 -0600

    PowerPC: Fix ftime gettimeofday internal call returning bogus data
    
    This patches fixes BZ#16430 by setting a different symbol for internal
    GLIBC calls that points to ifunc resolvers. For PPC32, if the symbol
    is defined as hidden (which is the case for gettimeofday and time) the
    compiler will create local branches (symbol@local) and linker will not
    create PLT calls (required for IFUNC). This will leads to internal symbol
    calling the IFUNC resolver instead of the resolved symbol.
    For PPC64 this behavior does not occur because a call to a function in
    another translation unit might use a different toc pointer thus requiring
    a PLT call.

diff --git a/ChangeLog b/ChangeLog
index 4e3a822..0992488 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+2014-01-16  Adhemerval Zanella  <azanella@linux.vnet.ibm.com>
+
+	[BZ#16430]
+	* sysdeps/unix/sysv/linux/powerpc/gettimeofday.c
+	(__GI___gettimeofday): Alias for a different internal symbol to avoid
+	local calls issues by not having a PLT stub required for IFUNC calls.
+	* sysdeps/unix/sysv/linux/powerpc/time.c (__GI_time): Likewise.
+
 2013-11-16  Alan Modra  <amodra@gmail.com>
 
 	* NEWS: Mention powerpc64le support and bugs fixed.
diff --git a/NEWS b/NEWS
index 2c6ad91..db471a4 100644
--- a/NEWS
+++ b/NEWS
@@ -10,7 +10,7 @@ Version 2.18.1
 * The following bugs are resolved with this release:
 
   14155, 14547, 14699, 15532, 15427, 15522, 15680, 15723, 15734, 15735,
-  15797, 15892, 15895, 15909, 15917, 15996, 16072, 16150.
+  15797, 15892, 15895, 15909, 15917, 15996, 16072, 16150, 16430.
 
 * Support for powerpc64le has been added.
 
diff --git a/sysdeps/unix/sysv/linux/powerpc/gettimeofday.c b/sysdeps/unix/sysv/linux/powerpc/gettimeofday.c
index 48c3f84..3ee063d 100644
--- a/sysdeps/unix/sysv/linux/powerpc/gettimeofday.c
+++ b/sysdeps/unix/sysv/linux/powerpc/gettimeofday.c
@@ -44,8 +44,24 @@ asm (".type __gettimeofday, %gnu_indirect_function");
 /* This is doing "libc_hidden_def (__gettimeofday)" but the compiler won't
    let us do it in C because it doesn't know we're defining __gettimeofday
    here in this file.  */
-asm (".globl __GI___gettimeofday\n"
-     "__GI___gettimeofday = __gettimeofday");
+asm (".globl __GI___gettimeofday");
+
+/* __GI___gettimeofday is defined as hidden and for ppc32 it enables the
+   compiler make a local call (symbol@local) for internal GLIBC usage. It
+   means the PLT won't be used and the ifunc resolver will be called directly.
+   For ppc64 a call to a function in another translation unit might use a
+   different toc pointer thus disallowing direct branchess and making internal
+   ifuncs calls safe.  */
+#ifdef __powerpc64__
+asm ("__GI___gettimeofday = __gettimeofday");
+#else
+int
+__gettimeofday_vsyscall (struct timeval *tv, struct timezone *tz)
+{
+  return INLINE_VSYSCALL (gettimeofday, 2, tv, tz);
+}
+asm ("__GI___gettimeofday = __gettimeofday_vsyscall");
+#endif
 
 #else
 
diff --git a/sysdeps/unix/sysv/linux/powerpc/time.c b/sysdeps/unix/sysv/linux/powerpc/time.c
index 2d77ece..85cc20e 100644
--- a/sysdeps/unix/sysv/linux/powerpc/time.c
+++ b/sysdeps/unix/sysv/linux/powerpc/time.c
@@ -54,8 +54,24 @@ asm (".type time, %gnu_indirect_function");
 /* This is doing "libc_hidden_def (time)" but the compiler won't
  * let us do it in C because it doesn't know we're defining time
  * here in this file.  */
-asm (".globl __GI_time\n"
-     "__GI_time = time");
+asm (".globl __GI_time");
+
+/* __GI_time is defined as hidden and for ppc32 it enables the
+   compiler make a local call (symbol@local) for internal GLIBC usage. It
+   means the PLT won't be used and the ifunc resolver will be called directly.
+   For ppc64 a call to a function in another translation unit might use a
+   different toc pointer thus disallowing direct branchess and making internal
+   ifuncs calls safe.  */
+#ifdef __powerpc64__
+asm ("__GI_time = time");
+#else
+time_t
+__time_vsyscall (time_t *t)
+{
+  return INLINE_VSYSCALL (time, 1, t);
+}
+asm ("__GI_time = __time_vsyscall");
+#endif
 
 #else
 

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=8209beac4644af4c2875f52f82c53c0d4be589ca

commit 8209beac4644af4c2875f52f82c53c0d4be589ca
Merge: 40e9bbd 38bf8b3
Author: Tulio Magno Quites Machado Filho <tuliom@linux.vnet.ibm.com>
Date:   Thu Nov 21 15:02:35 2013 -0200

    Merge the changes to add little endian support on PowerPC
    
    Discard all the previous changes from ibm/2.18/master in order to keep a
    clean branch.


http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=40e9bbdd3d2ea22c2455949959ced90e054f6023

commit 40e9bbdd3d2ea22c2455949959ced90e054f6023
Author: Alan Modra <amodra@gmail.com>
Date:   Sat Nov 16 10:18:28 2013 +1030

    Mention powerpc64le support in NEWS and README, plus bugs fixed.
    
    	* NEWS: Mention powerpc64le support and bugs fixed.
    	* README: Both big-endian and little-endian powerpc64 supported.

diff --git a/ChangeLog b/ChangeLog
index 07416ef..4e3a822 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,10 @@
 2013-11-16  Alan Modra  <amodra@gmail.com>
 
+	* NEWS: Mention powerpc64le support and bugs fixed.
+	* README: Both big-endian and little-endian powerpc64 supported.
+
+2013-11-16  Alan Modra  <amodra@gmail.com>
+
 	* libc-abis: PowerPC64le has ifunc too.
 
 2013-11-16  Alan Modra  <amodra@gmail.com>
diff --git a/NEWS b/NEWS
index a816bc1..2c6ad91 100644
--- a/NEWS
+++ b/NEWS
@@ -9,8 +9,10 @@ Version 2.18.1
 
 * The following bugs are resolved with this release:
 
-  14155, 14547, 14699, 15532, 15427, 15522, 15797, 15892, 15895, 15909,
-  15917, 15996, 16072, 16150.
+  14155, 14547, 14699, 15532, 15427, 15522, 15680, 15723, 15734, 15735,
+  15797, 15892, 15895, 15909, 15917, 15996, 16072, 16150.
+
+* Support for powerpc64le has been added.
 
 * CVE-2013-4237 The readdir_r function could write more than NAME_MAX bytes
   to the d_name member of struct dirent, or omit the terminating NUL
diff --git a/README b/README
index bb4ccb8..3052372 100644
--- a/README
+++ b/README
@@ -26,8 +26,8 @@ The GNU C Library supports these configurations for using Linux kernels:
 
 	i[4567]86-*-linux-gnu
 	x86_64-*-linux-gnu	Can build either x86_64 or x32
-	powerpc-*-linux-gnu	Hardware floating point required
-	powerpc64-*-linux-gnu
+	powerpc-*-linux-gnu	Hardware floating point required, BE only.
+	powerpc64-*-linux-gnu	Big-endian and little-endian.
 	s390-*-linux-gnu
 	s390x-*-linux-gnu
 	sh[34]-*-linux-gnu

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=74af96bf910f7e10289c72a397564dab19131b31

commit 74af96bf910f7e10289c72a397564dab19131b31
Author: Alan Modra <amodra@gmail.com>
Date:   Sat Nov 16 10:09:06 2013 +1030

    PowerPC64le has ifunc too.
    
    I believe this is really just a "documentation" fix.
    See https://sourceware.org/ml/binutils/2013-10/msg00059.html

diff --git a/ChangeLog b/ChangeLog
index 50a6b11..07416ef 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,9 @@
 2013-11-16  Alan Modra  <amodra@gmail.com>
 
+	* libc-abis: PowerPC64le has ifunc too.
+
+2013-11-16  Alan Modra  <amodra@gmail.com>
+
 	* sysdeps/unix/sysv/linux/powerpc/configure.in (arch_minimum_kernel):
 	Set for powerpc*le.
 	* sysdeps/unix/sysv/linux/powerpc/configure: Regenerate.
diff --git a/libc-abis b/libc-abis
index 8668e49..6e68c59 100644
--- a/libc-abis
+++ b/libc-abis
@@ -42,7 +42,6 @@ UNIQUE
 # Indirect PLT relocations.  Architecture dependent.
 IFUNC		x86_64-*-linux*
 IFUNC		i?86-*-linux*
-IFUNC		powerpc64-*-linux*
-IFUNC		powerpc-*-linux*
+IFUNC		powerpc*-*-linux*
 IFUNC		sparc64-*-linux*
 IFUNC		sparc-*-linux*

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=d5f593430c7748f64321ecac36162646420a6aaf

commit d5f593430c7748f64321ecac36162646420a6aaf
Author: Alan Modra <amodra@gmail.com>
Date:   Sat Oct 5 17:05:54 2013 +0930

    Set arch_minimum_kernel for powerpc*le.

diff --git a/ChangeLog b/ChangeLog
index b18cdaa..50a6b11 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,11 @@
 2013-11-16  Alan Modra  <amodra@gmail.com>
 
+	* sysdeps/unix/sysv/linux/powerpc/configure.in (arch_minimum_kernel):
+	Set for powerpc*le.
+	* sysdeps/unix/sysv/linux/powerpc/configure: Regenerate.
+
+2013-11-16  Alan Modra  <amodra@gmail.com>
+
 	[BZ #5268]
 	* include/gmp.h (__mpn_extract_double, __mpn_extract_long_double):
 	Update prototypes.
diff --git a/sysdeps/unix/sysv/linux/powerpc/configure b/sysdeps/unix/sysv/linux/powerpc/configure
index 7df7e48..a186ccd 100644
--- a/sysdeps/unix/sysv/linux/powerpc/configure
+++ b/sysdeps/unix/sysv/linux/powerpc/configure
@@ -75,3 +75,10 @@ $as_echo "$libc_cv_mabi_ibmlongdouble" >&6; }
     as_fn_error $? "this configuration requires -mlong-double-128 IBM extended format support" "$LINENO" 5
   fi
 fi
+
+case "$config_machine" in
+# FIXME: This should really be 3.12.
+# The lower version here matches common buildroot kernel headers used
+# by developers during LE bootstrap.  3.9 headers seem to work OK.
+  powerpc*le) arch_minimum_kernel=3.9 ;;
+esac
diff --git a/sysdeps/unix/sysv/linux/powerpc/configure.in b/sysdeps/unix/sysv/linux/powerpc/configure.in
index 1768ab1..6228352 100644
--- a/sysdeps/unix/sysv/linux/powerpc/configure.in
+++ b/sysdeps/unix/sysv/linux/powerpc/configure.in
@@ -35,3 +35,10 @@ long double foobar (long double x) { return x; }],
     AC_MSG_ERROR([this configuration requires -mlong-double-128 IBM extended format support])
   fi
 fi
+
+case "$config_machine" in
+# FIXME: This should really be 3.12.
+# The lower version here matches common buildroot kernel headers used
+# by developers during LE bootstrap.  3.9 headers seem to work OK.
+  powerpc*le) arch_minimum_kernel=3.9 ;;
+esac

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=c325a11f7fa409423514de4af55ba63cc559cbf0

commit c325a11f7fa409423514de4af55ba63cc559cbf0
Author: Alan Modra <amodra@gmail.com>
Date:   Sat Aug 17 19:11:11 2013 +0930

    A little more precise %Lf for IBM long double
    http://sourceware.org/ml/libc-alpha/2013-08/msg00106.html
    
    IBM long double has variable precision and we often have values with
    107 bits during the normal course of calculations.  It's possible to
    have an IBM long double with 2k bits of precision, and while some might
    argue we ought to print to the full precision, I'm not inclined to try
    to implement that.
    
    So this patch gives the mpn values returned from ldbl2mpn() an extra
    11 bits of precision.  To do that it's necessary to inform the caller
    of __mpn_extract_long_double() exactly how many bits are returned
    rather than assuming a fixed LDBL_MANT_DIG bits.  I did that
    indirectly by returning the number of zero bits in the last mp_limb,
    which turns out to be convenient both in __mpn_extract_long_double(),
    and it's caller.  Given the extra parameter it then becomes possible
    to omit shifting in __mpn_extract_long_double(), since the caller does
    that anyway.
    
    In the following, note that 1 - IEEE854_LONG_DOUBLE_BIAS is equal to
    LDBL_MIN_EXP - 1.  I prefer the former since we already use
    IEEE854_LONG_DOUBLE_BIAS in the exponent calculation for normalised
    values, and it reinforces the fact that denormals are treated as if
    their unbiased exponent was 1.
    
    	[BZ #5268]
    	* include/gmp.h (__mpn_extract_double, __mpn_extract_long_double):
    	Update prototypes.
    	* stdio-common/printf_fp.c: Likewise.
    	(__printf_fp): Use returned zero_bits.
    	* stdlib/dbl2mpn.c (__mpn_extract_double): Update funtion arguments.
    	* sysdeps/i386/ldbl2mpn.c (__mpn_extract_long_double): Don't perform
    	shifts for denormals here.  Instead return leading zero bit count
    	and adjust return value of function.
    	* sysdeps/ieee754/dbl-64/dbl2mpn.c (__mpn_extract_long_double): Likewise.
    	* sysdeps/ieee754/ldbl-128/ldbl2mpn.c (__mpn_extract_long_double):
    	Likewise.
    	* sysdeps/ieee754/ldbl-96/ldbl2mpn.c (__mpn_extract_long_double):
    	Likewise.
    	* sysdeps/ieee754/ldbl-128ibm/ldbl2mpn.c (__mpn_extract_long_double):
    	Likewise.  Return an extra 11 bits of precision.

diff --git a/ChangeLog b/ChangeLog
index 0bea4a9..b18cdaa 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,24 @@
 2013-11-16  Alan Modra  <amodra@gmail.com>
 
+	[BZ #5268]
+	* include/gmp.h (__mpn_extract_double, __mpn_extract_long_double):
+	Update prototypes.
+	* stdio-common/printf_fp.c: Likewise.
+	(__printf_fp): Use returned zero_bits.
+	* stdlib/dbl2mpn.c (__mpn_extract_double): Update funtion arguments.
+	* sysdeps/i386/ldbl2mpn.c (__mpn_extract_long_double): Don't perform
+	shifts for denormals here.  Instead return leading zero bit count
+	and adjust return value of function.
+	* sysdeps/ieee754/dbl-64/dbl2mpn.c (__mpn_extract_long_double): Likewise.
+	* sysdeps/ieee754/ldbl-128/ldbl2mpn.c (__mpn_extract_long_double):
+	Likewise.
+	* sysdeps/ieee754/ldbl-96/ldbl2mpn.c (__mpn_extract_long_double):
+	Likewise.
+	* sysdeps/ieee754/ldbl-128ibm/ldbl2mpn.c (__mpn_extract_long_double):
+	Likewise.  Return an extra 11 bits of precision.
+
+2013-11-16  Alan Modra  <amodra@gmail.com>
+
 	* Makerules (abilist): Define and use var in abilist rules.
 	* sysdeps/unix/sysv/linux/powerpc/Makefile (abilist): Define.
 	* sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/ld-le.abilist,
diff --git a/include/gmp.h b/include/gmp.h
index b741670..bcc9360 100644
--- a/include/gmp.h
+++ b/include/gmp.h
@@ -8,12 +8,12 @@
 
 /* Now define the internal interfaces.  */
 extern mp_size_t __mpn_extract_double (mp_ptr res_ptr, mp_size_t size,
-				       int *expt, int *is_neg,
-				       double value);
+				       int *expt, int *zero_bits,
+				       int *is_neg, double value);
 
 extern mp_size_t __mpn_extract_long_double (mp_ptr res_ptr, mp_size_t size,
-					    int *expt, int *is_neg,
-					    long double value);
+					    int *expt, int *zero_bits,
+					    int *is_neg, long double value);
 
 extern float __mpn_construct_float (mp_srcptr frac_ptr, int expt, int sign);
 
diff --git a/stdio-common/printf_fp.c b/stdio-common/printf_fp.c
index 2b93e6c..c0a7a82 100644
--- a/stdio-common/printf_fp.c
+++ b/stdio-common/printf_fp.c
@@ -134,11 +134,11 @@
   (u##size > v##size || (u##size == v##size && __mpn_cmp (u, v, u##size) >= 0))
 
 extern mp_size_t __mpn_extract_double (mp_ptr res_ptr, mp_size_t size,
-				       int *expt, int *is_neg,
-				       double value);
+				       int *expt, int *zero_bits,
+				       int *is_neg, double value);
 extern mp_size_t __mpn_extract_long_double (mp_ptr res_ptr, mp_size_t size,
-					    int *expt, int *is_neg,
-					    long double value);
+					    int *expt, int *zero_bits,
+					    int *is_neg, long double value);
 extern unsigned int __guess_grouping (unsigned int intdig_max,
 				      const char *grouping);
 
@@ -360,12 +360,13 @@ ___printf_fp (FILE *fp,
 	}
       else
 	{
+	  int zero_bits;
 	  fracsize = __mpn_extract_long_double (fp_input,
 						(sizeof (fp_input) /
 						 sizeof (fp_input[0])),
-						&exponent, &is_neg,
+						&exponent, &zero_bits, &is_neg,
 						fpnum.ldbl);
-	  to_shift = 1 + fracsize * BITS_PER_MP_LIMB - LDBL_MANT_DIG;
+	  to_shift = 1 + zero_bits;
 	}
     }
   else
@@ -406,11 +407,13 @@ ___printf_fp (FILE *fp,
 	}
       else
 	{
+	  int zero_bits;
 	  fracsize = __mpn_extract_double (fp_input,
 					   (sizeof (fp_input)
 					    / sizeof (fp_input[0])),
-					   &exponent, &is_neg, fpnum.dbl);
-	  to_shift = 1 + fracsize * BITS_PER_MP_LIMB - DBL_MANT_DIG;
+					   &exponent, &zero_bits, &is_neg,
+					   fpnum.dbl);
+	  to_shift = 1 + zero_bits;
 	}
     }
 
diff --git a/stdlib/dbl2mpn.c b/stdlib/dbl2mpn.c
index 429e20a..dd835f3 100644
--- a/stdlib/dbl2mpn.c
+++ b/stdlib/dbl2mpn.c
@@ -24,7 +24,7 @@
 
 mp_size_t
 __mpn_extract_double (mp_ptr res_ptr, mp_size_t size,
-		      int *expt, int *is_neg,
+		      int *expt, int *zero_bits, int *is_neg,
 		      double value)
 {
 #error "__mpn_extract_double is not implemented for this floating point format"
diff --git a/sysdeps/i386/ldbl2mpn.c b/sysdeps/i386/ldbl2mpn.c
index c7b322b..968aea5 100644
--- a/sysdeps/i386/ldbl2mpn.c
+++ b/sysdeps/i386/ldbl2mpn.c
@@ -29,7 +29,7 @@
 
 mp_size_t
 __mpn_extract_long_double (mp_ptr res_ptr, mp_size_t size,
-			   int *expt, int *is_neg,
+			   int *expt, int *zero_bits, int *is_neg,
 			   long double value)
 {
   union ieee854_long_double u;
@@ -51,18 +51,26 @@ __mpn_extract_long_double (mp_ptr res_ptr, mp_size_t size,
   #error "mp_limb size " BITS_PER_MP_LIMB "not accounted for"
 #endif
 
+/* The format does not fill the last limb.  There are some zeros.  */
+#define NUM_LEADING_ZEROS (N * BITS_PER_MP_LIMB - LDBL_MANT_DIG)
+  *zero_bits = NUM_LEADING_ZEROS;
+
   if (u.ieee.exponent == 0)
     {
       /* A biased exponent of zero is a special case.
 	 Either it is a zero or it is a denormal number.  */
       if (res_ptr[0] == 0 && res_ptr[N - 1] == 0) /* Assumes N<=2.  */
-	/* It's zero.  */
-	*expt = 0;
+	{
+	  /* It's zero.  */
+	  *expt = 0;
+	  return 1;
+	}
       else
 	{
 	  /* It is a denormal number, meaning it has no implicit leading
 	     one bit, and its exponent is in fact the format minimum.  */
 	  int cnt;
+	  int exp = 1 - IEEE854_LONG_DOUBLE_BIAS;
 
 	  /* One problem with Intel's 80-bit format is that the explicit
 	     leading one in the normalized representation has to be zero
@@ -74,24 +82,17 @@ __mpn_extract_long_double (mp_ptr res_ptr, mp_size_t size,
 	  if (res_ptr[N - 1] != 0)
 	    {
 	      count_leading_zeros (cnt, res_ptr[N - 1]);
-	      if (cnt != 0)
-		{
-#if N == 2
-		  res_ptr[N - 1] = res_ptr[N - 1] << cnt
-				   | (res_ptr[0] >> (BITS_PER_MP_LIMB - cnt));
-		  res_ptr[0] <<= cnt;
-#else
-		  res_ptr[N - 1] <<= cnt;
-#endif
-		}
-	      *expt = LDBL_MIN_EXP - 1 - cnt;
+	      *zero_bits = cnt;
+	      *expt = exp + NUM_LEADING_ZEROS - cnt;
+	      return N;
 	    }
 	  else if (res_ptr[0] != 0)
 	    {
 	      count_leading_zeros (cnt, res_ptr[0]);
-	      res_ptr[N - 1] = res_ptr[0] << cnt;
-	      res_ptr[0] = 0;
-	      *expt = LDBL_MIN_EXP - 1 - BITS_PER_MP_LIMB - cnt;
+	      exp -= BITS_PER_MP_LIMB;
+	      *zero_bits = cnt;
+	      *expt = exp + NUM_LEADING_ZEROS - cnt;
+	      return 1;
 	    }
 	  else
 	    {
@@ -104,7 +105,7 @@ __mpn_extract_long_double (mp_ptr res_ptr, mp_size_t size,
 #else
 	      res_ptr[0] = 0x8000000000000000ul;
 #endif
-	      *expt = LDBL_MIN_EXP - 1;
+	      *expt = 1 - IEEE854_LONG_DOUBLE_BIAS;
 	    }
 	}
     }
diff --git a/sysdeps/ieee754/dbl-64/dbl2mpn.c b/sysdeps/ieee754/dbl-64/dbl2mpn.c
index f2294de..cae062a 100644
--- a/sysdeps/ieee754/dbl-64/dbl2mpn.c
+++ b/sysdeps/ieee754/dbl-64/dbl2mpn.c
@@ -28,7 +28,7 @@
 
 mp_size_t
 __mpn_extract_double (mp_ptr res_ptr, mp_size_t size,
-		      int *expt, int *is_neg,
+		      int *expt, int *zero_bits, int *is_neg,
 		      double value)
 {
   union ieee754_double u;
@@ -49,9 +49,10 @@ __mpn_extract_double (mp_ptr res_ptr, mp_size_t size,
 #else
   #error "mp_limb size " BITS_PER_MP_LIMB "not accounted for"
 #endif
+
 /* The format does not fill the last limb.  There are some zeros.  */
-#define NUM_LEADING_ZEROS (BITS_PER_MP_LIMB \
-			   - (DBL_MANT_DIG - ((N - 1) * BITS_PER_MP_LIMB)))
+#define NUM_LEADING_ZEROS (N * BITS_PER_MP_LIMB - DBL_MANT_DIG)
+  *zero_bits = NUM_LEADING_ZEROS;
 
   if (u.ieee.exponent == 0)
     {
@@ -65,37 +66,20 @@ __mpn_extract_double (mp_ptr res_ptr, mp_size_t size,
           /* It is a denormal number, meaning it has no implicit leading
 	     one bit, and its exponent is in fact the format minimum.  */
 	  int cnt;
+	  int exp = 1 - IEEE754_DOUBLE_BIAS;
+	  int n = N;
 
 	  if (res_ptr[N - 1] != 0)
-	    {
-	      count_leading_zeros (cnt, res_ptr[N - 1]);
-	      cnt -= NUM_LEADING_ZEROS;
-#if N == 2
-	      res_ptr[N - 1] = res_ptr[1] << cnt
-			       | (N - 1)
-			         * (res_ptr[0] >> (BITS_PER_MP_LIMB - cnt));
-	      res_ptr[0] <<= cnt;
-#else
-	      res_ptr[N - 1] <<= cnt;
-#endif
-	      *expt = DBL_MIN_EXP - 1 - cnt;
-	    }
+	    count_leading_zeros (cnt, res_ptr[N - 1]);
 	  else
 	    {
 	      count_leading_zeros (cnt, res_ptr[0]);
-	      if (cnt >= NUM_LEADING_ZEROS)
-		{
-		  res_ptr[N - 1] = res_ptr[0] << (cnt - NUM_LEADING_ZEROS);
-		  res_ptr[0] = 0;
-		}
-	      else
-		{
-		  res_ptr[N - 1] = res_ptr[0] >> (NUM_LEADING_ZEROS - cnt);
-		  res_ptr[0] <<= BITS_PER_MP_LIMB - (NUM_LEADING_ZEROS - cnt);
-		}
-	      *expt = DBL_MIN_EXP - 1
-		      - (BITS_PER_MP_LIMB - NUM_LEADING_ZEROS) - cnt;
+	      exp -= BITS_PER_MP_LIMB;
+	      n = 1;
 	    }
+	  *zero_bits = cnt;
+	  *expt = exp + NUM_LEADING_ZEROS - cnt;
+	  return n;
 	}
     }
   else
diff --git a/sysdeps/ieee754/ldbl-128/ldbl2mpn.c b/sysdeps/ieee754/ldbl-128/ldbl2mpn.c
index 64f98a5..8e2145b 100644
--- a/sysdeps/ieee754/ldbl-128/ldbl2mpn.c
+++ b/sysdeps/ieee754/ldbl-128/ldbl2mpn.c
@@ -30,7 +30,7 @@
 
 mp_size_t
 __mpn_extract_long_double (mp_ptr res_ptr, mp_size_t size,
-			   int *expt, int *is_neg,
+			   int *expt, int *zero_bits, int *is_neg,
 			   long double value)
 {
   union ieee854_long_double u;
@@ -54,9 +54,10 @@ __mpn_extract_long_double (mp_ptr res_ptr, mp_size_t size,
 #else
   #error "mp_limb size " BITS_PER_MP_LIMB "not accounted for"
 #endif
+
 /* The format does not fill the last limb.  There are some zeros.  */
-#define NUM_LEADING_ZEROS (BITS_PER_MP_LIMB \
-			   - (LDBL_MANT_DIG - ((N - 1) * BITS_PER_MP_LIMB)))
+#define NUM_LEADING_ZEROS (N * BITS_PER_MP_LIMB - LDBL_MANT_DIG)
+  *zero_bits = NUM_LEADING_ZEROS;
 
   if (u.ieee.exponent == 0)
     {
@@ -64,70 +65,42 @@ __mpn_extract_long_double (mp_ptr res_ptr, mp_size_t size,
 	 Either it is a zero or it is a denormal number.  */
       if (res_ptr[0] == 0 && res_ptr[1] == 0
           && res_ptr[N - 2] == 0 && res_ptr[N - 1] == 0) /* Assumes N<=4.  */
-	/* It's zero.  */
-	*expt = 0;
+	{
+	  /* It's zero.  */
+	  *expt = 0;
+	  return 1;
+	}
       else
 	{
           /* It is a denormal number, meaning it has no implicit leading
 	     one bit, and its exponent is in fact the format minimum.  */
 	  int cnt;
+	  int exp = 1 - IEEE854_LONG_DOUBLE_BIAS;
+	  int n = N;
 
 #if N == 2
 	  if (res_ptr[N - 1] != 0)
-	    {
-	      count_leading_zeros (cnt, res_ptr[N - 1]);
-	      cnt -= NUM_LEADING_ZEROS;
-	      res_ptr[N - 1] = res_ptr[N - 1] << cnt
-			       | (res_ptr[0] >> (BITS_PER_MP_LIMB - cnt));
-	      res_ptr[0] <<= cnt;
-	      *expt = LDBL_MIN_EXP - 1 - cnt;
-	    }
+	    count_leading_zeros (cnt, res_ptr[N - 1]);
 	  else
 	    {
 	      count_leading_zeros (cnt, res_ptr[0]);
-	      if (cnt >= NUM_LEADING_ZEROS)
-		{
-		  res_ptr[N - 1] = res_ptr[0] << (cnt - NUM_LEADING_ZEROS);
-		  res_ptr[0] = 0;
-		}
-	      else
-		{
-		  res_ptr[N - 1] = res_ptr[0] >> (NUM_LEADING_ZEROS - cnt);
-		  res_ptr[0] <<= BITS_PER_MP_LIMB - (NUM_LEADING_ZEROS - cnt);
-		}
-	      *expt = LDBL_MIN_EXP - 1
-		- (BITS_PER_MP_LIMB - NUM_LEADING_ZEROS) - cnt;
+	      exp -= BITS_PER_MP_LIMB;
+	      n = 1;
 	    }
 #else
-	  int j, k, l;
+	  int j;
 
 	  for (j = N - 1; j > 0; j--)
 	    if (res_ptr[j] != 0)
 	      break;
 
 	  count_leading_zeros (cnt, res_ptr[j]);
-	  cnt -= NUM_LEADING_ZEROS;
-	  l = N - 1 - j;
-	  if (cnt < 0)
-	    {
-	      cnt += BITS_PER_MP_LIMB;
-	      l--;
-	    }
-	  if (!cnt)
-	    for (k = N - 1; k >= l; k--)
-	      res_ptr[k] = res_ptr[k-l];
-	  else
-	    {
-	      for (k = N - 1; k > l; k--)
-		res_ptr[k] = res_ptr[k-l] << cnt
-			     | res_ptr[k-l-1] >> (BITS_PER_MP_LIMB - cnt);
-	      res_ptr[k--] = res_ptr[0] << cnt;
-	    }
-
-	  for (; k >= 0; k--)
-	    res_ptr[k] = 0;
-	  *expt = LDBL_MIN_EXP - 1 - l * BITS_PER_MP_LIMB - cnt;
+	  exp -= (N - 1 - j) * BITS_PER_MP_LIMB;
+	  n = j + 1;
 #endif
+	  *zero_bits = cnt;
+	  *expt = exp + NUM_LEADING_ZEROS - cnt;
+	  return n;
 	}
     }
   else
diff --git a/sysdeps/ieee754/ldbl-128ibm/ldbl2mpn.c b/sysdeps/ieee754/ldbl-128ibm/ldbl2mpn.c
index e46fde7..14f9ed3 100644
--- a/sysdeps/ieee754/ldbl-128ibm/ldbl2mpn.c
+++ b/sysdeps/ieee754/ldbl-128ibm/ldbl2mpn.c
@@ -30,157 +30,121 @@
 
 mp_size_t
 __mpn_extract_long_double (mp_ptr res_ptr, mp_size_t size,
-			   int *expt, int *is_neg,
+			   int *expt, int *zero_bits, int *is_neg,
 			   long double value)
 {
   union ibm_extended_long_double u;
-  unsigned long long hi, lo;
+  uint64_t hi, lo;
   int ediff;
 
   u.ld = value;
 
   *is_neg = u.d[0].ieee.negative;
   *expt = (int) u.d[0].ieee.exponent - IEEE754_DOUBLE_BIAS;
+#define NUM_LEADING_ZEROS (128 - (LDBL_MANT_DIG + 11))
+  *zero_bits = NUM_LEADING_ZEROS;
 
-  lo = ((long long) u.d[1].ieee.mantissa0 << 32) | u.d[1].ieee.mantissa1;
-  hi = ((long long) u.d[0].ieee.mantissa0 << 32) | u.d[0].ieee.mantissa1;
+  lo = ((uint64_t) u.d[1].ieee.mantissa0 << 32) | u.d[1].ieee.mantissa1;
+  hi = ((uint64_t) u.d[0].ieee.mantissa0 << 32) | u.d[0].ieee.mantissa1;
 
-  /* If the lower double is not a denormal or zero then set the hidden
-     53rd bit.  */
-  if (u.d[1].ieee.exponent != 0)
-    lo |= 1ULL << 52;
-  else
-    lo = lo << 1;
-
-  /* The lower double is normalized separately from the upper.  We may
-     need to adjust the lower manitissa to reflect this.  */
-  ediff = u.d[0].ieee.exponent - u.d[1].ieee.exponent - 53;
-  if (ediff > 0)
+  if (u.d[0].ieee.exponent != 0)
     {
-      if (ediff < 64)
-	lo = lo >> ediff;
+      /* If the high double is not a denormal or zero then set the hidden
+	 53rd bit.  */
+      hi |= (uint64_t) 1 << 52;
+
+      /* If the lower double is not a denormal or zero then set the hidden
+	 53rd bit.  */
+      if (u.d[1].ieee.exponent != 0)
+	lo |= (uint64_t) 1 << 52;
       else
-	lo = 0;
-    }
-  else if (ediff < 0)
-    lo = lo << -ediff;
-
-  /* The high double may be rounded and the low double reflects the
-     difference between the long double and the rounded high double
-     value.  This is indicated by a differnce between the signs of the
-     high and low doubles.  */
-  if (u.d[0].ieee.negative != u.d[1].ieee.negative
-      && lo != 0)
-    {
-      lo = (1ULL << 53) - lo;
-      if (hi == 0)
+	lo = lo << 1;
+
+      /* We currently only have 53 bits in lo.  Gain a few more bits
+	 of precision.  */
+      lo = lo << 11;
+
+      /* The lower double is normalized separately from the upper.  We may
+	 need to adjust the lower manitissa to reflect this.  */
+      ediff = u.d[0].ieee.exponent - u.d[1].ieee.exponent - 53;
+      if (ediff > 0)
 	{
-	  /* we have a borrow from the hidden bit, so shift left 1.  */
-	  hi = 0x0ffffffffffffeLL | (lo >> 51);
-	  lo = 0x1fffffffffffffLL & (lo << 1);
-	  (*expt)--;
+	  if (ediff < 64)
+	    lo = lo >> ediff;
+	  else
+	    lo = 0;
 	}
-      else
-	hi--;
-    }
+      else if (ediff < 0)
+	lo = lo << -ediff;
+
+      /* The high double may be rounded and the low double reflects the
+	 difference between the long double and the rounded high double
+	 value.  This is indicated by a differnce between the signs of the
+	 high and low doubles.  */
+      if (u.d[0].ieee.negative != u.d[1].ieee.negative
+	  && lo != 0)
+	{
+	  hi--;
+	  lo = -lo;
+	  if (hi < (uint64_t) 1 << 52)
+	    {
+	      /* We have a borrow from the hidden bit, so shift left 1.  */
+	      hi = (hi << 1) | (lo >> 63);
+	      lo = lo << 1;
+	      (*expt)--;
+	    }
+	}
+
 #if BITS_PER_MP_LIMB == 32
-  /* Combine the mantissas to be contiguous.  */
-  res_ptr[0] = lo;
-  res_ptr[1] = (hi << (53 - 32)) | (lo >> 32);
-  res_ptr[2] = hi >> 11;
-  res_ptr[3] = hi >> (32 + 11);
-  #define N 4
+      res_ptr[0] = lo;
+      res_ptr[1] = lo >> 32;
+      res_ptr[2] = hi;
+      res_ptr[3] = hi >> 32;
+      return 4;
 #elif BITS_PER_MP_LIMB == 64
-  /* Combine the two mantissas to be contiguous.  */
-  res_ptr[0] = (hi << 53) | lo;
-  res_ptr[1] = hi >> 11;
-  #define N 2
+      res_ptr[0] = lo;
+      res_ptr[1] = hi;
+      return 2;
 #else
-  #error "mp_limb size " BITS_PER_MP_LIMB "not accounted for"
+# error "mp_limb size " BITS_PER_MP_LIMB "not accounted for"
 #endif
-/* The format does not fill the last limb.  There are some zeros.  */
-#define NUM_LEADING_ZEROS (BITS_PER_MP_LIMB \
-			   - (LDBL_MANT_DIG - ((N - 1) * BITS_PER_MP_LIMB)))
+    }
 
-  if (u.d[0].ieee.exponent == 0)
+  /* The high double is a denormal or zero.  The low double must
+     be zero.  A denormal is interpreted as having a biased
+     exponent of 1.  */
+  res_ptr[0] = hi;
+#if BITS_PER_MP_LIMB == 32
+  res_ptr[1] = hi >> 32;
+#endif
+  if (hi == 0)
     {
-      /* A biased exponent of zero is a special case.
-	 Either it is a zero or it is a denormal number.  */
-      if (res_ptr[0] == 0 && res_ptr[1] == 0
-	  && res_ptr[N - 2] == 0 && res_ptr[N - 1] == 0) /* Assumes N<=4.  */
-	/* It's zero.  */
-	*expt = 0;
+      /* It's zero.  */
+      *expt = 0;
+      return 1;
+    }
+  else
+    {
+      int cnt;
+      int exp = 1 - IEEE754_DOUBLE_BIAS;
+      int n = 1;
+
+#if BITS_PER_MP_LIMB == 32
+      if (res_ptr[1] != 0)
+	{
+	  count_leading_zeros (cnt, res_ptr[1]);
+	  n = 2;
+	}
       else
 	{
-	  /* It is a denormal number, meaning it has no implicit leading
-	     one bit, and its exponent is in fact the format minimum.  We
-	     use DBL_MIN_EXP instead of LDBL_MIN_EXP below because the
-	     latter describes the properties of both parts together, but
-	     the exponent is computed from the high part only.  */
-	  int cnt;
-
-#if N == 2
-	  if (res_ptr[N - 1] != 0)
-	    {
-	      count_leading_zeros (cnt, res_ptr[N - 1]);
-	      cnt -= NUM_LEADING_ZEROS;
-	      res_ptr[N - 1] = res_ptr[N - 1] << cnt
-			       | (res_ptr[0] >> (BITS_PER_MP_LIMB - cnt));
-	      res_ptr[0] <<= cnt;
-	      *expt = DBL_MIN_EXP - 1 - cnt;
-	    }
-	  else
-	    {
-	      count_leading_zeros (cnt, res_ptr[0]);
-	      if (cnt >= NUM_LEADING_ZEROS)
-		{
-		  res_ptr[N - 1] = res_ptr[0] << (cnt - NUM_LEADING_ZEROS);
-		  res_ptr[0] = 0;
-		}
-	      else
-		{
-		  res_ptr[N - 1] = res_ptr[0] >> (NUM_LEADING_ZEROS - cnt);
-		  res_ptr[0] <<= BITS_PER_MP_LIMB - (NUM_LEADING_ZEROS - cnt);
-		}
-	      *expt = DBL_MIN_EXP - 1
-		- (BITS_PER_MP_LIMB - NUM_LEADING_ZEROS) - cnt;
-	    }
+	  count_leading_zeros (cnt, res_ptr[0]);
+	  exp -= BITS_PER_MP_LIMB;
+	}
 #else
-	  int j, k, l;
-
-	  for (j = N - 1; j > 0; j--)
-	    if (res_ptr[j] != 0)
-	      break;
-
-	  count_leading_zeros (cnt, res_ptr[j]);
-	  cnt -= NUM_LEADING_ZEROS;
-	  l = N - 1 - j;
-	  if (cnt < 0)
-	    {
-	      cnt += BITS_PER_MP_LIMB;
-	      l--;
-	    }
-	  if (!cnt)
-	    for (k = N - 1; k >= l; k--)
-	      res_ptr[k] = res_ptr[k-l];
-	  else
-	    {
-	      for (k = N - 1; k > l; k--)
-		res_ptr[k] = res_ptr[k-l] << cnt
-			     | res_ptr[k-l-1] >> (BITS_PER_MP_LIMB - cnt);
-	      res_ptr[k--] = res_ptr[0] << cnt;
-	    }
-
-	  for (; k >= 0; k--)
-	    res_ptr[k] = 0;
-	  *expt = DBL_MIN_EXP - 1 - l * BITS_PER_MP_LIMB - cnt;
+      count_leading_zeros (cnt, hi);
 #endif
-	}
+      *zero_bits = cnt;
+      *expt = exp + NUM_LEADING_ZEROS - cnt;
+      return n;
     }
-  else
-    /* Add the implicit leading one bit for a normalized number.  */
-    res_ptr[N - 1] |= (mp_limb_t) 1 << (LDBL_MANT_DIG - 1
-					- ((N - 1) * BITS_PER_MP_LIMB));
-
-  return N;
 }
diff --git a/sysdeps/ieee754/ldbl-96/ldbl2mpn.c b/sysdeps/ieee754/ldbl-96/ldbl2mpn.c
index 3f85e0a..e83171b 100644
--- a/sysdeps/ieee754/ldbl-96/ldbl2mpn.c
+++ b/sysdeps/ieee754/ldbl-96/ldbl2mpn.c
@@ -30,7 +30,7 @@
 
 mp_size_t
 __mpn_extract_long_double (mp_ptr res_ptr, mp_size_t size,
-			   int *expt, int *is_neg,
+			   int *expt, int *zero_bits, int *is_neg,
 			   long double value)
 {
   union ieee854_long_double u;
@@ -52,41 +52,38 @@ __mpn_extract_long_double (mp_ptr res_ptr, mp_size_t size,
   #error "mp_limb size " BITS_PER_MP_LIMB "not accounted for"
 #endif
 
+/* The format does not fill the last limb.  There are some zeros.  */
+#define NUM_LEADING_ZEROS (N * BITS_PER_MP_LIMB - LDBL_MANT_DIG)
+  *zero_bits = NUM_LEADING_ZEROS;
+
   if (u.ieee.exponent == 0)
     {
       /* A biased exponent of zero is a special case.
 	 Either it is a zero or it is a denormal number.  */
       if (res_ptr[0] == 0 && res_ptr[N - 1] == 0) /* Assumes N<=2.  */
-	/* It's zero.  */
-	*expt = 0;
+	{
+	  /* It's zero.  */
+	  *expt = 0;
+	  return 1;
+	}
       else
 	{
           /* It is a denormal number, meaning it has no implicit leading
 	     one bit, and its exponent is in fact the format minimum.  */
 	  int cnt;
+	  int exp = 1 - IEEE854_LONG_DOUBLE_BIAS;
+	  int n = N;
 
 	  if (res_ptr[N - 1] != 0)
-	    {
-	      count_leading_zeros (cnt, res_ptr[N - 1]);
-	      if (cnt != 0)
-		{
-#if N == 2
-	          res_ptr[N - 1] = res_ptr[N - 1] << cnt
-			           | (res_ptr[0] >> (BITS_PER_MP_LIMB - cnt));
-	          res_ptr[0] <<= cnt;
-#else
-	          res_ptr[N - 1] <<= cnt;
-#endif
-		}
-	      *expt = LDBL_MIN_EXP - 1 - cnt;
-	    }
+	    count_leading_zeros (cnt, res_ptr[N - 1]);
 	  else
 	    {
 	      count_leading_zeros (cnt, res_ptr[0]);
-	      res_ptr[N - 1] = res_ptr[0] << cnt;
-	      res_ptr[0] = 0;
-	      *expt = LDBL_MIN_EXP - 1 - BITS_PER_MP_LIMB - cnt;
+	      exp -= BITS_PER_MP_LIMB;
+	      n = 1;
 	    }
+	  *zero_bits = cnt;
+	  *expt = exp + NUM_LEADING_ZEROS - cnt;
 	}
     }
 

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=e24fc3c2914e0e17836455991e43151d453eb34c

commit e24fc3c2914e0e17836455991e43151d453eb34c
Author: Alan Modra <amodra@gmail.com>
Date:   Thu Oct 3 14:09:27 2013 +0930

    PowerPC LE ABI tests
    http://sourceware.org/ml/libc-alpha/2013-08/msg00096.html
    
    This adds ABI tests for powerpc64le.
    
    	* Makerules (abilist): Define and use var in abilist rules.
    	* sysdeps/unix/sysv/linux/powerpc/Makefile (abilist): Define.
    	* sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/ld-le.abilist,
    	* sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libBrokenLocale-le.abilist,
    	* sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libanl-le.abilist,
    	* sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libc-le.abilist,
    	* sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libcrypt-le.abilist,
    	* sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libdl-le.abilist,
    	* sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libm-le.abilist,
    	* sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libnsl-le.abilist,
    	* sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libpthread-le.abilist,
    	* sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libresolv-le.abilist,
    	* sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/librt-le.abilist,
    	* sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libthread_db-le.abilist,
    	* sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libutil-le.abilist:
    	New files.

diff --git a/ChangeLog b/ChangeLog
index d44e821..0bea4a9 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,22 @@
+2013-11-16  Alan Modra  <amodra@gmail.com>
+
+	* Makerules (abilist): Define and use var in abilist rules.
+	* sysdeps/unix/sysv/linux/powerpc/Makefile (abilist): Define.
+	* sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/ld-le.abilist,
+	* sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libBrokenLocale-le.abilist,
+	* sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libanl-le.abilist,
+	* sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libc-le.abilist,
+	* sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libcrypt-le.abilist,
+	* sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libdl-le.abilist,
+	* sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libm-le.abilist,
+	* sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libnsl-le.abilist,
+	* sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libpthread-le.abilist,
+	* sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libresolv-le.abilist,
+	* sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/librt-le.abilist,
+	* sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libthread_db-le.abilist,
+	* sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libutil-le.abilist:
+	New files.
+
 2013-11-15  Adhemerval Zanella  <azanella@linux.vnet.ibm.com>
 
 	* sysdeps/powerpc/fpu/libm-test-ulps: Update.
diff --git a/Makerules b/Makerules
index 03eafb0..7d0bc1b 100644
--- a/Makerules
+++ b/Makerules
@@ -1144,7 +1144,11 @@ ifeq ($(versioning),yes)
 	LC_ALL=C $(OBJDUMP) --dynamic-syms $< > $@T
 	mv -f $@T $@
 
-vpath %.abilist $(+sysdep_dirs)
+ifndef abilist
+abilist=.abilist
+endif
+
+vpath %$(abilist) $(+sysdep_dirs)
 
 # The .PRECIOUS rule prevents the files built by an implicit rule whose
 # target pattern is %.symlist from being considered "intermediate files"
@@ -1153,24 +1157,24 @@ vpath %.abilist $(+sysdep_dirs)
 .PRECIOUS: %.symlist
 generated += $(extra-libs:=.symlist)
 
-check-abi-%: $(common-objpfx)config.make %.abilist $(objpfx)%.symlist
+check-abi-%: $(common-objpfx)config.make %$(abilist) $(objpfx)%.symlist
 	$(check-abi)
-check-abi-%: $(common-objpfx)config.make %.abilist $(common-objpfx)%.symlist
+check-abi-%: $(common-objpfx)config.make %$(abilist) $(common-objpfx)%.symlist
 	$(check-abi)
 define check-abi
-	diff -p -U 0 $(filter %.abilist,$^) $(filter %.symlist,$^)
+	diff -p -U 0 $(filter %$(abilist),$^) $(filter %.symlist,$^)
 endef
 
-update-abi-%: $(objpfx)%.symlist %.abilist
+update-abi-%: $(objpfx)%.symlist %$(abilist)
 	$(update-abi)
-update-abi-%: $(common-objpfx)%.symlist %.abilist
+update-abi-%: $(common-objpfx)%.symlist %$(abilist)
 	$(update-abi)
 define update-abi
 @if cmp -s $^ 2> /dev/null; \
  then \
-      echo '+++ $(filter %.abilist,$^) is unchanged'; \
+      echo '+++ $(filter %$(abilist),$^) is unchanged'; \
  else cp -f $^; \
-      echo '*** Now check $(filter %.abilist,$^) changes for correctness ***'; \
+      echo '*** Now check $(filter %$(abilist),$^) changes for correctness ***'; \
  fi
 endef
 
diff --git a/sysdeps/unix/sysv/linux/powerpc/Makefile b/sysdeps/unix/sysv/linux/powerpc/Makefile
index 395342f..890825e 100644
--- a/sysdeps/unix/sysv/linux/powerpc/Makefile
+++ b/sysdeps/unix/sysv/linux/powerpc/Makefile
@@ -31,3 +31,7 @@ sysdep_headers += bits/ppc.h
 sysdep_routines += get_timebase_freq
 tests += test-gettimebasefreq
 endif
+
+ifneq ($(findstring le,$(config-machine)),)
+abilist=-le.abilist
+endif
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/ld-le.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/ld-le.abilist
new file mode 100644
index 0000000..0f745f2
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/ld-le.abilist
@@ -0,0 +1,11 @@
+GLIBC_2.18
+ GLIBC_2.18 A
+ __libc_memalign F
+ __libc_stack_end D 0x8
+ __tls_get_addr F
+ _dl_mcount F
+ _r_debug D 0x28
+ calloc F
+ free F
+ malloc F
+ realloc F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libBrokenLocale-le.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libBrokenLocale-le.abilist
new file mode 100644
index 0000000..0ca5b6f
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libBrokenLocale-le.abilist
@@ -0,0 +1,3 @@
+GLIBC_2.18
+ GLIBC_2.18 A
+ __ctype_get_mb_cur_max F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libanl-le.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libanl-le.abilist
new file mode 100644
index 0000000..c25a1ab
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libanl-le.abilist
@@ -0,0 +1,6 @@
+GLIBC_2.18
+ GLIBC_2.18 A
+ gai_cancel F
+ gai_error F
+ gai_suspend F
+ getaddrinfo_a F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libc-le.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libc-le.abilist
new file mode 100644
index 0000000..691c8c0
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libc-le.abilist
@@ -0,0 +1,2169 @@
+GLIBC_2.18
+ GLIBC_2.18 A
+ _Exit F
+ _IO_2_1_stderr_ D 0xe0
+ _IO_2_1_stdin_ D 0xe0
+ _IO_2_1_stdout_ D 0xe0
+ _IO_adjust_column F
+ _IO_adjust_wcolumn F
+ _IO_default_doallocate F
+ _IO_default_finish F
+ _IO_default_pbackfail F
+ _IO_default_uflow F
+ _IO_default_xsgetn F
+ _IO_default_xsputn F
+ _IO_do_write F
+ _IO_doallocbuf F
+ _IO_fclose F
+ _IO_fdopen F
+ _IO_feof F
+ _IO_ferror F
+ _IO_fflush F
+ _IO_fgetpos F
+ _IO_fgetpos64 F
+ _IO_fgets F
+ _IO_file_attach F
+ _IO_file_close F
+ _IO_file_close_it F
+ _IO_file_doallocate F
+ _IO_file_finish F
+ _IO_file_fopen F
+ _IO_file_init F
+ _IO_file_jumps D 0xa8
+ _IO_file_open F
+ _IO_file_overflow F
+ _IO_file_read F
+ _IO_file_seek F
+ _IO_file_seekoff F
+ _IO_file_setbuf F
+ _IO_file_stat F
+ _IO_file_sync F
+ _IO_file_underflow F
+ _IO_file_write F
+ _IO_file_xsputn F
+ _IO_flockfile F
+ _IO_flush_all F
+ _IO_flush_all_linebuffered F
+ _IO_fopen F
+ _IO_fprintf F
+ _IO_fputs F
+ _IO_fread F
+ _IO_free_backup_area F
+ _IO_free_wbackup_area F
+ _IO_fsetpos F
+ _IO_fsetpos64 F
+ _IO_ftell F
+ _IO_ftrylockfile F
+ _IO_funlockfile F
+ _IO_fwrite F
+ _IO_getc F
+ _IO_getline F
+ _IO_getline_info F
+ _IO_gets F
+ _IO_init F
+ _IO_init_marker F
+ _IO_init_wmarker F
+ _IO_iter_begin F
+ _IO_iter_end F
+ _IO_iter_file F
+ _IO_iter_next F
+ _IO_least_wmarker F
+ _IO_link_in F
+ _IO_list_all D 0x8
+ _IO_list_lock F
+ _IO_list_resetlock F
+ _IO_list_unlock F
+ _IO_marker_delta F
+ _IO_marker_difference F
+ _IO_padn F
+ _IO_peekc_locked F
+ _IO_popen F
+ _IO_printf F
+ _IO_proc_close F
+ _IO_proc_open F
+ _IO_putc F
+ _IO_puts F
+ _IO_remove_marker F
+ _IO_seekmark F
+ _IO_seekoff F
+ _IO_seekpos F
+ _IO_seekwmark F
+ _IO_setb F
+ _IO_setbuffer F
+ _IO_setvbuf F
+ _IO_sgetn F
+ _IO_sprintf F
+ _IO_sputbackc F
+ _IO_sputbackwc F
+ _IO_sscanf F
+ _IO_str_init_readonly F
+ _IO_str_init_static F
+ _IO_str_overflow F
+ _IO_str_pbackfail F
+ _IO_str_seekoff F
+ _IO_str_underflow F
+ _IO_sungetc F
+ _IO_sungetwc F
+ _IO_switch_to_get_mode F
+ _IO_switch_to_main_wget_area F
+ _IO_switch_to_wbackup_area F
+ _IO_switch_to_wget_mode F
+ _IO_un_link F
+ _IO_ungetc F
+ _IO_unsave_markers F
+ _IO_unsave_wmarkers F
+ _IO_vfprintf F
+ _IO_vfscanf F
+ _IO_vsprintf F
+ _IO_wdefault_doallocate F
+ _IO_wdefault_finish F
+ _IO_wdefault_pbackfail F
+ _IO_wdefault_uflow F
+ _IO_wdefault_xsgetn F
+ _IO_wdefault_xsputn F
+ _IO_wdo_write F
+ _IO_wdoallocbuf F
+ _IO_wfile_jumps D 0xa8
+ _IO_wfile_overflow F
+ _IO_wfile_seekoff F
+ _IO_wfile_sync F
+ _IO_wfile_underflow F
+ _IO_wfile_xsputn F
+ _IO_wmarker_delta F
+ _IO_wsetb F
+ __adjtimex F
+ __after_morecore_hook D 0x8
+ __argz_count F
+ __argz_next F
+ __argz_stringify F
+ __asprintf F
+ __asprintf_chk F
+ __assert F
+ __assert_fail F
+ __assert_perror_fail F
+ __backtrace F
+ __backtrace_symbols F
+ __backtrace_symbols_fd F
+ __bsd_getpgrp F
+ __bzero F
+ __check_rhosts_file D 0x4
+ __chk_fail F
+ __clone F
+ __close F
+ __cmsg_nxthdr F
+ __confstr_chk F
+ __connect F
+ __ctype_b_loc F
+ __ctype_get_mb_cur_max F
+ __ctype_tolower_loc F
+ __ctype_toupper_loc F
+ __curbrk D 0x8
+ __cxa_at_quick_exit F
+ __cxa_atexit F
+ __cxa_finalize F
+ __cxa_thread_atexit_impl F
+ __cyg_profile_func_enter F
+ __cyg_profile_func_exit F
+ __daylight D 0x4
+ __dcgettext F
+ __default_morecore F
+ __dgettext F
+ __dprintf_chk F
+ __dup2 F
+ __duplocale F
+ __endmntent F
+ __environ D 0x8
+ __errno_location F
+ __fbufsize F
+ __fcntl F
+ __fdelt_chk F
+ __fdelt_warn F
+ __ffs F
+ __fgets_chk F
+ __fgets_unlocked_chk F
+ __fgetws_chk F
+ __fgetws_unlocked_chk F
+ __finite F
+ __finitef F
+ __finitel F
+ __flbf F
+ __fork F
+ __fpending F
+ __fprintf_chk F
+ __fpu_control D 0x4
+ __fpurge F
+ __fread_chk F
+ __fread_unlocked_chk F
+ __freadable F
+ __freading F
+ __free_hook D 0x8
+ __freelocale F
+ __fsetlocking F
+ __fwprintf_chk F
+ __fwritable F
+ __fwriting F
+ __fxstat F
+ __fxstat64 F
+ __fxstatat F
+ __fxstatat64 F
+ __getauxval F
+ __getcwd_chk F
+ __getdelim F
+ __getdomainname_chk F
+ __getgroups_chk F
+ __gethostname_chk F
+ __getlogin_r_chk F
+ __getmntent_r F
+ __getpagesize F
+ __getpgid F
+ __getpid F
+ __gets_chk F
+ __gettimeofday F
+ __getwd_chk F
+ __gmtime_r F
+ __h_errno_location F
+ __isalnum_l F
+ __isalpha_l F
+ __isascii_l F
+ __isblank_l F
+ __iscntrl_l F
+ __isctype F
+ __isdigit_l F
+ __isgraph_l F
+ __isinf F
+ __isinff F
+ __isinfl F
+ __islower_l F
+ __isnan F
+ __isnanf F
+ __isnanl F
+ __isoc99_fscanf F
+ __isoc99_fwscanf F
+ __isoc99_scanf F
+ __isoc99_sscanf F
+ __isoc99_swscanf F
+ __isoc99_vfscanf F
+ __isoc99_vfwscanf F
+ __isoc99_vscanf F
+ __isoc99_vsscanf F
+ __isoc99_vswscanf F
+ __isoc99_vwscanf F
+ __isoc99_wscanf F
+ __isprint_l F
+ __ispunct_l F
+ __isspace_l F
+ __isupper_l F
+ __iswalnum_l F
+ __iswalpha_l F
+ __iswblank_l F
+ __iswcntrl_l F
+ __iswctype F
+ __iswctype_l F
+ __iswdigit_l F
+ __iswgraph_l F
+ __iswlower_l F
+ __iswprint_l F
+ __iswpunct_l F
+ __iswspace_l F
+ __iswupper_l F
+ __iswxdigit_l F
+ __isxdigit_l F
+ __ivaliduser F
+ __key_decryptsession_pk_LOCAL D 0x8
+ __key_encryptsession_pk_LOCAL D 0x8
+ __key_gendes_LOCAL D 0x8
+ __libc_allocate_rtsig F
+ __libc_calloc F
+ __libc_current_sigrtmax F
+ __libc_current_sigrtmin F
+ __libc_free F
+ __libc_freeres F
+ __libc_init_first F
+ __libc_mallinfo F
+ __libc_malloc F
+ __libc_mallopt F
+ __libc_memalign F
+ __libc_pvalloc F
+ __libc_realloc F
+ __libc_sa_len F
+ __libc_start_main F
+ __libc_valloc F
+ __longjmp_chk F
+ __lseek F
+ __lxstat F
+ __lxstat64 F
+ __malloc_hook D 0x8
+ __malloc_initialize_hook D 0x8
+ __mbrlen F
+ __mbrtowc F
+ __mbsnrtowcs_chk F
+ __mbsrtowcs_chk F
+ __mbstowcs_chk F
+ __memalign_hook D 0x8
+ __memcpy_chk F
+ __memmove_chk F
+ __mempcpy F
+ __mempcpy_chk F
+ __mempcpy_small F
+ __memset_chk F
+ __monstartup F
+ __morecore D 0x8
+ __nanosleep F
+ __newlocale F
+ __nl_langinfo_l F
+ __nldbl__IO_fprintf F
+ __nldbl__IO_printf F
+ __nldbl__IO_sprintf F
+ __nldbl__IO_sscanf F
+ __nldbl__IO_vfprintf F
+ __nldbl__IO_vfscanf F
+ __nldbl__IO_vsprintf F
+ __nldbl___asprintf F
+ __nldbl___asprintf_chk F
+ __nldbl___dprintf_chk F
+ __nldbl___fprintf_chk F
+ __nldbl___fwprintf_chk F
+ __nldbl___isoc99_fscanf F
+ __nldbl___isoc99_fwscanf F
+ __nldbl___isoc99_scanf F
+ __nldbl___isoc99_sscanf F
+ __nldbl___isoc99_swscanf F
+ __nldbl___isoc99_vfscanf F
+ __nldbl___isoc99_vfwscanf F
+ __nldbl___isoc99_vscanf F
+ __nldbl___isoc99_vsscanf F
+ __nldbl___isoc99_vswscanf F
+ __nldbl___isoc99_vwscanf F
+ __nldbl___isoc99_wscanf F
+ __nldbl___obstack_printf_chk F
+ __nldbl___obstack_vprintf_chk F
+ __nldbl___printf_chk F
+ __nldbl___printf_fp F
+ __nldbl___snprintf_chk F
+ __nldbl___sprintf_chk F
+ __nldbl___strfmon_l F
+ __nldbl___swprintf_chk F
+ __nldbl___syslog_chk F
+ __nldbl___vasprintf_chk F
+ __nldbl___vdprintf_chk F
+ __nldbl___vfprintf_chk F
+ __nldbl___vfscanf F
+ __nldbl___vfwprintf_chk F
+ __nldbl___vprintf_chk F
+ __nldbl___vsnprintf F
+ __nldbl___vsnprintf_chk F
+ __nldbl___vsprintf_chk F
+ __nldbl___vsscanf F
+ __nldbl___vstrfmon F
+ __nldbl___vstrfmon_l F
+ __nldbl___vswprintf_chk F
+ __nldbl___vsyslog_chk F
+ __nldbl___vwprintf_chk F
+ __nldbl___wprintf_chk F
+ __nldbl_asprintf F
+ __nldbl_dprintf F
+ __nldbl_fprintf F
+ __nldbl_fscanf F
+ __nldbl_fwprintf F
+ __nldbl_fwscanf F
+ __nldbl_obstack_printf F
+ __nldbl_obstack_vprintf F
+ __nldbl_printf F
+ __nldbl_printf_size F
+ __nldbl_scanf F
+ __nldbl_snprintf F
+ __nldbl_sprintf F
+ __nldbl_sscanf F
+ __nldbl_strfmon F
+ __nldbl_strfmon_l F
+ __nldbl_swprintf F
+ __nldbl_swscanf F
+ __nldbl_syslog F
+ __nldbl_vasprintf F
+ __nldbl_vdprintf F
+ __nldbl_vfprintf F
+ __nldbl_vfscanf F
+ __nldbl_vfwprintf F
+ __nldbl_vfwscanf F
+ __nldbl_vprintf F
+ __nldbl_vscanf F
+ __nldbl_vsnprintf F
+ __nldbl_vsprintf F
+ __nldbl_vsscanf F
+ __nldbl_vswprintf F
+ __nldbl_vswscanf F
+ __nldbl_vsyslog F
+ __nldbl_vwprintf F
+ __nldbl_vwscanf F
+ __nldbl_wprintf F
+ __nldbl_wscanf F
+ __nss_configure_lookup F
+ __nss_database_lookup F
+ __nss_group_lookup F
+ __nss_hostname_digits_dots F
+ __nss_hosts_lookup F
+ __nss_next F
+ __nss_passwd_lookup F
+ __obstack_printf_chk F
+ __obstack_vprintf_chk F
+ __open F
+ __open64 F
+ __open64_2 F
+ __open_2 F
+ __openat64_2 F
+ __openat_2 F
+ __overflow F
+ __pipe F
+ __poll F
+ __poll_chk F
+ __posix_getopt F
+ __ppc_get_timebase_freq F
+ __ppoll_chk F
+ __pread64 F
+ __pread64_chk F
+ __pread_chk F
+ __printf_chk F
+ __printf_fp F
+ __profile_frequency F
+ __progname D 0x8
+ __progname_full D 0x8
+ __ptsname_r_chk F
+ __pwrite64 F
+ __rawmemchr F
+ __rcmd_errstr D 0x8
+ __read F
+ __read_chk F
+ __readlink_chk F
+ __readlinkat_chk F
+ __realloc_hook D 0x8
+ __realpath_chk F
+ __recv_chk F
+ __recvfrom_chk F
+ __register_atfork F
+ __res_init F
+ __res_nclose F
+ __res_ninit F
+ __res_randomid F
+ __res_state F
+ __rpc_thread_createerr F
+ __rpc_thread_svc_fdset F
+ __rpc_thread_svc_max_pollfd F
+ __rpc_thread_svc_pollfd F
+ __sbrk F
+ __sched_cpualloc F
+ __sched_cpucount F
+ __sched_cpufree F
+ __sched_get_priority_max F
+ __sched_get_priority_min F
+ __sched_getparam F
+ __sched_getscheduler F
+ __sched_setscheduler F
+ __sched_yield F
+ __select F
+ __send F
+ __setmntent F
+ __setpgid F
+ __sigaction F
+ __sigaddset F
+ __sigdelset F
+ __sigismember F
+ __signbit F
+ __signbitf F
+ __signbitl F
+ __sigpause F
+ __sigsetjmp F
+ __sigsuspend F
+ __snprintf_chk F
+ __sprintf_chk F
+ __stack_chk_fail F
+ __statfs F
+ __stpcpy F
+ __stpcpy_chk F
+ __stpcpy_small F
+ __stpncpy F
+ __stpncpy_chk F
+ __strcasecmp F
+ __strcasecmp_l F
+ __strcasestr F
+ __strcat_chk F
+ __strcoll_l F
+ __strcpy_chk F
+ __strcpy_small F
+ __strcspn_c1 F
+ __strcspn_c2 F
+ __strcspn_c3 F
+ __strdup F
+ __strerror_r F
+ __strfmon_l F
+ __strftime_l F
+ __strncasecmp_l F
+ __strncat_chk F
+ __strncpy_chk F
+ __strndup F
+ __strpbrk_c2 F
+ __strpbrk_c3 F
+ __strsep_1c F
+ __strsep_2c F
+ __strsep_3c F
+ __strsep_g F
+ __strspn_c1 F
+ __strspn_c2 F
+ __strspn_c3 F
+ __strtod_internal F
+ __strtod_l F
+ __strtof_internal F
+ __strtof_l F
+ __strtok_r F
+ __strtok_r_1c F
+ __strtol_internal F
+ __strtol_l F
+ __strtold_internal F
+ __strtold_l F
+ __strtoll_internal F
+ __strtoll_l F
+ __strtoul_internal F
+ __strtoul_l F
+ __strtoull_internal F
+ __strtoull_l F
+ __strverscmp F
+ __strxfrm_l F
+ __swprintf_chk F
+ __sysconf F
+ __sysctl F
+ __syslog_chk F
+ __sysv_signal F
+ __timezone D 0x8
+ __toascii_l F
+ __tolower_l F
+ __toupper_l F
+ __towctrans F
+ __towctrans_l F
+ __towlower_l F
+ __towupper_l F
+ __ttyname_r_chk F
+ __tzname D 0x10
+ __uflow F
+ __underflow F
+ __uselocale F
+ __vasprintf_chk F
+ __vdprintf_chk F
+ __vfork F
+ __vfprintf_chk F
+ __vfscanf F
+ __vfwprintf_chk F
+ __vprintf_chk F
+ __vsnprintf F
+ __vsnprintf_chk F
+ __vsprintf_chk F
+ __vsscanf F
+ __vswprintf_chk F
+ __vsyslog_chk F
+ __vwprintf_chk F
+ __wait F
+ __waitpid F
+ __wcpcpy_chk F
+ __wcpncpy_chk F
+ __wcrtomb_chk F
+ __wcscasecmp_l F
+ __wcscat_chk F
+ __wcscoll_l F
+ __wcscpy_chk F
+ __wcsftime_l F
+ __wcsncasecmp_l F
+ __wcsncat_chk F
+ __wcsncpy_chk F
+ __wcsnrtombs_chk F
+ __wcsrtombs_chk F
+ __wcstod_internal F
+ __wcstod_l F
+ __wcstof_internal F
+ __wcstof_l F
+ __wcstol_internal F
+ __wcstol_l F
+ __wcstold_internal F
+ __wcstold_l F
+ __wcstoll_internal F
+ __wcstoll_l F
+ __wcstombs_chk F
+ __wcstoul_internal F
+ __wcstoul_l F
+ __wcstoull_internal F
+ __wcstoull_l F
+ __wcsxfrm_l F
+ __wctomb_chk F
+ __wctrans_l F
+ __wctype_l F
+ __wmemcpy_chk F
+ __wmemmove_chk F
+ __wmempcpy_chk F
+ __wmemset_chk F
+ __woverflow F
+ __wprintf_chk F
+ __write F
+ __wuflow F
+ __wunderflow F
+ __xmknod F
+ __xmknodat F
+ __xpg_basename F
+ __xpg_sigpause F
+ __xpg_strerror_r F
+ __xstat F
+ __xstat64 F
+ _authenticate F
+ _dl_mcount_wrapper F
+ _dl_mcount_wrapper_check F
+ _environ D 0x8
+ _exit F
+ _flushlbf F
+ _libc_intl_domainname D 0x5
+ _longjmp F
+ _mcleanup F
+ _mcount F
+ _nl_default_dirname D 0x12
+ _nl_domain_bindings D 0x8
+ _nl_msg_cat_cntr D 0x4
+ _null_auth D 0x18
+ _obstack_allocated_p F
+ _obstack_begin F
+ _obstack_begin_1 F
+ _obstack_free F
+ _obstack_memory_used F
+ _obstack_newchunk F
+ _res D 0x238
+ _res_hconf D 0x48
+ _rpc_dtablesize F
+ _seterr_reply F
+ _setjmp F
+ _sys_errlist D 0x438
+ _sys_nerr D 0x4
+ _sys_siglist D 0x208
+ _tolower F
+ _toupper F
+ a64l F
+ abort F
+ abs F
+ accept F
+ accept4 F
+ access F
+ acct F
+ addmntent F
+ addseverity F
+ adjtime F
+ adjtimex F
+ advance F
+ alarm F
+ aligned_alloc F
+ alphasort F
+ alphasort64 F
+ argp_err_exit_status D 0x4
+ argp_error F
+ argp_failure F
+ argp_help F
+ argp_parse F
+ argp_program_bug_address D 0x8
+ argp_program_version D 0x8
+ argp_program_version_hook D 0x8
+ argp_state_help F
+ argp_usage F
+ argz_add F
+ argz_add_sep F
+ argz_append F
+ argz_count F
+ argz_create F
+ argz_create_sep F
+ argz_delete F
+ argz_extract F
+ argz_insert F
+ argz_next F
+ argz_replace F
+ argz_stringify F
+ asctime F
+ asctime_r F
+ asprintf F
+ atof F
+ atoi F
+ atol F
+ atoll F
+ authdes_create F
+ authdes_getucred F
+ authdes_pk_create F
+ authnone_create F
+ authunix_create F
+ authunix_create_default F
+ backtrace F
+ backtrace_symbols F
+ backtrace_symbols_fd F
+ basename F
+ bcmp F
+ bcopy F
+ bdflush F
+ bind F
+ bind_textdomain_codeset F
+ bindresvport F
+ bindtextdomain F
+ brk F
+ bsd_signal F
+ bsearch F
+ btowc F
+ bzero F
+ c16rtomb F
+ c32rtomb F
+ calloc F
+ callrpc F
+ canonicalize_file_name F
+ capget F
+ capset F
+ catclose F
+ catgets F
+ catopen F
+ cbc_crypt F
+ cfgetispeed F
+ cfgetospeed F
+ cfmakeraw F
+ cfree F
+ cfsetispeed F
+ cfsetospeed F
+ cfsetspeed F
+ chdir F
+ chflags F
+ chmod F
+ chown F
+ chroot F
+ clearenv F
+ clearerr F
+ clearerr_unlocked F
+ clnt_broadcast F
+ clnt_create F
+ clnt_pcreateerror F
+ clnt_perrno F
+ clnt_perror F
+ clnt_spcreateerror F
+ clnt_sperrno F
+ clnt_sperror F
+ clntraw_create F
+ clnttcp_create F
+ clntudp_bufcreate F
+ clntudp_create F
+ clntunix_create F
+ clock F
+ clock_adjtime F
+ clock_getcpuclockid F
+ clock_getres F
+ clock_gettime F
+ clock_nanosleep F
+ clock_settime F
+ clone F
+ close F
+ closedir F
+ closelog F
+ confstr F
+ connect F
+ copysign F
+ copysignf F
+ copysignl F
+ creat F
+ creat64 F
+ create_module F
+ ctermid F
+ ctime F
+ ctime_r F
+ cuserid F
+ daemon F
+ daylight D 0x4
+ dcgettext F
+ dcngettext F
+ delete_module F
+ des_setparity F
+ dgettext F
+ difftime F
+ dirfd F
+ dirname F
+ div F
+ dl_iterate_phdr F
+ dngettext F
+ dprintf F
+ drand48 F
+ drand48_r F
+ dup F
+ dup2 F
+ dup3 F
+ duplocale F
+ dysize F
+ eaccess F
+ ecb_crypt F
+ ecvt F
+ ecvt_r F
+ endaliasent F
+ endfsent F
+ endgrent F
+ endhostent F
+ endmntent F
+ endnetent F
+ endnetgrent F
+ endprotoent F
+ endpwent F
+ endrpcent F
+ endservent F
+ endsgent F
+ endspent F
+ endttyent F
+ endusershell F
+ endutent F
+ endutxent F
+ environ D 0x8
+ envz_add F
+ envz_entry F
+ envz_get F
+ envz_merge F
+ envz_remove F
+ envz_strip F
+ epoll_create F
+ epoll_create1 F
+ epoll_ctl F
+ epoll_pwait F
+ epoll_wait F
+ erand48 F
+ erand48_r F
+ err F
+ error F
+ error_at_line F
+ error_message_count D 0x4
+ error_one_per_line D 0x4
+ error_print_progname D 0x8
+ errx F
+ ether_aton F
+ ether_aton_r F
+ ether_hostton F
+ ether_line F
+ ether_ntoa F
+ ether_ntoa_r F
+ ether_ntohost F
+ euidaccess F
+ eventfd F
+ eventfd_read F
+ eventfd_write F
+ execl F
+ execle F
+ execlp F
+ execv F
+ execve F
+ execvp F
+ execvpe F
+ exit F
+ faccessat F
+ fallocate F
+ fallocate64 F
+ fanotify_init F
+ fanotify_mark F
+ fattach F
+ fchdir F
+ fchflags F
+ fchmod F
+ fchmodat F
+ fchown F
+ fchownat F
+ fclose F
+ fcloseall F
+ fcntl F
+ fcvt F
+ fcvt_r F
+ fdatasync F
+ fdetach F
+ fdopen F
+ fdopendir F
+ feof F
+ feof_unlocked F
+ ferror F
+ ferror_unlocked F
+ fexecve F
+ fflush F
+ fflush_unlocked F
+ ffs F
+ ffsl F
+ ffsll F
+ fgetc F
+ fgetc_unlocked F
+ fgetgrent F
+ fgetgrent_r F
+ fgetpos F
+ fgetpos64 F
+ fgetpwent F
+ fgetpwent_r F
+ fgets F
+ fgets_unlocked F
+ fgetsgent F
+ fgetsgent_r F
+ fgetspent F
+ fgetspent_r F
+ fgetwc F
+ fgetwc_unlocked F
+ fgetws F
+ fgetws_unlocked F
+ fgetxattr F
+ fileno F
+ fileno_unlocked F
+ finite F
+ finitef F
+ finitel F
+ flistxattr F
+ flock F
+ flockfile F
+ fmemopen F
+ fmtmsg F
+ fnmatch F
+ fopen F
+ fopen64 F
+ fopencookie F
+ fork F
+ fpathconf F
+ fprintf F
+ fputc F
+ fputc_unlocked F
+ fputs F
+ fputs_unlocked F
+ fputwc F
+ fputwc_unlocked F
+ fputws F
+ fputws_unlocked F
+ fread F
+ fread_unlocked F
+ free F
+ freeaddrinfo F
+ freeifaddrs F
+ freelocale F
+ fremovexattr F
+ freopen F
+ freopen64 F
+ frexp F
+ frexpf F
+ frexpl F
+ fscanf F
+ fseek F
+ fseeko F
+ fseeko64 F
+ fsetpos F
+ fsetpos64 F
+ fsetxattr F
+ fstatfs F
+ fstatfs64 F
+ fstatvfs F
+ fstatvfs64 F
+ fsync F
+ ftell F
+ ftello F
+ ftello64 F
+ ftime F
+ ftok F
+ ftruncate F
+ ftruncate64 F
+ ftrylockfile F
+ fts_children F
+ fts_close F
+ fts_open F
+ fts_read F
+ fts_set F
+ ftw F
+ ftw64 F
+ funlockfile F
+ futimens F
+ futimes F
+ futimesat F
+ fwide F
+ fwprintf F
+ fwrite F
+ fwrite_unlocked F
+ fwscanf F
+ gai_strerror F
+ gcvt F
+ get_avphys_pages F
+ get_current_dir_name F
+ get_kernel_syms F
+ get_myaddress F
+ get_nprocs F
+ get_nprocs_conf F
+ get_phys_pages F
+ getaddrinfo F
+ getaliasbyname F
+ getaliasbyname_r F
+ getaliasent F
+ getaliasent_r F
+ getauxval F
+ getc F
+ getc_unlocked F
+ getchar F
+ getchar_unlocked F
+ getcontext F
+ getcwd F
+ getdate F
+ getdate_err D 0x4
+ getdate_r F
+ getdelim F
+ getdirentries F
+ getdirentries64 F
+ getdomainname F
+ getdtablesize F
+ getegid F
+ getenv F
+ geteuid F
+ getfsent F
+ getfsfile F
+ getfsspec F
+ getgid F
+ getgrent F
+ getgrent_r F
+ getgrgid F
+ getgrgid_r F
+ getgrnam F
+ getgrnam_r F
+ getgrouplist F
+ getgroups F
+ gethostbyaddr F
+ gethostbyaddr_r F
+ gethostbyname F
+ gethostbyname2 F
+ gethostbyname2_r F
+ gethostbyname_r F
+ gethostent F
+ gethostent_r F
+ gethostid F
+ gethostname F
+ getifaddrs F
+ getipv4sourcefilter F
+ getitimer F
+ getline F
+ getloadavg F
+ getlogin F
+ getlogin_r F
+ getmntent F
+ getmntent_r F
+ getmsg F
+ getnameinfo F
+ getnetbyaddr F
+ getnetbyaddr_r F
+ getnetbyname F
+ getnetbyname_r F
+ getnetent F
+ getnetent_r F
+ getnetgrent F
+ getnetgrent_r F
+ getnetname F
+ getopt F
+ getopt_long F
+ getopt_long_only F
+ getpagesize F
+ getpass F
+ getpeername F
+ getpgid F
+ getpgrp F
+ getpid F
+ getpmsg F
+ getppid F
+ getpriority F
+ getprotobyname F
+ getprotobyname_r F
+ getprotobynumber F
+ getprotobynumber_r F
+ getprotoent F
+ getprotoent_r F
+ getpt F
+ getpublickey F
+ getpw F
+ getpwent F
+ getpwent_r F
+ getpwnam F
+ getpwnam_r F
+ getpwuid F
+ getpwuid_r F
+ getresgid F
+ getresuid F
+ getrlimit F
+ getrlimit64 F
+ getrpcbyname F
+ getrpcbyname_r F
+ getrpcbynumber F
+ getrpcbynumber_r F
+ getrpcent F
+ getrpcent_r F
+ getrpcport F
+ getrusage F
+ gets F
+ getsecretkey F
+ getservbyname F
+ getservbyname_r F
+ getservbyport F
+ getservbyport_r F
+ getservent F
+ getservent_r F
+ getsgent F
+ getsgent_r F
+ getsgnam F
+ getsgnam_r F
+ getsid F
+ getsockname F
+ getsockopt F
+ getsourcefilter F
+ getspent F
+ getspent_r F
+ getspnam F
+ getspnam_r F
+ getsubopt F
+ gettext F
+ gettimeofday F
+ getttyent F
+ getttynam F
+ getuid F
+ getusershell F
+ getutent F
+ getutent_r F
+ getutid F
+ getutid_r F
+ getutline F
+ getutline_r F
+ getutmp F
+ getutmpx F
+ getutxent F
+ getutxid F
+ getutxline F
+ getw F
+ getwc F
+ getwc_unlocked F
+ getwchar F
+ getwchar_unlocked F
+ getwd F
+ getxattr F
+ glob F
+ glob64 F
+ glob_pattern_p F
+ globfree F
+ globfree64 F
+ gmtime F
+ gmtime_r F
+ gnu_dev_major F
+ gnu_dev_makedev F
+ gnu_dev_minor F
+ gnu_get_libc_release F
+ gnu_get_libc_version F
+ grantpt F
+ group_member F
+ gsignal F
+ gtty F
+ h_errlist D 0x28
+ h_nerr D 0x4
+ hasmntopt F
+ hcreate F
+ hcreate_r F
+ hdestroy F
+ hdestroy_r F
+ herror F
+ host2netname F
+ hsearch F
+ hsearch_r F
+ hstrerror F
+ htonl F
+ htons F
+ iconv F
+ iconv_close F
+ iconv_open F
+ if_freenameindex F
+ if_indextoname F
+ if_nameindex F
+ if_nametoindex F
+ imaxabs F
+ imaxdiv F
+ in6addr_any D 0x10
+ in6addr_loopback D 0x10
+ index F
+ inet6_opt_append F
+ inet6_opt_find F
+ inet6_opt_finish F
+ inet6_opt_get_val F
+ inet6_opt_init F
+ inet6_opt_next F
+ inet6_opt_set_val F
+ inet6_option_alloc F
+ inet6_option_append F
+ inet6_option_find F
+ inet6_option_init F
+ inet6_option_next F
+ inet6_option_space F
+ inet6_rth_add F
+ inet6_rth_getaddr F
+ inet6_rth_init F
+ inet6_rth_reverse F
+ inet6_rth_segments F
+ inet6_rth_space F
+ inet_addr F
+ inet_aton F
+ inet_lnaof F
+ inet_makeaddr F
+ inet_netof F
+ inet_network F
+ inet_nsap_addr F
+ inet_nsap_ntoa F
+ inet_ntoa F
+ inet_ntop F
+ inet_pton F
+ init_module F
+ initgroups F
+ initstate F
+ initstate_r F
+ innetgr F
+ inotify_add_watch F
+ inotify_init F
+ inotify_init1 F
+ inotify_rm_watch F
+ insque F
+ ioctl F
+ iruserok F
+ iruserok_af F
+ isalnum F
+ isalnum_l F
+ isalpha F
+ isalpha_l F
+ isascii F
+ isastream F
+ isatty F
+ isblank F
+ isblank_l F
+ iscntrl F
+ iscntrl_l F
+ isctype F
+ isdigit F
+ isdigit_l F
+ isfdtype F
+ isgraph F
+ isgraph_l F
+ isinf F
+ isinff F
+ isinfl F
+ islower F
+ islower_l F
+ isnan F
+ isnanf F
+ isnanl F
+ isprint F
+ isprint_l F
+ ispunct F
+ ispunct_l F
+ isspace F
+ isspace_l F
+ isupper F
+ isupper_l F
+ iswalnum F
+ iswalnum_l F
+ iswalpha F
+ iswalpha_l F
+ iswblank F
+ iswblank_l F
+ iswcntrl F
+ iswcntrl_l F
+ iswctype F
+ iswctype_l F
+ iswdigit F
+ iswdigit_l F
+ iswgraph F
+ iswgraph_l F
+ iswlower F
+ iswlower_l F
+ iswprint F
+ iswprint_l F
+ iswpunct F
+ iswpunct_l F
+ iswspace F
+ iswspace_l F
+ iswupper F
+ iswupper_l F
+ iswxdigit F
+ iswxdigit_l F
+ isxdigit F
+ isxdigit_l F
+ jrand48 F
+ jrand48_r F
+ key_decryptsession F
+ key_decryptsession_pk F
+ key_encryptsession F
+ key_encryptsession_pk F
+ key_gendes F
+ key_get_conv F
+ key_secretkey_is_set F
+ key_setnet F
+ key_setsecret F
+ kill F
+ killpg F
+ klogctl F
+ l64a F
+ labs F
+ lchmod F
+ lchown F
+ lckpwdf F
+ lcong48 F
+ lcong48_r F
+ ldexp F
+ ldexpf F
+ ldexpl F
+ ldiv F
+ lfind F
+ lgetxattr F
+ link F
+ linkat F
+ listen F
+ listxattr F
+ llabs F
+ lldiv F
+ llistxattr F
+ llseek F
+ loc1 D 0x8
+ loc2 D 0x8
+ localeconv F
+ localtime F
+ localtime_r F
+ lockf F
+ lockf64 F
+ locs D 0x8
+ longjmp F
+ lrand48 F
+ lrand48_r F
+ lremovexattr F
+ lsearch F
+ lseek F
+ lseek64 F
+ lsetxattr F
+ lutimes F
+ madvise F
+ makecontext F
+ mallinfo F
+ malloc F
+ malloc_get_state F
+ malloc_info F
+ malloc_set_state F
+ malloc_stats F
+ malloc_trim F
+ malloc_usable_size F
+ mallopt F
+ mallwatch D 0x8
+ mblen F
+ mbrlen F
+ mbrtoc16 F
+ mbrtoc32 F
+ mbrtowc F
+ mbsinit F
+ mbsnrtowcs F
+ mbsrtowcs F
+ mbstowcs F
+ mbtowc F
+ mcheck F
+ mcheck_check_all F
+ mcheck_pedantic F
+ memalign F
+ memccpy F
+ memchr F
+ memcmp F
+ memcpy F
+ memfrob F
+ memmem F
+ memmove F
+ mempcpy F
+ memrchr F
+ memset F
+ mincore F
+ mkdir F
+ mkdirat F
+ mkdtemp F
+ mkfifo F
+ mkfifoat F
+ mkostemp F
+ mkostemp64 F
+ mkostemps F
+ mkostemps64 F
+ mkstemp F
+ mkstemp64 F
+ mkstemps F
+ mkstemps64 F
+ mktemp F
+ mktime F
+ mlock F
+ mlockall F
+ mmap F
+ mmap64 F
+ modf F
+ modff F
+ modfl F
+ moncontrol F
+ monstartup F
+ mount F
+ mprobe F
+ mprotect F
+ mrand48 F
+ mrand48_r F
+ mremap F
+ msgctl F
+ msgget F
+ msgrcv F
+ msgsnd F
+ msync F
+ mtrace F
+ munlock F
+ munlockall F
+ munmap F
+ muntrace F
+ name_to_handle_at F
+ nanosleep F
+ netname2host F
+ netname2user F
+ newlocale F
+ nfsservctl F
+ nftw F
+ nftw64 F
+ ngettext F
+ nice F
+ nl_langinfo F
+ nl_langinfo_l F
+ nrand48 F
+ nrand48_r F
+ ntohl F
+ ntohs F
+ ntp_adjtime F
+ ntp_gettime F
+ ntp_gettimex F
+ obstack_alloc_failed_handler D 0x8
+ obstack_exit_failure D 0x4
+ obstack_free F
+ obstack_printf F
+ obstack_vprintf F
+ on_exit F
+ open F
+ open64 F
+ open_by_handle_at F
+ open_memstream F
+ open_wmemstream F
+ openat F
+ openat64 F
+ opendir F
+ openlog F
+ optarg D 0x8
+ opterr D 0x4
+ optind D 0x4
+ optopt D 0x4
+ parse_printf_format F
+ passwd2des F
+ pathconf F
+ pause F
+ pclose F
+ perror F
+ personality F
+ pipe F
+ pipe2 F
+ pivot_root F
+ pmap_getmaps F
+ pmap_getport F
+ pmap_rmtcall F
+ pmap_set F
+ pmap_unset F
+ poll F
+ popen F
+ posix_fadvise F
+ posix_fadvise64 F
+ posix_fallocate F
+ posix_fallocate64 F
+ posix_madvise F
+ posix_memalign F
+ posix_openpt F
+ posix_spawn F
+ posix_spawn_file_actions_addclose F
+ posix_spawn_file_actions_adddup2 F
+ posix_spawn_file_actions_addopen F
+ posix_spawn_file_actions_destroy F
+ posix_spawn_file_actions_init F
+ posix_spawnattr_destroy F
+ posix_spawnattr_getflags F
+ posix_spawnattr_getpgroup F
+ posix_spawnattr_getschedparam F
+ posix_spawnattr_getschedpolicy F
+ posix_spawnattr_getsigdefault F
+ posix_spawnattr_getsigmask F
+ posix_spawnattr_init F
+ posix_spawnattr_setflags F
+ posix_spawnattr_setpgroup F
+ posix_spawnattr_setschedparam F
+ posix_spawnattr_setschedpolicy F
+ posix_spawnattr_setsigdefault F
+ posix_spawnattr_setsigmask F
+ posix_spawnp F
+ ppoll F
+ prctl F
+ pread F
+ pread64 F
+ preadv F
+ preadv64 F
+ printf F
+ printf_size F
+ printf_size_info F
+ prlimit F
+ prlimit64 F
+ process_vm_readv F
+ process_vm_writev F
+ profil F
+ program_invocation_name D 0x8
+ program_invocation_short_name D 0x8
+ pselect F
+ psiginfo F
+ psignal F
+ pthread_attr_destroy F
+ pthread_attr_getdetachstate F
+ pthread_attr_getinheritsched F
+ pthread_attr_getschedparam F
+ pthread_attr_getschedpolicy F
+ pthread_attr_getscope F
+ pthread_attr_init F
+ pthread_attr_setdetachstate F
+ pthread_attr_setinheritsched F
+ pthread_attr_setschedparam F
+ pthread_attr_setschedpolicy F
+ pthread_attr_setscope F
+ pthread_cond_broadcast F
+ pthread_cond_destroy F
+ pthread_cond_init F
+ pthread_cond_signal F
+ pthread_cond_timedwait F
+ pthread_cond_wait F
+ pthread_condattr_destroy F
+ pthread_condattr_init F
+ pthread_equal F
+ pthread_exit F
+ pthread_getschedparam F
+ pthread_mutex_destroy F
+ pthread_mutex_init F
+ pthread_mutex_lock F
+ pthread_mutex_unlock F
+ pthread_self F
+ pthread_setcancelstate F
+ pthread_setcanceltype F
+ pthread_setschedparam F
+ ptrace F
+ ptsname F
+ ptsname_r F
+ putc F
+ putc_unlocked F
+ putchar F
+ putchar_unlocked F
+ putenv F
+ putgrent F
+ putmsg F
+ putpmsg F
+ putpwent F
+ puts F
+ putsgent F
+ putspent F
+ pututline F
+ pututxline F
+ putw F
+ putwc F
+ putwc_unlocked F
+ putwchar F
+ putwchar_unlocked F
+ pvalloc F
+ pwrite F
+ pwrite64 F
+ pwritev F
+ pwritev64 F
+ qecvt F
+ qecvt_r F
+ qfcvt F
+ qfcvt_r F
+ qgcvt F
+ qsort F
+ qsort_r F
+ query_module F
+ quick_exit F
+ quotactl F
+ raise F
+ rand F
+ rand_r F
+ random F
+ random_r F
+ rawmemchr F
+ rcmd F
+ rcmd_af F
+ re_comp F
+ re_compile_fastmap F
+ re_compile_pattern F
+ re_exec F
+ re_match F
+ re_match_2 F
+ re_search F
+ re_search_2 F
+ re_set_registers F
+ re_set_syntax F
+ re_syntax_options D 0x8
+ read F
+ readahead F
+ readdir F
+ readdir64 F
+ readdir64_r F
+ readdir_r F
+ readlink F
+ readlinkat F
+ readv F
+ realloc F
+ realpath F
+ reboot F
+ recv F
+ recvfrom F
+ recvmmsg F
+ recvmsg F
+ regcomp F
+ regerror F
+ regexec F
+ regfree F
+ register_printf_function F
+ register_printf_modifier F
+ register_printf_specifier F
+ register_printf_type F
+ registerrpc F
+ remap_file_pages F
+ remove F
+ removexattr F
+ remque F
+ rename F
+ renameat F
+ revoke F
+ rewind F
+ rewinddir F
+ rexec F
+ rexec_af F
+ rexecoptions D 0x4
+ rindex F
+ rmdir F
+ rpc_createerr D 0x20
+ rpmatch F
+ rresvport F
+ rresvport_af F
+ rtime F
+ ruserok F
+ ruserok_af F
+ ruserpass F
+ sbrk F
+ scalbn F
+ scalbnf F
+ scalbnl F
+ scandir F
+ scandir64 F
+ scandirat F
+ scandirat64 F
+ scanf F
+ sched_get_priority_max F
+ sched_get_priority_min F
+ sched_getaffinity F
+ sched_getcpu F
+ sched_getparam F
+ sched_getscheduler F
+ sched_rr_get_interval F
+ sched_setaffinity F
+ sched_setparam F
+ sched_setscheduler F
+ sched_yield F
+ secure_getenv F
+ seed48 F
+ seed48_r F
+ seekdir F
+ select F
+ semctl F
+ semget F
+ semop F
+ semtimedop F
+ send F
+ sendfile F
+ sendfile64 F
+ sendmmsg F
+ sendmsg F
+ sendto F
+ setaliasent F
+ setbuf F
+ setbuffer F
+ setcontext F
+ setdomainname F
+ setegid F
+ setenv F
+ seteuid F
+ setfsent F
+ setfsgid F
+ setfsuid F
+ setgid F
+ setgrent F
+ setgroups F
+ sethostent F
+ sethostid F
+ sethostname F
+ setipv4sourcefilter F
+ setitimer F
+ setjmp F
+ setlinebuf F
+ setlocale F
+ setlogin F
+ setlogmask F
+ setmntent F
+ setnetent F
+ setnetgrent F
+ setns F
+ setpgid F
+ setpgrp F
+ setpriority F
+ setprotoent F
+ setpwent F
+ setregid F
+ setresgid F
+ setresuid F
+ setreuid F
+ setrlimit F
+ setrlimit64 F
+ setrpcent F
+ setservent F
+ setsgent F
+ setsid F
+ setsockopt F
+ setsourcefilter F
+ setspent F
+ setstate F
+ setstate_r F
+ settimeofday F
+ setttyent F
+ setuid F
+ setusershell F
+ setutent F
+ setutxent F
+ setvbuf F
+ setxattr F
+ sgetsgent F
+ sgetsgent_r F
+ sgetspent F
+ sgetspent_r F
+ shmat F
+ shmctl F
+ shmdt F
+ shmget F
+ shutdown F
+ sigaction F
+ sigaddset F
+ sigaltstack F
+ sigandset F
+ sigblock F
+ sigdelset F
+ sigemptyset F
+ sigfillset F
+ siggetmask F
+ sighold F
+ sigignore F
+ siginterrupt F
+ sigisemptyset F
+ sigismember F
+ siglongjmp F
+ signal F
+ signalfd F
+ sigorset F
+ sigpause F
+ sigpending F
+ sigprocmask F
+ sigqueue F
+ sigrelse F
+ sigreturn F
+ sigset F
+ sigsetmask F
+ sigstack F
+ sigsuspend F
+ sigtimedwait F
+ sigvec F
+ sigwait F
+ sigwaitinfo F
+ sleep F
+ snprintf F
+ sockatmark F
+ socket F
+ socketpair F
+ splice F
+ sprintf F
+ sprofil F
+ srand F
+ srand48 F
+ srand48_r F
+ srandom F
+ srandom_r F
+ sscanf F
+ ssignal F
+ sstk F
+ statfs F
+ statfs64 F
+ statvfs F
+ statvfs64 F
+ stderr D 0x8
+ stdin D 0x8
+ stdout D 0x8
+ step F
+ stime F
+ stpcpy F
+ stpncpy F
+ strcasecmp F
+ strcasecmp_l F
+ strcasestr F
+ strcat F
+ strchr F
+ strchrnul F
+ strcmp F
+ strcoll F
+ strcoll_l F
+ strcpy F
+ strcspn F
+ strdup F
+ strerror F
+ strerror_l F
+ strerror_r F
+ strfmon F
+ strfmon_l F
+ strfry F
+ strftime F
+ strftime_l F
+ strlen F
+ strncasecmp F
+ strncasecmp_l F
+ strncat F
+ strncmp F
+ strncpy F
+ strndup F
+ strnlen F
+ strpbrk F
+ strptime F
+ strptime_l F
+ strrchr F
+ strsep F
+ strsignal F
+ strspn F
+ strstr F
+ strtod F
+ strtod_l F
+ strtof F
+ strtof_l F
+ strtoimax F
+ strtok F
+ strtok_r F
+ strtol F
+ strtol_l F
+ strtold F
+ strtold_l F
+ strtoll F
+ strtoll_l F
+ strtoq F
+ strtoul F
+ strtoul_l F
+ strtoull F
+ strtoull_l F
+ strtoumax F
+ strtouq F
+ strverscmp F
+ strxfrm F
+ strxfrm_l F
+ stty F
+ svc_exit F
+ svc_fdset D 0x80
+ svc_getreq F
+ svc_getreq_common F
+ svc_getreq_poll F
+ svc_getreqset F
+ svc_max_pollfd D 0x4
+ svc_pollfd D 0x8
+ svc_register F
+ svc_run F
+ svc_sendreply F
+ svc_unregister F
+ svcauthdes_stats D 0x18
+ svcerr_auth F
+ svcerr_decode F
+ svcerr_noproc F
+ svcerr_noprog F
+ svcerr_progvers F
+ svcerr_systemerr F
+ svcerr_weakauth F
+ svcfd_create F
+ svcraw_create F
+ svctcp_create F
+ svcudp_bufcreate F
+ svcudp_create F
+ svcudp_enablecache F
+ svcunix_create F
+ svcunixfd_create F
+ swab F
+ swapcontext F
+ swapoff F
+ swapon F
+ swprintf F
+ swscanf F
+ symlink F
+ symlinkat F
+ sync F
+ sync_file_range F
+ syncfs F
+ sys_errlist D 0x438
+ sys_nerr D 0x4
+ sys_sigabbrev D 0x208
+ sys_siglist D 0x208
+ syscall F
+ sysconf F
+ sysctl F
+ sysinfo F
+ syslog F
+ system F
+ sysv_signal F
+ tcdrain F
+ tcflow F
+ tcflush F
+ tcgetattr F
+ tcgetpgrp F
+ tcgetsid F
+ tcsendbreak F
+ tcsetattr F
+ tcsetpgrp F
+ tdelete F
+ tdestroy F
+ tee F
+ telldir F
+ tempnam F
+ textdomain F
+ tfind F
+ time F
+ timegm F
+ timelocal F
+ timerfd_create F
+ timerfd_gettime F
+ timerfd_settime F
+ times F
+ timespec_get F
+ timezone D 0x8
+ tmpfile F
+ tmpfile64 F
+ tmpnam F
+ tmpnam_r F
+ toascii F
+ tolower F
+ tolower_l F
+ toupper F
+ toupper_l F
+ towctrans F
+ towctrans_l F
+ towlower F
+ towlower_l F
+ towupper F
+ towupper_l F
+ tr_break F
+ truncate F
+ truncate64 F
+ tsearch F
+ ttyname F
+ ttyname_r F
+ ttyslot F
+ twalk F
+ tzname D 0x10
+ tzset F
+ ualarm F
+ ulckpwdf F
+ ulimit F
+ umask F
+ umount F
+ umount2 F
+ uname F
+ ungetc F
+ ungetwc F
+ unlink F
+ unlinkat F
+ unlockpt F
+ unsetenv F
+ unshare F
+ updwtmp F
+ updwtmpx F
+ uselib F
+ uselocale F
+ user2netname F
+ usleep F
+ ustat F
+ utime F
+ utimensat F
+ utimes F
+ utmpname F
+ utmpxname F
+ valloc F
+ vasprintf F
+ vdprintf F
+ verr F
+ verrx F
+ versionsort F
+ versionsort64 F
+ vfork F
+ vfprintf F
+ vfscanf F
+ vfwprintf F
+ vfwscanf F
+ vhangup F
+ vlimit F
+ vmsplice F
+ vprintf F
+ vscanf F
+ vsnprintf F
+ vsprintf F
+ vsscanf F
+ vswprintf F
+ vswscanf F
+ vsyslog F
+ vtimes F
+ vwarn F
+ vwarnx F
+ vwprintf F
+ vwscanf F
+ wait F
+ wait3 F
+ wait4 F
+ waitid F
+ waitpid F
+ warn F
+ warnx F
+ wcpcpy F
+ wcpncpy F
+ wcrtomb F
+ wcscasecmp F
+ wcscasecmp_l F
+ wcscat F
+ wcschr F
+ wcschrnul F
+ wcscmp F
+ wcscoll F
+ wcscoll_l F
+ wcscpy F
+ wcscspn F
+ wcsdup F
+ wcsftime F
+ wcsftime_l F
+ wcslen F
+ wcsncasecmp F
+ wcsncasecmp_l F
+ wcsncat F
+ wcsncmp F
+ wcsncpy F
+ wcsnlen F
+ wcsnrtombs F
+ wcspbrk F
+ wcsrchr F
+ wcsrtombs F
+ wcsspn F
+ wcsstr F
+ wcstod F
+ wcstod_l F
+ wcstof F
+ wcstof_l F
+ wcstoimax F
+ wcstok F
+ wcstol F
+ wcstol_l F
+ wcstold F
+ wcstold_l F
+ wcstoll F
+ wcstoll_l F
+ wcstombs F
+ wcstoq F
+ wcstoul F
+ wcstoul_l F
+ wcstoull F
+ wcstoull_l F
+ wcstoumax F
+ wcstouq F
+ wcswcs F
+ wcswidth F
+ wcsxfrm F
+ wcsxfrm_l F
+ wctob F
+ wctomb F
+ wctrans F
+ wctrans_l F
+ wctype F
+ wctype_l F
+ wcwidth F
+ wmemchr F
+ wmemcmp F
+ wmemcpy F
+ wmemmove F
+ wmempcpy F
+ wmemset F
+ wordexp F
+ wordfree F
+ wprintf F
+ write F
+ writev F
+ wscanf F
+ xdecrypt F
+ xdr_accepted_reply F
+ xdr_array F
+ xdr_authdes_cred F
+ xdr_authdes_verf F
+ xdr_authunix_parms F
+ xdr_bool F
+ xdr_bytes F
+ xdr_callhdr F
+ xdr_callmsg F
+ xdr_char F
+ xdr_cryptkeyarg F
+ xdr_cryptkeyarg2 F
+ xdr_cryptkeyres F
+ xdr_des_block F
+ xdr_double F
+ xdr_enum F
+ xdr_float F
+ xdr_free F
+ xdr_getcredres F
+ xdr_hyper F
+ xdr_int F
+ xdr_int16_t F
+ xdr_int32_t F
+ xdr_int64_t F
+ xdr_int8_t F
+ xdr_key_netstarg F
+ xdr_key_netstres F
+ xdr_keybuf F
+ xdr_keystatus F
+ xdr_long F
+ xdr_longlong_t F
+ xdr_netnamestr F
+ xdr_netobj F
+ xdr_opaque F
+ xdr_opaque_auth F
+ xdr_pmap F
+ xdr_pmaplist F
+ xdr_pointer F
+ xdr_quad_t F
+ xdr_reference F
+ xdr_rejected_reply F
+ xdr_replymsg F
+ xdr_rmtcall_args F
+ xdr_rmtcallres F
+ xdr_short F
+ xdr_sizeof F
+ xdr_string F
+ xdr_u_char F
+ xdr_u_hyper F
+ xdr_u_int F
+ xdr_u_long F
+ xdr_u_longlong_t F
+ xdr_u_quad_t F
+ xdr_u_short F
+ xdr_uint16_t F
+ xdr_uint32_t F
+ xdr_uint64_t F
+ xdr_uint8_t F
+ xdr_union F
+ xdr_unixcred F
+ xdr_vector F
+ xdr_void F
+ xdr_wrapstring F
+ xdrmem_create F
+ xdrrec_create F
+ xdrrec_endofrecord F
+ xdrrec_eof F
+ xdrrec_skiprecord F
+ xdrstdio_create F
+ xencrypt F
+ xprt_register F
+ xprt_unregister F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libcrypt-le.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libcrypt-le.abilist
new file mode 100644
index 0000000..0ac28c5
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libcrypt-le.abilist
@@ -0,0 +1,9 @@
+GLIBC_2.18
+ GLIBC_2.18 A
+ crypt F
+ crypt_r F
+ encrypt F
+ encrypt_r F
+ fcrypt F
+ setkey F
+ setkey_r F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libdl-le.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libdl-le.abilist
new file mode 100644
index 0000000..aa89245
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libdl-le.abilist
@@ -0,0 +1,11 @@
+GLIBC_2.18
+ GLIBC_2.18 A
+ dladdr F
+ dladdr1 F
+ dlclose F
+ dlerror F
+ dlinfo F
+ dlmopen F
+ dlopen F
+ dlsym F
+ dlvsym F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libm-le.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libm-le.abilist
new file mode 100644
index 0000000..9bb4cbf
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libm-le.abilist
@@ -0,0 +1,405 @@
+GLIBC_2.18
+ GLIBC_2.18 A
+ _LIB_VERSION D 0x4
+ __acos_finite F
+ __acosf_finite F
+ __acosh_finite F
+ __acoshf_finite F
+ __acoshl_finite F
+ __acosl_finite F
+ __asin_finite F
+ __asinf_finite F
+ __asinl_finite F
+ __atan2_finite F
+ __atan2f_finite F
+ __atan2l_finite F
+ __atanh_finite F
+ __atanhf_finite F
+ __atanhl_finite F
+ __clog10 F
+ __clog10f F
+ __clog10l F
+ __cosh_finite F
+ __coshf_finite F
+ __coshl_finite F
+ __exp10_finite F
+ __exp10f_finite F
+ __exp10l_finite F
+ __exp2_finite F
+ __exp2f_finite F
+ __exp2l_finite F
+ __exp_finite F
+ __expf_finite F
+ __expl_finite F
+ __fe_dfl_env D 0x8
+ __fe_enabled_env D 0x8
+ __fe_nomask_env F
+ __fe_nonieee_env D 0x8
+ __finite F
+ __finitef F
+ __finitel F
+ __fmod_finite F
+ __fmodf_finite F
+ __fmodl_finite F
+ __fpclassify F
+ __fpclassifyf F
+ __fpclassifyl F
+ __gamma_r_finite F
+ __gammaf_r_finite F
+ __gammal_r_finite F
+ __hypot_finite F
+ __hypotf_finite F
+ __hypotl_finite F
+ __issignaling F
+ __issignalingf F
+ __issignalingl F
+ __j0_finite F
+ __j0f_finite F
+ __j0l_finite F
+ __j1_finite F
+ __j1f_finite F
+ __j1l_finite F
+ __jn_finite F
+ __jnf_finite F
+ __jnl_finite F
+ __lgamma_r_finite F
+ __lgammaf_r_finite F
+ __lgammal_r_finite F
+ __log10_finite F
+ __log10f_finite F
+ __log10l_finite F
+ __log2_finite F
+ __log2f_finite F
+ __log2l_finite F
+ __log_finite F
+ __logf_finite F
+ __logl_finite F
+ __nldbl_nexttowardf F
+ __pow_finite F
+ __powf_finite F
+ __powl_finite F
+ __remainder_finite F
+ __remainderf_finite F
+ __remainderl_finite F
+ __scalb_finite F
+ __scalbf_finite F
+ __scalbl_finite F
+ __signbit F
+ __signbitf F
+ __signbitl F
+ __sinh_finite F
+ __sinhf_finite F
+ __sinhl_finite F
+ __sqrt_finite F
+ __sqrtf_finite F
+ __sqrtl_finite F
+ __y0_finite F
+ __y0f_finite F
+ __y0l_finite F
+ __y1_finite F
+ __y1f_finite F
+ __y1l_finite F
+ __yn_finite F
+ __ynf_finite F
+ __ynl_finite F
+ acos F
+ acosf F
+ acosh F
+ acoshf F
+ acoshl F
+ acosl F
+ asin F
+ asinf F
+ asinh F
+ asinhf F
+ asinhl F
+ asinl F
+ atan F
+ atan2 F
+ atan2f F
+ atan2l F
+ atanf F
+ atanh F
+ atanhf F
+ atanhl F
+ atanl F
+ cabs F
+ cabsf F
+ cabsl F
+ cacos F
+ cacosf F
+ cacosh F
+ cacoshf F
+ cacoshl F
+ cacosl F
+ carg F
+ cargf F
+ cargl F
+ casin F
+ casinf F
+ casinh F
+ casinhf F
+ casinhl F
+ casinl F
+ catan F
+ catanf F
+ catanh F
+ catanhf F
+ catanhl F
+ catanl F
+ cbrt F
+ cbrtf F
+ cbrtl F
+ ccos F
+ ccosf F
+ ccosh F
+ ccoshf F
+ ccoshl F
+ ccosl F
+ ceil F
+ ceilf F
+ ceill F
+ cexp F
+ cexpf F
+ cexpl F
+ cimag F
+ cimagf F
+ cimagl F
+ clog F
+ clog10 F
+ clog10f F
+ clog10l F
+ clogf F
+ clogl F
+ conj F
+ conjf F
+ conjl F
+ copysign F
+ copysignf F
+ copysignl F
+ cos F
+ cosf F
+ cosh F
+ coshf F
+ coshl F
+ cosl F
+ cpow F
+ cpowf F
+ cpowl F
+ cproj F
+ cprojf F
+ cprojl F
+ creal F
+ crealf F
+ creall F
+ csin F
+ csinf F
+ csinh F
+ csinhf F
+ csinhl F
+ csinl F
+ csqrt F
+ csqrtf F
+ csqrtl F
+ ctan F
+ ctanf F
+ ctanh F
+ ctanhf F
+ ctanhl F
+ ctanl F
+ drem F
+ dremf F
+ dreml F
+ erf F
+ erfc F
+ erfcf F
+ erfcl F
+ erff F
+ erfl F
+ exp F
+ exp10 F
+ exp10f F
+ exp10l F
+ exp2 F
+ exp2f F
+ exp2l F
+ expf F
+ expl F
+ expm1 F
+ expm1f F
+ expm1l F
+ fabs F
+ fabsf F
+ fabsl F
+ fdim F
+ fdimf F
+ fdiml F
+ feclearexcept F
+ fedisableexcept F
+ feenableexcept F
+ fegetenv F
+ fegetexcept F
+ fegetexceptflag F
+ fegetround F
+ feholdexcept F
+ feraiseexcept F
+ fesetenv F
+ fesetexceptflag F
+ fesetround F
+ fetestexcept F
+ feupdateenv F
+ finite F
+ finitef F
+ finitel F
+ floor F
+ floorf F
+ floorl F
+ fma F
+ fmaf F
+ fmal F
+ fmax F
+ fmaxf F
+ fmaxl F
+ fmin F
+ fminf F
+ fminl F
+ fmod F
+ fmodf F
+ fmodl F
+ frexp F
+ frexpf F
+ frexpl F
+ gamma F
+ gammaf F
+ gammal F
+ hypot F
+ hypotf F
+ hypotl F
+ ilogb F
+ ilogbf F
+ ilogbl F
+ j0 F
+ j0f F
+ j0l F
+ j1 F
+ j1f F
+ j1l F
+ jn F
+ jnf F
+ jnl F
+ ldexp F
+ ldexpf F
+ ldexpl F
+ lgamma F
+ lgamma_r F
+ lgammaf F
+ lgammaf_r F
+ lgammal F
+ lgammal_r F
+ llrint F
+ llrintf F
+ llrintl F
+ llround F
+ llroundf F
+ llroundl F
+ log F
+ log10 F
+ log10f F
+ log10l F
+ log1p F
+ log1pf F
+ log1pl F
+ log2 F
+ log2f F
+ log2l F
+ logb F
+ logbf F
+ logbl F
+ logf F
+ logl F
+ lrint F
+ lrintf F
+ lrintl F
+ lround F
+ lroundf F
+ lroundl F
+ matherr F
+ modf F
+ modff F
+ modfl F
+ nan F
+ nanf F
+ nanl F
+ nearbyint F
+ nearbyintf F
+ nearbyintl F
+ nextafter F
+ nextafterf F
+ nextafterl F
+ nexttoward F
+ nexttowardf F
+ nexttowardl F
+ pow F
+ pow10 F
+ pow10f F
+ pow10l F
+ powf F
+ powl F
+ remainder F
+ remainderf F
+ remainderl F
+ remquo F
+ remquof F
+ remquol F
+ rint F
+ rintf F
+ rintl F
+ round F
+ roundf F
+ roundl F
+ scalb F
+ scalbf F
+ scalbl F
+ scalbln F
+ scalblnf F
+ scalblnl F
+ scalbn F
+ scalbnf F
+ scalbnl F
+ signgam D 0x4
+ significand F
+ significandf F
+ significandl F
+ sin F
+ sincos F
+ sincosf F
+ sincosl F
+ sinf F
+ sinh F
+ sinhf F
+ sinhl F
+ sinl F
+ sqrt F
+ sqrtf F
+ sqrtl F
+ tan F
+ tanf F
+ tanh F
+ tanhf F
+ tanhl F
+ tanl F
+ tgamma F
+ tgammaf F
+ tgammal F
+ trunc F
+ truncf F
+ truncl F
+ y0 F
+ y0f F
+ y0l F
+ y1 F
+ y1f F
+ y1l F
+ yn F
+ ynf F
+ ynl F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libnsl-le.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libnsl-le.abilist
new file mode 100644
index 0000000..a476875
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libnsl-le.abilist
@@ -0,0 +1,123 @@
+GLIBC_2.18
+ GLIBC_2.18 A
+ __free_fdresult F
+ __nis_default_access F
+ __nis_default_group F
+ __nis_default_owner F
+ __nis_default_ttl F
+ __nis_finddirectory F
+ __nis_hash F
+ __nisbind_connect F
+ __nisbind_create F
+ __nisbind_destroy F
+ __nisbind_next F
+ __yp_check F
+ nis_add F
+ nis_add_entry F
+ nis_addmember F
+ nis_checkpoint F
+ nis_clone_directory F
+ nis_clone_object F
+ nis_clone_result F
+ nis_creategroup F
+ nis_destroy_object F
+ nis_destroygroup F
+ nis_dir_cmp F
+ nis_domain_of F
+ nis_domain_of_r F
+ nis_first_entry F
+ nis_free_directory F
+ nis_free_object F
+ nis_free_request F
+ nis_freenames F
+ nis_freeresult F
+ nis_freeservlist F
+ nis_freetags F
+ nis_getnames F
+ nis_getservlist F
+ nis_ismember F
+ nis_leaf_of F
+ nis_leaf_of_r F
+ nis_lerror F
+ nis_list F
+ nis_local_directory F
+ nis_local_group F
+ nis_local_host F
+ nis_local_principal F
+ nis_lookup F
+ nis_mkdir F
+ nis_modify F
+ nis_modify_entry F
+ nis_name_of F
+ nis_name_of_r F
+ nis_next_entry F
+ nis_perror F
+ nis_ping F
+ nis_print_directory F
+ nis_print_entry F
+ nis_print_group F
+ nis_print_group_entry F
+ nis_print_link F
+ nis_print_object F
+ nis_print_result F
+ nis_print_rights F
+ nis_print_table F
+ nis_read_obj F
+ nis_remove F
+ nis_remove_entry F
+ nis_removemember F
+ nis_rmdir F
+ nis_servstate F
+ nis_sperrno F
+ nis_sperror F
+ nis_sperror_r F
+ nis_stats F
+ nis_verifygroup F
+ nis_write_obj F
+ readColdStartFile F
+ writeColdStartFile F
+ xdr_cback_data F
+ xdr_domainname F
+ xdr_keydat F
+ xdr_mapname F
+ xdr_obj_p F
+ xdr_peername F
+ xdr_valdat F
+ xdr_yp_buf F
+ xdr_ypall F
+ xdr_ypbind_binding F
+ xdr_ypbind_resp F
+ xdr_ypbind_resptype F
+ xdr_ypbind_setdom F
+ xdr_ypdelete_args F
+ xdr_ypmap_parms F
+ xdr_ypmaplist F
+ xdr_yppush_status F
+ xdr_yppushresp_xfr F
+ xdr_ypreq_key F
+ xdr_ypreq_nokey F
+ xdr_ypreq_xfr F
+ xdr_ypresp_all F
+ xdr_ypresp_key_val F
+ xdr_ypresp_maplist F
+ xdr_ypresp_master F
+ xdr_ypresp_order F
+ xdr_ypresp_val F
+ xdr_ypresp_xfr F
+ xdr_ypstat F
+ xdr_ypupdate_args F
+ xdr_ypxfrstat F
+ yp_all F
+ yp_bind F
+ yp_first F
+ yp_get_default_domain F
+ yp_maplist F
+ yp_master F
+ yp_match F
+ yp_next F
+ yp_order F
+ yp_unbind F
+ yp_update F
+ ypbinderr_string F
+ yperr_string F
+ ypprot_err F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libpthread-le.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libpthread-le.abilist
new file mode 100644
index 0000000..f25407d
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libpthread-le.abilist
@@ -0,0 +1,226 @@
+GLIBC_2.18
+ GLIBC_2.18 A
+ _IO_flockfile F
+ _IO_ftrylockfile F
+ _IO_funlockfile F
+ __close F
+ __connect F
+ __errno_location F
+ __fcntl F
+ __fork F
+ __h_errno_location F
+ __libc_allocate_rtsig F
+ __libc_current_sigrtmax F
+ __libc_current_sigrtmin F
+ __lseek F
+ __nanosleep F
+ __open F
+ __open64 F
+ __pread64 F
+ __pthread_cleanup_routine F
+ __pthread_getspecific F
+ __pthread_key_create F
+ __pthread_mutex_destroy F
+ __pthread_mutex_init F
+ __pthread_mutex_lock F
+ __pthread_mutex_trylock F
+ __pthread_mutex_unlock F
+ __pthread_mutexattr_destroy F
+ __pthread_mutexattr_init F
+ __pthread_mutexattr_settype F
+ __pthread_once F
+ __pthread_register_cancel F
+ __pthread_register_cancel_defer F
+ __pthread_rwlock_destroy F
+ __pthread_rwlock_init F
+ __pthread_rwlock_rdlock F
+ __pthread_rwlock_tryrdlock F
+ __pthread_rwlock_trywrlock F
+ __pthread_rwlock_unlock F
+ __pthread_rwlock_wrlock F
+ __pthread_setspecific F
+ __pthread_unregister_cancel F
+ __pthread_unregister_cancel_restore F
+ __pthread_unwind_next F
+ __pwrite64 F
+ __read F
+ __res_state F
+ __send F
+ __sigaction F
+ __vfork F
+ __wait F
+ __write F
+ _pthread_cleanup_pop F
+ _pthread_cleanup_pop_restore F
+ _pthread_cleanup_push F
+ _pthread_cleanup_push_defer F
+ accept F
+ close F
+ connect F
+ fcntl F
+ flockfile F
+ fork F
+ fsync F
+ ftrylockfile F
+ funlockfile F
+ longjmp F
+ lseek F
+ lseek64 F
+ msync F
+ nanosleep F
+ open F
+ open64 F
+ pause F
+ pread F
+ pread64 F
+ pthread_attr_destroy F
+ pthread_attr_getaffinity_np F
+ pthread_attr_getdetachstate F
+ pthread_attr_getguardsize F
+ pthread_attr_getinheritsched F
+ pthread_attr_getschedparam F
+ pthread_attr_getschedpolicy F
+ pthread_attr_getscope F
+ pthread_attr_getstack F
+ pthread_attr_getstackaddr F
+ pthread_attr_getstacksize F
+ pthread_attr_init F
+ pthread_attr_setaffinity_np F
+ pthread_attr_setdetachstate F
+ pthread_attr_setguardsize F
+ pthread_attr_setinheritsched F
+ pthread_attr_setschedparam F
+ pthread_attr_setschedpolicy F
+ pthread_attr_setscope F
+ pthread_attr_setstack F
+ pthread_attr_setstackaddr F
+ pthread_attr_setstacksize F
+ pthread_barrier_destroy F
+ pthread_barrier_init F
+ pthread_barrier_wait F
+ pthread_barrierattr_destroy F
+ pthread_barrierattr_getpshared F
+ pthread_barrierattr_init F
+ pthread_barrierattr_setpshared F
+ pthread_cancel F
+ pthread_cond_broadcast F
+ pthread_cond_destroy F
+ pthread_cond_init F
+ pthread_cond_signal F
+ pthread_cond_timedwait F
+ pthread_cond_wait F
+ pthread_condattr_destroy F
+ pthread_condattr_getclock F
+ pthread_condattr_getpshared F
+ pthread_condattr_init F
+ pthread_condattr_setclock F
+ pthread_condattr_setpshared F
+ pthread_create F
+ pthread_detach F
+ pthread_equal F
+ pthread_exit F
+ pthread_getaffinity_np F
+ pthread_getattr_default_np F
+ pthread_getattr_np F
+ pthread_getconcurrency F
+ pthread_getcpuclockid F
+ pthread_getname_np F
+ pthread_getschedparam F
+ pthread_getspecific F
+ pthread_join F
+ pthread_key_create F
+ pthread_key_delete F
+ pthread_kill F
+ pthread_kill_other_threads_np F
+ pthread_mutex_consistent F
+ pthread_mutex_consistent_np F
+ pthread_mutex_destroy F
+ pthread_mutex_getprioceiling F
+ pthread_mutex_init F
+ pthread_mutex_lock F
+ pthread_mutex_setprioceiling F
+ pthread_mutex_timedlock F
+ pthread_mutex_trylock F
+ pthread_mutex_unlock F
+ pthread_mutexattr_destroy F
+ pthread_mutexattr_getkind_np F
+ pthread_mutexattr_getprioceiling F
+ pthread_mutexattr_getprotocol F
+ pthread_mutexattr_getpshared F
+ pthread_mutexattr_getrobust F
+ pthread_mutexattr_getrobust_np F
+ pthread_mutexattr_gettype F
+ pthread_mutexattr_init F
+ pthread_mutexattr_setkind_np F
+ pthread_mutexattr_setprioceiling F
+ pthread_mutexattr_setprotocol F
+ pthread_mutexattr_setpshared F
+ pthread_mutexattr_setrobust F
+ pthread_mutexattr_setrobust_np F
+ pthread_mutexattr_settype F
+ pthread_once F
+ pthread_rwlock_destroy F
+ pthread_rwlock_init F
+ pthread_rwlock_rdlock F
+ pthread_rwlock_timedrdlock F
+ pthread_rwlock_timedwrlock F
+ pthread_rwlock_tryrdlock F
+ pthread_rwlock_trywrlock F
+ pthread_rwlock_unlock F
+ pthread_rwlock_wrlock F
+ pthread_rwlockattr_destroy F
+ pthread_rwlockattr_getkind_np F
+ pthread_rwlockattr_getpshared F
+ pthread_rwlockattr_init F
+ pthread_rwlockattr_setkind_np F
+ pthread_rwlockattr_setpshared F
+ pthread_self F
+ pthread_setaffinity_np F
+ pthread_setattr_default_np F
+ pthread_setcancelstate F
+ pthread_setcanceltype F
+ pthread_setconcurrency F
+ pthread_setname_np F
+ pthread_setschedparam F
+ pthread_setschedprio F
+ pthread_setspecific F
+ pthread_sigmask F
+ pthread_sigqueue F
+ pthread_spin_destroy F
+ pthread_spin_init F
+ pthread_spin_lock F
+ pthread_spin_trylock F
+ pthread_spin_unlock F
+ pthread_testcancel F
+ pthread_timedjoin_np F
+ pthread_tryjoin_np F
+ pthread_yield F
+ pwrite F
+ pwrite64 F
+ raise F
+ read F
+ recv F
+ recvfrom F
+ recvmsg F
+ sem_close F
+ sem_destroy F
+ sem_getvalue F
+ sem_init F
+ sem_open F
+ sem_post F
+ sem_timedwait F
+ sem_trywait F
+ sem_unlink F
+ sem_wait F
+ send F
+ sendmsg F
+ sendto F
+ sigaction F
+ siglongjmp F
+ sigwait F
+ system F
+ tcdrain F
+ vfork F
+ wait F
+ waitpid F
+ write F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libresolv-le.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libresolv-le.abilist
new file mode 100644
index 0000000..4dd7cd0
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libresolv-le.abilist
@@ -0,0 +1,93 @@
+GLIBC_2.18
+ GLIBC_2.18 A
+ __b64_ntop F
+ __b64_pton F
+ __dn_comp F
+ __dn_count_labels F
+ __dn_expand F
+ __dn_skipname F
+ __fp_nquery F
+ __fp_query F
+ __fp_resstat F
+ __hostalias F
+ __loc_aton F
+ __loc_ntoa F
+ __p_cdname F
+ __p_cdnname F
+ __p_class F
+ __p_class_syms D 0xa8
+ __p_fqname F
+ __p_fqnname F
+ __p_option F
+ __p_query F
+ __p_rcode F
+ __p_secstodate F
+ __p_time F
+ __p_type F
+ __p_type_syms D 0x450
+ __putlong F
+ __putshort F
+ __res_close F
+ __res_dnok F
+ __res_hnok F
+ __res_hostalias F
+ __res_isourserver F
+ __res_mailok F
+ __res_mkquery F
+ __res_nameinquery F
+ __res_nmkquery F
+ __res_nquery F
+ __res_nquerydomain F
+ __res_nsearch F
+ __res_nsend F
+ __res_ownok F
+ __res_queriesmatch F
+ __res_query F
+ __res_querydomain F
+ __res_search F
+ __res_send F
+ __sym_ntop F
+ __sym_ntos F
+ __sym_ston F
+ _gethtbyaddr F
+ _gethtbyname F
+ _gethtbyname2 F
+ _gethtent F
+ _getlong F
+ _getshort F
+ _res_opcodes D 0x80
+ _sethtent F
+ inet_net_ntop F
+ inet_net_pton F
+ inet_neta F
+ ns_datetosecs F
+ ns_format_ttl F
+ ns_get16 F
+ ns_get32 F
+ ns_initparse F
+ ns_makecanon F
+ ns_msg_getflag F
+ ns_name_compress F
+ ns_name_ntol F
+ ns_name_ntop F
+ ns_name_pack F
+ ns_name_pton F
+ ns_name_rollback F
+ ns_name_skip F
+ ns_name_uncompress F
+ ns_name_unpack F
+ ns_parse_ttl F
+ ns_parserr F
+ ns_put16 F
+ ns_put32 F
+ ns_samedomain F
+ ns_samename F
+ ns_skiprr F
+ ns_sprintrr F
+ ns_sprintrrf F
+ ns_subdomain F
+ res_gethostbyaddr F
+ res_gethostbyname F
+ res_gethostbyname2 F
+ res_send_setqhook F
+ res_send_setrhook F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/librt-le.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/librt-le.abilist
new file mode 100644
index 0000000..211e046
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/librt-le.abilist
@@ -0,0 +1,42 @@
+GLIBC_2.18
+ GLIBC_2.18 A
+ __mq_open_2 F
+ aio_cancel F
+ aio_cancel64 F
+ aio_error F
+ aio_error64 F
+ aio_fsync F
+ aio_fsync64 F
+ aio_init F
+ aio_read F
+ aio_read64 F
+ aio_return F
+ aio_return64 F
+ aio_suspend F
+ aio_suspend64 F
+ aio_write F
+ aio_write64 F
+ clock_getcpuclockid F
+ clock_getres F
+ clock_gettime F
+ clock_nanosleep F
+ clock_settime F
+ lio_listio F
+ lio_listio64 F
+ mq_close F
+ mq_getattr F
+ mq_notify F
+ mq_open F
+ mq_receive F
+ mq_send F
+ mq_setattr F
+ mq_timedreceive F
+ mq_timedsend F
+ mq_unlink F
+ shm_open F
+ shm_unlink F
+ timer_create F
+ timer_delete F
+ timer_getoverrun F
+ timer_gettime F
+ timer_settime F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libthread_db-le.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libthread_db-le.abilist
new file mode 100644
index 0000000..61d736a
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libthread_db-le.abilist
@@ -0,0 +1,42 @@
+GLIBC_2.18
+ GLIBC_2.18 A
+ td_init F
+ td_log F
+ td_symbol_list F
+ td_ta_clear_event F
+ td_ta_delete F
+ td_ta_enable_stats F
+ td_ta_event_addr F
+ td_ta_event_getmsg F
+ td_ta_get_nthreads F
+ td_ta_get_ph F
+ td_ta_get_stats F
+ td_ta_map_id2thr F
+ td_ta_map_lwp2thr F
+ td_ta_new F
+ td_ta_reset_stats F
+ td_ta_set_event F
+ td_ta_setconcurrency F
+ td_ta_thr_iter F
+ td_ta_tsd_iter F
+ td_thr_clear_event F
+ td_thr_dbresume F
+ td_thr_dbsuspend F
+ td_thr_event_enable F
+ td_thr_event_getmsg F
+ td_thr_get_info F
+ td_thr_getfpregs F
+ td_thr_getgregs F
+ td_thr_getxregs F
+ td_thr_getxregsize F
+ td_thr_set_event F
+ td_thr_setfpregs F
+ td_thr_setgregs F
+ td_thr_setprio F
+ td_thr_setsigpending F
+ td_thr_setxregs F
+ td_thr_sigsetmask F
+ td_thr_tls_get_addr F
+ td_thr_tlsbase F
+ td_thr_tsd F
+ td_thr_validate F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libutil-le.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libutil-le.abilist
new file mode 100644
index 0000000..5563672
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/nptl/libutil-le.abilist
@@ -0,0 +1,8 @@
+GLIBC_2.18
+ GLIBC_2.18 A
+ forkpty F
+ login F
+ login_tty F
+ logout F
+ logwtmp F
+ openpty F

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=8ed28bfe062d1e78f38dd1651b831e9d2318afd6

commit 8ed28bfe062d1e78f38dd1651b831e9d2318afd6
Author: Adhemerval Zanella <azanella@linux.vnet.ibm.com>
Date:   Fri Nov 15 15:10:10 2013 -0600

    Update powerpc-fpu ULPs.

diff --git a/ChangeLog b/ChangeLog
index 3e7c663..d44e821 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
+2013-11-15  Adhemerval Zanella  <azanella@linux.vnet.ibm.com>
+
+	* sysdeps/powerpc/fpu/libm-test-ulps: Update.
+
 2013-11-12  Ulrich Weigand  <Ulrich.Weigand@de.ibm.com>
 
 	* sysdeps/unix/sysv/linux/powerpc/Makefile (abi-variants): Rename
diff --git a/sysdeps/powerpc/fpu/libm-test-ulps b/sysdeps/powerpc/fpu/libm-test-ulps
index 3dcc344..37b2ca1 100644
--- a/sysdeps/powerpc/fpu/libm-test-ulps
+++ b/sysdeps/powerpc/fpu/libm-test-ulps
@@ -5927,11 +5927,31 @@ double: 1
 idouble: 1
 
 # gamma
+Test "gamma (-0x1p-10)":
+double: 1
+idouble: 1
+Test "gamma (-0x1p-15)":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "gamma (-0x1p-20)":
+double: 1
+idouble: 1
+Test "gamma (-0x1p-5)":
+double: 1
+idouble: 1
 Test "gamma (0.7)":
 double: 1
 float: 1
 idouble: 1
 ifloat: 1
+Test "gamma (0x1p-10)":
+float: 1
+ifloat: 1
+Test "gamma (0x1p-30)":
+double: 1
+idouble: 1
 Test "gamma (1.2)":
 double: 1
 float: 2
@@ -6131,9 +6151,9 @@ ildouble: 1
 ldouble: 1
 Test "jn (10, 10.0)":
 double: 2
-float: 1
+float: 2
 idouble: 2
-ifloat: 1
+ifloat: 2
 ildouble: 4
 ldouble: 4
 Test "jn (10, 2.0)":
@@ -6146,6 +6166,14 @@ double: 2
 float: 2
 idouble: 2
 ifloat: 2
+Test "jn (2, 0x1p1023)":
+ildouble: 1
+ldouble: 1
+Test "jn (2, 0x1p127)":
+double: 1
+idouble: 1
+ildouble: 1
+ldouble: 1
 Test "jn (2, 2.4048255576957729)":
 double: 2
 float: 1
@@ -6226,11 +6254,31 @@ ildouble: 7
 ldouble: 7
 
 # lgamma
+Test "lgamma (-0x1p-10)":
+double: 1
+idouble: 1
+Test "lgamma (-0x1p-15)":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "lgamma (-0x1p-20)":
+double: 1
+idouble: 1
+Test "lgamma (-0x1p-5)":
+double: 1
+idouble: 1
 Test "lgamma (0.7)":
 double: 1
 float: 1
 idouble: 1
 ifloat: 1
+Test "lgamma (0x1p-10)":
+float: 1
+ifloat: 1
+Test "lgamma (0x1p-30)":
+double: 1
+idouble: 1
 Test "lgamma (1.2)":
 double: 1
 float: 2
@@ -7337,6 +7385,19 @@ idouble: 3
 ifloat: 1
 ildouble: 1
 ldouble: 1
+Test "yn (2, 0x1.ffff62p+99)":
+double: 1
+idouble: 1
+Test "yn (2, 0x1p1023)":
+ildouble: 1
+ldouble: 1
+Test "yn (2, 0x1p127)":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
 Test "yn (3, 0.125)":
 double: 1
 idouble: 1

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=e7788aa8c0f54c1586b95fb135f065f3e9d71a24

commit e7788aa8c0f54c1586b95fb135f065f3e9d71a24
Author: Ulrich Weigand <Ulrich.Weigand@de.ibm.com>
Date:   Fri Nov 15 12:04:30 2013 -0600

    PowerPC64 ELFv2 ABI 6/6: Bump ld.so soname version number
    
    To avoid having a ELFv2 binary accidentally picking up an old ABI ld.so,
    this patch bumps the soname to ld64.so.2.
    
    In theory (or for testing purposes) this will also allow co-installing
    ld.so versions for both ABIs on the same system.  Note that the kernel
    will already be able to load executables of both ABIs.  However, there
    is currently no plan to use that theoretical possibility in a any
    supported distribution environment ...
    
    Note that in order to check which ABI to use, we need to invoke the
    compiler to check the _CALL_ELF macro; this is done in a new configure
    check in sysdeps/unix/sysv/linux/powerpc/powerpc64/configure.ac,
    replacing the hard-coded value of default-abi in the Makefile.

diff --git a/ChangeLog b/ChangeLog
index 1632319..3e7c663 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,4 +1,23 @@
 2013-11-12  Ulrich Weigand  <Ulrich.Weigand@de.ibm.com>
+
+	* sysdeps/unix/sysv/linux/powerpc/Makefile (abi-variants): Rename
+	"64" to "64-v1".  Add "64-v2".
+	(abi-64-options): Rename to ...
+	(abi-64-v1-options): ... this.   Redefine _CALL_ELF.
+	(abi-64-condition): Rename to ...
+	(abi-64-v1-condition): ... this.  Add _CALL_ELF check.,
+	(abi-64-ld-soname): Rename to ...
+	(abi-64-v1-ld-soname): ... this.
+	(abi-64-v2-options): Define.
+	(abi-64-v2-condition): Likewise.
+	(abi-64-v2-ld-soname): Likewise.
+	* sysdeps/unix/sysv/linux/powerpc/ldconfig.h
+	(SYSDEP_KNOWN_INTERPRETER_NAMES): Add "/lib64/ld64.so.2".
+	* sysdeps/unix/sysv/linux/powerpc/powerpc64/Makefile: Delete file.
+	* sysdeps/unix/sysv/linux/powerpc/powerpc64/configure.ac: New file.
+	* sysdeps/unix/sysv/linux/powerpc/powerpc64/configure: Generate.
+
+2013-11-12  Ulrich Weigand  <Ulrich.Weigand@de.ibm.com>
 	    Alan Modra  <amodra@gmail.com>
 
 	* sysdeps/powerpc/bits/link.h (La_ppc64v2_regs, La_ppc64v2_retval):
diff --git a/sysdeps/unix/sysv/linux/powerpc/Makefile b/sysdeps/unix/sysv/linux/powerpc/Makefile
index cf4de97..395342f 100644
--- a/sysdeps/unix/sysv/linux/powerpc/Makefile
+++ b/sysdeps/unix/sysv/linux/powerpc/Makefile
@@ -1,9 +1,12 @@
-abi-variants := 32 64
+abi-variants := 32 64-v1 64-v2
 abi-32-options := -U__powerpc64__
 abi-32-condition := __WORDSIZE == 32
-abi-64-options := -D__powerpc64__
-abi-64-condition := __WORDSIZE == 64
-abi-64-ld-soname := ld64.so.1
+abi-64-v1-options := -D__powerpc64__ -U_CALL_ELF -D_CALL_ELF=1
+abi-64-v1-condition := __WORDSIZE == 64 && _CALL_ELF != 2
+abi-64-v1-ld-soname := ld64.so.1
+abi-64-v2-options := -D__powerpc64__ -U_CALL_ELF -D_CALL_ELF=2
+abi-64-v2-condition := __WORDSIZE == 64 && _CALL_ELF == 2
+abi-64-v2-ld-soname := ld64.so.2
 
 ifeq ($(subdir),rt)
 librt-routines += rt-sysdep
diff --git a/sysdeps/unix/sysv/linux/powerpc/ldconfig.h b/sysdeps/unix/sysv/linux/powerpc/ldconfig.h
index 2c5f50d..92ea723 100644
--- a/sysdeps/unix/sysv/linux/powerpc/ldconfig.h
+++ b/sysdeps/unix/sysv/linux/powerpc/ldconfig.h
@@ -20,7 +20,8 @@
 
 #define SYSDEP_KNOWN_INTERPRETER_NAMES \
   { "/lib/ld.so.1", FLAG_ELF_LIBC6 },	\
-  { "/lib64/ld64.so.1", FLAG_ELF_LIBC6 },
+  { "/lib64/ld64.so.1", FLAG_ELF_LIBC6 }, \
+  { "/lib64/ld64.so.2", FLAG_ELF_LIBC6 },
 #define SYSDEP_KNOWN_LIBRARY_NAMES \
   { "libc.so.6", FLAG_ELF_LIBC6 },	\
   { "libm.so.6", FLAG_ELF_LIBC6 },
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/Makefile b/sysdeps/unix/sysv/linux/powerpc/powerpc64/Makefile
deleted file mode 100644
index 3ba3b1f..0000000
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/Makefile
+++ /dev/null
@@ -1,2 +0,0 @@
-# See Makeconfig regarding the use of default-abi.
-default-abi := 64
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/configure b/sysdeps/unix/sysv/linux/powerpc/powerpc64/configure
new file mode 100644
index 0000000..dc7c1a7
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/configure
@@ -0,0 +1,167 @@
+# This file is generated from configure.ac by Autoconf.  DO NOT EDIT!
+ # Local configure fragment for sysdeps/unix/sysv/linux/powerpc/powerpc64/.
+
+# Define default-abi according to compiler flags.
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5
+$as_echo_n "checking for grep that handles long lines and -e... " >&6; }
+if ${ac_cv_path_GREP+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -z "$GREP"; then
+  ac_path_GREP_found=false
+  # Loop through the user's path and test for each of PROGNAME-LIST
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_prog in grep ggrep; do
+    for ac_exec_ext in '' $ac_executable_extensions; do
+      ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext"
+      { test -f "$ac_path_GREP" && $as_test_x "$ac_path_GREP"; } || continue
+# Check for GNU ac_path_GREP and select it if it is found.
+  # Check for GNU $ac_path_GREP
+case `"$ac_path_GREP" --version 2>&1` in
+*GNU*)
+  ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;;
+*)
+  ac_count=0
+  $as_echo_n 0123456789 >"conftest.in"
+  while :
+  do
+    cat "conftest.in" "conftest.in" >"conftest.tmp"
+    mv "conftest.tmp" "conftest.in"
+    cp "conftest.in" "conftest.nl"
+    $as_echo 'GREP' >> "conftest.nl"
+    "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+    diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+    as_fn_arith $ac_count + 1 && ac_count=$as_val
+    if test $ac_count -gt ${ac_path_GREP_max-0}; then
+      # Best one so far, save it but keep looking for a better one
+      ac_cv_path_GREP="$ac_path_GREP"
+      ac_path_GREP_max=$ac_count
+    fi
+    # 10*(2^10) chars as input seems more than enough
+    test $ac_count -gt 10 && break
+  done
+  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+      $ac_path_GREP_found && break 3
+    done
+  done
+  done
+IFS=$as_save_IFS
+  if test -z "$ac_cv_path_GREP"; then
+    as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+  fi
+else
+  ac_cv_path_GREP=$GREP
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5
+$as_echo "$ac_cv_path_GREP" >&6; }
+ GREP="$ac_cv_path_GREP"
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5
+$as_echo_n "checking for egrep... " >&6; }
+if ${ac_cv_path_EGREP+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if echo a | $GREP -E '(a|b)' >/dev/null 2>&1
+   then ac_cv_path_EGREP="$GREP -E"
+   else
+     if test -z "$EGREP"; then
+  ac_path_EGREP_found=false
+  # Loop through the user's path and test for each of PROGNAME-LIST
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_prog in egrep; do
+    for ac_exec_ext in '' $ac_executable_extensions; do
+      ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext"
+      { test -f "$ac_path_EGREP" && $as_test_x "$ac_path_EGREP"; } || continue
+# Check for GNU ac_path_EGREP and select it if it is found.
+  # Check for GNU $ac_path_EGREP
+case `"$ac_path_EGREP" --version 2>&1` in
+*GNU*)
+  ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;;
+*)
+  ac_count=0
+  $as_echo_n 0123456789 >"conftest.in"
+  while :
+  do
+    cat "conftest.in" "conftest.in" >"conftest.tmp"
+    mv "conftest.tmp" "conftest.in"
+    cp "conftest.in" "conftest.nl"
+    $as_echo 'EGREP' >> "conftest.nl"
+    "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+    diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+    as_fn_arith $ac_count + 1 && ac_count=$as_val
+    if test $ac_count -gt ${ac_path_EGREP_max-0}; then
+      # Best one so far, save it but keep looking for a better one
+      ac_cv_path_EGREP="$ac_path_EGREP"
+      ac_path_EGREP_max=$ac_count
+    fi
+    # 10*(2^10) chars as input seems more than enough
+    test $ac_count -gt 10 && break
+  done
+  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+      $ac_path_EGREP_found && break 3
+    done
+  done
+  done
+IFS=$as_save_IFS
+  if test -z "$ac_cv_path_EGREP"; then
+    as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+  fi
+else
+  ac_cv_path_EGREP=$EGREP
+fi
+
+   fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5
+$as_echo "$ac_cv_path_EGREP" >&6; }
+ EGREP="$ac_cv_path_EGREP"
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the compiler is using the PowerPC64 ELFv2 ABI" >&5
+$as_echo_n "checking whether the compiler is using the PowerPC64 ELFv2 ABI... " >&6; }
+if ${libc_cv_ppc64_elfv2_abi+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#if _CALL_ELF == 2
+                      yes
+                     #endif
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "yes" >/dev/null 2>&1; then :
+  libc_cv_ppc64_elfv2_abi=yes
+else
+  libc_cv_ppc64_elfv2_abi=no
+fi
+rm -f conftest*
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_ppc64_elfv2_abi" >&5
+$as_echo "$libc_cv_ppc64_elfv2_abi" >&6; }
+if test $libc_cv_ppc64_elfv2_abi = yes; then
+  config_vars="$config_vars
+default-abi = 64-v2"
+else
+  config_vars="$config_vars
+default-abi = 64-v1"
+fi
+
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/configure.ac b/sysdeps/unix/sysv/linux/powerpc/powerpc64/configure.ac
new file mode 100644
index 0000000..52052d2
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/configure.ac
@@ -0,0 +1,16 @@
+GLIBC_PROVIDES dnl See aclocal.m4 in the top level source directory.
+# Local configure fragment for sysdeps/unix/sysv/linux/powerpc/powerpc64/.
+
+# Define default-abi according to compiler flags.
+AC_CACHE_CHECK([whether the compiler is using the PowerPC64 ELFv2 ABI],
+  [libc_cv_ppc64_elfv2_abi],
+  [AC_EGREP_CPP(yes,[#if _CALL_ELF == 2
+                      yes
+                     #endif
+  ], libc_cv_ppc64_elfv2_abi=yes, libc_cv_ppc64_elfv2_abi=no)])
+if test $libc_cv_ppc64_elfv2_abi = yes; then
+  LIBC_CONFIG_VAR([default-abi], [64-v2])
+else
+  LIBC_CONFIG_VAR([default-abi], [64-v1])
+fi
+

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=3e1d1af62ffe085247e84f3d70cfebfbf144f859

commit 3e1d1af62ffe085247e84f3d70cfebfbf144f859
Author: Ulrich Weigand <Ulrich.Weigand@de.ibm.com>
Date:   Fri Nov 15 12:01:33 2013 -0600

    PowerPC64 ELFv2 ABI 5/6: LD_AUDIT interface changes
    
    The ELFv2 ABI changes the calling convention by passing and returning
    structures in registers in more cases than the old ABI:
    http://gcc.gnu.org/ml/gcc-patches/2013-11/msg01145.html
    http://gcc.gnu.org/ml/gcc-patches/2013-11/msg01147.html
    
    For the most part, this does not affect glibc, since glibc assembler
    files do not use structure parameters / return values.  However, one
    place is affected: the LD_AUDIT interface provides a structure to
    the audit routine that contains all registers holding function
    argument and return values for the intercepted PLT call.
    
    Since the new ABI now sometimes uses registers to return values
    that were never used for this purpose in the old ABI, this structure
    has to be extended.  To force audit routines to be modified for the
    new ABI if necessary, the patch defines v2 variants of the la_ppc64
    types and routines.
    
    In addition, the patch contains two unrelated changes to the
    PLT trampoline routines: it fixes a bug where FPR return values
    were stored in the wrong place, and it removes the unnecessary
    save/restore of CR.

diff --git a/ChangeLog b/ChangeLog
index d3f51a2..1632319 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,4 +1,27 @@
 2013-11-12  Ulrich Weigand  <Ulrich.Weigand@de.ibm.com>
+	    Alan Modra  <amodra@gmail.com>
+
+	* sysdeps/powerpc/bits/link.h (La_ppc64v2_regs, La_ppc64v2_retval):
+	New versions for use with the ELFv2 ABI.
+	(la_ppc64v2_gnu_pltenter, la_ppc64v2_gnu_pltexit): Add prototypes.
+	* sysdeps/powerpc/lsdodefs.h (struct La_ppc64v2_regs): Add forward
+	declaration.
+	(struct La_ppc64v2_retval): Likewise.
+	(ARCH_PLTENTER_MEMBERS): Add ppc64v2_gnu_pltenter.
+	(ARCH_PLTEXIT_MEMBERS): Add ppc64v2_gnu_pltexit.
+	* sysdeps/powerpc/powerpc64/dl-machine.h (ARCH_LA_PLTENTER): Define
+	to ppc64v2_gnu_pltenter if _CALL_ELF == 2.
+	(ARCH_LA_PLTEXIT): Define to ppc64v2_gnu_pltexit if _CALL_ELF == 2.
+	* sysdeps/powerpc/powerpc64/dl-trampoline.S (_dl_runtime_resolve):
+	Do not save or restore CR.
+	(FRAME_SIZE, VR_RTN): Provide updated values for _CALL_ELF == 2.
+	(_dl_profile_resolve): Do no save or restore CR.  Support extended
+	return values for ELFv2 ABI.  Fix location of FPR return registers.
+	* sysdeps/powerpc/powerpc64/tst-audit.h (pltenter, pltexit): Provide
+	updated values for _CALL_ELF == 2.
+	(La_regs, La_retval, int_retval): Likewise.
+
+2013-11-12  Ulrich Weigand  <Ulrich.Weigand@de.ibm.com>
 
 	* sysdeps/powerpc/powerpc64/sysdep.h (FRAME_MIN_SIZE): Define.
 	(FRAME_MIN_SIZE_PARM): Likewise.
diff --git a/sysdeps/powerpc/bits/link.h b/sysdeps/powerpc/bits/link.h
index f06092f..2f1da8b 100644
--- a/sysdeps/powerpc/bits/link.h
+++ b/sysdeps/powerpc/bits/link.h
@@ -63,7 +63,7 @@ extern unsigned int la_ppc32_gnu_pltexit (Elf32_Sym *__sym,
 
 __END_DECLS
 
-#else
+#elif _CALL_ELF != 2
 
 /* Registers for entry into PLT on PPC64.  */
 typedef struct La_ppc64_regs
@@ -107,4 +107,48 @@ extern unsigned int la_ppc64_gnu_pltexit (Elf64_Sym *__sym,
 
 __END_DECLS
 
+#else
+
+/* Registers for entry into PLT on PPC64 in the ELFv2 ABI.  */
+typedef struct La_ppc64v2_regs
+{
+  uint64_t lr_reg[8];
+  double lr_fp[13];
+  uint32_t __padding;
+  uint32_t lr_vrsave;
+  uint32_t lr_vreg[12][4] __attribute__ ((aligned (16)));
+  uint64_t lr_r1;
+  uint64_t lr_lr;
+} La_ppc64v2_regs;
+
+/* Return values for calls from PLT on PPC64 in the ELFv2 ABI.  */
+typedef struct La_ppc64v2_retval
+{
+  uint64_t lrv_r3;
+  uint64_t lrv_r4;
+  double lrv_fp[10];
+  uint32_t lrv_vreg[8][4] __attribute__ ((aligned (16)));
+} La_ppc64v2_retval;
+
+
+__BEGIN_DECLS
+
+extern Elf64_Addr la_ppc64v2_gnu_pltenter (Elf64_Sym *__sym,
+					   unsigned int __ndx,
+					   uintptr_t *__refcook,
+					   uintptr_t *__defcook,
+					   La_ppc64v2_regs *__regs,
+					   unsigned int *__flags,
+					   const char *__symname,
+					   long int *__framesizep);
+extern unsigned int la_ppc64v2_gnu_pltexit (Elf64_Sym *__sym,
+					    unsigned int __ndx,
+					    uintptr_t *__refcook,
+					    uintptr_t *__defcook,
+					    const La_ppc64v2_regs *__inregs,
+					    La_ppc64v2_retval *__outregs,
+					    const char *__symname);
+
+__END_DECLS
+
 #endif
diff --git a/sysdeps/powerpc/ldsodefs.h b/sysdeps/powerpc/ldsodefs.h
index ef849e9..435821c 100644
--- a/sysdeps/powerpc/ldsodefs.h
+++ b/sysdeps/powerpc/ldsodefs.h
@@ -25,6 +25,8 @@ struct La_ppc32_regs;
 struct La_ppc32_retval;
 struct La_ppc64_regs;
 struct La_ppc64_retval;
+struct La_ppc64v2_regs;
+struct La_ppc64v2_retval;
 
 #define ARCH_PLTENTER_MEMBERS						\
     Elf32_Addr (*ppc32_gnu_pltenter) (Elf32_Sym *, unsigned int, uintptr_t *, \
@@ -34,7 +36,12 @@ struct La_ppc64_retval;
     Elf64_Addr (*ppc64_gnu_pltenter) (Elf64_Sym *, unsigned int, uintptr_t *, \
 				      uintptr_t *, struct La_ppc64_regs *, \
 				      unsigned int *, const char *name,	\
-				      long int *framesizep)
+				      long int *framesizep);		\
+    Elf64_Addr (*ppc64v2_gnu_pltenter) (Elf64_Sym *, unsigned int,	\
+					uintptr_t *,  uintptr_t *,	\
+					struct La_ppc64v2_regs *,	\
+					unsigned int *, const char *name, \
+					long int *framesizep)
 
 #define ARCH_PLTEXIT_MEMBERS						\
     unsigned int (*ppc32_gnu_pltexit) (Elf32_Sym *, unsigned int,	\
@@ -47,7 +54,14 @@ struct La_ppc64_retval;
 				       uintptr_t *,			\
 				       uintptr_t *,			\
 				       const struct La_ppc64_regs *,	\
-				       struct La_ppc64_retval *, const char *)
+				       struct La_ppc64_retval *,	\
+				       const char *);			\
+    unsigned int (*ppc64v2_gnu_pltexit) (Elf64_Sym *, unsigned int,	\
+					 uintptr_t *,			\
+					 uintptr_t *,			\
+					 const struct La_ppc64v2_regs *,\
+					 struct La_ppc64v2_retval *,	\
+					 const char *)
 
 #include_next <ldsodefs.h>
 
diff --git a/sysdeps/powerpc/powerpc64/dl-machine.h b/sysdeps/powerpc/powerpc64/dl-machine.h
index eccfbb3..36f3916 100644
--- a/sysdeps/powerpc/powerpc64/dl-machine.h
+++ b/sysdeps/powerpc/powerpc64/dl-machine.h
@@ -545,8 +545,13 @@ elf_machine_plt_value (struct link_map *map, const Elf64_Rela *reloc,
 
 
 /* Names of the architecture-specific auditing callback functions.  */
+#if _CALL_ELF != 2
 #define ARCH_LA_PLTENTER ppc64_gnu_pltenter
 #define ARCH_LA_PLTEXIT ppc64_gnu_pltexit
+#else
+#define ARCH_LA_PLTENTER ppc64v2_gnu_pltenter
+#define ARCH_LA_PLTEXIT ppc64v2_gnu_pltexit
+#endif
 
 #endif /* dl_machine_h */
 
diff --git a/sysdeps/powerpc/powerpc64/dl-trampoline.S b/sysdeps/powerpc/powerpc64/dl-trampoline.S
index 18c8a3a..69ce523 100644
--- a/sysdeps/powerpc/powerpc64/dl-trampoline.S
+++ b/sysdeps/powerpc/powerpc64/dl-trampoline.S
@@ -50,11 +50,8 @@ EALIGN(_dl_runtime_resolve, 4, 0)
 /* Store the LR in the LR Save area.  */
 	std	r0,FRAME_SIZE+FRAME_LR_SAVE(r1)
 	cfi_offset (lr, FRAME_LR_SAVE)
-	mfcr	r0
 	std	r9,INT_PARMS+48(r1)
 	std	r10,INT_PARMS+56(r1)
-/* I'm almost certain we don't have to save cr...  be safe.  */
-	std	r0,FRAME_SIZE+FRAME_CR_SAVE(r1)
 	bl	JUMPTARGET(_dl_fixup)
 #ifndef SHARED
 	nop
@@ -66,11 +63,9 @@ EALIGN(_dl_runtime_resolve, 4, 0)
 	ld	r8,INT_PARMS+40(r1)
 	ld	r7,INT_PARMS+32(r1)
 	mtlr	r0
-	ld	r0,FRAME_SIZE+FRAME_CR_SAVE(r1)
 	ld	r6,INT_PARMS+24(r1)
 	ld	r5,INT_PARMS+16(r1)
 	ld	r4,INT_PARMS+8(r1)
-	mtcrf	0xFF,r0
 /* Prepare for calling the function returned by fixup.  */
 	PPC64_LOAD_FUNCPTR r3
 	ld	r3,INT_PARMS+0(r1)
@@ -85,18 +80,30 @@ END(_dl_runtime_resolve)
 #undef FRAME_SIZE
 #undef INT_PARMS
 
-	/* Stack layout:
-	   (Note: some of these are not required for the ELFv2 ABI.)
-	  +592   previous backchain
-	  +584   spill_r31
-	  +576   spill_r30
-	  +560   v1
-	  +552   fp4
-	  +544   fp3
-	  +536   fp2
-	  +528   fp1
-	  +520   r4
-	  +512   r3
+	/* Stack layout:		ELFv2 ABI.
+					+752   previous backchain
+					+744   spill_r31
+					+736   spill_r30
+					+720   v8
+					+704   v7
+					+688   v6
+					+672   v5
+					+656   v4
+					+640   v3
+					+624   v2
+					+608   v1
+					+600   fp10
+	  ELFv1 ABI			+592   fp9
+	  +592   previous backchain	+584   fp8
+	  +584   spill_r31		+576   fp7
+	  +576   spill_r30		+568   fp6
+	  +560   v1			+560   fp5
+	  +552   fp4			+552   fp4
+	  +544   fp3			+544   fp3
+	  +536   fp2			+536   fp2
+	  +528   fp1			+528   fp1
+	  +520   r4			+520   r4
+	  +512   r3			+512   r3
 	   return values
           +504   free
 	  +496   stackframe
@@ -157,10 +164,15 @@ END(_dl_runtime_resolve)
 	  +8     CR save area
 	r1+0     stack back chain
 	*/
-#define FRAME_SIZE 592
+#if _CALL_ELF == 2
+# define FRAME_SIZE 752
+# define VR_RTN 608
+#else
+# define FRAME_SIZE 592
+# define VR_RTN 560
+#endif
 #define INT_RTN 512
 #define FPR_RTN 528
-#define VR_RTN 560
 #define STACK_FRAME 496
 #define CALLING_LR 488
 #define CALLING_SP 480
@@ -205,18 +217,14 @@ EALIGN(_dl_profile_resolve, 4, 0)
 	mflr	r5
 	std	r7,INT_PARMS+32(r1)
 	std	r8,INT_PARMS+40(r1)
-/* Store the LR in the LR Save area of the previous frame.  */
-/* XXX Do we have to do this?  */
+/* Store the LR in the LR Save area.  */
 	la	r8,FRAME_SIZE(r1)
 	std	r5,FRAME_SIZE+FRAME_LR_SAVE(r1)
 	cfi_offset (lr, FRAME_LR_SAVE)
 	std	r5,CALLING_LR(r1)
-	mfcr	r0
 	std	r9,INT_PARMS+48(r1)
 	std	r10,INT_PARMS+56(r1)
 	std	r8,CALLING_SP(r1)
-/* I'm almost certain we don't have to save cr...  be safe.  */
-	std	r0,FRAME_SIZE+FRAME_CR_SAVE(r1)
 	ld	r12,.LC__dl_hwcap@toc(r2)
 #ifdef SHARED
 	/* Load _rtld_local_ro._dl_hwcap.  */
@@ -319,11 +327,9 @@ L(restoreFXR):
 	ld	r8,INT_PARMS+40(r1)
 	ld	r7,INT_PARMS+32(r1)
 	mtlr	r0
-	ld	r0,FRAME_SIZE+FRAME_CR_SAVE(r1)
 	ld	r6,INT_PARMS+24(r1)
 	ld	r5,INT_PARMS+16(r1)
 	ld	r4,INT_PARMS+8(r1)
-	mtcrf	0xFF,r0
 /* Prepare for calling the function returned by fixup.  */
 	PPC64_LOAD_FUNCPTR r3
 	ld	r3,INT_PARMS+0(r1)
@@ -346,10 +352,11 @@ L(restoreFXR):
 	lfd	fp12,FPR_PARMS+88(r1)
 	lfd	fp13,FPR_PARMS+96(r1)
 /* Unwind the stack frame, and jump.  */
-	ld	r31,584(r1)
-	ld	r30,576(r1)
+	ld	r31,FRAME_SIZE-8(r1)
+	ld	r30,FRAME_SIZE-16(r1)
 	addi	r1,r1,FRAME_SIZE
 	bctr
+
 L(do_pltexit):
 	la	r10,(VR_PARMS+0)(r1)
 	la	r9,(VR_PARMS+16)(r1)
@@ -383,11 +390,9 @@ L(restoreFXR2):
 	ld	r8,INT_PARMS+40(r1)
 	ld	r7,INT_PARMS+32(r1)
 	mtlr	r0
-	ld	r0,FRAME_SIZE+FRAME_CR_SAVE(r1)
 	ld	r6,INT_PARMS+24(r1)
 	ld	r5,INT_PARMS+16(r1)
 	ld	r4,INT_PARMS+8(r1)
-	mtcrf	0xFF,r0
 /* Prepare for calling the function returned by fixup.  */
 	std	r2,FRAME_TOC_SAVE(r1)
 	PPC64_LOAD_FUNCPTR r3
@@ -413,16 +418,37 @@ L(restoreFXR2):
 /* But return here and store the return values.  */
 	std	r3,INT_RTN(r1)
 	std	r4,INT_RTN+8(r1)
-	stfd	fp1,FPR_PARMS+0(r1)
-	stfd	fp2,FPR_PARMS+8(r1)
+	stfd	fp1,FPR_RTN+0(r1)
+	stfd	fp2,FPR_RTN+8(r1)
 	cmpdi	cr0,r12,0
 	la	r10,VR_RTN(r1)
-	stfd	fp3,FPR_PARMS+16(r1)
-	stfd	fp4,FPR_PARMS+24(r1)
+	stfd	fp3,FPR_RTN+16(r1)
+	stfd	fp4,FPR_RTN+24(r1)
+#if _CALL_ELF == 2
+	la	r12,VR_RTN+16(r1)
+	stfd	fp5,FPR_RTN+32(r1)
+	stfd	fp6,FPR_RTN+40(r1)
+	li	r5,32
+	li	r6,64
+	stfd	fp7,FPR_RTN+48(r1)
+	stfd	fp8,FPR_RTN+56(r1)
+	stfd	fp9,FPR_RTN+64(r1)
+	stfd	fp10,FPR_RTN+72(r1)
+#endif
 	mr	r3,r31
 	mr	r4,r30
 	beq	L(callpltexit)
 	stvx	v2,0,r10
+#if _CALL_ELF == 2
+	stvx	v3,0,r12
+	stvx	v4,r5,r10
+	stvx	v5,r5,r12
+	addi	r5,r5,64
+	stvx	v6,r6,r10
+	stvx	v7,r6,r12
+	stvx	v8,r5,r10
+	stvx	v9,r5,r12
+#endif
 L(callpltexit):
 	addi	r5,r1,INT_PARMS
 	addi	r6,r1,INT_RTN
@@ -434,18 +460,39 @@ L(callpltexit):
 	lwz	r12,VR_VRSAVE(r1)
 	ld	r3,INT_RTN(r1)
 	ld	r4,INT_RTN+8(r1)
-	lfd	fp1,FPR_PARMS+0(r1)
-	lfd	fp2,FPR_PARMS+8(r1)
+	lfd	fp1,FPR_RTN+0(r1)
+	lfd	fp2,FPR_RTN+8(r1)
 	cmpdi	cr0,r12,0
-	la	r10,VR_RTN(r1)
-	lfd	fp3,FPR_PARMS+16(r1)
-	lfd	fp4,FPR_PARMS+24(r1)
+	la	r11,VR_RTN(r1)
+	lfd	fp3,FPR_RTN+16(r1)
+	lfd	fp4,FPR_RTN+24(r1)
+#if _CALL_ELF == 2
+	la	r12,VR_RTN+16(r1)
+	lfd	fp5,FPR_RTN+32(r1)
+	lfd	fp6,FPR_RTN+40(r1)
+	li	r30,32
+	li	r31,64
+	lfd	fp7,FPR_RTN+48(r1)
+	lfd	fp8,FPR_RTN+56(r1)
+	lfd	fp9,FPR_RTN+64(r1)
+	lfd	fp10,FPR_RTN+72(r1)
+#endif
 	beq	L(pltexitreturn)
-	lvx	v2,0,r10
+	lvx	v2,0,r11
+#if _CALL_ELF == 2
+	lvx	v3,0,r12
+	lvx	v4,r30,r11
+	lvx	v5,r30,r12
+	addi	r30,r30,64
+	lvx	v6,r31,r11
+	lvx	v7,r31,r12
+	lvx	v8,r30,r11
+	lvx	v9,r30,r12
+#endif
 L(pltexitreturn):
 	ld	r0,FRAME_SIZE+FRAME_LR_SAVE(r1)
-	ld	r31,584(r1)
-	ld	r30,576(r1)
+	ld	r31,FRAME_SIZE-8(r1)
+	ld	r30,FRAME_SIZE-16(r1)
 	mtlr	r0
 	ld	r1,0(r1)
 	blr
diff --git a/sysdeps/powerpc/powerpc64/tst-audit.h b/sysdeps/powerpc/powerpc64/tst-audit.h
index ad6545e..0fbe1fe 100644
--- a/sysdeps/powerpc/powerpc64/tst-audit.h
+++ b/sysdeps/powerpc/powerpc64/tst-audit.h
@@ -18,8 +18,16 @@
    License along with the GNU C Library.  If not, see
    <http://www.gnu.org/licenses/>.  */
 
+#if _CALL_ELF != 2
 #define pltenter la_ppc64_gnu_pltenter
 #define pltexit la_ppc64_gnu_pltexit
 #define La_regs La_ppc64_regs
 #define La_retval La_ppc64_retval
 #define int_retval lrv_r3
+#else
+#define pltenter la_ppc64v2_gnu_pltenter
+#define pltexit la_ppc64v2_gnu_pltexit
+#define La_regs La_ppc64v2_regs
+#define La_retval La_ppc64v2_retval
+#define int_retval lrv_r3
+#endif

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=1e9e44f367d335c263ab432af03a66e6f383b021

commit 1e9e44f367d335c263ab432af03a66e6f383b021
Author: Ulrich Weigand <Ulrich.Weigand@de.ibm.com>
Date:   Fri Nov 15 11:59:39 2013 -0600

    PowerPC64 ELFv2 ABI 4/6: Stack frame layout changes
    
    This updates glibc for the changes in the ELFv2 relating to the
    stack frame layout.  These are described in more detail here:
    http://gcc.gnu.org/ml/gcc-patches/2013-11/msg01149.html
    http://gcc.gnu.org/ml/gcc-patches/2013-11/msg01146.html
    
    Specifically, the "compiler and linker doublewords" were removed,
    which has the effect that the save slot for the TOC register is
    now at offset 24 rather than 40 to the stack pointer.
    
    In addition, a function may now no longer necessarily assume that
    its caller has set up a 64-byte register save area its use.
    
    To address the first change, the patch goes through all assembler
    files and replaces immediate offsets in instructions accessing the
    ABI-defined stack slots by symbolic offsets.  Those already were
    defined in ucontext_i.sym and used in some of the context routines,
    but that doesn't really seem like the right place for those defines.
    
    The patch instead defines those symbolic offsets in sysdeps.h,
    in two variants for the old and new ABI, and uses them systematically
    in all assembler files, not just the context routines.
    
    The second change only affected a few assembler files that used
    the save area to temporarily store some registers.  In those
    cases where this happens within a leaf function, this patch
    changes the code to store those registers to the "red zone"
    below the stack pointer.  Otherwise, the functions already allocate
    a stack frame, and the patch changes them to add extra space in
    these frames as temporary space for the ELFv2 ABI.

diff --git a/ChangeLog b/ChangeLog
index a9496d8..d3f51a2 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,4 +1,54 @@
 2013-11-12  Ulrich Weigand  <Ulrich.Weigand@de.ibm.com>
+
+	* sysdeps/powerpc/powerpc64/sysdep.h (FRAME_MIN_SIZE): Define.
+	(FRAME_MIN_SIZE_PARM): Likewise.
+	(FRAME_BACKCHAIN): Likewise.
+	(FRAME_CR_SAVE): Likewise.
+	(FRAME_LR_SAVE): Likewise.
+	(FRAME_TOC_SAVE): Likewise.
+	(FRAME_PARM_SAVE): Likewise.
+	(FRAME_PARM1_SAVE, FRAME_PARM2_SAVE, FRAME_PARM3_SAVE,
+	FRAME_PARM4_SAVE, FRAME_PARM5_SAVE, FRAME_PARM6_SAVE,
+	FRAME_PARM7_SAVE, FRAME_PARM8_SAVE, FRAME_PARM9_SAVE): Likewise.
+	(call_mcount_parm_offset): New macro.
+	(SAVE_ARG, REST_ARG, CFI_SAVE_ARG): Use it.
+	(PROF): Use symbolic stack frame offsets.
+	(TAIL_CALL_SYSCALL_ERROR): Likewise.
+	* sysdeps/powerpc/powerpc64/dl-trampoline.S (FRAME_SIZE, INT_PARMS):
+	Redefine in terms of FRAME_MIN_SIZE.
+	(_dl_runtime_resolve): Use symbolic stack frame offsets.
+	(_dl_profile_resolve): Likewise.  Update comment.
+	* sysdeps/powerpc/powerpc64/setjmp-common.S (__GI__setjmp): Use
+	symbols stack frame offsets.
+	(__sigsetjmp): Likewise.
+	* sysdeps/powerpc/powerpc64/__longjmp-common.S (__longjmp): Likewise.
+	* sysdeps/powerpc/powerpc64/ppc-mcount.S (_mcount): Likewise.
+	* sysdeps/powerpc/powerpc64/crti.S (_init, _fini): Likewise.
+	* sysdeps/powerpc/powerpc64/crtn.S (_init, _fini): Likewise.
+
+	* sysdeps/unix/sysv/linux/powerpc/powerpc64/ucontext_i.sym
+	(FRAME_BACKCHAIN): Remove.
+	(FRAME_CR_SAVE): Likewise.
+	(FRAME_LR_SAVE): Likewise.
+	(FRAME_COMPILER_DW): Likewise.
+	(FRAME_LINKER_DW): Likewise.
+	(FRAME_TOC_SAVE): Likewise.
+	(FRAME_PARM_SAVE): Likewise.
+	(FRAME_PARM1_SAVE, FRAME_PARM2_SAVE, FRAME_PARM3_SAVE,
+	FRAME_PARM4_SAVE, FRAME_PARM5_SAVE, FRAME_PARM6_SAVE,
+	FRAME_PARM7_SAVE, FRAME_PARM8_SAVE, FRAME_PARM9_SAVE): Likewise.
+	* sysdeps/unix/sysv/linux/powerpc/powerpc64/____longjmp_chk.S
+	(CHECK_SP): Use symbolic stack frame offsets.
+	* sysdeps/unix/sysv/linux/powerpc/powerpc64/brk.S (__brk): Use "red
+	zone" instead of caller's parameter save area for temp storage.
+	* sysdeps/unix/sysv/linux/powerpc/powerpc64/clone.S (__clone):
+	Likewise.  Also, use symbolic stack frame offsets.
+	* sysdeps/unix/sysv/linux/powerpc/powerpc64/socket.S (FRAMESIZE,
+	stackblock): Redefine for _CALL_ELF == 2 to save parameters into
+	our own stack frame instead of the caller's.
+	(__socket): Use symbolic stack frame offsets.
+
+2013-11-12  Ulrich Weigand  <Ulrich.Weigand@de.ibm.com>
 	    Alan Modra  <amodra@gmail.com>
 
 	* elf/elf.h (DT_PPC64_OPT, PPC64_OPT_TLS, PPC64_OPT_MULTI_TOC):
diff --git a/nptl/ChangeLog b/nptl/ChangeLog
index 3ac857a..4c84d1e 100644
--- a/nptl/ChangeLog
+++ b/nptl/ChangeLog
@@ -1,5 +1,18 @@
 2013-11-12  Ulrich Weigand  <Ulrich.Weigand@de.ibm.com>
 
+	* sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep-cancel.h
+	(CANCEL_FRAMESIZE, CANCEL_PARM_SAVE): New macros to save parameters
+	into our own stack frame instead of the caller's.
+	(PSEUDO): Use them.  Use symbolic stack frame offsets.
+	(DOCARGS_1, UNDOCARGS_1): Use CANCEL_PARM_SAVE.
+	(DOCARGS_2, UNDOCARGS_2): Likewise.
+	(DOCARGS_3, UNDOCARGS_3): Likewise.
+	(DOCARGS_4, UNDOCARGS_4): Likewise.
+	(DOCARGS_5, UNDOCARGS_5): Likewise.
+	(DOCARGS_6, UNDOCARGS_6): Likewise.
+
+2013-11-12  Ulrich Weigand  <Ulrich.Weigand@de.ibm.com>
+
 	* sysdeps/powerpc/tls.h (tcbhead_t): Add __private_ss field.
 
 2013-10-03  Siddhesh Poyarekar  <siddhesh@redhat.com>
diff --git a/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep-cancel.h b/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep-cancel.h
index 51e021d..d711dc6 100644
--- a/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep-cancel.h
+++ b/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep-cancel.h
@@ -31,6 +31,14 @@
 #  define DASHDASHPFX(str) __##str
 # endif
 
+#if _CALL_ELF == 2
+#define CANCEL_FRAMESIZE (FRAME_MIN_SIZE+16+48)
+#define CANCEL_PARM_SAVE (FRAME_MIN_SIZE+16)
+#else
+#define CANCEL_FRAMESIZE (FRAME_MIN_SIZE+16)
+#define CANCEL_PARM_SAVE (CANCEL_FRAMESIZE+FRAME_PARM_SAVE)
+#endif
+
 # undef PSEUDO
 # define PSEUDO(name, syscall_name, args)				\
   .section ".text";							\
@@ -44,52 +52,52 @@
     PSEUDO_RET;								\
   .size DASHDASHPFX(syscall_name##_nocancel),.-DASHDASHPFX(syscall_name##_nocancel);	\
   .Lpseudo_cancel:							\
-    stdu 1,-128(1);							\
-    cfi_adjust_cfa_offset (128);					\
+    stdu 1,-CANCEL_FRAMESIZE(1);					\
+    cfi_adjust_cfa_offset (CANCEL_FRAMESIZE);				\
     mflr 9;								\
-    std  9,128+16(1);							\
-    cfi_offset (lr, 16);						\
+    std  9,CANCEL_FRAMESIZE+FRAME_LR_SAVE(1);				\
+    cfi_offset (lr, FRAME_LR_SAVE);					\
     DOCARGS_##args;	/* save syscall args around CENABLE.  */	\
     CENABLE;								\
-    std  3,112(1);	/* store CENABLE return value (MASK).  */	\
+    std  3,FRAME_MIN_SIZE(1); /* store CENABLE return value (MASK).  */	\
     UNDOCARGS_##args;	/* restore syscall args.  */			\
     DO_CALL (SYS_ify (syscall_name));					\
     mfcr 0;		/* save CR/R3 around CDISABLE.  */		\
-    std  3,120(1);							\
-    std  0,128+8(1);							\
-    cfi_offset (cr, 8);							\
-    ld   3,112(1);	/* pass MASK to CDISABLE.  */			\
+    std  3,FRAME_MIN_SIZE+8(1);						\
+    std  0,CANCEL_FRAMESIZE+FRAME_CR_SAVE(1);				\
+    cfi_offset (cr, FRAME_CR_SAVE);					\
+    ld   3,FRAME_MIN_SIZE(1); /* pass MASK to CDISABLE.  */		\
     CDISABLE;								\
-    ld   9,128+16(1);							\
-    ld   0,128+8(1);	/* restore CR/R3. */				\
-    ld   3,120(1);							\
+    ld   9,CANCEL_FRAMESIZE+FRAME_LR_SAVE(1);				\
+    ld   0,CANCEL_FRAMESIZE+FRAME_CR_SAVE(1); /* restore CR/R3. */	\
+    ld   3,FRAME_MIN_SIZE+8(1);						\
     mtlr 9;								\
     mtcr 0;								\
-    addi 1,1,128;							\
-    cfi_adjust_cfa_offset (-128);					\
+    addi 1,1,CANCEL_FRAMESIZE;						\
+    cfi_adjust_cfa_offset (-CANCEL_FRAMESIZE);				\
     cfi_restore (lr);							\
     cfi_restore (cr)
 
 # define DOCARGS_0
 # define UNDOCARGS_0
 
-# define DOCARGS_1	std 3,128+48(1); DOCARGS_0
-# define UNDOCARGS_1	ld 3,128+48(1); UNDOCARGS_0
+# define DOCARGS_1	std 3,CANCEL_PARM_SAVE(1); DOCARGS_0
+# define UNDOCARGS_1	ld 3,CANCEL_PARM_SAVE(1); UNDOCARGS_0
 
-# define DOCARGS_2	std 4,128+56(1); DOCARGS_1
-# define UNDOCARGS_2	ld 4,128+56(1); UNDOCARGS_1
+# define DOCARGS_2	std 4,CANCEL_PARM_SAVE+8(1); DOCARGS_1
+# define UNDOCARGS_2	ld 4,CANCEL_PARM_SAVE+8(1); UNDOCARGS_1
 
-# define DOCARGS_3	std 5,128+64(1); DOCARGS_2
-# define UNDOCARGS_3	ld 5,128+64(1); UNDOCARGS_2
+# define DOCARGS_3	std 5,CANCEL_PARM_SAVE+16(1); DOCARGS_2
+# define UNDOCARGS_3	ld 5,CANCEL_PARM_SAVE+16(1); UNDOCARGS_2
 
-# define DOCARGS_4	std 6,128+72(1); DOCARGS_3
-# define UNDOCARGS_4	ld 6,128+72(1); UNDOCARGS_3
+# define DOCARGS_4	std 6,CANCEL_PARM_SAVE+24(1); DOCARGS_3
+# define UNDOCARGS_4	ld 6,CANCEL_PARM_SAVE+24(1); UNDOCARGS_3
 
-# define DOCARGS_5	std 7,128+80(1); DOCARGS_4
-# define UNDOCARGS_5	ld 7,128+80(1); UNDOCARGS_4
+# define DOCARGS_5	std 7,CANCEL_PARM_SAVE+32(1); DOCARGS_4
+# define UNDOCARGS_5	ld 7,CANCEL_PARM_SAVE+32(1); UNDOCARGS_4
 
-# define DOCARGS_6	std 8,128+88(1); DOCARGS_5
-# define UNDOCARGS_6	ld 8,128+88(1); UNDOCARGS_5
+# define DOCARGS_6	std 8,CANCEL_PARM_SAVE+40(1); DOCARGS_5
+# define UNDOCARGS_6	ld 8,CANCEL_PARM_SAVE+40(1); UNDOCARGS_5
 
 # ifdef IS_IN_libpthread
 #  ifdef SHARED
diff --git a/sysdeps/powerpc/powerpc64/__longjmp-common.S b/sysdeps/powerpc/powerpc64/__longjmp-common.S
index 4f1e3c8..ce5a018 100644
--- a/sysdeps/powerpc/powerpc64/__longjmp-common.S
+++ b/sysdeps/powerpc/powerpc64/__longjmp-common.S
@@ -130,7 +130,7 @@ L(no_vmx):
 	ld r14,((JB_GPRS+0)*8)(r3)
 	lfd fp14,((JB_FPRS+0)*8)(r3)
 #if defined SHARED && !defined IS_IN_rtld
-	std r2,40(r1)	/* Restore the callers TOC save area.  */
+	std r2,FRAME_TOC_SAVE(r1)	/* Restore the callers TOC save area.  */
 #endif
 	ld r15,((JB_GPRS+1)*8)(r3)
 	lfd fp15,((JB_FPRS+1)*8)(r3)
@@ -148,7 +148,7 @@ L(no_vmx):
 	PTR_DEMANGLE2 (r0, r25)
 #endif
 	mtlr r0
-/* 	std r2,40(r1)	Restore the TOC save area.  */
+/* 	std r2,FRAME_TOC_SAVE(r1)	Restore the TOC save area.  */
 	ld r21,((JB_GPRS+7)*8)(r3)
 	lfd fp21,((JB_FPRS+7)*8)(r3)
 	ld r22,((JB_GPRS+8)*8)(r3)
diff --git a/sysdeps/powerpc/powerpc64/crti.S b/sysdeps/powerpc/powerpc64/crti.S
index 7eff7fd..6e1ece8 100644
--- a/sysdeps/powerpc/powerpc64/crti.S
+++ b/sysdeps/powerpc/powerpc64/crti.S
@@ -66,8 +66,8 @@
 BODY_LABEL (_init):
 	LOCALENTRY(_init)
 	mflr 0
-	std 0, 16(r1)
-	stdu r1, -112(r1)
+	std 0, FRAME_LR_SAVE(r1)
+	stdu r1, -FRAME_MIN_SIZE_PARM(r1)
 #if PREINIT_FUNCTION_WEAK
 	addis r9, r2, .LC0@toc@ha
 	ld r0, .LC0@toc@l(r9)
@@ -84,5 +84,5 @@ BODY_LABEL (_init):
 BODY_LABEL (_fini):
 	LOCALENTRY(_fini)
 	mflr 0
-	std 0, 16(r1)
-	stdu r1, -112(r1)
+	std 0, FRAME_LR_SAVE(r1)
+	stdu r1, -FRAME_MIN_SIZE_PARM(r1)
diff --git a/sysdeps/powerpc/powerpc64/crtn.S b/sysdeps/powerpc/powerpc64/crtn.S
index 364e53a..cdd3b0f 100644
--- a/sysdeps/powerpc/powerpc64/crtn.S
+++ b/sysdeps/powerpc/powerpc64/crtn.S
@@ -39,13 +39,13 @@
 #include <sysdep.h>
 
 	.section .init,"ax",@progbits
-	addi r1, r1, 112
-	ld r0, 16(r1)
+	addi r1, r1, FRAME_MIN_SIZE_PARM
+	ld r0, FRAME_LR_SAVE(r1)
 	mtlr r0
 	blr
 
 	.section .fini,"ax",@progbits
-	addi r1, r1, 112
-	ld r0, 16(r1)
+	addi r1, r1, FRAME_MIN_SIZE_PARM
+	ld r0, FRAME_LR_SAVE(r1)
 	mtlr r0
 	blr
diff --git a/sysdeps/powerpc/powerpc64/dl-trampoline.S b/sysdeps/powerpc/powerpc64/dl-trampoline.S
index e31311c..18c8a3a 100644
--- a/sysdeps/powerpc/powerpc64/dl-trampoline.S
+++ b/sysdeps/powerpc/powerpc64/dl-trampoline.S
@@ -26,13 +26,13 @@
    parm1 (r3) and the index (r0) need to be converted to an offset
    (index * 24) in parm2 (r4).  */
 
-#define FRAME_SIZE 176
+#define FRAME_SIZE (FRAME_MIN_SIZE+64)
 /* We need to save the registers used to pass parameters, ie. r3 thru
    r10;  Use local var space rather than the parameter save area,
    because gcc as of 2010/05 doesn't allocate a proper stack frame for
    a function that makes no calls except for __tls_get_addr and we
    might be here resolving the __tls_get_addr call.  */
-#define INT_PARMS 112
+#define INT_PARMS FRAME_MIN_SIZE
 EALIGN(_dl_runtime_resolve, 4, 0)
 	stdu	r1,-FRAME_SIZE(r1)
 	cfi_adjust_cfa_offset (FRAME_SIZE)
@@ -48,25 +48,25 @@ EALIGN(_dl_runtime_resolve, 4, 0)
 	mflr	r0
 	std	r8,INT_PARMS+40(r1)
 /* Store the LR in the LR Save area.  */
-	std	r0,FRAME_SIZE+16(r1)
-	cfi_offset (lr, 16)
+	std	r0,FRAME_SIZE+FRAME_LR_SAVE(r1)
+	cfi_offset (lr, FRAME_LR_SAVE)
 	mfcr	r0
 	std	r9,INT_PARMS+48(r1)
 	std	r10,INT_PARMS+56(r1)
 /* I'm almost certain we don't have to save cr...  be safe.  */
-	std	r0,FRAME_SIZE+8(r1)
+	std	r0,FRAME_SIZE+FRAME_CR_SAVE(r1)
 	bl	JUMPTARGET(_dl_fixup)
 #ifndef SHARED
 	nop
 #endif
 /* Put the registers back.  */
-	ld	r0,FRAME_SIZE+16(r1)
+	ld	r0,FRAME_SIZE+FRAME_LR_SAVE(r1)
 	ld	r10,INT_PARMS+56(r1)
 	ld	r9,INT_PARMS+48(r1)
 	ld	r8,INT_PARMS+40(r1)
 	ld	r7,INT_PARMS+32(r1)
 	mtlr	r0
-	ld	r0,FRAME_SIZE+8(r1)
+	ld	r0,FRAME_SIZE+FRAME_CR_SAVE(r1)
 	ld	r6,INT_PARMS+24(r1)
 	ld	r5,INT_PARMS+16(r1)
 	ld	r4,INT_PARMS+8(r1)
@@ -76,7 +76,7 @@ EALIGN(_dl_runtime_resolve, 4, 0)
 	ld	r3,INT_PARMS+0(r1)
 #if _CALL_ELF == 2
 /* Restore the caller's TOC in case we jump to a local entry point.  */
-	ld	r2,FRAME_SIZE+40(r1)
+	ld	r2,FRAME_SIZE+FRAME_TOC_SAVE(r1)
 #endif
 /* Unwind the stack frame, and jump.  */
 	addi	r1,r1,FRAME_SIZE
@@ -86,6 +86,7 @@ END(_dl_runtime_resolve)
 #undef INT_PARMS
 
 	/* Stack layout:
+	   (Note: some of these are not required for the ELFv2 ABI.)
 	  +592   previous backchain
 	  +584   spill_r31
 	  +576   spill_r30
@@ -147,10 +148,11 @@ END(_dl_runtime_resolve)
 	  +64    parm3
 	  +56    parm2
 	  +48    parm1
-	 * Parameter save area, Allocated by the call, at least 8 double words
-	  +40    TOC save area
-	  +32    Reserved for linker
-	  +24    Reserved for compiler
+	 * Parameter save area
+	 * (v1 ABI: Allocated by the call, at least 8 double words)
+	  +40    v1 ABI: TOC save area
+	  +32    v1 ABI: Reserved for linker
+	  +24    v1 ABI: Reserved for compiler / v2 ABI: TOC save area
 	  +16    LR save area
 	  +8     CR save area
 	r1+0     stack back chain
@@ -206,15 +208,15 @@ EALIGN(_dl_profile_resolve, 4, 0)
 /* Store the LR in the LR Save area of the previous frame.  */
 /* XXX Do we have to do this?  */
 	la	r8,FRAME_SIZE(r1)
-	std	r5,FRAME_SIZE+16(r1)
-	cfi_offset (lr, 16)
+	std	r5,FRAME_SIZE+FRAME_LR_SAVE(r1)
+	cfi_offset (lr, FRAME_LR_SAVE)
 	std	r5,CALLING_LR(r1)
 	mfcr	r0
 	std	r9,INT_PARMS+48(r1)
 	std	r10,INT_PARMS+56(r1)
 	std	r8,CALLING_SP(r1)
 /* I'm almost certain we don't have to save cr...  be safe.  */
-	std	r0,FRAME_SIZE+8(r1)
+	std	r0,FRAME_SIZE+FRAME_CR_SAVE(r1)
 	ld	r12,.LC__dl_hwcap@toc(r2)
 #ifdef SHARED
 	/* Load _rtld_local_ro._dl_hwcap.  */
@@ -311,13 +313,13 @@ L(saveFP):
 	lvx	v12,r11,r10
 	lvx	v13,r11,r9
 L(restoreFXR):
-	ld	r0,FRAME_SIZE+16(r1)
+	ld	r0,FRAME_SIZE+FRAME_LR_SAVE(r1)
 	ld	r10,INT_PARMS+56(r1)
 	ld	r9,INT_PARMS+48(r1)
 	ld	r8,INT_PARMS+40(r1)
 	ld	r7,INT_PARMS+32(r1)
 	mtlr	r0
-	ld	r0,FRAME_SIZE+8(r1)
+	ld	r0,FRAME_SIZE+FRAME_CR_SAVE(r1)
 	ld	r6,INT_PARMS+24(r1)
 	ld	r5,INT_PARMS+16(r1)
 	ld	r4,INT_PARMS+8(r1)
@@ -327,7 +329,7 @@ L(restoreFXR):
 	ld	r3,INT_PARMS+0(r1)
 #if _CALL_ELF == 2
 /* Restore the caller's TOC in case we jump to a local entry point.  */
-	ld	r2,FRAME_SIZE+40(r1)
+	ld	r2,FRAME_SIZE+FRAME_TOC_SAVE(r1)
 #endif
 /* Load the floating point registers.  */
 	lfd	fp1,FPR_PARMS+0(r1)
@@ -375,19 +377,19 @@ L(do_pltexit):
 	lvx	v12,r11,r10
 	lvx	v13,r11,r9
 L(restoreFXR2):
-	ld	r0,FRAME_SIZE+16(r1)
+	ld	r0,FRAME_SIZE+FRAME_LR_SAVE(r1)
 	ld	r10,INT_PARMS+56(r1)
 	ld	r9,INT_PARMS+48(r1)
 	ld	r8,INT_PARMS+40(r1)
 	ld	r7,INT_PARMS+32(r1)
 	mtlr	r0
-	ld	r0,FRAME_SIZE+8(r1)
+	ld	r0,FRAME_SIZE+FRAME_CR_SAVE(r1)
 	ld	r6,INT_PARMS+24(r1)
 	ld	r5,INT_PARMS+16(r1)
 	ld	r4,INT_PARMS+8(r1)
 	mtcrf	0xFF,r0
 /* Prepare for calling the function returned by fixup.  */
-	std	r2,40(r1)
+	std	r2,FRAME_TOC_SAVE(r1)
 	PPC64_LOAD_FUNCPTR r3
 	ld	r3,INT_PARMS+0(r1)
 /* Load the floating point registers.  */
@@ -406,7 +408,7 @@ L(restoreFXR2):
 	lfd	fp13,FPR_PARMS+96(r1)
 /* Call the target function.  */
 	bctrl
-	ld	r2,40(r1)
+	ld	r2,FRAME_TOC_SAVE(r1)
 	lwz	r12,VR_VRSAVE(r1)
 /* But return here and store the return values.  */
 	std	r3,INT_RTN(r1)
@@ -441,7 +443,7 @@ L(callpltexit):
 	beq	L(pltexitreturn)
 	lvx	v2,0,r10
 L(pltexitreturn):
-	ld	r0,FRAME_SIZE+16(r1)
+	ld	r0,FRAME_SIZE+FRAME_LR_SAVE(r1)
 	ld	r31,584(r1)
 	ld	r30,576(r1)
 	mtlr	r0
diff --git a/sysdeps/powerpc/powerpc64/ppc-mcount.S b/sysdeps/powerpc/powerpc64/ppc-mcount.S
index 3d21a70..9824a55 100644
--- a/sysdeps/powerpc/powerpc64/ppc-mcount.S
+++ b/sysdeps/powerpc/powerpc64/ppc-mcount.S
@@ -24,16 +24,16 @@
 ENTRY(_mcount)
 	mflr		 r4
 	ld		 r11, 0(r1)
-	stdu		 r1,-112(r1)
-	cfi_adjust_cfa_offset (112)
-	std		 r4, 128(r1)
-	cfi_offset (lr, 16)
-	ld		 r3, 16(r11)
+	stdu		 r1,-FRAME_MIN_SIZE(r1)
+	cfi_adjust_cfa_offset (FRAME_MIN_SIZE)
+	std		 r4, FRAME_MIN_SIZE+FRAME_LR_SAVE(r1)
+	cfi_offset (lr, FRAME_LR_SAVE)
+	ld		 r3, FRAME_LR_SAVE(r11)
 	bl		 JUMPTARGET(__mcount_internal)
 	nop
-	ld		 r0, 128(r1)
+	ld		 r0, FRAME_MIN_SIZE+FRAME_LR_SAVE(r1)
 	mtlr		 r0
-	addi		 r1,r1,112
+	addi		 r1,r1,FRAME_MIN_SIZE
 	blr
 END(_mcount)
 
diff --git a/sysdeps/powerpc/powerpc64/setjmp-common.S b/sysdeps/powerpc/powerpc64/setjmp-common.S
index db4b349..9e4fb02 100644
--- a/sysdeps/powerpc/powerpc64/setjmp-common.S
+++ b/sysdeps/powerpc/powerpc64/setjmp-common.S
@@ -54,7 +54,7 @@ END (setjmp)
    bugz #269.  __GI__setjmp is used in csu/libc-start.c when
    HAVE_CLEANUP_JMP_BUF is defined.  */
 ENTRY (__GI__setjmp)
-	std r2,40(r1)		/* Save the callers TOC in the save area.  */
+	std r2,FRAME_TOC_SAVE(r1)		/* Save the callers TOC in the save area.  */
 	CALL_MCOUNT 1
 	li r4,0			/* Set second argument to 0.  */
 	b JUMPTARGET (GLUE(__sigsetjmp,_ent))
@@ -80,7 +80,7 @@ JUMPTARGET(GLUE(__sigsetjmp,_ent)):
 #endif
 	mflr r0
 #if defined SHARED && !defined IS_IN_rtld
-	ld   r5,40(r1)	/* Retrieve the callers TOC.  */
+	ld   r5,FRAME_TOC_SAVE(r1)	/* Retrieve the callers TOC.  */
 	std  r5,(JB_GPR2*8)(3)
 #else
 	std  r2,(JB_GPR2*8)(3)
@@ -216,14 +216,14 @@ L(no_vmx):
 	b	JUMPTARGET (__sigjmp_save)
 #else
 	mflr	r0
-	std	r0,16(r1)
-	stdu	r1,-112(r1)
-	cfi_adjust_cfa_offset(112)
-	cfi_offset(lr,16)
+	std	r0,FRAME_LR_SAVE(r1)
+	stdu	r1,-FRAME_MIN_SIZE(r1)
+	cfi_adjust_cfa_offset(FRAME_MIN_SIZE)
+	cfi_offset(lr,FRAME_LR_SAVE)
 	bl	JUMPTARGET (__sigjmp_save)
 	nop
-	ld	r0,112+16(r1)
-	addi	r1,r1,112
+	ld	r0,FRAME_MIN_SIZE+FRAME_LR_SAVE(r1)
+	addi	r1,r1,FRAME_MIN_SIZE
 	mtlr	r0
 	blr
 #endif
diff --git a/sysdeps/powerpc/powerpc64/sysdep.h b/sysdeps/powerpc/powerpc64/sysdep.h
index 779fd90..112e418 100644
--- a/sysdeps/powerpc/powerpc64/sysdep.h
+++ b/sysdeps/powerpc/powerpc64/sysdep.h
@@ -20,25 +20,67 @@
 
 #ifdef __ASSEMBLER__
 
+/* Stack frame offsets.  */
+#if _CALL_ELF != 2
+#define FRAME_MIN_SIZE		112
+#define FRAME_MIN_SIZE_PARM	112
+#define FRAME_BACKCHAIN		0
+#define FRAME_CR_SAVE		8
+#define FRAME_LR_SAVE		16
+#define FRAME_TOC_SAVE		40
+#define FRAME_PARM_SAVE		48
+#define FRAME_PARM1_SAVE	48
+#define FRAME_PARM2_SAVE	56
+#define FRAME_PARM3_SAVE	64
+#define FRAME_PARM4_SAVE	72
+#define FRAME_PARM5_SAVE	80
+#define FRAME_PARM6_SAVE	88
+#define FRAME_PARM7_SAVE	96
+#define FRAME_PARM8_SAVE	104
+#define FRAME_PARM9_SAVE	112
+#else
+#define FRAME_MIN_SIZE		32
+#define FRAME_MIN_SIZE_PARM	96
+#define FRAME_BACKCHAIN		0
+#define FRAME_CR_SAVE		8
+#define FRAME_LR_SAVE		16
+#define FRAME_TOC_SAVE		24
+#define FRAME_PARM_SAVE		32
+#define FRAME_PARM1_SAVE	32
+#define FRAME_PARM2_SAVE	40
+#define FRAME_PARM3_SAVE	48
+#define FRAME_PARM4_SAVE	56
+#define FRAME_PARM5_SAVE	64
+#define FRAME_PARM6_SAVE	72
+#define FRAME_PARM7_SAVE	80
+#define FRAME_PARM8_SAVE	88
+#define FRAME_PARM9_SAVE	96
+#endif
+
 /* Support macros for CALL_MCOUNT.  */
+#if _CALL_ELF == 2
+#define call_mcount_parm_offset (-64)
+#else
+#define call_mcount_parm_offset FRAME_PARM_SAVE
+#endif
 	.macro SAVE_ARG NARG
 	.if \NARG
 	SAVE_ARG \NARG-1
-	std	2+\NARG,40+8*(\NARG)(1)
+	std	2+\NARG,call_mcount_parm_offset-8+8*(\NARG)(1)
 	.endif
 	.endm
 
 	.macro REST_ARG NARG
 	.if \NARG
 	REST_ARG \NARG-1
-	ld	2+\NARG,112+40+8*(\NARG)(1)
+	ld	2+\NARG,FRAME_MIN_SIZE_PARM+call_mcount_parm_offset-8+8*(\NARG)(1)
 	.endif
 	.endm
 
 	.macro CFI_SAVE_ARG NARG
 	.if \NARG
 	CFI_SAVE_ARG \NARG-1
-	cfi_offset(2+\NARG,40+8*(\NARG))
+	cfi_offset(2+\NARG,call_mcount_parm_offset-8+8*(\NARG))
 	.endif
 	.endm
 
@@ -55,20 +97,20 @@
 #ifdef	PROF
 	mflr	r0
 	SAVE_ARG \NARG
-	std	r0,16(r1)
-	stdu	r1,-112(r1)
-	cfi_adjust_cfa_offset(112)
-	cfi_offset(lr,16)
+	std	r0,FRAME_LR_SAVE(r1)
+	stdu	r1,-FRAME_MIN_SIZE_PARM(r1)
+	cfi_adjust_cfa_offset(FRAME_MIN_SIZE_PARM)
+	cfi_offset(lr,FRAME_LR_SAVE)
 	CFI_SAVE_ARG \NARG
 	bl	JUMPTARGET (_mcount)
 #ifndef SHARED
 	nop
 #endif
-	ld	r0,128(r1)
+	ld	r0,FRAME_MIN_SIZE_PARM+FRAME_LR_SAVE(r1)
 	REST_ARG \NARG
 	mtlr	r0
-	addi	r1,r1,112
-	cfi_adjust_cfa_offset(-112)
+	addi	r1,r1,FRAME_MIN_SIZE_PARM
+	cfi_adjust_cfa_offset(-FRAME_MIN_SIZE_PARM)
 	cfi_restore(lr)
 	CFI_REST_ARG \NARG
 #endif
@@ -267,15 +309,15 @@ LT_LABELSUFFIX(name,_name_end): ; \
     .else; \
 .Local_syscall_error: \
     mflr 0; \
-    std 0,16(1); \
-    stdu 1,-112(1); \
-    cfi_adjust_cfa_offset(112); \
-    cfi_offset(lr,16); \
+    std 0,FRAME_LR_SAVE(1); \
+    stdu 1,-FRAME_MIN_SIZE(1); \
+    cfi_adjust_cfa_offset(FRAME_MIN_SIZE); \
+    cfi_offset(lr,FRAME_LR_SAVE); \
     bl JUMPTARGET(__syscall_error); \
     nop; \
-    ld 0,112+16(1); \
-    addi 1,1,112; \
-    cfi_adjust_cfa_offset(-112); \
+    ld 0,FRAME_MIN_SIZE+FRAME_LR_SAVE(1); \
+    addi 1,1,FRAME_MIN_SIZE; \
+    cfi_adjust_cfa_offset(-FRAME_MIN_SIZE); \
     mtlr 0; \
     cfi_restore(lr); \
     blr; \
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/____longjmp_chk.S b/sysdeps/unix/sysv/linux/powerpc/powerpc64/____longjmp_chk.S
index 270e21e..ae576d6 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/____longjmp_chk.S
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/____longjmp_chk.S
@@ -33,24 +33,24 @@
 	cmpld	reg, r1;				\
 	bge+	.Lok;					\
 	mflr	r0;					\
-	std	r0,16(r1);				\
+	std	r0,FRAME_LR_SAVE(r1);			\
 	mr	r31,r3;					\
 	mr	r30,r4;					\
-	stdu	r1,-144(r1);				\
+	stdu	r1,-FRAME_MIN_SIZE-32(r1);		\
 	cfi_remember_state;				\
-	cfi_adjust_cfa_offset (144);			\
-	cfi_offset (lr, 16);				\
+	cfi_adjust_cfa_offset (FRAME_MIN_SIZE+32);	\
+	cfi_offset (lr, FRAME_LR_SAVE);			\
 	li	r3,0;					\
-	addi	r4,r1,112;				\
+	addi	r4,r1,FRAME_MIN_SIZE;			\
 	li	r0,__NR_sigaltstack;			\
 	sc;						\
 	/* Without working sigaltstack we cannot perform the test.  */ \
 	bso	.Lok2;					\
-	lwz	r0,112+8(r1);				\
+	lwz	r0,FRAME_MIN_SIZE+8(r1);		\
 	andi.	r4,r0,1;				\
 	beq	.Lfail;					\
-	ld	r0,112+16(r1);				\
-	ld	r4,112(r1);				\
+	ld	r0,FRAME_MIN_SIZE+16(r1);		\
+	ld	r4,FRAME_MIN_SIZE(r1);			\
 	add	r4,r4,r0;				\
 	sub	r3,r3,reg;				\
 	cmpld	r3,r0;					\
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/brk.S b/sysdeps/unix/sysv/linux/powerpc/powerpc64/brk.S
index 348aeb5..33cdf25 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/brk.S
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/brk.S
@@ -28,9 +28,9 @@
 ENTRY (__brk)
 	CALL_MCOUNT 1
 
-	std	r3,48(r1)
+	std	r3,-8(r1)
 	DO_CALL(SYS_ify(brk))
-	ld	r6,48(r1)
+	ld	r6,-8(r1)
 	ld	r5,.LC__curbrk@toc(r2)
 	std     r3,0(r5)
 	cmpld   r6,r3
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/clone.S b/sysdeps/unix/sysv/linux/powerpc/powerpc64/clone.S
index 4151d15..37d9d24 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/clone.S
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/clone.S
@@ -40,22 +40,22 @@ ENTRY (__clone)
 	cror	cr0*4+eq,cr1*4+eq,cr0*4+eq
 	beq-	cr0,L(badargs)
 
-	/* Save some regs in parm save area.  */
+	/* Save some regs in the "red zone".  */
 #ifdef RESET_PID
-	std	r29,48(r1)
+	std	r29,-24(r1)
 #endif
-	std	r30,56(r1)
-	std	r31,64(r1)
+	std	r30,-16(r1)
+	std	r31,-8(r1)
 #ifdef RESET_PID
-	cfi_offset(r29,48)
+	cfi_offset(r29,-24)
 #endif
-	cfi_offset(r30,56)
-	cfi_offset(r31,64)
+	cfi_offset(r30,-16)
+	cfi_offset(r31,-8)
 
 	/* Set up stack frame for child.  */
 	clrrdi	r4,r4,4
 	li	r0,0
-	stdu	r0,-112(r4) /* min stack frame is 112 bytes per ABI */
+	stdu	r0,-FRAME_MIN_SIZE_PARM(r4)
 
 	/* Save fn, args, stack across syscall.  */
 	mr	r30,r3			/* Function in r30.  */
@@ -97,12 +97,12 @@ L(nomoregetpid):
 L(oldpid):
 #endif
 
-	std	r2,40(r1)
+	std	r2,FRAME_TOC_SAVE(r1)
 	/* Call procedure.  */
 	PPC64_LOAD_FUNCPTR r30
 	mr	r3,r31
 	bctrl
-	ld	r2,40(r1)
+	ld	r2,FRAME_TOC_SAVE(r1)
 	/* Call _exit with result from procedure.  */
 #ifdef SHARED
 	b	JUMPTARGET(__GI__exit)
@@ -121,15 +121,15 @@ L(badargs):
 L(parent):
 	/* Parent.  Restore registers & return.  */
 #ifdef RESET_PID
-	cfi_offset(r29,48)
+	cfi_offset(r29,-24)
 #endif
-	cfi_offset(r30,56)
-	cfi_offset(r31,64)
+	cfi_offset(r30,-16)
+	cfi_offset(r31,-8)
 #ifdef RESET_PID
-	ld	r29,48(r1)
+	ld	r29,-24(r1)
 #endif
-	ld	r30,56(r1)
-	ld	r31,64(r1)
+	ld	r30,-16(r1)
+	ld	r31,-8(r1)
 #ifdef RESET_PID
 	cfi_restore(r29)
 #endif
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/socket.S b/sysdeps/unix/sysv/linux/powerpc/powerpc64/socket.S
index 018e55c..aba2d80 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/socket.S
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/socket.S
@@ -46,8 +46,13 @@
 # endif
 #endif
 
-#define FRAMESIZE 128
-#define stackblock FRAMESIZE+48 /* offset to parm save area.  */
+#if _CALL_ELF == 2
+#define FRAMESIZE (FRAME_MIN_SIZE+16+64)
+#define stackblock (FRAME_MIN_SIZE+16)
+#else
+#define FRAMESIZE (FRAME_MIN_SIZE+16)
+#define stackblock (FRAMESIZE+FRAME_PARM_SAVE) /* offset to parm save area.  */
+#endif
 
 	.text
 ENTRY(__socket)
@@ -98,22 +103,22 @@ ENTRY(__socket)
 .Lsocket_cancel:
 	cfi_adjust_cfa_offset(FRAMESIZE)
 	mflr	r9
-	std	r9,FRAMESIZE+16(r1)
-	cfi_offset (lr, 16)
+	std	r9,FRAMESIZE+FRAME_LR_SAVE(r1)
+	cfi_offset (lr, FRAME_LR_SAVE)
 	CENABLE
-	std	r3,120(r1)
+	std	r3,FRAME_MIN_SIZE+8(r1)
 	li	r3,P(SOCKOP_,socket)
 	addi	r4,r1,stackblock
 	DO_CALL(SYS_ify(socketcall))
 	mfcr	r0
-	std	r3,112(r1)
-	std	r0,FRAMESIZE+8(r1)
-	cfi_offset (cr, 8)
-	ld  	r3,120(r1)
+	std	r3,FRAME_MIN_SIZE(r1)
+	std	r0,FRAMESIZE+FRAME_CR_SAVE(r1)
+	cfi_offset (cr, FRAME_CR_SAVE)
+	ld  	r3,FRAME_MIN_SIZE+8(r1)
 	CDISABLE
-	ld	r4,FRAMESIZE+16(r1)
-	ld	r0,FRAMESIZE+8(r1)
-	ld	r3,112(r1)
+	ld	r4,FRAMESIZE+FRAME_LR_SAVE(r1)
+	ld	r0,FRAMESIZE+FRAME_CR_SAVE(r1)
+	ld	r3,FRAME_MIN_SIZE(r1)
 	mtlr	r4
 	mtcr	r0
 	addi	r1,r1,FRAMESIZE
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/ucontext_i.sym b/sysdeps/unix/sysv/linux/powerpc/powerpc64/ucontext_i.sym
index a35418d..8364e46 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/ucontext_i.sym
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/ucontext_i.sym
@@ -8,27 +8,6 @@ SIG_BLOCK
 SIG_SETMASK
 
 
--- Offsets of the fields in the powerpc64 ABI stack frame.
--- XXX Do these correspond to some struct?
-
-FRAME_BACKCHAIN		0
-FRAME_CR_SAVE		8
-FRAME_LR_SAVE		16
-FRAME_COMPILER_DW	24
-FRAME_LINKER_DW		32
-FRAME_TOC_SAVE		40
-FRAME_PARM_SAVE		48
-FRAME_PARM1_SAVE	48
-FRAME_PARM2_SAVE	56
-FRAME_PARM3_SAVE	64
-FRAME_PARM4_SAVE	72
-FRAME_PARM5_SAVE	80
-FRAME_PARM6_SAVE	88
-FRAME_PARM7_SAVE	96
-FRAME_PARM8_SAVE	104
-FRAME_PARM9_SAVE	112
-
-
 -- Offsets of the fields in the ucontext_t structure.
 #define ucontext(member)	offsetof (ucontext_t, member)
 #define mcontext(member)	ucontext (uc_mcontext.member)

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=f52b81721f85a00fdd9e69702dc5f64dac9ce460

commit f52b81721f85a00fdd9e69702dc5f64dac9ce460
Author: Ulrich Weigand <Ulrich.Weigand@de.ibm.com>
Date:   Fri Nov 15 11:56:31 2013 -0600

    PowerPC64 ELFv2 ABI 3/6: PLT local entry point optimization
    
    This is a follow-on to the previous patch to support the ELFv2 ABI in the
    dynamic loader, split off into its own patch since it is just an optional
    optimization.
    
    In the ELFv2 ABI, most functions define both a global and a local entry
    point; the local entry requires r2 to be already set up by the caller
    to point to the callee's TOC; while the global entry does not require
    the caller to know about the callee's TOC, but it needs to set up r12
    to the callee's entry point address.
    
    Now, when setting up a PLT slot, the dynamic linker will usually need
    to enter the target function's global entry point.  However, if the
    linker can prove that the target function is in the same DSO as the
    PLT slot itself, and the whole DSO only uses a single TOC (which the
    linker will let ld.so know via a DT_PPC64_OPT entry), then it is
    possible to actually enter the local entry point address into the
    PLT slot, for a slight improvement in performance.
    
    Note that this uncovered a problem on the first call via _dl_runtime_resolve,
    because that routine neglected to restore the caller's TOC before calling
    the target function for the first time, since it assumed that function
    would always reload its own TOC anyway ...

diff --git a/ChangeLog b/ChangeLog
index 154f379..a9496d8 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,6 +1,23 @@
 2013-11-12  Ulrich Weigand  <Ulrich.Weigand@de.ibm.com>
 	    Alan Modra  <amodra@gmail.com>
 
+	* elf/elf.h (DT_PPC64_OPT, PPC64_OPT_TLS, PPC64_OPT_MULTI_TOC):
+	Define.
+	(STO_PPC64_LOCAL_BIT, STO_PPC64_LOCAL_MASK,
+	PPC64_LOCAL_ENTRY_OFFSET): Define.
+	* sysdeps/powerpc/powerpc64/dl-machine.h (ppc64_local_entry_offset):
+	New function.
+	(elf_machine_fixup_plt): Call it.
+	(elf_machine_plt_conflict): Likewise.  Add map, sym_map, and
+	reloc arguments.
+	(elf_machine_rela): Update call to elf_machine_plt_conflict.
+	* sysdeps/powerpc/powerpc64/dl-trampoline.S (_dl_runtime_resolve,
+	_dl_profile_resolve) [_CALL_ELF == 2]: Restore caller's TOC into
+	r2 before calling target.
+
+2013-11-12  Ulrich Weigand  <Ulrich.Weigand@de.ibm.com>
+	    Alan Modra  <amodra@gmail.com>
+
 	* sysdeps/powerpc/powerpc64/sysdep.h [_CALL_ELF == 2]
 	(PPC64_LOAD_FUNCPTR, DOT_LABEL, BODY_LABEL, ENTRY_2, END_2): New
 	versions of macros to support ELFv2 ABI.
diff --git a/elf/elf.h b/elf/elf.h
index 331ad3e..d3fea9d 100644
--- a/elf/elf.h
+++ b/elf/elf.h
@@ -2281,8 +2281,19 @@ typedef Elf32_Addr Elf32_Conflict;
 #define DT_PPC64_GLINK  (DT_LOPROC + 0)
 #define DT_PPC64_OPD	(DT_LOPROC + 1)
 #define DT_PPC64_OPDSZ	(DT_LOPROC + 2)
+#define DT_PPC64_OPT	(DT_LOPROC + 3)
 #define DT_PPC64_NUM    3
 
+/* PowerPC64 specific values for the DT_PPC64_OPT Dyn entry.  */
+#define PPC64_OPT_TLS		1
+#define PPC64_OPT_MULTI_TOC	2
+
+/* PowerPC64 specific values for the Elf64_Sym st_other field.  */
+#define STO_PPC64_LOCAL_BIT	5
+#define STO_PPC64_LOCAL_MASK	(7 << STO_PPC64_LOCAL_BIT)
+#define PPC64_LOCAL_ENTRY_OFFSET(other)				\
+ (((1 << (((other) & STO_PPC64_LOCAL_MASK) >> STO_PPC64_LOCAL_BIT)) >> 2) << 2)
+
 
 /* ARM specific declarations */
 
diff --git a/sysdeps/powerpc/powerpc64/dl-machine.h b/sysdeps/powerpc/powerpc64/dl-machine.h
index f222bb0..eccfbb3 100644
--- a/sysdeps/powerpc/powerpc64/dl-machine.h
+++ b/sysdeps/powerpc/powerpc64/dl-machine.h
@@ -424,6 +424,42 @@ elf_machine_runtime_setup (struct link_map *map, int lazy, int profile)
   return lazy;
 }
 
+#if _CALL_ELF == 2
+/* If the PLT entry whose reloc is 'reloc' resolves to a function in
+   the same object, return the target function's local entry point
+   offset if usable.  */
+static inline Elf64_Addr __attribute__ ((always_inline))
+ppc64_local_entry_offset (struct link_map *map, lookup_t sym_map,
+			  const Elf64_Rela *reloc)
+{
+  const Elf64_Sym *symtab;
+  const Elf64_Sym *sym;
+
+  /* If the target function is in a different object, we cannot
+     use the local entry point.  */
+  if (sym_map != map)
+    return 0;
+
+  /* If the linker inserted multiple TOCs, we cannot use the
+     local entry point.  */
+  if (map->l_info[DT_PPC64(OPT)]
+      && (map->l_info[DT_PPC64(OPT)]->d_un.d_val & PPC64_OPT_MULTI_TOC))
+    return 0;
+
+  /* Otherwise, we can use the local entry point.  Retrieve its offset
+     from the symbol's ELF st_other field.  */
+  symtab = (const void *) D_PTR (map, l_info[DT_SYMTAB]);
+  sym = &symtab[ELFW(R_SYM) (reloc->r_info)];
+
+  /* If the target function is an ifunc then the local entry offset is
+     for the resolver, not the final destination.  */
+  if (__builtin_expect (ELFW(ST_TYPE) (sym->st_info) == STT_GNU_IFUNC, 0))
+    return 0;
+
+  return PPC64_LOCAL_ENTRY_OFFSET (sym->st_other);
+}
+#endif
+
 /* Change the PLT entry whose reloc is 'reloc' to call the actual
    routine.  */
 static inline Elf64_Addr __attribute__ ((always_inline))
@@ -470,6 +506,7 @@ elf_machine_fixup_plt (struct link_map *map, lookup_t sym_map,
   PPC_DCBST (&plt->fd_func);
   PPC_ISYNC;
 #else
+  finaladdr += ppc64_local_entry_offset (map, sym_map, reloc);
   *reloc_addr = finaladdr;
 #endif
 
@@ -477,7 +514,9 @@ elf_machine_fixup_plt (struct link_map *map, lookup_t sym_map,
 }
 
 static inline void __attribute__ ((always_inline))
-elf_machine_plt_conflict (Elf64_Addr *reloc_addr, Elf64_Addr finaladdr)
+elf_machine_plt_conflict (struct link_map *map, lookup_t sym_map,
+			  const Elf64_Rela *reloc,
+			  Elf64_Addr *reloc_addr, Elf64_Addr finaladdr)
 {
 #if _CALL_ELF != 2
   Elf64_FuncDesc *plt = (Elf64_FuncDesc *) reloc_addr;
@@ -491,6 +530,7 @@ elf_machine_plt_conflict (Elf64_Addr *reloc_addr, Elf64_Addr finaladdr)
   PPC_DCBST (&plt->fd_toc);
   PPC_SYNC;
 #else
+  finaladdr += ppc64_local_entry_offset (map, sym_map, reloc);
   *reloc_addr = finaladdr;
 #endif
 }
@@ -646,7 +686,7 @@ elf_machine_rela (struct link_map *map,
       /* Fall thru */
     case R_PPC64_JMP_SLOT:
 #ifdef RESOLVE_CONFLICT_FIND_MAP
-      elf_machine_plt_conflict (reloc_addr, value);
+      elf_machine_plt_conflict (map, sym_map, reloc, reloc_addr, value);
 #else
       elf_machine_fixup_plt (map, sym_map, reloc, reloc_addr, value);
 #endif
diff --git a/sysdeps/powerpc/powerpc64/dl-trampoline.S b/sysdeps/powerpc/powerpc64/dl-trampoline.S
index bffc4cb..e31311c 100644
--- a/sysdeps/powerpc/powerpc64/dl-trampoline.S
+++ b/sysdeps/powerpc/powerpc64/dl-trampoline.S
@@ -74,6 +74,10 @@ EALIGN(_dl_runtime_resolve, 4, 0)
 /* Prepare for calling the function returned by fixup.  */
 	PPC64_LOAD_FUNCPTR r3
 	ld	r3,INT_PARMS+0(r1)
+#if _CALL_ELF == 2
+/* Restore the caller's TOC in case we jump to a local entry point.  */
+	ld	r2,FRAME_SIZE+40(r1)
+#endif
 /* Unwind the stack frame, and jump.  */
 	addi	r1,r1,FRAME_SIZE
 	bctr
@@ -321,6 +325,10 @@ L(restoreFXR):
 /* Prepare for calling the function returned by fixup.  */
 	PPC64_LOAD_FUNCPTR r3
 	ld	r3,INT_PARMS+0(r1)
+#if _CALL_ELF == 2
+/* Restore the caller's TOC in case we jump to a local entry point.  */
+	ld	r2,FRAME_SIZE+40(r1)
+#endif
 /* Load the floating point registers.  */
 	lfd	fp1,FPR_PARMS+0(r1)
 	lfd	fp2,FPR_PARMS+8(r1)

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=fe301b50f108bbf8d899e191ad68b857ddf8147c

commit fe301b50f108bbf8d899e191ad68b857ddf8147c
Author: Ulrich Weigand <Ulrich.Weigand@de.ibm.com>
Date:   Fri Nov 15 11:54:51 2013 -0600

    PowerPC64 ELFv2 ABI 2/6: Remove function descriptors
    
    This patch adds support for the ELFv2 ABI feature to remove function
    descriptors.  See this GCC patch for in-depth discussion:
    http://gcc.gnu.org/ml/gcc-patches/2013-11/msg01141.html
    
    This mostly involves two types of changes: updating assembler source
    files to the new logic, and updating the dynamic loader.
    
    After the refactoring in the previous patch, most of the assembler source
    changes can be handled simply by providing ELFv2 versions of the
    macros in sysdep.h.   One somewhat non-obvious change is in __GI__setjmp:
    this used to "fall through" to the immediately following __setjmp ENTRY
    point.  This is no longer safe in the ELFv2 since ENTRY defines both
    a global and a local entry point, and you cannot simply fall through
    to a global entry point as it requires r12 to be set up.
    
    Also, makecontext needs to be updated to set up registers according to
    the new ABI for calling into the context's start routine.
    
    The dynamic linker changes mostly consist of removing special code
    to handle function descriptors.  We also need to support the new PLT
    and glink format used by the the ELFv2 linker, see:
    https://sourceware.org/ml/binutils/2013-10/msg00376.html
    
    In addition, the dynamic linker now verifies that the dynamic libraries
    it loads match its own ABI.
    
    The hack in VDSO_IFUNC_RET to "synthesize" a function descriptor
    for vDSO routines is also no longer necessary for ELFv2.

diff --git a/ChangeLog b/ChangeLog
index 9bd9834..154f379 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,4 +1,37 @@
 2013-11-12  Ulrich Weigand  <Ulrich.Weigand@de.ibm.com>
+	    Alan Modra  <amodra@gmail.com>
+
+	* sysdeps/powerpc/powerpc64/sysdep.h [_CALL_ELF == 2]
+	(PPC64_LOAD_FUNCPTR, DOT_LABEL, BODY_LABEL, ENTRY_2, END_2): New
+	versions of macros to support ELFv2 ABI.
+	(LOCALENTRY): New macro.
+	(ENTRY, EALIGN): Use it.
+	* sysdeps/powerpc/powerpc64/crti.S (_init, _fini): Use LOCALENTRY.
+	* sysdeps/powerpc/powerpc64/setjmp-common.S (__GI__setjmp): Do not
+	fall through into ENTRY entry point.
+	* libc/sysdeps/powerpc/powerpc64/dl-machine.h (Elf64_FuncDesc):
+	Only define if _CALL_ELF != 2.
+
+	(elf_machine_matches_host): Verify ABI version matches.
+	(RTLD_START): Use LOCALENTRY.
+	(elf_machine_type_class): Use SHN_UNDEF PLT handling for ELFv2 ABI.
+	(PLT_INITIAL_ENTRY_WORDS): New version for _CALL_ELF != 2.
+	(PLT_ENTRY_WORDS): New macro.
+	(GLINK_INITIAL_ENTRY_WORDS, GLINK_ENTRY_WORDS): Likewise.
+	(elf_machine_runtime_setup): Support ELFv2 ABI.
+	(elf_machine_fixup_plt): Likewise.
+	(elf_machine_plt_conflict): Likewise.
+	(resolve_ifunc): Likewise.
+	* sysdeps/powerpc/powerpc64/dl-irel.h (elf_irela): Likewise.
+	* sysdeps/unix/sysv/linux/powerpc/bits/libc-vdso.h (VDSO_IFUNC_RET):
+	Likewise.
+	* sysdeps/unix/sysv/linux/powerpc/powerpc64/ldsodefs.h
+	(DL_ADDR_SYM_MATCH): Only define if _CALL_ELF != 2.
+	* sysdeps/unix/sysv/linux/powerpc/powerpc64/makecontext.S
+	(makecontext): Support ELFv2 ABI.
+	* elf/elf.h (EF_PPC64_ABI): Define.
+
+2013-11-12  Ulrich Weigand  <Ulrich.Weigand@de.ibm.com>
 
 	* sysdeps/powerpc/powerpc64/sysdep.h [ASSEMBLER] (PPC64_LOAD_FUNCPTR):
 	New assembler macro.
diff --git a/elf/elf.h b/elf/elf.h
index 98c722e..331ad3e 100644
--- a/elf/elf.h
+++ b/elf/elf.h
@@ -2271,6 +2271,12 @@ typedef Elf32_Addr Elf32_Conflict;
 #define R_PPC64_REL16_HI	251	/* half16   (sym+add-.)@h */
 #define R_PPC64_REL16_HA	252	/* half16   (sym+add-.)@ha */
 
+/* e_flags bits specifying ABI.
+   1 for original function descriptor using ABI,
+   2 for revised ABI without function descriptors,
+   0 for unspecified or not using any features affected by the differences.  */
+#define EF_PPC64_ABI	3
+
 /* PowerPC64 specific values for the Dyn d_tag field.  */
 #define DT_PPC64_GLINK  (DT_LOPROC + 0)
 #define DT_PPC64_OPD	(DT_LOPROC + 1)
diff --git a/sysdeps/powerpc/powerpc64/crti.S b/sysdeps/powerpc/powerpc64/crti.S
index 116199d..7eff7fd 100644
--- a/sysdeps/powerpc/powerpc64/crti.S
+++ b/sysdeps/powerpc/powerpc64/crti.S
@@ -64,6 +64,7 @@
 	ENTRY_2(_init)
 	.align ALIGNARG (2)
 BODY_LABEL (_init):
+	LOCALENTRY(_init)
 	mflr 0
 	std 0, 16(r1)
 	stdu r1, -112(r1)
@@ -81,6 +82,7 @@ BODY_LABEL (_init):
 	ENTRY_2(_fini)
 	.align ALIGNARG (2)
 BODY_LABEL (_fini):
+	LOCALENTRY(_fini)
 	mflr 0
 	std 0, 16(r1)
 	stdu r1, -112(r1)
diff --git a/sysdeps/powerpc/powerpc64/dl-irel.h b/sysdeps/powerpc/powerpc64/dl-irel.h
index d85c614..a500aa6 100644
--- a/sysdeps/powerpc/powerpc64/dl-irel.h
+++ b/sysdeps/powerpc/powerpc64/dl-irel.h
@@ -50,7 +50,11 @@ elf_irela (const Elf64_Rela *reloc)
     {
       Elf64_Addr *const reloc_addr = (void *) reloc->r_offset;
       Elf64_Addr value = elf_ifunc_invoke(reloc->r_addend);
+#if _CALL_ELF != 2
       *(Elf64_FuncDesc *) reloc_addr = *(Elf64_FuncDesc *) value;
+#else
+      *reloc_addr = value;
+#endif
     }
   else
     __libc_fatal ("unexpected reloc type in static binary");
diff --git a/sysdeps/powerpc/powerpc64/dl-machine.h b/sysdeps/powerpc/powerpc64/dl-machine.h
index a623be5..f222bb0 100644
--- a/sysdeps/powerpc/powerpc64/dl-machine.h
+++ b/sysdeps/powerpc/powerpc64/dl-machine.h
@@ -31,6 +31,7 @@
    in l_info array.  */
 #define DT_PPC64(x) (DT_PPC64_##x - DT_LOPROC + DT_NUM)
 
+#if _CALL_ELF != 2
 /* A PowerPC64 function descriptor.  The .plt (procedure linkage
    table) and .opd (official procedure descriptor) sections are
    arrays of these.  */
@@ -40,6 +41,7 @@ typedef struct
   Elf64_Addr fd_toc;
   Elf64_Addr fd_aux;
 } Elf64_FuncDesc;
+#endif
 
 #define ELF_MULT_MACHINES_SUPPORTED
 
@@ -47,6 +49,18 @@ typedef struct
 static inline int
 elf_machine_matches_host (const Elf64_Ehdr *ehdr)
 {
+  /* Verify that the binary matches our ABI version.  */
+  if ((ehdr->e_flags & EF_PPC64_ABI) != 0)
+    {
+#if _CALL_ELF != 2
+      if ((ehdr->e_flags & EF_PPC64_ABI) != 1)
+        return 0;
+#else
+      if ((ehdr->e_flags & EF_PPC64_ABI) != 2)
+        return 0;
+#endif
+    }
+
   return ehdr->e_machine == EM_PPC64;
 }
 
@@ -124,6 +138,7 @@ elf_machine_dynamic (void)
 "	.align	2\n"							\
 "	" ENTRY_2(_start) "\n"						\
 BODY_PREFIX "_start:\n"							\
+"	" LOCALENTRY(_start) "\n"						\
 /* We start with the following on the stack, from top:			\
    argc (4 bytes);							\
    arguments for program (terminated by NULL);				\
@@ -165,6 +180,7 @@ DL_STARTING_UP_DEF							\
    Changing these is strongly discouraged (not least because argc is	\
    passed by value!).  */						\
 BODY_PREFIX "_dl_start_user:\n"						\
+"	" LOCALENTRY(_dl_start_user) "\n"				\
 /* the address of _start in r30.  */					\
 "	mr	30,3\n"							\
 /* &_dl_argc in 29, &_dl_argv in 27, and _dl_loaded in 28.  */		\
@@ -256,8 +272,22 @@ BODY_PREFIX "_dl_start_user:\n"						\
    relocations behave "normally", ie. always use the real address
    like PLT relocations.  So always set ELF_RTYPE_CLASS_PLT.  */
 
+#if _CALL_ELF != 2
 #define elf_machine_type_class(type) \
   (ELF_RTYPE_CLASS_PLT | (((type) == R_PPC64_COPY) * ELF_RTYPE_CLASS_COPY))
+#else
+/* And now that you have read that large comment, you can disregard it
+   all for ELFv2.  ELFv2 does need the special SHN_UNDEF treatment.  */
+#define IS_PPC64_TLS_RELOC(R)						\
+  (((R) >= R_PPC64_TLS && (R) <= R_PPC64_DTPREL16_HIGHESTA)		\
+   || ((R) >= R_PPC64_TPREL16_HIGH && (R) <= R_PPC64_DTPREL16_HIGHA))
+
+#define elf_machine_type_class(type) \
+  ((((type) == R_PPC64_JMP_SLOT					\
+     || (type) == R_PPC64_ADDR24				\
+     || IS_PPC64_TLS_RELOC (type)) * ELF_RTYPE_CLASS_PLT)	\
+   | (((type) == R_PPC64_COPY) * ELF_RTYPE_CLASS_COPY))
+#endif
 
 /* A reloc type used for ld.so cmdline arg lookups to reject PLT entries.  */
 #define ELF_MACHINE_JMP_SLOT	R_PPC64_JMP_SLOT
@@ -266,8 +296,19 @@ BODY_PREFIX "_dl_start_user:\n"						\
 #define ELF_MACHINE_NO_REL 1
 
 /* Stuff for the PLT.  */
+#if _CALL_ELF != 2
 #define PLT_INITIAL_ENTRY_WORDS 3
+#define PLT_ENTRY_WORDS 3
+#define GLINK_INITIAL_ENTRY_WORDS 8
+/* The first 32k entries of glink can set an index and branch using two
+   instructions; past that point, glink uses three instructions.  */
+#define GLINK_ENTRY_WORDS(I) (((I) < 0x8000)? 2 : 3)
+#else
+#define PLT_INITIAL_ENTRY_WORDS 2
+#define PLT_ENTRY_WORDS 1
 #define GLINK_INITIAL_ENTRY_WORDS 8
+#define GLINK_ENTRY_WORDS(I) 1
+#endif
 
 #define PPC_DCBST(where) asm volatile ("dcbst 0,%0" : : "r"(where) : "memory")
 #define PPC_DCBT(where) asm volatile ("dcbt 0,%0" : : "r"(where) : "memory")
@@ -312,38 +353,45 @@ elf_machine_runtime_setup (struct link_map *map, int lazy, int profile)
 
       if (lazy)
 	{
-	  /* The function descriptor of the appropriate trampoline
-	     routine is used to set the 1st and 2nd doubleword of the
-	     plt_reserve.  */
-	  Elf64_FuncDesc *resolve_fd;
 	  Elf64_Word glink_offset;
-	  /* the plt_reserve area is the 1st 3 doublewords of the PLT */
-	  Elf64_FuncDesc *plt_reserve = (Elf64_FuncDesc *) plt;
 	  Elf64_Word offset;
+	  Elf64_Addr dlrr;
 
-	  resolve_fd = (Elf64_FuncDesc *) (profile ? _dl_profile_resolve
-					   : _dl_runtime_resolve);
+	  dlrr = (Elf64_Addr) (profile ? _dl_profile_resolve
+				       : _dl_runtime_resolve);
 	  if (profile && GLRO(dl_profile) != NULL
 	      && _dl_name_match_p (GLRO(dl_profile), map))
 	    /* This is the object we are looking for.  Say that we really
 	       want profiling and the timers are started.  */
 	    GL(dl_profile_map) = map;
 
-
+#if _CALL_ELF != 2
 	  /* We need to stuff the address/TOC of _dl_runtime_resolve
 	     into doublewords 0 and 1 of plt_reserve.  Then we need to
 	     stuff the map address into doubleword 2 of plt_reserve.
 	     This allows the GLINK0 code to transfer control to the
 	     correct trampoline which will transfer control to fixup
 	     in dl-machine.c.  */
-	  plt_reserve->fd_func = resolve_fd->fd_func;
-	  plt_reserve->fd_toc  = resolve_fd->fd_toc;
-	  plt_reserve->fd_aux  = (Elf64_Addr) map;
+	  {
+	    /* The plt_reserve area is the 1st 3 doublewords of the PLT.  */
+	    Elf64_FuncDesc *plt_reserve = (Elf64_FuncDesc *) plt;
+	    Elf64_FuncDesc *resolve_fd = (Elf64_FuncDesc *) dlrr;
+	    plt_reserve->fd_func = resolve_fd->fd_func;
+	    plt_reserve->fd_toc  = resolve_fd->fd_toc;
+	    plt_reserve->fd_aux  = (Elf64_Addr) map;
 #ifdef RTLD_BOOTSTRAP
-	  /* When we're bootstrapping, the opd entry will not have
-	     been relocated yet.  */
-	  plt_reserve->fd_func += l_addr;
-	  plt_reserve->fd_toc  += l_addr;
+	    /* When we're bootstrapping, the opd entry will not have
+	       been relocated yet.  */
+	    plt_reserve->fd_func += l_addr;
+	    plt_reserve->fd_toc  += l_addr;
+#endif
+	  }
+#else
+	  /* When we don't have function descriptors, the first doubleword
+	     of the PLT holds the address of _dl_runtime_resolve, and the
+	     second doubleword holds the map address.  */
+	  plt[0] = dlrr;
+	  plt[1] = (Elf64_Addr) map;
 #endif
 
 	  /* Set up the lazy PLT entries.  */
@@ -354,14 +402,8 @@ elf_machine_runtime_setup (struct link_map *map, int lazy, int profile)
 	    {
 
 	      plt[offset] = (Elf64_Xword) &glink[glink_offset];
-	      offset += 3;
-	      /* The first 32k entries of glink can set an index and
-		 branch using two instructions;  Past that point,
-		 glink uses three instructions.  */
-	      if (i < 0x8000)
-		glink_offset += 2;
-	      else
-		glink_offset += 3;
+	      offset += PLT_ENTRY_WORDS;
+	      glink_offset += GLINK_ENTRY_WORDS (i);
 	    }
 
 	  /* Now, we've modified data.  We need to write the changes from
@@ -389,6 +431,7 @@ elf_machine_fixup_plt (struct link_map *map, lookup_t sym_map,
 		       const Elf64_Rela *reloc,
 		       Elf64_Addr *reloc_addr, Elf64_Addr finaladdr)
 {
+#if _CALL_ELF != 2
   Elf64_FuncDesc *plt = (Elf64_FuncDesc *) reloc_addr;
   Elf64_FuncDesc *rel = (Elf64_FuncDesc *) finaladdr;
   Elf64_Addr offset = 0;
@@ -426,6 +469,9 @@ elf_machine_fixup_plt (struct link_map *map, lookup_t sym_map,
   plt->fd_func = rel->fd_func + offset;
   PPC_DCBST (&plt->fd_func);
   PPC_ISYNC;
+#else
+  *reloc_addr = finaladdr;
+#endif
 
   return finaladdr;
 }
@@ -433,6 +479,7 @@ elf_machine_fixup_plt (struct link_map *map, lookup_t sym_map,
 static inline void __attribute__ ((always_inline))
 elf_machine_plt_conflict (Elf64_Addr *reloc_addr, Elf64_Addr finaladdr)
 {
+#if _CALL_ELF != 2
   Elf64_FuncDesc *plt = (Elf64_FuncDesc *) reloc_addr;
   Elf64_FuncDesc *rel = (Elf64_FuncDesc *) finaladdr;
 
@@ -443,6 +490,9 @@ elf_machine_plt_conflict (Elf64_Addr *reloc_addr, Elf64_Addr finaladdr)
   PPC_DCBST (&plt->fd_aux);
   PPC_DCBST (&plt->fd_toc);
   PPC_SYNC;
+#else
+  *reloc_addr = finaladdr;
+#endif
 }
 
 /* Return the final value of a plt relocation.  */
@@ -512,6 +562,7 @@ auto inline Elf64_Addr __attribute__ ((always_inline))
 resolve_ifunc (Elf64_Addr value,
 	       const struct link_map *map, const struct link_map *sym_map)
 {
+#if _CALL_ELF != 2
 #ifndef RESOLVE_CONFLICT_FIND_MAP
   /* The function we are calling may not yet have its opd entry relocated.  */
   Elf64_FuncDesc opd;
@@ -529,6 +580,7 @@ resolve_ifunc (Elf64_Addr value,
       value = (Elf64_Addr) &opd;
     }
 #endif
+#endif
   return ((Elf64_Addr (*) (unsigned long int)) value) (GLRO(dl_hwcap));
 }
 
diff --git a/sysdeps/powerpc/powerpc64/setjmp-common.S b/sysdeps/powerpc/powerpc64/setjmp-common.S
index 1829b9a..db4b349 100644
--- a/sysdeps/powerpc/powerpc64/setjmp-common.S
+++ b/sysdeps/powerpc/powerpc64/setjmp-common.S
@@ -55,9 +55,10 @@ END (setjmp)
    HAVE_CLEANUP_JMP_BUF is defined.  */
 ENTRY (__GI__setjmp)
 	std r2,40(r1)		/* Save the callers TOC in the save area.  */
-	cfi_endproc
-END_2 (__GI__setjmp)
-/* Fall thru. */
+	CALL_MCOUNT 1
+	li r4,0			/* Set second argument to 0.  */
+	b JUMPTARGET (GLUE(__sigsetjmp,_ent))
+END (__GI__setjmp)
 #endif
 
 ENTRY (_setjmp)
diff --git a/sysdeps/powerpc/powerpc64/sysdep.h b/sysdeps/powerpc/powerpc64/sysdep.h
index cc89b3c..779fd90 100644
--- a/sysdeps/powerpc/powerpc64/sysdep.h
+++ b/sysdeps/powerpc/powerpc64/sysdep.h
@@ -74,6 +74,8 @@
 #endif
 	.endm
 
+#if _CALL_ELF != 2
+
 /* Macro to prepare for calling via a function pointer.  */
 	.macro PPC64_LOAD_FUNCPTR PTR
 	ld      r12,0(\PTR)
@@ -115,13 +117,37 @@ name##: OPD_ENT (name);				\
 	.size name,.-BODY_LABEL(name);		\
 	.size BODY_LABEL(name),.-BODY_LABEL(name);
 #endif
+#define LOCALENTRY(name)
+
+#else /* _CALL_ELF */
+
+/* Macro to prepare for calling via a function pointer.  */
+	.macro PPC64_LOAD_FUNCPTR PTR
+	mr	r12,\PTR
+	mtctr   r12
+	.endm
+
+#define DOT_LABEL(X) X
+#define BODY_LABEL(X) X
+#define ENTRY_2(name)	\
+	.globl name;				\
+	.type name,@function;
+#define END_2(name)	\
+	.size name,.-name;
+#define LOCALENTRY(name)	\
+1:      addis	r2,r12,.TOC.-1b@ha; \
+        addi	r2,r2,.TOC.-1b@l; \
+	.localentry name,.-name;
+
+#endif /* _CALL_ELF */
 
 #define ENTRY(name)	\
 	.section	".text";		\
 	ENTRY_2(name)				\
 	.align ALIGNARG(2);			\
 BODY_LABEL(name):				\
-	cfi_startproc;
+	cfi_startproc;				\
+	LOCALENTRY(name)
 
 #define EALIGN_W_0  /* No words to insert.  */
 #define EALIGN_W_1  nop
@@ -140,7 +166,8 @@ BODY_LABEL(name):				\
 	.align ALIGNARG(alignt);		\
 	EALIGN_W_##words;			\
 BODY_LABEL(name):				\
-	cfi_startproc;
+	cfi_startproc;				\
+	LOCALENTRY(name)
 
 /* Local labels stripped out by the linker.  */
 #undef L
@@ -295,6 +322,8 @@ LT_LABELSUFFIX(name,_name_end): ; \
 
 #else /* !__ASSEMBLER__ */
 
+#if _CALL_ELF != 2
+
 #define PPC64_LOAD_FUNCPTR(ptr) \
 	"ld 	12,0(" #ptr ");\n"					\
 	"ld	2,8(" #ptr ");\n"					\
@@ -335,5 +364,26 @@ LT_LABELSUFFIX(name,_name_end): ; \
 	".size " #name ",.-" BODY_PREFIX #name ";\n"			\
 	".size " BODY_PREFIX #name ",.-" BODY_PREFIX #name ";"
 #endif
+#define LOCALENTRY(name)
+
+#else /* _CALL_ELF */
+
+#define PPC64_LOAD_FUNCPTR(ptr) \
+	"mr	12," #ptr ";\n"						\
+	"mtctr 	12;"
+
+#define DOT_PREFIX ""
+#define BODY_PREFIX ""
+#define ENTRY_2(name)	\
+	".type " #name ",@function;\n"					\
+	".globl " #name ";"
+#define END_2(name)	\
+	".size " #name ",.-" #name ";"
+#define LOCALENTRY(name)	\
+	"1: addis 2,12,.TOC.-1b@ha;\n"					\
+	"addi	2,2,.TOC.-1b@l;\n"					\
+	".localentry " #name ",.-" #name ";"
+
+#endif /* _CALL_ELF */
 
 #endif	/* __ASSEMBLER__ */
diff --git a/sysdeps/unix/sysv/linux/powerpc/bits/libc-vdso.h b/sysdeps/unix/sysv/linux/powerpc/bits/libc-vdso.h
index d189169..31dd15e 100644
--- a/sysdeps/unix/sysv/linux/powerpc/bits/libc-vdso.h
+++ b/sysdeps/unix/sysv/linux/powerpc/bits/libc-vdso.h
@@ -41,7 +41,7 @@ extern void *__vdso_sigtramp32;
 extern void *__vdso_sigtramp_rt32;
 #endif
 
-#if defined(__PPC64__) || defined(__powerpc64__)
+#if (defined(__PPC64__) || defined(__powerpc64__)) && _CALL_ELF != 2
 /* The correct solution is for _dl_vdso_vsym to return the address of the OPD
    for the kernel VDSO function.  That address would then be stored in the
    __vdso_* variables and returned as the result of the IFUNC resolver function.
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/ldsodefs.h b/sysdeps/unix/sysv/linux/powerpc/powerpc64/ldsodefs.h
index 4263b1a..d043968 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/ldsodefs.h
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/ldsodefs.h
@@ -23,6 +23,8 @@
 
 /* Now define our stuff.  */
 
+#if _CALL_ELF != 2
+
 static __always_inline bool
 _dl_ppc64_is_opd_sym (const struct link_map *l, const ElfW(Sym) *sym)
 {
@@ -73,4 +75,6 @@ _dl_ppc64_addr_sym_match (const struct link_map *l, const ElfW(Sym) *sym,
 #define DL_ADDR_SYM_MATCH(L, SYM, MATCHSYM, ADDR) \
   _dl_ppc64_addr_sym_match (L, SYM, MATCHSYM, ADDR)
 
+#endif
+
 #endif /* ldsodefs.h */
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/makecontext.S b/sysdeps/unix/sysv/linux/powerpc/powerpc64/makecontext.S
index a7b0a18..b6d82bd 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/makecontext.S
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/makecontext.S
@@ -111,6 +111,7 @@ L(parmloop):
 
 L(noparms):
 
+#if _CALL_ELF != 2
   /* Load the function address and TOC from the function descriptor
      and store them in the ucontext as NIP and r2.  Store the 3rd
      field of the function descriptor into the ucontext as r11 in case
@@ -121,6 +122,12 @@ L(noparms):
   std   r0,(SIGCONTEXT_GP_REGS+(PT_NIP*8))(r3)
   std   r10,(SIGCONTEXT_GP_REGS+(PT_R2*8))(r3)
   std   r9,(SIGCONTEXT_GP_REGS+(PT_R11*8))(r3)
+#else
+  /* In the ELFv2 ABI, the function pointer is already the address.
+     Store it as NIP and r12 as required by the ABI.  */
+  std   r4,(SIGCONTEXT_GP_REGS+(PT_NIP*8))(r3)
+  std   r4,(SIGCONTEXT_GP_REGS+(PT_R12*8))(r3)
+#endif
 
   /* If the target function returns we need to do some cleanup.  We use a
      code trick to get the address of our cleanup function into the link

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=5446d084fc64c279212616305bbc3c727a6b6d70

commit 5446d084fc64c279212616305bbc3c727a6b6d70
Author: Ulrich Weigand <Ulrich.Weigand@de.ibm.com>
Date:   Fri Nov 15 11:52:37 2013 -0600

    PowerPC64 ELFv2 ABI 1/6: Code refactoring
    
    This is the first patch to support the new ELFv2 ABI in glibc.
    
    As preparation, this patch simply refactors some of the powerpc64 assembler
    code to move all code related to creating function descriptors (.opd section)
    or using function descriptors (function pointer call) into a central place
    in sysdep.h.
    
    Note that most locations creating .opd entries were already using macros
    in sysdep.h, this patch simply extends this to the remaining places.
    
    No relevant change in generated code expected.

diff --git a/ChangeLog b/ChangeLog
index 1a0a8a1..9bd9834 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,21 @@
+2013-11-12  Ulrich Weigand  <Ulrich.Weigand@de.ibm.com>
+
+	* sysdeps/powerpc/powerpc64/sysdep.h [ASSEMBLER] (PPC64_LOAD_FUNCPTR):
+	New assembler macro.
+	[ASSEMBLER] (ENTRY_1): Do not switch to .text section here ...
+	[ASSEMBLER] (ENTRY): ... but instead here ...
+	[ASSEMBLER] (EALIGN): ... and here.
+	[!ASSEMBLER] (PPC64_LOAD_FUNCPTR): New macro.
+	[!ASSEMBLER] (ENTRY_1): New macro; set up .opd entry.
+	[!ASSEMBLER] (ENTRY_2): Use it.
+	* sysdeps/powerpc/powerpc64/dl-machine.h (RTLD_START): Update for
+	ENTRY_2 changes.  Use PPC64_LOAD_FUNCPTR.
+	* sysdeps/powerpc/powerpc64/dl-trampoline.S (_dl_runtime_resolve,
+	_dl_profile_resolve): Use PPC64_LOAD_FUNCPTR.
+	* sysdeps/powerpc/powerpc64/crti.S (_init, _fini): Use ENTRY_2.
+	* sysdeps/unix/sysv/linux/powerpc/powerpc64/clone.S (clone):
+	Use PPC64_LOAD_FUNCPTR.
+
 2013-11-12  Alan Modra  <amodra@gmail.com>
 
 	* elf/elf.h (R_PPC64_TLSGD, R_PPC64_TLSLD, R_PPC64_TOCSAVE): Define.
diff --git a/sysdeps/powerpc/powerpc64/crti.S b/sysdeps/powerpc/powerpc64/crti.S
index 967dc66..116199d 100644
--- a/sysdeps/powerpc/powerpc64/crti.S
+++ b/sysdeps/powerpc/powerpc64/crti.S
@@ -60,18 +60,8 @@
 .LC0:
 	.tc PREINIT_FUNCTION[TC], PREINIT_FUNCTION
 #endif
-	.type BODY_LABEL (_init), @function
-	.globl _init
-	.section ".opd", "aw"
-	.align 3
-_init:	OPD_ENT (_init)
-#ifdef HAVE_ASM_GLOBAL_DOT_NAME
-	.globl BODY_LABEL (_init)
-	.size _init, 24
-#else
-	.type _init, @function
-#endif
 	.section ".init", "ax", @progbits
+	ENTRY_2(_init)
 	.align ALIGNARG (2)
 BODY_LABEL (_init):
 	mflr 0
@@ -87,18 +77,8 @@ BODY_LABEL (_init):
 	nop
 1:
 
-	.type BODY_LABEL (_fini), @function
-	.globl _fini
-	.section ".opd", "aw"
-	.align 3
-_fini:	OPD_ENT (_fini)
-#ifdef HAVE_ASM_GLOBAL_DOT_NAME
-	.globl BODY_LABEL (_fini)
-	.size _fini, 24
-#else
-	.type _fini, @function
-#endif
 	.section ".fini", "ax", @progbits
+	ENTRY_2(_fini)
 	.align ALIGNARG (2)
 BODY_LABEL (_fini):
 	mflr 0
diff --git a/sysdeps/powerpc/powerpc64/dl-machine.h b/sysdeps/powerpc/powerpc64/dl-machine.h
index 19fa4fa..a623be5 100644
--- a/sysdeps/powerpc/powerpc64/dl-machine.h
+++ b/sysdeps/powerpc/powerpc64/dl-machine.h
@@ -122,14 +122,7 @@ elf_machine_dynamic (void)
 #define RTLD_START \
   asm (".pushsection \".text\"\n"					\
 "	.align	2\n"							\
-"	.type	" BODY_PREFIX "_start,@function\n"			\
-"	.pushsection \".opd\",\"aw\"\n"					\
-"	.align	3\n"							\
-"	.globl	_start\n"						\
 "	" ENTRY_2(_start) "\n"						\
-"_start:\n"								\
-"	" OPD_ENT(_start) "\n"						\
-"	.popsection\n"							\
 BODY_PREFIX "_start:\n"							\
 /* We start with the following on the stack, from top:			\
    argc (4 bytes);							\
@@ -154,11 +147,6 @@ BODY_PREFIX "_start:\n"							\
 ".LT__start_name_end:\n"						\
 "	.align 2\n"							\
 "	" END_2(_start) "\n"						\
-"	.globl	_dl_start_user\n"					\
-"	.pushsection \".opd\",\"aw\"\n"					\
-"_dl_start_user:\n"							\
-"	" OPD_ENT(_dl_start_user) "\n"					\
-"	.popsection\n"							\
 "	.pushsection	\".toc\",\"aw\"\n"				\
 DL_STARTING_UP_DEF							\
 ".LC__rtld_local:\n"							\
@@ -170,7 +158,6 @@ DL_STARTING_UP_DEF							\
 ".LC__dl_fini:\n"							\
 "	.tc _dl_fini[TC],_dl_fini\n"					\
 "	.popsection\n"							\
-"	.type	" BODY_PREFIX "_dl_start_user,@function\n"		\
 "	" ENTRY_2(_dl_start_user) "\n"					\
 /* Now, we do our main work of calling initialisation procedures.	\
    The ELF ABI doesn't say anything about parameters for these,		\
@@ -228,10 +215,7 @@ BODY_PREFIX "_dl_start_user:\n"						\
 /* Now, call the start function descriptor at r30...  */		\
 "	.globl	._dl_main_dispatch\n"					\
 "._dl_main_dispatch:\n"							\
-"	ld	0,0(30)\n"						\
-"	ld	2,8(30)\n"						\
-"	mtctr	0\n"							\
-"	ld	11,16(30)\n"						\
+"	" PPC64_LOAD_FUNCPTR(30) "\n"					\
 "	bctr\n"								\
 ".LT__dl_start_user:\n"							\
 "	.long 0\n"							\
diff --git a/sysdeps/powerpc/powerpc64/dl-trampoline.S b/sysdeps/powerpc/powerpc64/dl-trampoline.S
index 4dde276..bffc4cb 100644
--- a/sysdeps/powerpc/powerpc64/dl-trampoline.S
+++ b/sysdeps/powerpc/powerpc64/dl-trampoline.S
@@ -71,12 +71,8 @@ EALIGN(_dl_runtime_resolve, 4, 0)
 	ld	r5,INT_PARMS+16(r1)
 	ld	r4,INT_PARMS+8(r1)
 	mtcrf	0xFF,r0
-/* Load the target address, toc and static chain reg from the function
-   descriptor returned by fixup.  */
-	ld	r0,0(r3)
-	ld	r2,8(r3)
-	mtctr	r0
-	ld	r11,16(r3)
+/* Prepare for calling the function returned by fixup.  */
+	PPC64_LOAD_FUNCPTR r3
 	ld	r3,INT_PARMS+0(r1)
 /* Unwind the stack frame, and jump.  */
 	addi	r1,r1,FRAME_SIZE
@@ -322,13 +318,9 @@ L(restoreFXR):
 	ld	r5,INT_PARMS+16(r1)
 	ld	r4,INT_PARMS+8(r1)
 	mtcrf	0xFF,r0
-/* Load the target address, toc and static chain reg from the function
-   descriptor returned by fixup.  */
-	ld	r0,0(r3)
-	ld	r2,8(r3)
-	ld	r11,16(r3)
+/* Prepare for calling the function returned by fixup.  */
+	PPC64_LOAD_FUNCPTR r3
 	ld	r3,INT_PARMS+0(r1)
-	mtctr	r0
 /* Load the floating point registers.  */
 	lfd	fp1,FPR_PARMS+0(r1)
 	lfd	fp2,FPR_PARMS+8(r1)
@@ -386,14 +378,10 @@ L(restoreFXR2):
 	ld	r5,INT_PARMS+16(r1)
 	ld	r4,INT_PARMS+8(r1)
 	mtcrf	0xFF,r0
-/* Load the target address, toc and static chain reg from the function
-   descriptor returned by fixup.  */
-	ld	r0,0(r3)
+/* Prepare for calling the function returned by fixup.  */
 	std	r2,40(r1)
-	ld	r2,8(r3)
-	ld	r11,16(r3)
+	PPC64_LOAD_FUNCPTR r3
 	ld	r3,INT_PARMS+0(r1)
-	mtctr	r0
 /* Load the floating point registers.  */
 	lfd	fp1,FPR_PARMS+0(r1)
 	lfd	fp2,FPR_PARMS+8(r1)
diff --git a/sysdeps/powerpc/powerpc64/sysdep.h b/sysdeps/powerpc/powerpc64/sysdep.h
index 57fa8ba..cc89b3c 100644
--- a/sysdeps/powerpc/powerpc64/sysdep.h
+++ b/sysdeps/powerpc/powerpc64/sysdep.h
@@ -74,6 +74,14 @@
 #endif
 	.endm
 
+/* Macro to prepare for calling via a function pointer.  */
+	.macro PPC64_LOAD_FUNCPTR PTR
+	ld      r12,0(\PTR)
+	ld      r2,8(\PTR)
+	mtctr   r12
+	ld      r11,16(\PTR)
+	.endm
+
 #ifdef USE_PPC64_OVERLAPPING_OPD
 # define OPD_ENT(name)	.quad BODY_LABEL (name), .TOC.@tocbase
 #else
@@ -81,7 +89,6 @@
 #endif
 
 #define ENTRY_1(name)	\
-	.section	".text";		\
 	.type BODY_LABEL(name),@function;	\
 	.globl name;				\
 	.section ".opd","aw";			\
@@ -110,6 +117,7 @@ name##: OPD_ENT (name);				\
 #endif
 
 #define ENTRY(name)	\
+	.section	".text";		\
 	ENTRY_2(name)				\
 	.align ALIGNARG(2);			\
 BODY_LABEL(name):				\
@@ -127,6 +135,7 @@ BODY_LABEL(name):				\
 /* EALIGN is like ENTRY, but does alignment to 'words'*4 bytes
    past a 2^alignt boundary.  */
 #define EALIGN(name, alignt, words) \
+	.section	".text";		\
 	ENTRY_2(name)				\
 	.align ALIGNARG(alignt);		\
 	EALIGN_W_##words;			\
@@ -286,24 +295,42 @@ LT_LABELSUFFIX(name,_name_end): ; \
 
 #else /* !__ASSEMBLER__ */
 
+#define PPC64_LOAD_FUNCPTR(ptr) \
+	"ld 	12,0(" #ptr ");\n"					\
+	"ld	2,8(" #ptr ");\n"					\
+	"mtctr	12;\n"							\
+	"ld	11,16(" #ptr ");"
+
 #ifdef USE_PPC64_OVERLAPPING_OPD
 # define OPD_ENT(name)	".quad " BODY_PREFIX #name ", .TOC.@tocbase;"
 #else
 # define OPD_ENT(name)	".quad " BODY_PREFIX #name ", .TOC.@tocbase, 0;"
 #endif
 
+#define ENTRY_1(name)	\
+	".type   " BODY_PREFIX #name ",@function;\n"			\
+	".globl " #name ";\n"						\
+	".pushsection \".opd\",\"aw\";\n"				\
+	".align  3;\n"							\
+#name ":\n"								\
+	OPD_ENT (name) "\n"						\
+	".popsection;"
+
 #ifdef HAVE_ASM_GLOBAL_DOT_NAME
 # define DOT_PREFIX "."
 # define BODY_PREFIX "."
 # define ENTRY_2(name)	\
 	".globl " BODY_PREFIX #name ";\n"				\
+	ENTRY_1(name) "\n"						\
 	".size  " #name ", 24;"
 # define END_2(name)	\
 	".size " BODY_PREFIX #name ",.-" BODY_PREFIX #name ";"
 #else
 # define DOT_PREFIX ""
 # define BODY_PREFIX ".LY"
-# define ENTRY_2(name) ".type " #name ",@function;"
+# define ENTRY_2(name)	\
+	".type " #name ",@function;\n"					\
+	ENTRY_1(name)
 # define END_2(name)	\
 	".size " #name ",.-" BODY_PREFIX #name ";\n"			\
 	".size " BODY_PREFIX #name ",.-" BODY_PREFIX #name ";"
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/clone.S b/sysdeps/unix/sysv/linux/powerpc/powerpc64/clone.S
index cf46856..4151d15 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/clone.S
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/clone.S
@@ -99,9 +99,7 @@ L(oldpid):
 
 	std	r2,40(r1)
 	/* Call procedure.  */
-	ld	r0,0(r30)
-	ld	r2,8(r30)
-	mtctr	r0
+	PPC64_LOAD_FUNCPTR r30
 	mr	r3,r31
 	bctrl
 	ld	r2,40(r1)

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=47a519a15c82486e7f5a15e0f81a58df301017d9

commit 47a519a15c82486e7f5a15e0f81a58df301017d9
Author: Alan Modra <amodra@gmail.com>
Date:   Fri Nov 15 11:51:18 2013 -0600

    PowerPC64: Report overflow on @h and @ha relocations
    
    This patch updates glibc in accordance with the binutils patch checked
    in here:
    https://sourceware.org/ml/binutils/2013-10/msg00372.html
    
    This changes the various R_PPC64_..._HI and _HA relocations to report
    32-bit overflows.  The motivation is that existing uses of @h / @ha
    are to build up 32-bit offsets (for the "medium model" TOC access
    that GCC now defaults to), and we'd really like to see failures at
    link / load time rather than silent truncations.
    
    For those rare cases where a modifier is needed to build up a 64-bit
    constant, new relocations _HIGH / _HIGHA are supported.
    
    The patch also fixes a bug in overflow checking for the R_PPC64_ADDR30
    and R_PPC64_ADDR32 relocations.

diff --git a/ChangeLog b/ChangeLog
index 7b4c702..1a0a8a1 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,17 @@
+2013-11-12  Alan Modra  <amodra@gmail.com>
+
+	* elf/elf.h (R_PPC64_TLSGD, R_PPC64_TLSLD, R_PPC64_TOCSAVE): Define.
+	(R_PPC64_ADDR16_HIGH, R_PPC64_ADDR16_HIGHA): Likewise.
+	(R_PPC64_TPREL16_HIGH, R_PPC64_TPREL16_HIGHA): Likewise.
+	(R_PPC64_DTPREL16_HIGH, R_PPC64_DTPREL16_HIGHA): Likewise.
+
+	* sysdeps/powerpc/powerpc64/dl-machine.h (elf_machine_rela): Add
+	overflow checking for R_PPC64_ADDR16_HI, R_PPC64_ADDR16_HA,
+	R_PPC64_TPREL16_HI, and R_PPC64_TPREL16_HA.
+	Support new R_PPC64_ADDR16_HIGH, R_PPC64_ADDR16_HIGHA,
+	R_PPC64_TPREL16_HIGH, and R_PPC64_TPREL16_HIGHA relocations.
+	Fix overflow checking for R_PPC64_ADDR30 and R_PPC64_ADDR32.
+
 2013-11-12  Ulrich Weigand  <Ulrich.Weigand@de.ibm.com>
 
 	* sysdeps/unix/sysv/linux/powerpc/powerpc64/makecontext.S
diff --git a/elf/elf.h b/elf/elf.h
index f372271..98c722e 100644
--- a/elf/elf.h
+++ b/elf/elf.h
@@ -2251,6 +2251,17 @@ typedef Elf32_Addr Elf32_Conflict;
 #define R_PPC64_DTPREL16_HIGHERA 104 /* half16	(sym+add)@dtprel@highera */
 #define R_PPC64_DTPREL16_HIGHEST 105 /* half16	(sym+add)@dtprel@highest */
 #define R_PPC64_DTPREL16_HIGHESTA 106 /* half16	(sym+add)@dtprel@highesta */
+#define R_PPC64_TLSGD		107 /* none	(sym+add)@tlsgd */
+#define R_PPC64_TLSLD		108 /* none	(sym+add)@tlsld */
+#define R_PPC64_TOCSAVE		109 /* none */
+
+/* Added when HA and HI relocs were changed to report overflows.  */
+#define R_PPC64_ADDR16_HIGH	110
+#define R_PPC64_ADDR16_HIGHA	111
+#define R_PPC64_TPREL16_HIGH	112
+#define R_PPC64_TPREL16_HIGHA	113
+#define R_PPC64_DTPREL16_HIGH	114
+#define R_PPC64_DTPREL16_HIGHA	115
 
 /* GNU extension to support local ifunc.  */
 #define R_PPC64_JMP_IREL	247
diff --git a/sysdeps/powerpc/powerpc64/dl-machine.h b/sysdeps/powerpc/powerpc64/dl-machine.h
index 18cf157..19fa4fa 100644
--- a/sysdeps/powerpc/powerpc64/dl-machine.h
+++ b/sysdeps/powerpc/powerpc64/dl-machine.h
@@ -669,11 +669,25 @@ elf_machine_rela (struct link_map *map,
 
     case R_PPC64_TPREL16_HI:
       value = elf_machine_tprel (map, sym_map, sym, reloc);
+      if (dont_expect (value + 0x80000000 >= 0x100000000LL))
+	_dl_reloc_overflow (map, "R_PPC64_TPREL16_HI", reloc_addr, refsym);
+      *(Elf64_Half *) reloc_addr = PPC_HI (value);
+      break;
+
+    case R_PPC64_TPREL16_HIGH:
+      value = elf_machine_tprel (map, sym_map, sym, reloc);
       *(Elf64_Half *) reloc_addr = PPC_HI (value);
       break;
 
     case R_PPC64_TPREL16_HA:
       value = elf_machine_tprel (map, sym_map, sym, reloc);
+      if (dont_expect (value + 0x80008000 >= 0x100000000LL))
+	_dl_reloc_overflow (map, "R_PPC64_TPREL16_HA", reloc_addr, refsym);
+      *(Elf64_Half *) reloc_addr = PPC_HA (value);
+      break;
+
+    case R_PPC64_TPREL16_HIGHA:
+      value = elf_machine_tprel (map, sym_map, sym, reloc);
       *(Elf64_Half *) reloc_addr = PPC_HA (value);
       break;
 
@@ -709,17 +723,23 @@ elf_machine_rela (struct link_map *map,
       break;
 
     case R_PPC64_ADDR16_HI:
+      if (dont_expect (value + 0x80000000 >= 0x100000000LL))
+	_dl_reloc_overflow (map, "R_PPC64_ADDR16_HI", reloc_addr, refsym);
+    case R_PPC64_ADDR16_HIGH:
       *(Elf64_Half *) reloc_addr = PPC_HI (value);
       break;
 
     case R_PPC64_ADDR16_HA:
+      if (dont_expect (value + 0x80008000 >= 0x100000000LL))
+	_dl_reloc_overflow (map, "R_PPC64_ADDR16_HA", reloc_addr, refsym);
+    case R_PPC64_ADDR16_HIGHA:
       *(Elf64_Half *) reloc_addr = PPC_HA (value);
       break;
 
     case R_PPC64_ADDR30:
       {
 	Elf64_Addr delta = value - (Elf64_Xword) reloc_addr;
-	if (dont_expect ((delta + 0x80000000) >= 0x10000000
+	if (dont_expect ((delta + 0x80000000) >= 0x100000000LL
 			 || (delta & 3) != 0))
 	  _dl_reloc_overflow (map, "R_PPC64_ADDR30", reloc_addr, refsym);
 	BIT_INSERT (*(Elf64_Word *) reloc_addr, delta, 0xfffffffc);
@@ -755,7 +775,7 @@ elf_machine_rela (struct link_map *map,
       return;
 
     case R_PPC64_ADDR32:
-      if (dont_expect ((value + 0x80000000) >= 0x10000000))
+      if (dont_expect ((value + 0x80000000) >= 0x100000000LL))
 	_dl_reloc_overflow (map, "R_PPC64_ADDR32", reloc_addr, refsym);
       *(Elf64_Word *) reloc_addr = value;
       return;

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=f0e592f61ef14f3633a35c9a761525e46c03629a

commit f0e592f61ef14f3633a35c9a761525e46c03629a
Author: Ulrich Weigand <Ulrich.Weigand@de.ibm.com>
Date:   Fri Nov 15 11:49:21 2013 -0600

    PowerPC64: Fix incorrect CFI in *context routines
    
    The context established by "makecontext" has a link register pointing
    back to an error path within the makecontext routine.  This is currently
    covered by the CFI FDE for makecontext itself, which is simply wrong
    for the stack frame *inside* the context.  When trying to unwind (e.g.
    doing a backtrace) in a routine inside a context created by makecontext,
    this can lead to uninitialized stack slots being accessed, causing the
    unwinder to crash in the worst case.
    
    Similarly, during parts of the "setcontext" routine, when the stack
    pointer has already been switched to point to the new context, the
    address range is still covered by the CFI FDE for setcontext.  When
    trying to unwind in that situation (e.g. backtrace from an async
    signal handler for profiling), it is again possible that the unwinder
    crashes.
    
    Theses are all problems in existing code, but the changes in stack
    frame layout appear to make the "worst case" much more likely in
    the ELFv2 ABI context.  This causes regressions e.g. in the libgo
    testsuite on ELFv2.
    
    This patch fixes this by ending the makecontext/setcontext FDEs
    before those problematic parts of the assembler, similar to what
    is already done on other platforms.   This fixes the libgo
    regression on ELFv2.

diff --git a/ChangeLog b/ChangeLog
index 4ab2fc4..7b4c702 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+2013-11-12  Ulrich Weigand  <Ulrich.Weigand@de.ibm.com>
+
+	* sysdeps/unix/sysv/linux/powerpc/powerpc64/makecontext.S
+	(__makecontext): Fix incorrect CFI when backtracing out of
+	context created via makecontext.
+	* sysdeps/unix/sysv/linux/powerpc/powerpc64/secontext.S
+	(__setcontext): Fix incorrect CFI during switch to new context.
+	(__novec_setcontext): Likewise.
+
 2013-11-08  Adhemerval Zanella  <azanella@linux.vnet.ibm.com>
 
 	* sysdeps/unix/sysv/linux/powerpc/bits/libc-vdso.h (VDSO_IFUNC_RET):
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/makecontext.S b/sysdeps/unix/sysv/linux/powerpc/powerpc64/makecontext.S
index 32fc47c..a7b0a18 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/makecontext.S
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/makecontext.S
@@ -129,6 +129,10 @@ L(noparms):
      the cpu link stack used to predict blr return addresses.  */
   bcl	20,31,L(gotexitcodeaddr);
 
+  /* End FDE now, because while executing on the context's stack
+     the unwind info would be wrong otherwise.  */
+  cfi_endproc
+
 	/* This is the helper code which gets called if a function which
 	   is registered with 'makecontext' returns.  In this case we
 	   have to install the context listed in the uc_link element of
@@ -157,6 +161,11 @@ L(do_exit):
 #endif
 	b    L(do_exit)
 
+  /* Re-establish FDE for the rest of the actual makecontext routine.  */
+  cfi_startproc
+  cfi_offset (lr, FRAME_LR_SAVE)
+  cfi_adjust_cfa_offset (128)
+
   /* The address of the exit code is in the link register.  Store the lr
      in the ucontext as LNK so the target function will return to our
      exit code.  */
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/setcontext.S b/sysdeps/unix/sysv/linux/powerpc/powerpc64/setcontext.S
index e1f0b86..5ec19ba 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/setcontext.S
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/setcontext.S
@@ -129,6 +129,10 @@ ENTRY(__novec_setcontext)
   lfd  fp1,(SIGCONTEXT_FP_REGS+(PT_R1*8))(r31)
   lfd  fp0,(SIGCONTEXT_FP_REGS+(PT_R0*8))(r31)
 
+  /* End FDE now, because the unwind info would be wrong while
+     we're reloading registers to switch to the new context.  */
+  cfi_endproc
+
   ld   r0,(SIGCONTEXT_GP_REGS+(PT_LNK*8))(r31)
   ld   r1,(SIGCONTEXT_GP_REGS+(PT_R1*8))(r31)
   mtlr r0
@@ -177,6 +181,11 @@ ENTRY(__novec_setcontext)
   ld   r31,(SIGCONTEXT_GP_REGS+(PT_R31*8))(r31)
   bctr
 
+  /* Re-establish FDE for the rest of the actual setcontext routine.  */
+  cfi_startproc
+  cfi_offset (lr, FRAME_LR_SAVE)
+  cfi_adjust_cfa_offset (128)
+
 L(nv_error_exit):
   ld   r0,128+FRAME_LR_SAVE(r1)
   addi r1,r1,128
@@ -403,6 +412,10 @@ L(has_no_vec):
   lfd  fp1,(SIGCONTEXT_FP_REGS+(PT_R1*8))(r31)
   lfd  fp0,(SIGCONTEXT_FP_REGS+(PT_R0*8))(r31)
 
+  /* End FDE now, because the unwind info would be wrong while
+     we're reloading registers to switch to the new context.  */
+  cfi_endproc
+
   ld   r0,(SIGCONTEXT_GP_REGS+(PT_LNK*8))(r31)
   ld   r1,(SIGCONTEXT_GP_REGS+(PT_R1*8))(r31)
   mtlr r0
@@ -451,6 +464,11 @@ L(has_no_vec):
   ld   r31,(SIGCONTEXT_GP_REGS+(PT_R31*8))(r31)
   bctr
 
+  /* Re-establish FDE for the rest of the actual setcontext routine.  */
+  cfi_startproc
+  cfi_offset (lr, FRAME_LR_SAVE)
+  cfi_adjust_cfa_offset (128)
+
 L(error_exit):
   ld   r0,128+FRAME_LR_SAVE(r1)
   addi r1,r1,128

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=f3f9eb461294f1da1f2aa7c39c77e563caa74007

commit f3f9eb461294f1da1f2aa7c39c77e563caa74007
Author: Ulrich Weigand <Ulrich.Weigand@de.ibm.com>
Date:   Fri Nov 15 11:47:44 2013 -0600

    PowerPC64: Add __private_ss field to TCB header
    
    the TCB header on Intel contains a field __private_ss that is used
    to efficiently implement the -fsplit-stack GCC feature.
    
    In order to prepare for a possible future implementation of that
    feature on powerpc64, we'd like to reserve a similar field in
    the TCB header as well.  (It would be good if this went in with
    or before the ELFv2 patches to ensure that this field will be
    available always in the ELFv2 environment.)
    
    The field needs to be added at the front of tcbhead_t structure
    to avoid changing the ABI; see the recent discussion when adding
    the EBB fields.

diff --git a/nptl/ChangeLog b/nptl/ChangeLog
index 2d78490..3ac857a 100644
--- a/nptl/ChangeLog
+++ b/nptl/ChangeLog
@@ -1,3 +1,7 @@
+2013-11-12  Ulrich Weigand  <Ulrich.Weigand@de.ibm.com>
+
+	* sysdeps/powerpc/tls.h (tcbhead_t): Add __private_ss field.
+
 2013-10-03  Siddhesh Poyarekar  <siddhesh@redhat.com>
 
 	[BZ #15996]
diff --git a/nptl/sysdeps/powerpc/tls.h b/nptl/sysdeps/powerpc/tls.h
index 8e0ada6..c21c027 100644
--- a/nptl/sysdeps/powerpc/tls.h
+++ b/nptl/sysdeps/powerpc/tls.h
@@ -61,6 +61,8 @@ typedef union dtv
    are private.  */
 typedef struct
 {
+  /* GCC split stack support.  */
+  void *__private_ss;
   /* Reservation for the Event-Based Branching ABI.  */
   uintptr_t ebb_handler;
   uintptr_t ebb_ctx_pointer;

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=718786a12ee3f566dc1c0898f82d843ef4145c8e

commit 718786a12ee3f566dc1c0898f82d843ef4145c8e
Author: Adhemerval Zanella <azanella@linux.vnet.ibm.com>
Date:   Thu Nov 7 05:34:22 2013 -0600

    PowerPC: Fix vDSO missing ODP entries
    
    This patch fixes the vDSO symbol used directed in IFUNC resolver where
    they do not have an associated ODP entry leading to undefined behavior
    in some cases. It adds an artificial OPD static entry to such cases
    and set its TOC to non 0 to avoid triggering lazy resolutions.

diff --git a/ChangeLog b/ChangeLog
index d5f760b..4ab2fc4 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2013-11-08  Adhemerval Zanella  <azanella@linux.vnet.ibm.com>
+
+	* sysdeps/unix/sysv/linux/powerpc/bits/libc-vdso.h (VDSO_IFUNC_RET):
+	Add artificial ODP entry for vDSO symbol for PPC64.
+	* sysdeps/unix/sysv/linux/powerpc/gettimeofday.c: Adjust includes.
+	* sysdeps/unix/sysv/linux/powerpc/time.c: Likewise.
+
 2013-09-25  Adhemerval Zanella  <azanella@linux.vnet.ibm.com>
 
 	* sysdeps/powerpc/powerpc64/stackguard-macros.h (POINTER_CHK_GUARD:
diff --git a/sysdeps/unix/sysv/linux/powerpc/bits/libc-vdso.h b/sysdeps/unix/sysv/linux/powerpc/bits/libc-vdso.h
index ba54de4..d189169 100644
--- a/sysdeps/unix/sysv/linux/powerpc/bits/libc-vdso.h
+++ b/sysdeps/unix/sysv/linux/powerpc/bits/libc-vdso.h
@@ -41,12 +41,32 @@ extern void *__vdso_sigtramp32;
 extern void *__vdso_sigtramp_rt32;
 #endif
 
-/* This macro is needed for PPC64 to return a skeleton OPD entry of a vDSO
-   symbol.  This works because _dl_vdso_vsym always return the function
-   address, and no vDSO symbols use the TOC or chain pointers from the OPD
-   so we can allow them to be garbage.  */
 #if defined(__PPC64__) || defined(__powerpc64__)
-#define VDSO_IFUNC_RET(value)  ((void *) &(value))
+/* The correct solution is for _dl_vdso_vsym to return the address of the OPD
+   for the kernel VDSO function.  That address would then be stored in the
+   __vdso_* variables and returned as the result of the IFUNC resolver function.
+   Yet, the kernel does not contain any OPD entries for the VDSO functions
+   (incomplete implementation).  However, PLT relocations for IFUNCs still expect
+   the address of an OPD to be returned from the IFUNC resolver function (since
+   PLT entries on PPC64 are just copies of OPDs).  The solution for now is to
+   create an artificial static OPD for each VDSO function returned by a resolver
+   function.  The TOC value is set to a non-zero value to avoid triggering lazy
+   symbol resolution via .glink0/.plt0 for a zero TOC (requires thread-safe PLT
+   sequences) when the dynamic linker isn't prepared for it e.g. RTLD_NOW.  None
+   of the kernel VDSO routines use the TOC or AUX values so any non-zero value
+   will work.  Note that function pointer comparisons will not use this artificial
+   static OPD since those are resolved via ADDR64 relocations and will point at
+   the non-IFUNC default OPD for the symbol.  Lastly, because the IFUNC relocations
+   are processed immediately at startup the resolver functions and this code need
+   not be thread-safe, but if the caller writes to a PLT slot it must do so in a
+   thread-safe manner with all the required barriers.  */
+#define VDSO_IFUNC_RET(value)                            \
+  ({                                                     \
+    static Elf64_FuncDesc vdso_opd = { .fd_toc = ~0x0 }; \
+    vdso_opd.fd_func = (Elf64_Addr)value;                \
+    &vdso_opd;                                           \
+  })
+
 #else
 #define VDSO_IFUNC_RET(value)  ((void *) (value))
 #endif
diff --git a/sysdeps/unix/sysv/linux/powerpc/gettimeofday.c b/sysdeps/unix/sysv/linux/powerpc/gettimeofday.c
index 6506d75..48c3f84 100644
--- a/sysdeps/unix/sysv/linux/powerpc/gettimeofday.c
+++ b/sysdeps/unix/sysv/linux/powerpc/gettimeofday.c
@@ -22,6 +22,7 @@
 
 # include <dl-vdso.h>
 # include <bits/libc-vdso.h>
+# include <dl-machine.h>
 
 void *gettimeofday_ifunc (void) __asm__ ("__gettimeofday");
 
diff --git a/sysdeps/unix/sysv/linux/powerpc/time.c b/sysdeps/unix/sysv/linux/powerpc/time.c
index 66b4eb3..2d77ece 100644
--- a/sysdeps/unix/sysv/linux/powerpc/time.c
+++ b/sysdeps/unix/sysv/linux/powerpc/time.c
@@ -20,7 +20,9 @@
 
 # include <time.h>
 # include <sysdep.h>
+# include <dl-vdso.h>
 # include <bits/libc-vdso.h>
+# include <dl-machine.h>
 
 void *time_ifunc (void) asm ("time");
 

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=d128971aa2bc7d7a0b7aaed8c3f546d1d5cc858b

commit d128971aa2bc7d7a0b7aaed8c3f546d1d5cc858b
Author: Adhemerval Zanella <azanella@linux.vnet.ibm.com>
Date:   Wed Sep 25 13:43:04 2013 -0500

    PowerPC: Fix POINTER_CHK_GUARD thread register for PPC64

diff --git a/ChangeLog b/ChangeLog
index 9698a1d..d5f760b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2013-09-25  Adhemerval Zanella  <azanella@linux.vnet.ibm.com>
+
+	* sysdeps/powerpc/powerpc64/stackguard-macros.h (POINTER_CHK_GUARD:
+	Fix thread ID register.
+
 2013-09-11  Will Newton  <will.newton@linaro.org>
 
 	[BZ #15857]
diff --git a/sysdeps/powerpc/powerpc64/stackguard-macros.h b/sysdeps/powerpc/powerpc64/stackguard-macros.h
index 4620f96..e80a683 100644
--- a/sysdeps/powerpc/powerpc64/stackguard-macros.h
+++ b/sysdeps/powerpc/powerpc64/stackguard-macros.h
@@ -6,7 +6,7 @@
 #define POINTER_CHK_GUARD \
   ({												\
      uintptr_t x;										\
-     asm ("ld %0,%1(2)"										\
+     asm ("ld %0,%1(13)"										\
 	  : "=r" (x)										\
 	  : "i" (offsetof (tcbhead_t, pointer_guard) - TLS_TCB_OFFSET - sizeof (tcbhead_t))	\
          );											\

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=6e610d1dd8a23ed21352e1f3b366becee0ec6fc2

commit 6e610d1dd8a23ed21352e1f3b366becee0ec6fc2
Author: Will Newton <will.newton@linaro.org>
Date:   Fri Sep 13 09:26:02 2013 +0100

    Add CVE-2013-4332 to NEWS.

diff --git a/NEWS b/NEWS
index d97a4ac..a816bc1 100644
--- a/NEWS
+++ b/NEWS
@@ -45,6 +45,11 @@ Version 2.18
   15655, 15666, 15667, 15674, 15711, 15755, 15759, 15797, 15892, 15893,
   15895.
 
+* CVE-2013-4332 The pvalloc, valloc, memalign, posix_memalign and
+  aligned_alloc functions could allocate too few bytes or corrupt the
+  heap when passed very large allocation size values (Bugzilla #15855,
+  #15856, #15857).
+
 * CVE-2013-4788 The pointer guard used for pointer mangling was not
   initialized for static applications resulting in the security feature
   being disabled. The pointer guard is now correctly initialized to a

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=66a49fcc5e0cd5d652347ee5983c0bbd00fdeee9

commit 66a49fcc5e0cd5d652347ee5983c0bbd00fdeee9
Author: Will Newton <will.newton@linaro.org>
Date:   Fri Aug 16 12:54:29 2013 +0100

    malloc: Check for integer overflow in memalign.
    
    A large bytes parameter to memalign could cause an integer overflow
    and corrupt allocator internals. Check the overflow does not occur
    before continuing with the allocation.
    
    ChangeLog:
    
    2013-09-11  Will Newton  <will.newton@linaro.org>
    
    	[BZ #15857]
    	* malloc/malloc.c (__libc_memalign): Check the value of bytes
    	does not overflow.

diff --git a/ChangeLog b/ChangeLog
index 4ec9ada..9698a1d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,11 @@
 2013-09-11  Will Newton  <will.newton@linaro.org>
 
+	[BZ #15857]
+	* malloc/malloc.c (__libc_memalign): Check the value of bytes
+	does not overflow.
+
+2013-09-11  Will Newton  <will.newton@linaro.org>
+
 	[BZ #15856]
 	* malloc/malloc.c (__libc_valloc): Check the value of bytes
 	does not overflow.
diff --git a/malloc/malloc.c b/malloc/malloc.c
index 31e2dfa..ebbe86d 100644
--- a/malloc/malloc.c
+++ b/malloc/malloc.c
@@ -3015,6 +3015,13 @@ __libc_memalign(size_t alignment, size_t bytes)
   /* Otherwise, ensure that it is at least a minimum chunk size */
   if (alignment <  MINSIZE) alignment = MINSIZE;
 
+  /* Check for overflow.  */
+  if (bytes > SIZE_MAX - alignment - MINSIZE)
+    {
+      __set_errno (ENOMEM);
+      return 0;
+    }
+
   arena_get(ar_ptr, bytes + alignment + MINSIZE);
   if(!ar_ptr)
     return 0;

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=ed595041168e6353afeb6157181ef9d5e047bb11

commit ed595041168e6353afeb6157181ef9d5e047bb11
Author: Will Newton <will.newton@linaro.org>
Date:   Fri Aug 16 11:59:37 2013 +0100

    malloc: Check for integer overflow in valloc.
    
    A large bytes parameter to valloc could cause an integer overflow
    and corrupt allocator internals. Check the overflow does not occur
    before continuing with the allocation.
    
    ChangeLog:
    
    2013-09-11  Will Newton  <will.newton@linaro.org>
    
    	[BZ #15856]
    	* malloc/malloc.c (__libc_valloc): Check the value of bytes
    	does not overflow.

diff --git a/ChangeLog b/ChangeLog
index e35032f..4ec9ada 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,11 @@
 2013-09-11  Will Newton  <will.newton@linaro.org>
 
+	[BZ #15856]
+	* malloc/malloc.c (__libc_valloc): Check the value of bytes
+	does not overflow.
+
+2013-09-11  Will Newton  <will.newton@linaro.org>
+
 	[BZ #15855]
 	* malloc/malloc.c (__libc_pvalloc): Check the value of bytes
 	does not overflow.
diff --git a/malloc/malloc.c b/malloc/malloc.c
index bcc08c4..31e2dfa 100644
--- a/malloc/malloc.c
+++ b/malloc/malloc.c
@@ -3046,6 +3046,13 @@ __libc_valloc(size_t bytes)
 
   size_t pagesz = GLRO(dl_pagesize);
 
+  /* Check for overflow.  */
+  if (bytes > SIZE_MAX - pagesz - MINSIZE)
+    {
+      __set_errno (ENOMEM);
+      return 0;
+    }
+
   void *(*hook) (size_t, size_t, const void *) =
     force_reg (__memalign_hook);
   if (__builtin_expect (hook != NULL, 0))

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=b0f1586fb49af2bb472ef07bce0cc558800ba024

commit b0f1586fb49af2bb472ef07bce0cc558800ba024
Author: Will Newton <will.newton@linaro.org>
Date:   Mon Aug 12 15:08:02 2013 +0100

    malloc: Check for integer overflow in pvalloc.
    
    A large bytes parameter to pvalloc could cause an integer overflow
    and corrupt allocator internals. Check the overflow does not occur
    before continuing with the allocation.
    
    ChangeLog:
    
    2013-09-11  Will Newton  <will.newton@linaro.org>
    
    	[BZ #15855]
    	* malloc/malloc.c (__libc_pvalloc): Check the value of bytes
    	does not overflow.

diff --git a/ChangeLog b/ChangeLog
index 52346e0..e35032f 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2013-09-11  Will Newton  <will.newton@linaro.org>
+
+	[BZ #15855]
+	* malloc/malloc.c (__libc_pvalloc): Check the value of bytes
+	does not overflow.
+
 2013-09-23  Carlos O'Donell  <carlos@redhat.com>
 
 	[BZ #15754]
diff --git a/malloc/malloc.c b/malloc/malloc.c
index be472b2..bcc08c4 100644
--- a/malloc/malloc.c
+++ b/malloc/malloc.c
@@ -3082,6 +3082,13 @@ __libc_pvalloc(size_t bytes)
   size_t page_mask = GLRO(dl_pagesize) - 1;
   size_t rounded_bytes = (bytes + page_mask) & ~(page_mask);
 
+  /* Check for overflow.  */
+  if (bytes > SIZE_MAX - 2*pagesz - MINSIZE)
+    {
+      __set_errno (ENOMEM);
+      return 0;
+    }
+
   void *(*hook) (size_t, size_t, const void *) =
     force_reg (__memalign_hook);
   if (__builtin_expect (hook != NULL, 0))

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=19a903fb37a199ee7d11f7cff9b7fd90c8b67e32

commit 19a903fb37a199ee7d11f7cff9b7fd90c8b67e32
Author: Carlos O'Donell <carlos@redhat.com>
Date:   Mon Sep 23 00:52:09 2013 -0400

    BZ #15754: CVE-2013-4788
    
    The pointer guard used for pointer mangling was not initialized for
    static applications resulting in the security feature being disabled.
    The pointer guard is now correctly initialized to a random value for
    static applications. Existing static applications need to be
    recompiled to take advantage of the fix.
    
    The test tst-ptrguard1-static and tst-ptrguard1 add regression
    coverage to ensure the pointer guards are sufficiently random
    and initialized to a default value.

diff --git a/ChangeLog b/ChangeLog
index 2a11ed8..52346e0 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,21 @@
+2013-09-23  Carlos O'Donell  <carlos@redhat.com>
+
+	[BZ #15754]
+	* elf/Makefile (tests): Add tst-ptrguard1.
+	(tests-static): Add tst-ptrguard1-static.
+	(tst-ptrguard1-ARGS): Define.
+	(tst-ptrguard1-static-ARGS): Define.
+	* elf/tst-ptrguard1.c: New file.
+	* elf/tst-ptrguard1-static.c: New file.
+	* sysdeps/x86_64/stackguard-macros.h: Define POINTER_CHK_GUARD.
+	* sysdeps/i386/stackguard-macros.h: Likewise.
+	* sysdeps/powerpc/powerpc32/stackguard-macros.h: Likewise.
+	* sysdeps/powerpc/powerpc64/stackguard-macros.h: Likewise.
+	* sysdeps/s390/s390-32/stackguard-macros.h: Likewise.
+	* sysdeps/s390/s390-64/stackguard-macros.h: Likewise.
+	* sysdeps/sparc/sparc32/stackguard-macros.h: Likewise.
+	* sysdeps/sparc/sparc64/stackguard-macros.h: Likewise.
+
 2013-09-23  Siddhesh Poyarekar  <siddhesh@redhat.com>
 
 	[BZ #14547]
diff --git a/NEWS b/NEWS
index e83c78c..d97a4ac 100644
--- a/NEWS
+++ b/NEWS
@@ -45,6 +45,12 @@ Version 2.18
   15655, 15666, 15667, 15674, 15711, 15755, 15759, 15797, 15892, 15893,
   15895.
 
+* CVE-2013-4788 The pointer guard used for pointer mangling was not
+  initialized for static applications resulting in the security feature
+  being disabled. The pointer guard is now correctly initialized to a
+  random value for static applications. Existing static applications need
+  to be recompiled to take advantage of the fix (bug 15754).
+
 * CVE-2012-4412 The strcoll implementation caches indices and rules for
   large collation sequences to optimize multiple passes.  This cache
   computation may overflow for large collation sequences and may cause a
diff --git a/csu/libc-start.c b/csu/libc-start.c
index e5da3ef..c898d06 100644
--- a/csu/libc-start.c
+++ b/csu/libc-start.c
@@ -37,6 +37,12 @@ extern void __pthread_initialize_minimal (void);
    in thread local area.  */
 uintptr_t __stack_chk_guard attribute_relro;
 # endif
+# ifndef  THREAD_SET_POINTER_GUARD
+/* Only exported for architectures that don't store the pointer guard
+   value in thread local area.  */
+uintptr_t __pointer_chk_guard_local
+	attribute_relro attribute_hidden __attribute__ ((nocommon));
+# endif
 #endif
 
 #ifdef HAVE_PTR_NTHREADS
@@ -195,6 +201,16 @@ LIBC_START_MAIN (int (*main) (int, char **, char ** MAIN_AUXVEC_DECL),
 # else
   __stack_chk_guard = stack_chk_guard;
 # endif
+
+  /* Set up the pointer guard value.  */
+  uintptr_t pointer_chk_guard = _dl_setup_pointer_guard (_dl_random,
+							 stack_chk_guard);
+# ifdef THREAD_SET_POINTER_GUARD
+  THREAD_SET_POINTER_GUARD (pointer_chk_guard);
+# else
+  __pointer_chk_guard_local = pointer_chk_guard;
+# endif
+
 #endif
 
   /* Register the destructor of the dynamic linker if there is any.  */
diff --git a/elf/Makefile b/elf/Makefile
index 3b58649..98834f4 100644
--- a/elf/Makefile
+++ b/elf/Makefile
@@ -121,7 +121,8 @@ endif
 tests = tst-tls1 tst-tls2 tst-tls9 tst-leaks1 \
 	tst-array1 tst-array2 tst-array3 tst-array4 tst-array5
 tests-static = tst-tls1-static tst-tls2-static tst-stackguard1-static \
-	       tst-leaks1-static tst-array1-static tst-array5-static
+	       tst-leaks1-static tst-array1-static tst-array5-static \
+	       tst-ptrguard1-static
 ifeq (yes,$(build-shared))
 tests-static += tst-tls9-static
 tst-tls9-static-ENV = \
@@ -145,7 +146,8 @@ tests += loadtest restest1 preloadtest loadfail multiload origtest resolvfail \
 	 tst-audit1 tst-audit2 tst-audit8 \
 	 tst-stackguard1 tst-addr1 tst-thrlock \
 	 tst-unique1 tst-unique2 tst-unique3 tst-unique4 \
-	 tst-initorder tst-initorder2 tst-relsort1 tst-null-argv
+	 tst-initorder tst-initorder2 tst-relsort1 tst-null-argv \
+	 tst-ptrguard1
 #	 reldep9
 test-srcs = tst-pathopt
 selinux-enabled := $(shell cat /selinux/enforce 2> /dev/null)
@@ -1016,6 +1018,9 @@ LDFLAGS-order2mod2.so = $(no-as-needed)
 tst-stackguard1-ARGS = --command "$(host-test-program-cmd) --child"
 tst-stackguard1-static-ARGS = --command "$(objpfx)tst-stackguard1-static --child"
 
+tst-ptrguard1-ARGS = --command "$(host-test-program-cmd) --child"
+tst-ptrguard1-static-ARGS = --command "$(objpfx)tst-ptrguard1-static --child"
+
 $(objpfx)tst-leaks1: $(libdl)
 $(objpfx)tst-leaks1-mem: $(objpfx)tst-leaks1.out
 	$(common-objpfx)malloc/mtrace $(objpfx)tst-leaks1.mtrace > $@
diff --git a/elf/tst-ptrguard1-static.c b/elf/tst-ptrguard1-static.c
new file mode 100644
index 0000000..7aff3b7
--- /dev/null
+++ b/elf/tst-ptrguard1-static.c
@@ -0,0 +1 @@
+#include "tst-ptrguard1.c"
diff --git a/elf/tst-ptrguard1.c b/elf/tst-ptrguard1.c
new file mode 100644
index 0000000..c344a04
--- /dev/null
+++ b/elf/tst-ptrguard1.c
@@ -0,0 +1,202 @@
+/* Copyright (C) 2013 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/>.  */
+
+#include <errno.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/wait.h>
+#include <stackguard-macros.h>
+#include <tls.h>
+#include <unistd.h>
+
+#ifndef POINTER_CHK_GUARD
+extern uintptr_t __pointer_chk_guard;
+# define POINTER_CHK_GUARD __pointer_chk_guard
+#endif
+
+static const char *command;
+static bool child;
+static uintptr_t ptr_chk_guard_copy;
+static bool ptr_chk_guard_copy_set;
+static int fds[2];
+
+static void __attribute__ ((constructor))
+con (void)
+{
+  ptr_chk_guard_copy = POINTER_CHK_GUARD;
+  ptr_chk_guard_copy_set = true;
+}
+
+static int
+uintptr_t_cmp (const void *a, const void *b)
+{
+  if (*(uintptr_t *) a < *(uintptr_t *) b)
+    return 1;
+  if (*(uintptr_t *) a > *(uintptr_t *) b)
+    return -1;
+  return 0;
+}
+
+static int
+do_test (void)
+{
+  if (!ptr_chk_guard_copy_set)
+    {
+      puts ("constructor has not been run");
+      return 1;
+    }
+
+  if (ptr_chk_guard_copy != POINTER_CHK_GUARD)
+    {
+      puts ("POINTER_CHK_GUARD changed between constructor and do_test");
+      return 1;
+    }
+
+  if (child)
+    {
+      write (2, &ptr_chk_guard_copy, sizeof (ptr_chk_guard_copy));
+      return 0;
+    }
+
+  if (command == NULL)
+    {
+      puts ("missing --command or --child argument");
+      return 1;
+    }
+
+#define N 16
+  uintptr_t child_ptr_chk_guards[N + 1];
+  child_ptr_chk_guards[N] = ptr_chk_guard_copy;
+  int i;
+  for (i = 0; i < N; ++i)
+    {
+      if (pipe (fds) < 0)
+	{
+	  printf ("couldn't create pipe: %m\n");
+	  return 1;
+	}
+
+      pid_t pid = fork ();
+      if (pid < 0)
+	{
+	  printf ("fork failed: %m\n");
+	  return 1;
+	}
+
+      if (!pid)
+	{
+	  if (ptr_chk_guard_copy != POINTER_CHK_GUARD)
+	    {
+	      puts ("POINTER_CHK_GUARD changed after fork");
+	      exit (1);
+	    }
+
+	  close (fds[0]);
+	  close (2);
+	  dup2 (fds[1], 2);
+	  close (fds[1]);
+
+	  system (command);
+	  exit (0);
+	}
+
+      close (fds[1]);
+
+      if (TEMP_FAILURE_RETRY (read (fds[0], &child_ptr_chk_guards[i],
+				    sizeof (uintptr_t))) != sizeof (uintptr_t))
+	{
+	  puts ("could not read ptr_chk_guard value from child");
+	  return 1;
+	}
+
+      close (fds[0]);
+
+      pid_t termpid;
+      int status;
+      termpid = TEMP_FAILURE_RETRY (waitpid (pid, &status, 0));
+      if (termpid == -1)
+	{
+	  printf ("waitpid failed: %m\n");
+	  return 1;
+	}
+      else if (termpid != pid)
+	{
+	  printf ("waitpid returned %ld != %ld\n",
+		  (long int) termpid, (long int) pid);
+	  return 1;
+	}
+      else if (!WIFEXITED (status) || WEXITSTATUS (status))
+	{
+	  puts ("child hasn't exited with exit status 0");
+	  return 1;
+	}
+    }
+
+  qsort (child_ptr_chk_guards, N + 1, sizeof (uintptr_t), uintptr_t_cmp);
+
+  /* The default pointer guard is the same as the default stack guard.
+     They are only set to default if dl_random is NULL.  */
+  uintptr_t default_guard = 0;
+  unsigned char *p = (unsigned char *) &default_guard;
+  p[sizeof (uintptr_t) - 1] = 255;
+  p[sizeof (uintptr_t) - 2] = '\n';
+  p[0] = 0;
+
+  /* Test if the pointer guard canaries are either randomized,
+     or equal to the default pointer guard value.
+     Even with randomized pointer guards it might happen
+     that the random number generator generates the same
+     values, but if that happens in more than half from
+     the 16 runs, something is very wrong.  */
+  int ndifferences = 0;
+  int ndefaults = 0;
+  for (i = 0; i < N; ++i)
+    {
+      if (child_ptr_chk_guards[i] != child_ptr_chk_guards[i+1])
+	ndifferences++;
+      else if (child_ptr_chk_guards[i] == default_guard)
+	ndefaults++;
+    }
+
+  printf ("differences %d defaults %d\n", ndifferences, ndefaults);
+
+  if (ndifferences < N / 2 && ndefaults < N / 2)
+    {
+      puts ("pointer guard values are not randomized enough");
+      puts ("nor equal to the default value");
+      return 1;
+    }
+
+  return 0;
+}
+
+#define OPT_COMMAND	10000
+#define OPT_CHILD	10001
+#define CMDLINE_OPTIONS	\
+  { "command", required_argument, NULL, OPT_COMMAND },  \
+  { "child", no_argument, NULL, OPT_CHILD },
+#define CMDLINE_PROCESS	\
+  case OPT_COMMAND:	\
+    command = optarg;	\
+    break;		\
+  case OPT_CHILD:	\
+    child = true;	\
+    break;
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/ports/ChangeLog.ia64 b/ports/ChangeLog.ia64
index 92b81cb..f61f37f 100644
--- a/ports/ChangeLog.ia64
+++ b/ports/ChangeLog.ia64
@@ -1,3 +1,8 @@
+2013-09-22  Carlos O'Donell  <carlos@redhat.com>
+
+	[BZ #15754]
+	* sysdeps/ia64/stackguard-macros.h: Define POINTER_CHK_GUARD.
+
 2013-07-04  Andreas Jaeger  <aj@suse.de>
 
 	* sysdeps/unix/sysv/linux/ia64/sys/ptrace.h (PTRACE_LISTEN):
diff --git a/ports/ChangeLog.tile b/ports/ChangeLog.tile
index a2ec5e1..972bd81 100644
--- a/ports/ChangeLog.tile
+++ b/ports/ChangeLog.tile
@@ -1,3 +1,8 @@
+2013-09-22  Carlos O'Donell  <carlos@redhat.com>
+
+	[BZ #15754]
+	* sysdeps/tile/stackguard-macros.h: Define POINTER_CHK_GUARD.
+
 2013-07-22  Chris Metcalf  <cmetcalf@tilera.com>
 
 	[BZ #15759]
diff --git a/ports/sysdeps/ia64/stackguard-macros.h b/ports/sysdeps/ia64/stackguard-macros.h
index dc683c2..3907293 100644
--- a/ports/sysdeps/ia64/stackguard-macros.h
+++ b/ports/sysdeps/ia64/stackguard-macros.h
@@ -2,3 +2,6 @@
 
 #define STACK_CHK_GUARD \
   ({ uintptr_t x; asm ("adds %0 = -8, r13;; ld8 %0 = [%0]" : "=r" (x)); x; })
+
+#define POINTER_CHK_GUARD \
+  ({ uintptr_t x; asm ("adds %0 = -16, r13;; ld8 %0 = [%0]" : "=r" (x)); x; })
diff --git a/ports/sysdeps/tile/stackguard-macros.h b/ports/sysdeps/tile/stackguard-macros.h
index 589ea2b..f2e041b 100644
--- a/ports/sysdeps/tile/stackguard-macros.h
+++ b/ports/sysdeps/tile/stackguard-macros.h
@@ -4,11 +4,17 @@
 # if __WORDSIZE == 64
 #  define STACK_CHK_GUARD \
   ({ uintptr_t x; asm ("addi %0, tp, -16; ld %0, %0" : "=r" (x)); x; })
+#  define POINTER_CHK_GUARD \
+  ({ uintptr_t x; asm ("addi %0, tp, -24; ld %0, %0" : "=r" (x)); x; })
 # else
 #  define STACK_CHK_GUARD \
   ({ uintptr_t x; asm ("addi %0, tp, -8; ld4s %0, %0" : "=r" (x)); x; })
+#  define POINTER_CHK_GUARD \
+  ({ uintptr_t x; asm ("addi %0, tp, -12; ld4s %0, %0" : "=r" (x)); x; })
 # endif
 #else
 # define STACK_CHK_GUARD \
   ({ uintptr_t x; asm ("addi %0, tp, -8; lw %0, %0" : "=r" (x)); x; })
+# define POINTER_CHK_GUARD \
+  ({ uintptr_t x; asm ("addi %0, tp, -12; lw %0, %0" : "=r" (x)); x; })
 #endif
diff --git a/sysdeps/generic/stackguard-macros.h b/sysdeps/generic/stackguard-macros.h
index ababf65..4fa3d96 100644
--- a/sysdeps/generic/stackguard-macros.h
+++ b/sysdeps/generic/stackguard-macros.h
@@ -2,3 +2,6 @@
 
 extern uintptr_t __stack_chk_guard;
 #define STACK_CHK_GUARD __stack_chk_guard
+
+extern uintptr_t __pointer_chk_guard_local;
+#define POINTER_CHK_GUARD __pointer_chk_guard_local
diff --git a/sysdeps/i386/stackguard-macros.h b/sysdeps/i386/stackguard-macros.h
index 8c31e19..0397629 100644
--- a/sysdeps/i386/stackguard-macros.h
+++ b/sysdeps/i386/stackguard-macros.h
@@ -2,3 +2,11 @@
 
 #define STACK_CHK_GUARD \
   ({ uintptr_t x; asm ("movl %%gs:0x14, %0" : "=r" (x)); x; })
+
+#define POINTER_CHK_GUARD \
+  ({							\
+     uintptr_t x;					\
+     asm ("movl %%gs:%c1, %0" : "=r" (x)		\
+	  : "i" (offsetof (tcbhead_t, pointer_guard)));	\
+     x;							\
+   })
diff --git a/sysdeps/powerpc/powerpc32/stackguard-macros.h b/sysdeps/powerpc/powerpc32/stackguard-macros.h
index 839f6a4..b3d0af8 100644
--- a/sysdeps/powerpc/powerpc32/stackguard-macros.h
+++ b/sysdeps/powerpc/powerpc32/stackguard-macros.h
@@ -2,3 +2,13 @@
 
 #define STACK_CHK_GUARD \
   ({ uintptr_t x; asm ("lwz %0,-28680(2)" : "=r" (x)); x; })
+
+#define POINTER_CHK_GUARD \
+  ({												\
+     uintptr_t x;										\
+     asm ("lwz %0,%1(2)"									\
+	  : "=r" (x)										\
+	  : "i" (offsetof (tcbhead_t, pointer_guard) - TLS_TCB_OFFSET - sizeof (tcbhead_t))	\
+         );											\
+     x;												\
+   })
diff --git a/sysdeps/powerpc/powerpc64/stackguard-macros.h b/sysdeps/powerpc/powerpc64/stackguard-macros.h
index 9da879c..4620f96 100644
--- a/sysdeps/powerpc/powerpc64/stackguard-macros.h
+++ b/sysdeps/powerpc/powerpc64/stackguard-macros.h
@@ -2,3 +2,13 @@
 
 #define STACK_CHK_GUARD \
   ({ uintptr_t x; asm ("ld %0,-28688(13)" : "=r" (x)); x; })
+
+#define POINTER_CHK_GUARD \
+  ({												\
+     uintptr_t x;										\
+     asm ("ld %0,%1(2)"										\
+	  : "=r" (x)										\
+	  : "i" (offsetof (tcbhead_t, pointer_guard) - TLS_TCB_OFFSET - sizeof (tcbhead_t))	\
+         );											\
+     x;												\
+   })
diff --git a/sysdeps/s390/s390-32/stackguard-macros.h b/sysdeps/s390/s390-32/stackguard-macros.h
index b74c579..449e8d4 100644
--- a/sysdeps/s390/s390-32/stackguard-macros.h
+++ b/sysdeps/s390/s390-32/stackguard-macros.h
@@ -2,3 +2,14 @@
 
 #define STACK_CHK_GUARD \
   ({ uintptr_t x; asm ("ear %0,%%a0; l %0,0x14(%0)" : "=a" (x)); x; })
+
+/* On s390/s390x there is no unique pointer guard, instead we use the
+   same value as the stack guard.  */
+#define POINTER_CHK_GUARD \
+  ({							\
+     uintptr_t x;					\
+     asm ("ear %0,%%a0; l %0,%1(%0)"			\
+	  : "=a" (x)					\
+	  : "i" (offsetof (tcbhead_t, stack_guard)));	\
+     x;							\
+   })
diff --git a/sysdeps/s390/s390-64/stackguard-macros.h b/sysdeps/s390/s390-64/stackguard-macros.h
index 0cebb5f..c8270fb 100644
--- a/sysdeps/s390/s390-64/stackguard-macros.h
+++ b/sysdeps/s390/s390-64/stackguard-macros.h
@@ -2,3 +2,17 @@
 
 #define STACK_CHK_GUARD \
   ({ uintptr_t x; asm ("ear %0,%%a0; sllg %0,%0,32; ear %0,%%a1; lg %0,0x28(%0)" : "=a" (x)); x; })
+
+/* On s390/s390x there is no unique pointer guard, instead we use the
+   same value as the stack guard.  */
+#define POINTER_CHK_GUARD \
+  ({							\
+     uintptr_t x;					\
+     asm ("ear %0,%%a0;"				\
+	  "sllg %0,%0,32;"				\
+	  "ear %0,%%a1;"				\
+	  "lg %0,%1(%0)"				\
+	 : "=a" (x)					\
+	 : "i" (offsetof (tcbhead_t, stack_guard)));	\
+     x;							\
+   })
diff --git a/sysdeps/sparc/sparc32/stackguard-macros.h b/sysdeps/sparc/sparc32/stackguard-macros.h
index c0b02b0..1eef0f1 100644
--- a/sysdeps/sparc/sparc32/stackguard-macros.h
+++ b/sysdeps/sparc/sparc32/stackguard-macros.h
@@ -2,3 +2,6 @@
 
 #define STACK_CHK_GUARD \
   ({ uintptr_t x; asm ("ld [%%g7+0x14], %0" : "=r" (x)); x; })
+
+#define POINTER_CHK_GUARD \
+  ({ uintptr_t x; asm ("ld [%%g7+0x18], %0" : "=r" (x)); x; })
diff --git a/sysdeps/sparc/sparc64/stackguard-macros.h b/sysdeps/sparc/sparc64/stackguard-macros.h
index 80f0635..cc0c12c 100644
--- a/sysdeps/sparc/sparc64/stackguard-macros.h
+++ b/sysdeps/sparc/sparc64/stackguard-macros.h
@@ -2,3 +2,6 @@
 
 #define STACK_CHK_GUARD \
   ({ uintptr_t x; asm ("ldx [%%g7+0x28], %0" : "=r" (x)); x; })
+
+#define POINTER_CHK_GUARD \
+  ({ uintptr_t x; asm ("ldx [%%g7+0x30], %0" : "=r" (x)); x; })
diff --git a/sysdeps/x86_64/stackguard-macros.h b/sysdeps/x86_64/stackguard-macros.h
index d7fedb3..1948800 100644
--- a/sysdeps/x86_64/stackguard-macros.h
+++ b/sysdeps/x86_64/stackguard-macros.h
@@ -4,3 +4,8 @@
   ({ uintptr_t x;						\
      asm ("mov %%fs:%c1, %0" : "=r" (x)				\
 	  : "i" (offsetof (tcbhead_t, stack_guard))); x; })
+
+#define POINTER_CHK_GUARD \
+  ({ uintptr_t x;						\
+     asm ("mov %%fs:%c1, %0" : "=r" (x)				\
+	  : "i" (offsetof (tcbhead_t, pointer_guard))); x; })

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=4415a70617fdc4a47a6302f69b943c9c51ae8cac

commit 4415a70617fdc4a47a6302f69b943c9c51ae8cac
Author: Siddhesh Poyarekar <siddhesh@redhat.com>
Date:   Mon Sep 23 11:24:30 2013 +0530

    Check for integer overflow in cache size computation in strcoll
    
    strcoll is implemented using a cache for indices and weights of
    collation sequences in the strings so that subsequent passes do not
    have to search through collation data again.  For very large string
    inputs, the cache size computation could overflow.  In such a case,
    use the fallback function that does not cache indices and weights of
    collation sequences.
    
    Fixes CVE-2012-4412.

diff --git a/ChangeLog b/ChangeLog
index 6886e5f..2a11ed8 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,6 +1,12 @@
 2013-09-23  Siddhesh Poyarekar  <siddhesh@redhat.com>
 
 	[BZ #14547]
+	* string/tst-strcoll-overflow.c: New test case.
+	* string/Makefile (xtests): Add tst-strcoll-overflow.
+	* string/strcoll_l.c (STRCOLL): Skip allocating memory for
+	cache if string sizes may cause integer overflow.
+
+	[BZ #14547]
 	* string/strcoll_l.c (coll_seq): New members rule, idx,
 	save_idx and back_us.
 	(get_next_seq_nocache): New function.
diff --git a/NEWS b/NEWS
index aec8b00..e83c78c 100644
--- a/NEWS
+++ b/NEWS
@@ -45,6 +45,12 @@ Version 2.18
   15655, 15666, 15667, 15674, 15711, 15755, 15759, 15797, 15892, 15893,
   15895.
 
+* CVE-2012-4412 The strcoll implementation caches indices and rules for
+  large collation sequences to optimize multiple passes.  This cache
+  computation may overflow for large collation sequences and may cause a
+  stack or buffer overflow.  This is now fixed to use a slower algorithm
+  which does not use a cache if there is an integer overflow.
+
 * CVE-2013-2207 Incorrectly granting access to another user's pseudo-terminal
   has been fixed by disabling the use of pt_chown (Bugzilla #15755).
   Distributions can re-enable building and using pt_chown via the new configure
diff --git a/string/Makefile b/string/Makefile
index 72d3e29..17f9d68 100644
--- a/string/Makefile
+++ b/string/Makefile
@@ -57,6 +57,8 @@ tests		:= tester inl-tester noinl-tester testcopy test-ffs	\
 tests-ifunc := $(strop-tests:%=test-%-ifunc)
 tests += $(tests-ifunc)
 
+xtests = tst-strcoll-overflow
+
 include ../Rules
 
 tester-ENV = LANGUAGE=C
diff --git a/string/strcoll_l.c b/string/strcoll_l.c
index eb042ff..4ee101a 100644
--- a/string/strcoll_l.c
+++ b/string/strcoll_l.c
@@ -524,7 +524,15 @@ STRCOLL (const STRING_TYPE *s1, const STRING_TYPE *s2, __locale_t l)
   memset (&seq1, 0, sizeof (seq1));
   seq2 = seq1;
 
-  if (! __libc_use_alloca ((s1len + s2len) * (sizeof (int32_t) + 1)))
+  size_t size_max = SIZE_MAX / (sizeof (int32_t) + 1);
+
+  if (MIN (s1len, s2len) > size_max
+      || MAX (s1len, s2len) > size_max - MIN (s1len, s2len))
+    {
+      /* If the strings are long enough to cause overflow in the size request,
+         then skip the allocation and proceed with the non-cached routines.  */
+    }
+  else if (! __libc_use_alloca ((s1len + s2len) * (sizeof (int32_t) + 1)))
     {
       seq1.idxarr = (int32_t *) malloc ((s1len + s2len) * (sizeof (int32_t) + 1));
 
diff --git a/string/tst-strcoll-overflow.c b/string/tst-strcoll-overflow.c
new file mode 100644
index 0000000..bb665ac
--- /dev/null
+++ b/string/tst-strcoll-overflow.c
@@ -0,0 +1,61 @@
+/* Copyright (C) 2013 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/>.  */
+
+#include <locale.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+/* Verify that strcoll does not crash for large strings for which it cannot
+   cache weight lookup results.  The size is large enough to cause integer
+   overflows on 32-bit as well as buffer overflows on 64-bit.  The test should
+   work reasonably reliably when overcommit is disabled, but it obviously
+   depends on how much memory the system has.  There's a limitation to this
+   test in that it does not run to completion.  Actually collating such a
+   large string can take days and we can't have xcheck running that long.  For
+   that reason, we run the test for about 5 minutes and then assume that
+   everything is fine if there are no crashes.  */
+#define SIZE 0x40000000ul
+
+int
+do_test (void)
+{
+  if (setlocale (LC_COLLATE, "en_GB.UTF-8") == NULL)
+    {
+      puts ("setlocale failed, cannot test for overflow");
+      return 0;
+    }
+
+  char *p = malloc (SIZE);
+
+  if (p == NULL)
+    {
+      puts ("could not allocate memory");
+      return 1;
+    }
+
+  memset (p, 'x', SIZE - 1);
+  p[SIZE - 1] = 0;
+  printf ("%d\n", strcoll (p, p));
+  return 0;
+}
+
+#define TIMEOUT 300
+#define EXPECTED_SIGNAL SIGALRM
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=5326e2c77bbd559fec9dc50e6d250eb0ce6a8d8c

commit 5326e2c77bbd559fec9dc50e6d250eb0ce6a8d8c
Author: Siddhesh Poyarekar <siddhesh@redhat.com>
Date:   Mon Sep 23 11:20:02 2013 +0530

    Fall back to non-cached sequence traversal and comparison on malloc fail
    
    strcoll currently falls back to alloca if malloc fails, resulting in a
    possible stack overflow.  This patch implements sequence traversal and
    comparison without caching indices and rules.
    
    Fixes CVE-2012-4424.

diff --git a/ChangeLog b/ChangeLog
index 2394806..6886e5f 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,4 +1,12 @@
-2013-08-20  Siddhesh Poyarekar  <siddhesh@redhat.com>
+2013-09-23  Siddhesh Poyarekar  <siddhesh@redhat.com>
+
+	[BZ #14547]
+	* string/strcoll_l.c (coll_seq): New members rule, idx,
+	save_idx and back_us.
+	(get_next_seq_nocache): New function.
+	(do_compare_nocache): New function.
+	(STRCOLL): Use get_next_seq_nocache and do_compare_nocache
+	when malloc fails.
 
 	* string/strcoll_l.c (coll_seq): New structure.
 	(get_next_seq_cached): New function.
diff --git a/NEWS b/NEWS
index 8b228b0..aec8b00 100644
--- a/NEWS
+++ b/NEWS
@@ -9,8 +9,8 @@ Version 2.18.1
 
 * The following bugs are resolved with this release:
 
-  14155, 14699, 15532, 15427, 15522, 15797, 15892, 15895, 15909, 15917,
-  15996, 16072, 16150.
+  14155, 14547, 14699, 15532, 15427, 15522, 15797, 15892, 15895, 15909,
+  15917, 15996, 16072, 16150.
 
 * CVE-2013-4237 The readdir_r function could write more than NAME_MAX bytes
   to the d_name member of struct dirent, or omit the terminating NUL
@@ -18,6 +18,12 @@ Version 2.18.1
 
 * CVE-2013-4458 Stack overflow in getaddrinfo with large number of results
   for AF_INET6 has been fixed (Bugzilla #16072).
+
+* CVE-2012-4424 The strcoll implementation uses malloc to cache indices and
+  rules for large collation sequences to optimize multiple passes and falls
+  back to alloca if malloc fails, resulting in a possible stack overflow.
+  The implementation now falls back to an uncached collation sequence lookup
+  if malloc fails.
 
 Version 2.18
 
diff --git a/string/strcoll_l.c b/string/strcoll_l.c
index 50ed84d..eb042ff 100644
--- a/string/strcoll_l.c
+++ b/string/strcoll_l.c
@@ -45,7 +45,7 @@
 typedef struct
 {
   int len;			/* Length of the current sequence.  */
-  int val;			/* Position of the sequence relative to the
+  size_t val;			/* Position of the sequence relative to the
 				   previous non-ignored sequence.  */
   size_t idxnow;		/* Current index in sequences.  */
   size_t idxmax;		/* Maximum index in sequences.  */
@@ -55,6 +55,12 @@ typedef struct
   const USTRING_TYPE *us;	/* The string.  */
   int32_t *idxarr;		/* Array to cache weight indices.  */
   unsigned char *rulearr;	/* Array to cache rules.  */
+  unsigned char rule;		/* Saved rule for the first sequence.  */
+  int32_t idx;			/* Index to weight of the current sequence.  */
+  int32_t save_idx;		/* Save looked up index of a forward
+				   sequence after the last backward
+				   sequence.  */
+  const USTRING_TYPE *back_us;	/* Beginning of the backward sequence.  */
 } coll_seq;
 
 /* Get next sequence.  The weight indices are cached, so we don't need to
@@ -64,7 +70,7 @@ get_next_seq_cached (coll_seq *seq, int nrules, int pass,
 		     const unsigned char *rulesets,
 		     const USTRING_TYPE *weights)
 {
-  int val = seq->val = 0;
+  size_t val = seq->val = 0;
   int len = seq->len;
   size_t backw_stop = seq->backw_stop;
   size_t backw = seq->backw;
@@ -146,7 +152,7 @@ get_next_seq (coll_seq *seq, int nrules, const unsigned char *rulesets,
 	      const USTRING_TYPE *extra, const int32_t *indirect)
 {
 #include WEIGHT_H
-  int val = seq->val = 0;
+  size_t val = seq->val = 0;
   int len = seq->len;
   size_t backw_stop = seq->backw_stop;
   size_t backw = seq->backw;
@@ -162,7 +168,7 @@ get_next_seq (coll_seq *seq, int nrules, const unsigned char *rulesets,
       ++val;
       if (backw_stop != ~0ul)
 	{
-	  /* The is something pushed.  */
+	  /* There is something pushed.  */
 	  if (backw == backw_stop)
 	    {
 	      /* The last pushed character was handled.  Continue
@@ -227,15 +233,199 @@ get_next_seq (coll_seq *seq, int nrules, const unsigned char *rulesets,
   seq->us = us;
 }
 
-/* Compare two sequences.  */
+/* Get next sequence.  Traverse the string as required.  This function does not
+   set or use any index or rule cache.  */
+static void
+get_next_seq_nocache (coll_seq *seq, int nrules, const unsigned char *rulesets,
+		      const USTRING_TYPE *weights, const int32_t *table,
+		      const USTRING_TYPE *extra, const int32_t *indirect,
+		      int pass)
+{
+#include WEIGHT_H
+  size_t val = seq->val = 0;
+  int len = seq->len;
+  size_t backw_stop = seq->backw_stop;
+  size_t backw = seq->backw;
+  size_t idxcnt = seq->idxcnt;
+  size_t idxmax = seq->idxmax;
+  int32_t idx = seq->idx;
+  const USTRING_TYPE *us = seq->us;
+
+  while (len == 0)
+    {
+      ++val;
+      if (backw_stop != ~0ul)
+	{
+	  /* There is something pushed.  */
+	  if (backw == backw_stop)
+	    {
+	      /* The last pushed character was handled.  Continue
+		 with forward characters.  */
+	      if (idxcnt < idxmax)
+		{
+		  idx = seq->save_idx;
+		  backw_stop = ~0ul;
+		}
+	      else
+		{
+		  /* Nothing anymore.  The backward sequence ended with
+		     the last sequence in the string.  Note that len is
+		     still zero.  */
+		  idx = 0;
+		  break;
+	        }
+	    }
+	  else
+	    {
+	      /* XXX Traverse BACKW sequences from the beginning of
+		 BACKW_STOP to get the next sequence.  Is ther a quicker way
+	         to do this?  */
+	      size_t i = backw_stop;
+	      us = seq->back_us;
+	      while (i < backw)
+		{
+		  int32_t tmp = findidx (&us, -1);
+		  idx = tmp & 0xffffff;
+		  i++;
+		}
+	      --backw;
+	      us = seq->us;
+	    }
+	}
+      else
+	{
+	  backw_stop = idxmax;
+	  int32_t prev_idx = idx;
+
+	  while (*us != L('\0'))
+	    {
+	      int32_t tmp = findidx (&us, -1);
+	      unsigned char rule = tmp >> 24;
+	      prev_idx = idx;
+	      idx = tmp & 0xffffff;
+	      idxcnt = idxmax++;
+
+	      /* Save the rule for the first sequence.  */
+	      if (__glibc_unlikely (idxcnt == 0))
+	        seq->rule = rule;
+
+	      if ((rulesets[rule * nrules + pass]
+		   & sort_backward) == 0)
+		/* No more backward characters to push.  */
+		break;
+	      ++idxcnt;
+	    }
+
+	  if (backw_stop >= idxcnt)
+	    {
+	      /* No sequence at all or just one.  */
+	      if (idxcnt == idxmax || backw_stop > idxcnt)
+		/* Note that len is still zero.  */
+		break;
+
+	      backw_stop = ~0ul;
+	    }
+	  else
+	    {
+	      /* We pushed backward sequences.  If the stream ended with the
+		 backward sequence, then we process the last sequence we
+		 found.  Otherwise we process the sequence before the last
+		 one since the last one was a forward sequence.  */
+	      seq->back_us = seq->us;
+	      seq->us = us;
+	      backw = idxcnt;
+	      if (idxmax > idxcnt)
+		{
+		  backw--;
+		  seq->save_idx = idx;
+		  idx = prev_idx;
+		}
+	      if (backw > backw_stop)
+		backw--;
+	    }
+	}
+
+      len = weights[idx++];
+      /* Skip over indices of previous levels.  */
+      for (int i = 0; i < pass; i++)
+	{
+	  idx += len;
+	  len = weights[idx];
+	  idx++;
+	}
+    }
+
+  /* Update the structure.  */
+  seq->val = val;
+  seq->len = len;
+  seq->backw_stop = backw_stop;
+  seq->backw = backw;
+  seq->idxcnt = idxcnt;
+  seq->idxmax = idxmax;
+  seq->us = us;
+  seq->idx = idx;
+}
+
+/* Compare two sequences.  This version does not use the index and rules
+   cache.  */
+static int
+do_compare_nocache (coll_seq *seq1, coll_seq *seq2, int position,
+		    const USTRING_TYPE *weights)
+{
+  int seq1len = seq1->len;
+  int seq2len = seq2->len;
+  size_t val1 = seq1->val;
+  size_t val2 = seq2->val;
+  int idx1 = seq1->idx;
+  int idx2 = seq2->idx;
+  int result = 0;
+
+  /* Test for position if necessary.  */
+  if (position && val1 != val2)
+    {
+      result = val1 > val2 ? 1 : -1;
+      goto out;
+    }
+
+  /* Compare the two sequences.  */
+  do
+    {
+      if (weights[idx1] != weights[idx2])
+	{
+	  /* The sequences differ.  */
+	  result = weights[idx1] - weights[idx2];
+	  goto out;
+	}
+
+      /* Increment the offsets.  */
+      ++idx1;
+      ++idx2;
+
+      --seq1len;
+      --seq2len;
+    }
+  while (seq1len > 0 && seq2len > 0);
+
+  if (position && seq1len != seq2len)
+    result = seq1len - seq2len;
+
+out:
+  seq1->len = seq1len;
+  seq2->len = seq2len;
+  seq1->idx = idx1;
+  seq2->idx = idx2;
+  return result;
+}
+
+/* Compare two sequences using the index cache.  */
 static int
 do_compare (coll_seq *seq1, coll_seq *seq2, int position,
 	    const USTRING_TYPE *weights)
 {
   int seq1len = seq1->len;
   int seq2len = seq2->len;
-  int val1 = seq1->val;
-  int val2 = seq2->val;
+  size_t val1 = seq1->val;
+  size_t val2 = seq2->val;
   int32_t *idx1arr = seq1->idxarr;
   int32_t *idx2arr = seq2->idxarr;
   int idx1now = seq1->idxnow;
@@ -245,7 +435,7 @@ do_compare (coll_seq *seq1, coll_seq *seq2, int position,
   /* Test for position if necessary.  */
   if (position && val1 != val2)
     {
-      result = val1 - val2;
+      result = val1 > val2 ? 1 : -1;
       goto out;
     }
 
@@ -334,57 +524,62 @@ STRCOLL (const STRING_TYPE *s1, const STRING_TYPE *s2, __locale_t l)
   memset (&seq1, 0, sizeof (seq1));
   seq2 = seq1;
 
-  /* We need the elements of the strings as unsigned values since they
-     are used as indices.  */
-  seq1.us = (const USTRING_TYPE *) s1;
-  seq2.us = (const USTRING_TYPE *) s2;
-
   if (! __libc_use_alloca ((s1len + s2len) * (sizeof (int32_t) + 1)))
     {
       seq1.idxarr = (int32_t *) malloc ((s1len + s2len) * (sizeof (int32_t) + 1));
-      seq2.idxarr = &seq1.idxarr[s1len];
-      seq1.rulearr = (unsigned char *) &seq2.idxarr[s2len];
-      seq2.rulearr = &seq1.rulearr[s1len];
-
-      if (seq1.idxarr == NULL)
-	/* No memory.  Well, go with the stack then.
-
-	   XXX Once this implementation is stable we will handle this
-	   differently.  Instead of precomputing the indices we will
-	   do this in time.  This means, though, that this happens for
-	   every pass again.  */
-	goto try_stack;
-      use_malloc = true;
+
+      /* If we failed to allocate memory, we leave everything as NULL so that
+	 we use the nocache version of traversal and comparison functions.  */
+      if (seq1.idxarr != NULL)
+	{
+	  seq2.idxarr = &seq1.idxarr[s1len];
+	  seq1.rulearr = (unsigned char *) &seq2.idxarr[s2len];
+	  seq2.rulearr = &seq1.rulearr[s1len];
+	  use_malloc = true;
+	}
     }
   else
     {
-    try_stack:
       seq1.idxarr = (int32_t *) alloca (s1len * sizeof (int32_t));
       seq2.idxarr = (int32_t *) alloca (s2len * sizeof (int32_t));
       seq1.rulearr = (unsigned char *) alloca (s1len);
       seq2.rulearr = (unsigned char *) alloca (s2len);
     }
 
-  seq1.rulearr[0] = 0;
+  int rule = 0;
 
   /* Cache values in the first pass and if needed, use them in subsequent
      passes.  */
   for (int pass = 0; pass < nrules; ++pass)
     {
       seq1.idxcnt = 0;
+      seq1.idx = 0;
+      seq2.idx = 0;
       seq1.backw_stop = ~0ul;
       seq1.backw = ~0ul;
       seq2.idxcnt = 0;
       seq2.backw_stop = ~0ul;
       seq2.backw = ~0ul;
 
+      /* We need the elements of the strings as unsigned values since they
+	 are used as indices.  */
+      seq1.us = (const USTRING_TYPE *) s1;
+      seq2.us = (const USTRING_TYPE *) s2;
+
       /* We assume that if a rule has defined `position' in one section
 	 this is true for all of them.  */
-      int position = rulesets[seq1.rulearr[0] * nrules + pass] & sort_position;
+      int position = rulesets[rule * nrules + pass] & sort_position;
 
       while (1)
 	{
-	  if (pass == 0)
+	  if (__glibc_unlikely (seq1.idxarr == NULL))
+	    {
+	      get_next_seq_nocache (&seq1, nrules, rulesets, weights, table,
+				    extra, indirect, pass);
+	      get_next_seq_nocache (&seq2, nrules, rulesets, weights, table,
+				    extra, indirect, pass);
+	    }
+	  else if (pass == 0)
 	    {
 	      get_next_seq (&seq1, nrules, rulesets, weights, table, extra,
 			    indirect);
@@ -411,10 +606,18 @@ STRCOLL (const STRING_TYPE *s1, const STRING_TYPE *s2, __locale_t l)
 	      goto free_and_return;
 	    }
 
-	  result = do_compare (&seq1, &seq2, position, weights);
+	  if (__glibc_unlikely (seq1.idxarr == NULL))
+	    result = do_compare_nocache (&seq1, &seq2, position, weights);
+	  else
+	    result = do_compare (&seq1, &seq2, position, weights);
 	  if (result != 0)
 	    goto free_and_return;
 	}
+
+      if (__glibc_likely (seq1.rulearr != NULL))
+	rule = seq1.rulearr[0];
+      else
+	rule = seq1.rule;
     }
 
   /* Free the memory if needed.  */

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=eb5e4ca15296911a3052268da127ac5fe9cb8a5c

commit eb5e4ca15296911a3052268da127ac5fe9cb8a5c
Author: Siddhesh Poyarekar <siddhesh@redhat.com>
Date:   Tue Aug 20 08:40:05 2013 +0530

    Simplify strcoll implementation
    
    Break up strcoll into simpler functions so that the logic is easier to
    follow and maintain.

diff --git a/ChangeLog b/ChangeLog
index 9124a19..2394806 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+2013-08-20  Siddhesh Poyarekar  <siddhesh@redhat.com>
+
+	* string/strcoll_l.c (coll_seq): New structure.
+	(get_next_seq_cached): New function.
+	(get_next_seq): New function.
+	(do_compare): New function.
+	(STRCOLL): Use GNU style definition.  Simplify implementation
+	by using get_next_seq, get_next_seq_cached and do_compare.
+
 2013-10-31  Andreas Schwab  <schwab@suse.de>
 
 	[BZ# 15917]
diff --git a/string/strcoll_l.c b/string/strcoll_l.c
index ecda08f..50ed84d 100644
--- a/string/strcoll_l.c
+++ b/string/strcoll_l.c
@@ -41,11 +41,244 @@
 
 #include "../locale/localeinfo.h"
 
+/* Track status while looking for sequences in a string.  */
+typedef struct
+{
+  int len;			/* Length of the current sequence.  */
+  int val;			/* Position of the sequence relative to the
+				   previous non-ignored sequence.  */
+  size_t idxnow;		/* Current index in sequences.  */
+  size_t idxmax;		/* Maximum index in sequences.  */
+  size_t idxcnt;		/* Current count of indices.  */
+  size_t backw;			/* Current Backward sequence index.  */
+  size_t backw_stop;		/* Index where the backward sequences stop.  */
+  const USTRING_TYPE *us;	/* The string.  */
+  int32_t *idxarr;		/* Array to cache weight indices.  */
+  unsigned char *rulearr;	/* Array to cache rules.  */
+} coll_seq;
+
+/* Get next sequence.  The weight indices are cached, so we don't need to
+   traverse the string.  */
+static void
+get_next_seq_cached (coll_seq *seq, int nrules, int pass,
+		     const unsigned char *rulesets,
+		     const USTRING_TYPE *weights)
+{
+  int val = seq->val = 0;
+  int len = seq->len;
+  size_t backw_stop = seq->backw_stop;
+  size_t backw = seq->backw;
+  size_t idxcnt = seq->idxcnt;
+  size_t idxmax = seq->idxmax;
+  size_t idxnow = seq->idxnow;
+  unsigned char *rulearr = seq->rulearr;
+  int32_t *idxarr = seq->idxarr;
+
+  while (len == 0)
+    {
+      ++val;
+      if (backw_stop != ~0ul)
+	{
+	  /* There is something pushed.  */
+	  if (backw == backw_stop)
+	    {
+	      /* The last pushed character was handled.  Continue
+		 with forward characters.  */
+	      if (idxcnt < idxmax)
+		{
+		  idxnow = idxcnt;
+		  backw_stop = ~0ul;
+		}
+	      else
+		{
+		  /* Nothing any more.  The backward sequence
+		     ended with the last sequence in the string.  */
+		  idxnow = ~0ul;
+		  break;
+		}
+	    }
+	  else
+	    idxnow = --backw;
+	}
+      else
+	{
+	  backw_stop = idxcnt;
+
+	  while (idxcnt < idxmax)
+	    {
+	      if ((rulesets[rulearr[idxcnt] * nrules + pass]
+		   & sort_backward) == 0)
+		/* No more backward characters to push.  */
+		break;
+	      ++idxcnt;
+	    }
+
+	  if (backw_stop == idxcnt)
+	    {
+	      /* No sequence at all or just one.  */
+	      if (idxcnt == idxmax)
+		/* Note that LEN is still zero.  */
+		break;
+
+	      backw_stop = ~0ul;
+	      idxnow = idxcnt++;
+	    }
+	  else
+	    /* We pushed backward sequences.  */
+	    idxnow = backw = idxcnt - 1;
+	}
+      len = weights[idxarr[idxnow]++];
+    }
+
+  /* Update the structure.  */
+  seq->val = val;
+  seq->len = len;
+  seq->backw_stop = backw_stop;
+  seq->backw = backw;
+  seq->idxcnt = idxcnt;
+  seq->idxnow = idxnow;
+}
+
+/* Get next sequence.  Traverse the string as required.  */
+static void
+get_next_seq (coll_seq *seq, int nrules, const unsigned char *rulesets,
+	      const USTRING_TYPE *weights, const int32_t *table,
+	      const USTRING_TYPE *extra, const int32_t *indirect)
+{
+#include WEIGHT_H
+  int val = seq->val = 0;
+  int len = seq->len;
+  size_t backw_stop = seq->backw_stop;
+  size_t backw = seq->backw;
+  size_t idxcnt = seq->idxcnt;
+  size_t idxmax = seq->idxmax;
+  size_t idxnow = seq->idxnow;
+  unsigned char *rulearr = seq->rulearr;
+  int32_t *idxarr = seq->idxarr;
+  const USTRING_TYPE *us = seq->us;
+
+  while (len == 0)
+    {
+      ++val;
+      if (backw_stop != ~0ul)
+	{
+	  /* The is something pushed.  */
+	  if (backw == backw_stop)
+	    {
+	      /* The last pushed character was handled.  Continue
+		 with forward characters.  */
+	      if (idxcnt < idxmax)
+		{
+		  idxnow = idxcnt;
+		  backw_stop = ~0ul;
+		}
+	      else
+		/* Nothing any more.  The backward sequence ended with
+		   the last sequence in the string.  Note that LEN
+		   is still zero.  */
+		break;
+	    }
+	  else
+	    idxnow = --backw;
+	}
+      else
+	{
+	  backw_stop = idxmax;
+
+	  while (*us != L('\0'))
+	    {
+	      int32_t tmp = findidx (&us, -1);
+	      rulearr[idxmax] = tmp >> 24;
+	      idxarr[idxmax] = tmp & 0xffffff;
+	      idxcnt = idxmax++;
+
+	      if ((rulesets[rulearr[idxcnt] * nrules]
+		   & sort_backward) == 0)
+		/* No more backward characters to push.  */
+		break;
+	      ++idxcnt;
+	    }
+
+	  if (backw_stop >= idxcnt)
+	    {
+	      /* No sequence at all or just one.  */
+	      if (idxcnt == idxmax || backw_stop > idxcnt)
+		/* Note that LEN is still zero.  */
+		break;
+
+	      backw_stop = ~0ul;
+	      idxnow = idxcnt;
+	    }
+	  else
+	    /* We pushed backward sequences.  */
+	    idxnow = backw = idxcnt - 1;
+	}
+      len = weights[idxarr[idxnow]++];
+    }
+
+  /* Update the structure.  */
+  seq->val = val;
+  seq->len = len;
+  seq->backw_stop = backw_stop;
+  seq->backw = backw;
+  seq->idxcnt = idxcnt;
+  seq->idxmax = idxmax;
+  seq->idxnow = idxnow;
+  seq->us = us;
+}
+
+/* Compare two sequences.  */
+static int
+do_compare (coll_seq *seq1, coll_seq *seq2, int position,
+	    const USTRING_TYPE *weights)
+{
+  int seq1len = seq1->len;
+  int seq2len = seq2->len;
+  int val1 = seq1->val;
+  int val2 = seq2->val;
+  int32_t *idx1arr = seq1->idxarr;
+  int32_t *idx2arr = seq2->idxarr;
+  int idx1now = seq1->idxnow;
+  int idx2now = seq2->idxnow;
+  int result = 0;
+
+  /* Test for position if necessary.  */
+  if (position && val1 != val2)
+    {
+      result = val1 - val2;
+      goto out;
+    }
+
+  /* Compare the two sequences.  */
+  do
+    {
+      if (weights[idx1arr[idx1now]] != weights[idx2arr[idx2now]])
+	{
+	  /* The sequences differ.  */
+	  result = weights[idx1arr[idx1now]] - weights[idx2arr[idx2now]];
+	  goto out;
+	}
+
+      /* Increment the offsets.  */
+      ++idx1arr[idx1now];
+      ++idx2arr[idx2now];
+
+      --seq1len;
+      --seq2len;
+    }
+  while (seq1len > 0 && seq2len > 0);
+
+  if (position && seq1len != seq2len)
+    result = seq1len - seq2len;
+
+out:
+  seq1->len = seq1len;
+  seq2->len = seq2len;
+  return result;
+}
+
 int
-STRCOLL (s1, s2, l)
-     const STRING_TYPE *s1;
-     const STRING_TYPE *s2;
-     __locale_t l;
+STRCOLL (const STRING_TYPE *s1, const STRING_TYPE *s2, __locale_t l)
 {
   struct __locale_data *current = l->__locales[LC_COLLATE];
   uint_fast32_t nrules = current->values[_NL_ITEM_INDEX (_NL_COLLATE_NRULES)].word;
@@ -56,34 +289,6 @@ STRCOLL (s1, s2, l)
   const USTRING_TYPE *weights;
   const USTRING_TYPE *extra;
   const int32_t *indirect;
-  uint_fast32_t pass;
-  int result = 0;
-  const USTRING_TYPE *us1;
-  const USTRING_TYPE *us2;
-  size_t s1len;
-  size_t s2len;
-  int32_t *idx1arr;
-  int32_t *idx2arr;
-  unsigned char *rule1arr;
-  unsigned char *rule2arr;
-  size_t idx1max;
-  size_t idx2max;
-  size_t idx1cnt;
-  size_t idx2cnt;
-  size_t idx1now;
-  size_t idx2now;
-  size_t backw1_stop;
-  size_t backw2_stop;
-  size_t backw1;
-  size_t backw2;
-  int val1;
-  int val2;
-  int position;
-  int seq1len;
-  int seq2len;
-  int use_malloc;
-
-#include WEIGHT_H
 
   if (nrules == 0)
     return STRCMP (s1, s2);
@@ -98,7 +303,6 @@ STRCOLL (s1, s2, l)
     current->values[_NL_ITEM_INDEX (CONCAT(_NL_COLLATE_EXTRA,SUFFIX))].string;
   indirect = (const int32_t *)
     current->values[_NL_ITEM_INDEX (CONCAT(_NL_COLLATE_INDIRECT,SUFFIX))].string;
-  use_malloc = 0;
 
   assert (((uintptr_t) table) % __alignof__ (table[0]) == 0);
   assert (((uintptr_t) weights) % __alignof__ (weights[0]) == 0);
@@ -106,18 +310,13 @@ STRCOLL (s1, s2, l)
   assert (((uintptr_t) indirect) % __alignof__ (indirect[0]) == 0);
 
   /* We need this a few times.  */
-  s1len = STRLEN (s1);
-  s2len = STRLEN (s2);
+  size_t s1len = STRLEN (s1);
+  size_t s2len = STRLEN (s2);
 
   /* Catch empty strings.  */
-  if (__builtin_expect (s1len == 0, 0) || __builtin_expect (s2len == 0, 0))
+  if (__glibc_unlikely (s1len == 0) || __glibc_unlikely (s2len == 0))
     return (s1len != 0) - (s2len != 0);
 
-  /* We need the elements of the strings as unsigned values since they
-     are used as indeces.  */
-  us1 = (const USTRING_TYPE *) s1;
-  us2 = (const USTRING_TYPE *) s2;
-
   /* Perform the first pass over the string and while doing this find
      and store the weights for each character.  Since we want this to
      be as fast as possible we are using `alloca' to store the temporary
@@ -127,411 +326,101 @@ STRCOLL (s1, s2, l)
 
      Please note that the localedef programs makes sure that `position'
      is not used at the first level.  */
+
+  coll_seq seq1, seq2;
+  bool use_malloc = false;
+  int result = 0;
+
+  memset (&seq1, 0, sizeof (seq1));
+  seq2 = seq1;
+
+  /* We need the elements of the strings as unsigned values since they
+     are used as indices.  */
+  seq1.us = (const USTRING_TYPE *) s1;
+  seq2.us = (const USTRING_TYPE *) s2;
+
   if (! __libc_use_alloca ((s1len + s2len) * (sizeof (int32_t) + 1)))
     {
-      idx1arr = (int32_t *) malloc ((s1len + s2len) * (sizeof (int32_t) + 1));
-      idx2arr = &idx1arr[s1len];
-      rule1arr = (unsigned char *) &idx2arr[s2len];
-      rule2arr = &rule1arr[s1len];
+      seq1.idxarr = (int32_t *) malloc ((s1len + s2len) * (sizeof (int32_t) + 1));
+      seq2.idxarr = &seq1.idxarr[s1len];
+      seq1.rulearr = (unsigned char *) &seq2.idxarr[s2len];
+      seq2.rulearr = &seq1.rulearr[s1len];
 
-      if (idx1arr == NULL)
+      if (seq1.idxarr == NULL)
 	/* No memory.  Well, go with the stack then.
 
 	   XXX Once this implementation is stable we will handle this
-	   differently.  Instead of precomputing the indeces we will
+	   differently.  Instead of precomputing the indices we will
 	   do this in time.  This means, though, that this happens for
 	   every pass again.  */
 	goto try_stack;
-      use_malloc = 1;
+      use_malloc = true;
     }
   else
     {
     try_stack:
-      idx1arr = (int32_t *) alloca (s1len * sizeof (int32_t));
-      idx2arr = (int32_t *) alloca (s2len * sizeof (int32_t));
-      rule1arr = (unsigned char *) alloca (s1len);
-      rule2arr = (unsigned char *) alloca (s2len);
+      seq1.idxarr = (int32_t *) alloca (s1len * sizeof (int32_t));
+      seq2.idxarr = (int32_t *) alloca (s2len * sizeof (int32_t));
+      seq1.rulearr = (unsigned char *) alloca (s1len);
+      seq2.rulearr = (unsigned char *) alloca (s2len);
     }
 
-  idx1cnt = 0;
-  idx2cnt = 0;
-  idx1max = 0;
-  idx2max = 0;
-  idx1now = 0;
-  idx2now = 0;
-  backw1_stop = ~0ul;
-  backw2_stop = ~0ul;
-  backw1 = ~0ul;
-  backw2 = ~0ul;
-  seq1len = 0;
-  seq2len = 0;
-  position = rulesets[0] & sort_position;
-  while (1)
-    {
-      val1 = 0;
-      val2 = 0;
-
-      /* Get the next non-IGNOREd element for string `s1'.  */
-      if (seq1len == 0)
-	do
-	  {
-	    ++val1;
-
-	    if (backw1_stop != ~0ul)
-	      {
-		/* The is something pushed.  */
-		if (backw1 == backw1_stop)
-		  {
-		    /* The last pushed character was handled.  Continue
-		       with forward characters.  */
-		    if (idx1cnt < idx1max)
-		      {
-			idx1now = idx1cnt;
-			backw1_stop = ~0ul;
-		      }
-		    else
-		      /* Nothing anymore.  The backward sequence ended with
-			 the last sequence in the string.  Note that seq1len
-			 is still zero.  */
-		      break;
-		  }
-		else
-		  idx1now = --backw1;
-	      }
-	    else
-	      {
-		backw1_stop = idx1max;
-
-		while (*us1 != L('\0'))
-		  {
-		    int32_t tmp = findidx (&us1, -1);
-		    rule1arr[idx1max] = tmp >> 24;
-		    idx1arr[idx1max] = tmp & 0xffffff;
-		    idx1cnt = idx1max++;
-
-		    if ((rulesets[rule1arr[idx1cnt] * nrules]
-			 & sort_backward) == 0)
-		      /* No more backward characters to push.  */
-		      break;
-		    ++idx1cnt;
-		  }
-
-		if (backw1_stop >= idx1cnt)
-		  {
-		    /* No sequence at all or just one.  */
-		    if (idx1cnt == idx1max || backw1_stop > idx1cnt)
-		      /* Note that seq1len is still zero.  */
-		      break;
-
-		    backw1_stop = ~0ul;
-		    idx1now = idx1cnt;
-		  }
-		else
-		  /* We pushed backward sequences.  */
-		  idx1now = backw1 = idx1cnt - 1;
-	      }
-	  }
-	while ((seq1len = weights[idx1arr[idx1now]++]) == 0);
-
-      /* And the same for string `s2'.  */
-      if (seq2len == 0)
-	do
-	  {
-	    ++val2;
-
-	    if (backw2_stop != ~0ul)
-	      {
-		/* The is something pushed.  */
-		if (backw2 == backw2_stop)
-		  {
-		    /* The last pushed character was handled.  Continue
-		       with forward characters.  */
-		    if (idx2cnt < idx2max)
-		      {
-			idx2now = idx2cnt;
-			backw2_stop = ~0ul;
-		      }
-		    else
-		      /* Nothing anymore.  The backward sequence ended with
-			 the last sequence in the string.  Note that seq2len
-			 is still zero.  */
-		      break;
-		  }
-		else
-		  idx2now = --backw2;
-	      }
-	    else
-	      {
-		backw2_stop = idx2max;
-
-		while (*us2 != L('\0'))
-		  {
-		    int32_t tmp = findidx (&us2, -1);
-		    rule2arr[idx2max] = tmp >> 24;
-		    idx2arr[idx2max] = tmp & 0xffffff;
-		    idx2cnt = idx2max++;
-
-		    if ((rulesets[rule2arr[idx2cnt] * nrules]
-			 & sort_backward) == 0)
-		      /* No more backward characters to push.  */
-		      break;
-		    ++idx2cnt;
-		  }
-
-		if (backw2_stop >= idx2cnt)
-		  {
-		    /* No sequence at all or just one.  */
-		    if (idx2cnt == idx2max || backw2_stop > idx2cnt)
-		      /* Note that seq1len is still zero.  */
-		      break;
-
-		    backw2_stop = ~0ul;
-		    idx2now = idx2cnt;
-		  }
-		else
-		  /* We pushed backward sequences.  */
-		  idx2now = backw2 = idx2cnt - 1;
-	      }
-	  }
-	while ((seq2len = weights[idx2arr[idx2now]++]) == 0);
-
-      /* See whether any or both strings are empty.  */
-      if (seq1len == 0 || seq2len == 0)
-	{
-	  if (seq1len == seq2len)
-	    /* Both ended.  So far so good, both strings are equal at the
-	       first level.  */
-	    break;
-
-	  /* This means one string is shorter than the other.  Find out
-	     which one and return an appropriate value.  */
-	  result = seq1len == 0 ? -1 : 1;
-	  goto free_and_return;
-	}
-
-      /* Test for position if necessary.  */
-      if (position && val1 != val2)
-	{
-	  result = val1 - val2;
-	  goto free_and_return;
-	}
-
-      /* Compare the two sequences.  */
-      do
-	{
-	  if (weights[idx1arr[idx1now]] != weights[idx2arr[idx2now]])
-	    {
-	      /* The sequences differ.  */
-	      result = weights[idx1arr[idx1now]] - weights[idx2arr[idx2now]];
-	      goto free_and_return;
-	    }
-
-	  /* Increment the offsets.  */
-	  ++idx1arr[idx1now];
-	  ++idx2arr[idx2now];
+  seq1.rulearr[0] = 0;
 
-	  --seq1len;
-	  --seq2len;
-	}
-      while (seq1len > 0 && seq2len > 0);
-
-      if (position && seq1len != seq2len)
-	{
-	  result = seq1len - seq2len;
-	  goto free_and_return;
-	}
-    }
-
-  /* Now the remaining passes over the weights.  We now use the
-     indeces we found before.  */
-  for (pass = 1; pass < nrules; ++pass)
+  /* Cache values in the first pass and if needed, use them in subsequent
+     passes.  */
+  for (int pass = 0; pass < nrules; ++pass)
     {
+      seq1.idxcnt = 0;
+      seq1.backw_stop = ~0ul;
+      seq1.backw = ~0ul;
+      seq2.idxcnt = 0;
+      seq2.backw_stop = ~0ul;
+      seq2.backw = ~0ul;
+
       /* We assume that if a rule has defined `position' in one section
 	 this is true for all of them.  */
-      idx1cnt = 0;
-      idx2cnt = 0;
-      backw1_stop = ~0ul;
-      backw2_stop = ~0ul;
-      backw1 = ~0ul;
-      backw2 = ~0ul;
-      position = rulesets[rule1arr[0] * nrules + pass] & sort_position;
+      int position = rulesets[seq1.rulearr[0] * nrules + pass] & sort_position;
 
       while (1)
 	{
-	  val1 = 0;
-	  val2 = 0;
-
-	  /* Get the next non-IGNOREd element for string `s1'.  */
-	  if (seq1len == 0)
-	    do
-	      {
-		++val1;
-
-		if (backw1_stop != ~0ul)
-		  {
-		    /* The is something pushed.  */
-		    if (backw1 == backw1_stop)
-		      {
-			/* The last pushed character was handled.  Continue
-			   with forward characters.  */
-			if (idx1cnt < idx1max)
-			  {
-			    idx1now = idx1cnt;
-			    backw1_stop = ~0ul;
-			  }
-			else
-			  {
-			    /* Nothing anymore.  The backward sequence
-			       ended with the last sequence in the string.  */
-			    idx1now = ~0ul;
-			    break;
-			  }
-		      }
-		    else
-		      idx1now = --backw1;
-		  }
-		else
-		  {
-		    backw1_stop = idx1cnt;
-
-		    while (idx1cnt < idx1max)
-		      {
-			if ((rulesets[rule1arr[idx1cnt] * nrules + pass]
-			     & sort_backward) == 0)
-			  /* No more backward characters to push.  */
-			  break;
-			++idx1cnt;
-		      }
-
-		    if (backw1_stop == idx1cnt)
-		      {
-			/* No sequence at all or just one.  */
-			if (idx1cnt == idx1max)
-			  /* Note that seq1len is still zero.  */
-			  break;
-
-			backw1_stop = ~0ul;
-			idx1now = idx1cnt++;
-		      }
-		    else
-		      /* We pushed backward sequences.  */
-		      idx1now = backw1 = idx1cnt - 1;
-		  }
-	      }
-	    while ((seq1len = weights[idx1arr[idx1now]++]) == 0);
-
-	  /* And the same for string `s2'.  */
-	  if (seq2len == 0)
-	    do
-	      {
-		++val2;
-
-		if (backw2_stop != ~0ul)
-		  {
-		    /* The is something pushed.  */
-		    if (backw2 == backw2_stop)
-		      {
-			/* The last pushed character was handled.  Continue
-			   with forward characters.  */
-			if (idx2cnt < idx2max)
-			  {
-			    idx2now = idx2cnt;
-			    backw2_stop = ~0ul;
-			  }
-			else
-			  {
-			    /* Nothing anymore.  The backward sequence
-			       ended with the last sequence in the string.  */
-			    idx2now = ~0ul;
-			    break;
-			  }
-		      }
-		    else
-		      idx2now = --backw2;
-		  }
-		else
-		  {
-		    backw2_stop = idx2cnt;
-
-		    while (idx2cnt < idx2max)
-		      {
-			if ((rulesets[rule2arr[idx2cnt] * nrules + pass]
-			     & sort_backward) == 0)
-			  /* No more backward characters to push.  */
-			  break;
-			++idx2cnt;
-		      }
-
-		    if (backw2_stop == idx2cnt)
-		      {
-			/* No sequence at all or just one.  */
-			if (idx2cnt == idx2max)
-			  /* Note that seq2len is still zero.  */
-			  break;
-
-			backw2_stop = ~0ul;
-			idx2now = idx2cnt++;
-		      }
-		    else
-		      /* We pushed backward sequences.  */
-		      idx2now = backw2 = idx2cnt - 1;
-		  }
-	      }
-	    while ((seq2len = weights[idx2arr[idx2now]++]) == 0);
+	  if (pass == 0)
+	    {
+	      get_next_seq (&seq1, nrules, rulesets, weights, table, extra,
+			    indirect);
+	      get_next_seq (&seq2, nrules, rulesets, weights, table, extra,
+			    indirect);
+	    }
+	  else
+	    {
+	      get_next_seq_cached (&seq1, nrules, pass, rulesets, weights);
+	      get_next_seq_cached (&seq2, nrules, pass, rulesets, weights);
+	    }
 
 	  /* See whether any or both strings are empty.  */
-	  if (seq1len == 0 || seq2len == 0)
+	  if (seq1.len == 0 || seq2.len == 0)
 	    {
-	      if (seq1len == seq2len)
+	      if (seq1.len == seq2.len)
 		/* Both ended.  So far so good, both strings are equal
 		   at this level.  */
 		break;
 
 	      /* This means one string is shorter than the other.  Find out
 		 which one and return an appropriate value.  */
-	      result = seq1len == 0 ? -1 : 1;
+	      result = seq1.len == 0 ? -1 : 1;
 	      goto free_and_return;
 	    }
 
-	  /* Test for position if necessary.  */
-	  if (position && val1 != val2)
-	    {
-	      result = val1 - val2;
-	      goto free_and_return;
-	    }
-
-	  /* Compare the two sequences.  */
-	  do
-	    {
-	      if (weights[idx1arr[idx1now]] != weights[idx2arr[idx2now]])
-		{
-		  /* The sequences differ.  */
-		  result = (weights[idx1arr[idx1now]]
-			    - weights[idx2arr[idx2now]]);
-		  goto free_and_return;
-		}
-
-	      /* Increment the offsets.  */
-	      ++idx1arr[idx1now];
-	      ++idx2arr[idx2now];
-
-	      --seq1len;
-	      --seq2len;
-	    }
-	  while (seq1len > 0 && seq2len > 0);
-
-	  if (position && seq1len != seq2len)
-	    {
-	      result = seq1len - seq2len;
-	      goto free_and_return;
-	    }
+	  result = do_compare (&seq1, &seq2, position, weights);
+	  if (result != 0)
+	    goto free_and_return;
 	}
     }
 
   /* Free the memory if needed.  */
  free_and_return:
   if (use_malloc)
-    free (idx1arr);
+    free (seq1.idxarr);
 
   return result;
 }

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=92f45f230c8abdf91195f2f7e4f003754755a0c6

commit 92f45f230c8abdf91195f2f7e4f003754755a0c6
Author: Andreas Schwab <schwab@suse.de>
Date:   Thu Oct 31 12:51:03 2013 +0100

    Fix parsing of 0e+0 as float

diff --git a/ChangeLog b/ChangeLog
index 2404b75..9124a19 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2013-10-31  Andreas Schwab  <schwab@suse.de>
+
+	[BZ# 15917]
+	* stdio-common/vfscanf.c (_IO_vfwscanf): Handle leading '0' not
+	followed by 'x' as part of digit sequence.
+	* stdio-common/tst-sscanf.c (double_tests2): New tests.
+
 2013-10-04  Adhemerval Zanella  <azanella@linux.vnet.ibm.com>
 
 	* sysdeps/powerpc/powerpc64/strcpy.S (strcpy): Add word load/store
diff --git a/NEWS b/NEWS
index c70f333..8b228b0 100644
--- a/NEWS
+++ b/NEWS
@@ -9,8 +9,8 @@ Version 2.18.1
 
 * The following bugs are resolved with this release:
 
-  14155, 14699, 15532, 15427, 15522, 15797, 15892, 15895, 15909, 15996,
-  16072, 16150.
+  14155, 14699, 15532, 15427, 15522, 15797, 15892, 15895, 15909, 15917,
+  15996, 16072, 16150.
 
 * CVE-2013-4237 The readdir_r function could write more than NAME_MAX bytes
   to the d_name member of struct dirent, or omit the terminating NUL
diff --git a/stdio-common/tst-sscanf.c b/stdio-common/tst-sscanf.c
index 1edb227..3c34f58 100644
--- a/stdio-common/tst-sscanf.c
+++ b/stdio-common/tst-sscanf.c
@@ -109,6 +109,19 @@ struct test double_tests[] =
   { L("-inf"), L("%g"), 1 }
 };
 
+struct test2
+{
+  const CHAR *str;
+  const CHAR *fmt;
+  int retval;
+  char residual;
+} double_tests2[] =
+{
+  { L("0e+0"), L("%g%c"), 1, 0 },
+  { L("0xe+0"), L("%g%c"), 2, '+' },
+  { L("0x.e+0"), L("%g%c"), 2, '+' },
+};
+
 int
 main (void)
 {
@@ -196,5 +209,26 @@ main (void)
 	}
     }
 
+  for (i = 0; i < sizeof (double_tests2) / sizeof (double_tests2[0]); ++i)
+    {
+      double dummy;
+      int ret;
+      char c = 0;
+
+      if ((ret = SSCANF (double_tests2[i].str, double_tests2[i].fmt,
+			 &dummy, &c)) != double_tests2[i].retval)
+	{
+	  printf ("double_tests2[%d] returned %d != %d\n",
+		  i, ret, double_tests2[i].retval);
+	  result = 1;
+	}
+      else if (ret == 2 && c != double_tests2[i].residual)
+	{
+	  printf ("double_tests2[%d] stopped at '%c' != '%c'\n",
+		  i, c, double_tests2[i].residual);
+	  result = 1;
+	}
+    }
+
   return result;
 }
diff --git a/stdio-common/vfscanf.c b/stdio-common/vfscanf.c
index 3430567..093c8b0 100644
--- a/stdio-common/vfscanf.c
+++ b/stdio-common/vfscanf.c
@@ -1966,6 +1966,8 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
 		  if (width > 0)
 		    --width;
 		}
+	      else
+		got_digit = 1;
 	    }
 
 	  while (1)

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=2849f111a87a5e9c715fb8379163869781dc9ad7

commit 2849f111a87a5e9c715fb8379163869781dc9ad7
Author: Adhemerval Zanella <azanella@linux.vnet.ibm.com>
Date:   Thu Sep 26 09:29:19 2013 -0500

    PowerPC: strcpy/stpcpy optimization for PPC64/POWER7
    
    This patch intends to unify both strcpy and stpcpy implementationsi
    for PPC64 and PPC64/POWER7. The idead default powerpc64 implementation
    is to provide both doubleword and word aligned memory access.
    
    For PPC64/POWER7 is also provide doubleword and word memory access,
    remove the branch hints, use the cmpb instruction for compare
    doubleword/words, and add an optimization for inputs of same alignment.

diff --git a/ChangeLog b/ChangeLog
index 0afcd3f..2404b75 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+2013-10-04  Adhemerval Zanella  <azanella@linux.vnet.ibm.com>
+
+	* sysdeps/powerpc/powerpc64/strcpy.S (strcpy): Add word load/store
+	to provide a boost for large inputs with word alignment.
+	* sysdeps/powerpc/powerpc64/stpcpy.S (__stpcpy): Rewrite
+	implementation based on optimized PPC64 strcpy.
+	* sysdeps/powerpc/powerpc64/power7/strcpy.S: New file: optimized
+	strcpy for PPC64/POWER7 based on both doubleword and word load/store.
+	* sysdeps/powerpc/powerpc64/power7/stpcpy.S: New file: optimized
+	stpcpy for PPC64/POWER7 based on PPC64/POWER7 strcpy.
+
 2013-10-25  Siddhesh Poyarekar  <siddhesh@redhat.com>
 
 <<<<<<< HEAD
diff --git a/sysdeps/powerpc/powerpc64/power7/stpcpy.S b/sysdeps/powerpc/powerpc64/power7/stpcpy.S
new file mode 100644
index 0000000..727dd06
--- /dev/null
+++ b/sysdeps/powerpc/powerpc64/power7/stpcpy.S
@@ -0,0 +1,24 @@
+/* Optimized stpcpy implementation for PowerPC64/POWER7.
+   Copyright (C) 2013 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/>.  */
+
+#define USE_AS_STPCPY
+#include <sysdeps/powerpc/powerpc64/power7/strcpy.S>
+
+weak_alias (__stpcpy, stpcpy)
+libc_hidden_def (__stpcpy)
+libc_hidden_builtin_def (stpcpy)
diff --git a/sysdeps/powerpc/powerpc64/power7/strcpy.S b/sysdeps/powerpc/powerpc64/power7/strcpy.S
new file mode 100644
index 0000000..5c341a1
--- /dev/null
+++ b/sysdeps/powerpc/powerpc64/power7/strcpy.S
@@ -0,0 +1,274 @@
+/* Optimized strcpy/stpcpy implementation for PowerPC64/POWER7.
+   Copyright (C) 2013 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/>.  */
+
+#include <sysdep.h>
+
+/* Implements the function
+
+   char * [r3] strcpy (char *dest [r3], const char *src [r4])
+
+   or
+
+   char * [r3] strcpy (char *dest [r3], const char *src [r4])
+
+   if USE_AS_STPCPY is defined. It tries to use aligned memory accesses
+   when possible using the following algorithm:
+
+   if (((((uintptr_t)dst & 0x7UL) == 0) && ((uintptr_t)src & 0x7UL) == 0))
+     goto aligned_doubleword_copy;
+   if (((((uintptr_t)dst & 0x3UL) == 0) && ((uintptr_t)src & 0x3UL) == 0))
+     goto aligned_word_copy;
+   if (((uintptr_t)dst & 0x7UL) == ((uintptr_t)src & 0x7UL))
+     goto same_alignment;
+   goto unaligned;
+
+   The aligned comparison are made using cmpb instructions.  */
+
+#ifdef USE_AS_STPCPY
+# define FUNC_NAME __stpcpy
+#else
+# define FUNC_NAME strcpy
+#endif
+
+	.machine  power7
+EALIGN (FUNC_NAME, 4, 0)
+	CALL_MCOUNT 2
+
+#define rTMP	r0
+#ifdef USE_AS_STPCPY
+#define rRTN	r3	/* pointer to previous word/doubleword in dest */
+#else
+#define rRTN	r12	/* pointer to previous word/doubleword in dest */
+#endif
+#define rSRC	r4	/* pointer to previous word/doubleword in src */
+#define rMASK	r5	/* mask 0xffffffff | 0xffffffffffffffff */
+#define rWORD	r6	/* current word from src */
+#define rALT	r7	/* alternate word from src */
+#define rRTNAL	r8	/* alignment of return pointer */
+#define rSRCAL	r9	/* alignment of source pointer */
+#define rALCNT	r10	/* bytes to read to reach 8 bytes alignment */
+#define rSUBAL	r11	/* doubleword minus unaligned displacement */
+
+#ifndef USE_AS_STPCPY
+/* Save the dst pointer to use as return value.  */
+	mr	rRTN, r3
+#endif
+	or	rTMP, rSRC, rRTN
+	clrldi.	rTMP, rTMP, 61
+	bne	L(check_word_alignment)
+	b	L(aligned_doubleword_copy)
+
+L(same_alignment):
+/* Src and dst with same alignment: align both to doubleword.  */
+	mr	rALCNT, rRTN
+	lbz	rWORD, 0(rSRC)
+	subfic	rSUBAL, rRTNAL, 8
+	addi	rRTN, rRTN, 1
+	addi	rSRC, rSRC, 1
+	cmpdi	cr7, rWORD, 0
+	stb	rWORD, 0(rALCNT)
+	beq	cr7, L(s2)
+
+	add	rALCNT, rALCNT, rSUBAL
+	subf	rALCNT, rRTN, rALCNT
+	addi	rALCNT, rALCNT, 1
+	mtctr	rALCNT
+	b	L(s1)
+
+	.align 4
+L(s0):
+	addi	rSRC, rSRC, 1
+	lbz	rWORD, -1(rSRC)
+	cmpdi	cr7, rWORD, 0
+	stb	rWORD, -1(rALCNT)
+	beqlr	cr7
+	mr	rRTN, rALCNT
+L(s1):
+	addi	rALCNT, rRTN,1
+	bdnz	L(s0)
+	b L(aligned_doubleword_copy)
+	.align 4
+L(s2):
+	mr	rRTN, rALCNT
+	blr
+
+/* For doubleword aligned memory, operate using doubleword load and stores.  */
+	.align 4
+L(aligned_doubleword_copy):
+	li	rMASK, 0
+	addi	rRTN, rRTN, -8
+	ld	rWORD, 0(rSRC)
+	b	L(g2)
+
+	.align 4
+L(g0):	ldu	rALT, 8(rSRC)
+	stdu	rWORD, 8(rRTN)
+	cmpb	rTMP, rALT, rMASK
+	cmpdi	rTMP, 0
+	bne	L(g1)
+	ldu	rWORD, 8(rSRC)
+	stdu	rALT, 8(rRTN)
+L(g2):	cmpb	rTMP, rWORD, rMASK
+	cmpdi	rTMP, 0		/* If rTMP is 0, no null's have been found.  */
+	beq	L(g0)
+
+	mr	rALT, rWORD
+/* We've hit the end of the string.  Do the rest byte-by-byte.  */
+L(g1):
+#ifdef __LITTLE_ENDIAN__
+	extrdi.	rTMP, rALT, 8, 56
+	stbu	rALT, 8(rRTN)
+	beqlr-
+	extrdi.	rTMP, rALT, 8, 48
+	stbu	rTMP, 1(rRTN)
+	beqlr-
+	extrdi.	rTMP, rALT, 8, 40
+	stbu	rTMP, 1(rRTN)
+	beqlr-
+	extrdi.	rTMP, rALT, 8, 32
+	stbu	rTMP, 1(rRTN)
+	beqlr-
+	extrdi.	rTMP, rALT, 8, 24
+	stbu	rTMP, 1(rRTN)
+	beqlr-
+	extrdi.	rTMP, rALT, 8, 16
+	stbu	rTMP, 1(rRTN)
+	beqlr-
+	extrdi.	rTMP, rALT, 8, 8
+	stbu	rTMP, 1(rRTN)
+	beqlr-
+	extrdi	rTMP, rALT, 8, 0
+	stbu	rTMP, 1(rRTN)
+#else
+	extrdi.	rTMP, rALT, 8, 0
+	stbu	rTMP, 8(rRTN)
+	beqlr
+	extrdi.	rTMP, rALT, 8, 8
+	stbu	rTMP, 1(rRTN)
+	beqlr
+	extrdi.	rTMP, rALT, 8, 16
+	stbu	rTMP, 1(rRTN)
+	beqlr
+	extrdi.	rTMP, rALT, 8, 24
+	stbu	rTMP, 1(rRTN)
+	beqlr
+	extrdi.	rTMP, rALT, 8, 32
+	stbu	rTMP, 1(rRTN)
+	beqlr
+	extrdi.	rTMP, rALT, 8, 40
+	stbu	rTMP, 1(rRTN)
+	beqlr
+	extrdi.	rTMP, rALT, 8, 48
+	stbu	rTMP, 1(rRTN)
+	beqlr
+	stbu	rALT, 1(rRTN)
+#endif
+	blr
+
+L(check_word_alignment):
+	clrldi. rTMP, rTMP, 62
+	beq	L(aligned_word_copy)
+	rldicl	rRTNAL, rRTN, 0, 61
+	rldicl	rSRCAL, rSRC, 0, 61
+	cmpld	cr7, rSRCAL, rRTNAL
+	beq	cr7, L(same_alignment)
+	b	L(unaligned)
+
+/* For word aligned memory, operate using word load and stores.  */
+	.align	4
+L(aligned_word_copy):
+	li	rMASK, 0
+	addi	rRTN, rRTN, -4
+	lwz	rWORD, 0(rSRC)
+	b	L(g5)
+
+	.align	4
+L(g3):	lwzu	rALT, 4(rSRC)
+	stwu	rWORD, 4(rRTN)
+	cmpb	rTMP, rALT, rMASK
+	cmpwi	rTMP, 0
+	bne	L(g4)
+	lwzu	rWORD, 4(rSRC)
+	stwu	rALT, 4(rRTN)
+L(g5):	cmpb	rTMP, rWORD, rMASK
+	cmpwi	rTMP, 0		/* If rTMP is 0, no null in word.  */
+	beq	L(g3)
+
+	mr      rALT, rWORD
+/* We've hit the end of the string.  Do the rest byte-by-byte.  */
+L(g4):
+#ifdef __LITTLE_ENDIAN__
+	rlwinm.	rTMP, rALT, 0, 24, 31
+	stbu	rALT, 4(rRTN)
+	beqlr-
+	rlwinm.	rTMP, rALT, 24, 24, 31
+	stbu	rTMP, 1(rRTN)
+	beqlr-
+	rlwinm.	rTMP, rALT, 16, 24, 31
+	stbu	rTMP, 1(rRTN)
+	beqlr-
+	rlwinm	rTMP, rALT, 8, 24, 31
+	stbu	rTMP, 1(rRTN)
+#else
+	rlwinm. rTMP, rALT, 8, 24, 31
+	stbu    rTMP, 4(rRTN)
+	beqlr
+	rlwinm. rTMP, rALT, 16, 24, 31
+	stbu    rTMP, 1(rRTN)
+	beqlr
+	rlwinm. rTMP, rALT, 24, 24, 31
+	stbu    rTMP, 1(rRTN)
+	beqlr
+	stbu    rALT, 1(rRTN)
+#endif
+	blr
+
+/* Oh well.  In this case, we just do a byte-by-byte copy.  */
+	.align	4
+L(unaligned):
+	lbz	rWORD, 0(rSRC)
+	addi	rRTN, rRTN, -1
+	cmpdi	rWORD, 0
+	beq	L(u2)
+
+	.align 	5
+L(u0):	lbzu	rALT, 1(rSRC)
+	stbu	rWORD, 1(rRTN)
+	cmpdi	rALT, 0
+	beq	L(u1)
+	lbzu	rWORD, 1(rSRC)
+	stbu	rALT, 1(rRTN)
+	cmpdi	rWORD, 0
+	beq	L(u2)
+	lbzu	rALT, 1(rSRC)
+	stbu	rWORD, 1(rRTN)
+	cmpdi	rALT, 0
+	beq	L(u1)
+	lbzu	rWORD, 1(rSRC)
+	stbu	rALT, 1(rRTN)
+	cmpdi	rWORD, 0
+	bne	L(u0)
+L(u2):	stbu	rWORD, 1(rRTN)
+	blr
+L(u1):	stbu	rALT, 1(rRTN)
+	blr
+END (FUNC_NAME)
+
+#ifndef USE_AS_STPCPY
+libc_hidden_builtin_def (strcpy)
+#endif
diff --git a/sysdeps/powerpc/powerpc64/stpcpy.S b/sysdeps/powerpc/powerpc64/stpcpy.S
index c0b3972..09aa3be 100644
--- a/sysdeps/powerpc/powerpc64/stpcpy.S
+++ b/sysdeps/powerpc/powerpc64/stpcpy.S
@@ -16,103 +16,8 @@
    License along with the GNU C Library; if not, see
    <http://www.gnu.org/licenses/>.  */
 
-#include <sysdep.h>
-
-/* See strlen.s for comments on how the end-of-string testing works.  */
-
-/* char * [r3] stpcpy (char *dest [r3], const char *src [r4])  */
-
-EALIGN (__stpcpy, 4, 0)
-	CALL_MCOUNT 2
-
-#define rTMP	r0
-#define rRTN	r3
-#define rDEST	r3		/* pointer to previous word in dest */
-#define rSRC	r4		/* pointer to previous word in src */
-#define rWORD	r6		/* current word from src */
-#define rFEFE	r7		/* 0xfefefeff */
-#define r7F7F	r8		/* 0x7f7f7f7f */
-#define rNEG	r9		/* ~(word in src | 0x7f7f7f7f) */
-#define rALT	r10		/* alternate word from src */
-
-	or	rTMP, rSRC, rDEST
-	clrldi.	rTMP, rTMP, 62
-	addi	rDEST, rDEST, -4
-	bne	L(unaligned)
-
-	lis	rFEFE, -0x101
-	lis	r7F7F, 0x7f7f
-	lwz	rWORD, 0(rSRC)
-	addi	rFEFE, rFEFE, -0x101
-	addi	r7F7F, r7F7F, 0x7f7f
-	b	L(g2)
-
-L(g0):	lwzu	rALT, 4(rSRC)
-	stwu	rWORD, 4(rDEST)
-	add	rTMP, rFEFE, rALT
-	nor	rNEG, r7F7F, rALT
-	and.	rTMP, rTMP, rNEG
-	bne-	L(g1)
-	lwzu	rWORD, 4(rSRC)
-	stwu	rALT, 4(rDEST)
-L(g2):	add	rTMP, rFEFE, rWORD
-	nor	rNEG, r7F7F, rWORD
-	and.	rTMP, rTMP, rNEG
-	beq+	L(g0)
-
-	mr	rALT, rWORD
-/* We've hit the end of the string.  Do the rest byte-by-byte.  */
-L(g1):
-#ifdef __LITTLE_ENDIAN__
-	rlwinm.	rTMP, rALT, 0, 24, 31
-	stbu	rALT, 4(rDEST)
-	beqlr-
-	rlwinm.	rTMP, rALT, 24, 24, 31
-	stbu	rTMP, 1(rDEST)
-	beqlr-
-	rlwinm.	rTMP, rALT, 16, 24, 31
-	stbu	rTMP, 1(rDEST)
-	beqlr-
-	rlwinm	rTMP, rALT, 8, 24, 31
-	stbu	rTMP, 1(rDEST)
-	blr
-#else
-	rlwinm.	rTMP, rALT, 8, 24, 31
-	stbu	rTMP, 4(rDEST)
-	beqlr-
-	rlwinm.	rTMP, rALT, 16, 24, 31
-	stbu	rTMP, 1(rDEST)
-	beqlr-
-	rlwinm.	rTMP, rALT, 24, 24, 31
-	stbu	rTMP, 1(rDEST)
-	beqlr-
-	stbu	rALT, 1(rDEST)
-	blr
-#endif
-
-/* Oh well.  In this case, we just do a byte-by-byte copy.  */
-	.align 4
-	nop
-L(unaligned):
-	lbz	rWORD, 0(rSRC)
-	addi	rDEST, rDEST, 3
-	cmpwi	rWORD, 0
-	beq-	L(u2)
-
-L(u0):	lbzu	rALT, 1(rSRC)
-	stbu	rWORD, 1(rDEST)
-	cmpwi	rALT, 0
-	beq-	L(u1)
-	nop		/* Let 601 load start of loop.  */
-	lbzu	rWORD, 1(rSRC)
-	stbu	rALT, 1(rDEST)
-	cmpwi	rWORD, 0
-	bne+	L(u0)
-L(u2):	stbu	rWORD, 1(rDEST)
-	blr
-L(u1):	stbu	rALT, 1(rDEST)
-	blr
-END (__stpcpy)
+#define USE_AS_STPCPY
+#include <sysdeps/powerpc/powerpc64/strcpy.S>
 
 weak_alias (__stpcpy, stpcpy)
 libc_hidden_def (__stpcpy)
diff --git a/sysdeps/powerpc/powerpc64/strcpy.S b/sysdeps/powerpc/powerpc64/strcpy.S
index a7fd85b..793325d 100644
--- a/sysdeps/powerpc/powerpc64/strcpy.S
+++ b/sysdeps/powerpc/powerpc64/strcpy.S
@@ -22,25 +22,38 @@
 
 /* char * [r3] strcpy (char *dest [r3], const char *src [r4])  */
 
-EALIGN (strcpy, 4, 0)
+#ifdef USE_AS_STPCPY
+# define FUNC_NAME __stpcpy
+#else
+# define FUNC_NAME strcpy
+#endif
+
+EALIGN (FUNC_NAME, 4, 0)
 	CALL_MCOUNT 2
 
 #define rTMP	r0
-#define rRTN	r3	/* incoming DEST arg preserved as result */
-#define rSRC	r4	/* pointer to previous word in src */
-#define rDEST	r5	/* pointer to previous word in dest */
+#ifdef USE_AS_STPCPY
+#define rRTN    r3      /* pointer to previous word/doubleword in dest */
+#else
+#define rRTN    r12     /* pointer to previous word/doubleword in dest */
+#endif
+#define rSRC	r4	/* pointer to previous word/doubleword in src */
 #define rWORD	r6	/* current word from src */
-#define rFEFE	r7	/* constant 0xfefefefefefefeff (-0x0101010101010101) */
-#define r7F7F	r8	/* constant 0x7f7f7f7f7f7f7f7f */
-#define rNEG	r9	/* ~(word in s1 | 0x7f7f7f7f7f7f7f7f) */
+#define rFEFE	r7	/* constant 0xfefefeff | 0xfefefefefefefeff */
+#define r7F7F	r8	/* constant 0x7f7f7f7f | 0x7f7f7f7f7f7f7f7f */
+#define rNEG	r9	/* ~(word in s1 | r7F7F) */
 #define rALT	r10	/* alternate word from src */
 
-	dcbt	0,rSRC
+#ifndef USE_AS_STPCPY
+/* Save the dst pointer to use as return value.  */
+	mr      rRTN, r3
+#endif
 	or	rTMP, rSRC, rRTN
 	clrldi.	rTMP, rTMP, 61
-	addi	rDEST, rRTN, -8
-	dcbtst	0,rRTN
-	bne	L(unaligned)
+	bne	L(check_word_alignment)
+
+/* For doubleword aligned memory, operate using doubleword load and stores.  */
+	addi	rRTN, rRTN, -8
 
 	lis	rFEFE, -0x101
 	lis	r7F7F, 0x7f7f
@@ -53,13 +66,13 @@ EALIGN (strcpy, 4, 0)
 	b	L(g2)
 
 L(g0):	ldu	rALT, 8(rSRC)
-	stdu	rWORD, 8(rDEST)
+	stdu	rWORD, 8(rRTN)
 	add	rTMP, rFEFE, rALT
 	nor	rNEG, r7F7F, rALT
 	and.	rTMP, rTMP, rNEG
 	bne-	L(g1)
 	ldu	rWORD, 8(rSRC)
-	stdu	rALT, 8(rDEST)
+	stdu	rALT, 8(rRTN)
 L(g2):	add	rTMP, rFEFE, rWORD
 	nor	rNEG, r7F7F, rWORD
 	and.	rTMP, rTMP, rNEG
@@ -70,77 +83,134 @@ L(g2):	add	rTMP, rFEFE, rWORD
 L(g1):
 #ifdef __LITTLE_ENDIAN__
 	extrdi.	rTMP, rALT, 8, 56
-	stb	rALT, 8(rDEST)
+	stbu	rALT, 8(rRTN)
 	beqlr-
 	extrdi.	rTMP, rALT, 8, 48
-	stb	rTMP, 9(rDEST)
+	stbu	rTMP, 1(rRTN)
 	beqlr-
 	extrdi.	rTMP, rALT, 8, 40
-	stb	rTMP, 10(rDEST)
+	stbu	rTMP, 1(rRTN)
 	beqlr-
 	extrdi.	rTMP, rALT, 8, 32
-	stb	rTMP, 11(rDEST)
+	stbu	rTMP, 1(rRTN)
 	beqlr-
 	extrdi.	rTMP, rALT, 8, 24
-	stb	rTMP, 12(rDEST)
+	stbu	rTMP, 1(rRTN)
 	beqlr-
 	extrdi.	rTMP, rALT, 8, 16
-	stb	rTMP, 13(rDEST)
+	stbu	rTMP, 1(rRTN)
 	beqlr-
 	extrdi.	rTMP, rALT, 8, 8
-	stb	rTMP, 14(rDEST)
+	stbu	rTMP, 1(rRTN)
 	beqlr-
 	extrdi	rTMP, rALT, 8, 0
-	stb	rTMP, 15(rDEST)
-	blr
+	stbu	rTMP, 1(rRTN)
 #else
 	extrdi.	rTMP, rALT, 8, 0
-	stb	rTMP, 8(rDEST)
+	stbu	rTMP, 8(rRTN)
 	beqlr-
 	extrdi.	rTMP, rALT, 8, 8
-	stb	rTMP, 9(rDEST)
+	stbu	rTMP, 1(rRTN)
 	beqlr-
 	extrdi.	rTMP, rALT, 8, 16
-	stb	rTMP, 10(rDEST)
+	stbu	rTMP, 1(rRTN)
 	beqlr-
 	extrdi.	rTMP, rALT, 8, 24
-	stb	rTMP, 11(rDEST)
+	stbu	rTMP, 1(rRTN)
 	beqlr-
 	extrdi.	rTMP, rALT, 8, 32
-	stb	rTMP, 12(rDEST)
-	beqlr-
+	stbu	rTMP, 1(rRTN)
+	beqlr
 	extrdi.	rTMP, rALT, 8, 40
-	stb	rTMP, 13(rDEST)
+	stbu	rTMP, 1(rRTN)
 	beqlr-
 	extrdi.	rTMP, rALT, 8, 48
-	stb	rTMP, 14(rDEST)
+	stbu	rTMP, 1(rRTN)
 	beqlr-
-	stb	rALT, 15(rDEST)
+	stbu	rALT, 1(rRTN)
+#endif
 	blr
+
+L(check_word_alignment):
+	clrldi. rTMP, rTMP, 62
+	bne     L(unaligned)
+
+/* For word aligned memory, operate using word load and stores.  */
+	addi	rRTN, rRTN, -4
+
+	lis	rFEFE, -0x101
+	lis	r7F7F, 0x7f7f
+	lwz	rWORD, 0(rSRC)
+	addi	rFEFE, rFEFE, -0x101
+	addi	r7F7F, r7F7F, 0x7f7f
+	b	L(g5)
+
+L(g3):	lwzu	rALT, 4(rSRC)
+	stwu	rWORD, 4(rRTN)
+	add	rTMP, rFEFE, rALT
+	nor	rNEG, r7F7F, rALT
+	and.	rTMP, rTMP, rNEG
+	bne-	L(g4)
+	lwzu	rWORD, 4(rSRC)
+	stwu	rALT, 4(rRTN)
+L(g5):	add	rTMP, rFEFE, rWORD
+	nor	rNEG, r7F7F, rWORD
+	and.	rTMP, rTMP, rNEG
+	beq+	L(g3)
+
+	mr	rALT, rWORD
+/* We've hit the end of the string.  Do the rest byte-by-byte.  */
+L(g4):
+#ifdef __LITTLE_ENDIAN__
+	rlwinm.	rTMP, rALT, 0, 24, 31
+	stbu	rALT, 4(rRTN)
+	beqlr-
+	rlwinm.	rTMP, rALT, 24, 24, 31
+	stbu	rTMP, 1(rRTN)
+	beqlr-
+	rlwinm.	rTMP, rALT, 16, 24, 31
+	stbu	rTMP, 1(rRTN)
+	beqlr-
+	rlwinm	rTMP, rALT, 8, 24, 31
+	stbu	rTMP, 1(rRTN)
+#else
+	rlwinm.	rTMP, rALT, 8, 24, 31
+	stbu	rTMP, 4(rRTN)
+	beqlr-
+	rlwinm.	rTMP, rALT, 16, 24, 31
+	stbu	rTMP, 1(rRTN)
+	beqlr-
+	rlwinm.	rTMP, rALT, 24, 24, 31
+	stbu	rTMP, 1(rRTN)
+	beqlr-
+	stbu	rALT, 1(rRTN)
 #endif
+	blr
 
 /* Oh well.  In this case, we just do a byte-by-byte copy.  */
 	.align 4
 	nop
 L(unaligned):
 	lbz	rWORD, 0(rSRC)
-	addi	rDEST, rRTN, -1
+	addi	rRTN, rRTN, -1
 	cmpwi	rWORD, 0
 	beq-	L(u2)
 
 L(u0):	lbzu	rALT, 1(rSRC)
-	stbu	rWORD, 1(rDEST)
+	stbu	rWORD, 1(rRTN)
 	cmpwi	rALT, 0
 	beq-	L(u1)
 	nop		/* Let 601 load start of loop.  */
 	lbzu	rWORD, 1(rSRC)
-	stbu	rALT, 1(rDEST)
+	stbu	rALT, 1(rRTN)
 	cmpwi	rWORD, 0
 	bne+	L(u0)
-L(u2):	stb	rWORD, 1(rDEST)
+L(u2):	stbu	rWORD, 1(rRTN)
 	blr
-L(u1):	stb	rALT, 1(rDEST)
+L(u1):	stbu	rALT, 1(rRTN)
 	blr
+END (FUNC_NAME)
 
-END (strcpy)
+#ifndef USE_AS_STPCPY
 libc_hidden_builtin_def (strcpy)
+#endif

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=6f4b109567445b1ed70300bb0cb1752cb9998ec9

commit 6f4b109567445b1ed70300bb0cb1752cb9998ec9
Author: Siddhesh Poyarekar <siddhesh@redhat.com>
Date:   Fri Oct 25 10:22:12 2013 +0530

    Fix stack overflow due to large AF_INET6 requests
    
    Resolves #16072 (CVE-2013-4458).
    
    This patch fixes another stack overflow in getaddrinfo when it is
    called with AF_INET6.  The AF_UNSPEC case was fixed as CVE-2013-1914,
    but the AF_INET6 case went undetected back then.

diff --git a/ChangeLog b/ChangeLog
index b970fe1..0afcd3f 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,6 @@
-2013-10-10  Joseph Myers  <joseph@codsourcery.com>
+2013-10-25  Siddhesh Poyarekar  <siddhesh@redhat.com>
 
+<<<<<<< HEAD
 	* sysdeps/ieee754/ldbl-128ibm/e_acosl.c (__ieee754_acosl): Check
 	for NaNs before doing comparisons on argument.
 	* sysdeps/ieee754/ldbl-128ibm/e_asinl.c (__ieee754_asinl):
@@ -490,8 +491,12 @@
 
 	* sysdeps/unix/sysv/linux/tst-fanotify.c: New test.
 	* sysdeps/unix/sysv/linux/Makefile (tests): Add tst-fanotify.
+=======
+	[BZ #16072]
+	* sysdeps/posix/getaddrinfo.c (gethosts): Allocate tmpbuf on
+	heap for large requests.
+>>>>>>> 6f95434... Fix stack overflow due to large AF_INET6 requests
 
->>>>>>> ffa3cd7... Fix lgammaf spurious underflow (bug 15427).
 2013-09-02  Joseph Myers  <joseph@codesourcery.com>
 
 	[BZ #14155]
diff --git a/NEWS b/NEWS
index b25af8e..c70f333 100644
--- a/NEWS
+++ b/NEWS
@@ -10,11 +10,14 @@ Version 2.18.1
 * The following bugs are resolved with this release:
 
   14155, 14699, 15532, 15427, 15522, 15797, 15892, 15895, 15909, 15996,
-  16150.
+  16072, 16150.
 
 * CVE-2013-4237 The readdir_r function could write more than NAME_MAX bytes
   to the d_name member of struct dirent, or omit the terminating NUL
   character.  (Bugzilla #14699).
+
+* CVE-2013-4458 Stack overflow in getaddrinfo with large number of results
+  for AF_INET6 has been fixed (Bugzilla #16072).
 
 Version 2.18
 
diff --git a/sysdeps/posix/getaddrinfo.c b/sysdeps/posix/getaddrinfo.c
index 7bb3ded..2e97255 100644
--- a/sysdeps/posix/getaddrinfo.c
+++ b/sysdeps/posix/getaddrinfo.c
@@ -197,7 +197,22 @@ gaih_inet_serv (const char *servicename, const struct gaih_typeproto *tp,
 				&rc, &herrno, NULL, &localcanon));	      \
     if (rc != ERANGE || herrno != NETDB_INTERNAL)			      \
       break;								      \
-    tmpbuf = extend_alloca (tmpbuf, tmpbuflen, 2 * tmpbuflen);		      \
+    if (!malloc_tmpbuf && __libc_use_alloca (alloca_used + 2 * tmpbuflen))    \
+      tmpbuf = extend_alloca_account (tmpbuf, tmpbuflen, 2 * tmpbuflen,	      \
+				      alloca_used);			      \
+    else								      \
+      {									      \
+	char *newp = realloc (malloc_tmpbuf ? tmpbuf : NULL,		      \
+			      2 * tmpbuflen);				      \
+	if (newp == NULL)						      \
+	  {								      \
+	    result = -EAI_MEMORY;					      \
+	    goto free_and_return;					      \
+	  }								      \
+	tmpbuf = newp;							      \
+	malloc_tmpbuf = true;						      \
+	tmpbuflen = 2 * tmpbuflen;					      \
+      }									      \
   }									      \
   if (status == NSS_STATUS_SUCCESS && rc == 0)				      \
     h = &th;								      \
@@ -209,7 +224,8 @@ gaih_inet_serv (const char *servicename, const struct gaih_typeproto *tp,
 	{								      \
 	  __set_h_errno (herrno);					      \
 	  _res.options |= old_res_options & RES_USE_INET6;		      \
-	  return -EAI_SYSTEM;						      \
+	  result = -EAI_SYSTEM;						      \
+	  goto free_and_return;						      \
 	}								      \
       if (herrno == TRY_AGAIN)						      \
 	no_data = EAI_AGAIN;						      \

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=52aafee302d34ddd2afb6bea31d838e61555e154

commit 52aafee302d34ddd2afb6bea31d838e61555e154
Author: Joseph Myers <joseph@codesourcery.com>
Date:   Thu Oct 10 19:11:30 2013 +0000

    Avoid ordered comparisons of NaNs in ldbl-128ibm acosl and asinl.

diff --git a/ChangeLog b/ChangeLog
index bf099c9..b970fe1 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2013-10-10  Joseph Myers  <joseph@codsourcery.com>
+
+	* sysdeps/ieee754/ldbl-128ibm/e_acosl.c (__ieee754_acosl): Check
+	for NaNs before doing comparisons on argument.
+	* sysdeps/ieee754/ldbl-128ibm/e_asinl.c (__ieee754_asinl):
+	Likewise.
+
 2013-10-04  Alan Modra  <amodra@gmail.com>
 
 	* sysdeps/powerpc/powerpc32/dl-machine.c (__process_machine_rela):
diff --git a/sysdeps/ieee754/ldbl-128ibm/e_acosl.c b/sysdeps/ieee754/ldbl-128ibm/e_acosl.c
index 8663993..2cb2882 100644
--- a/sysdeps/ieee754/ldbl-128ibm/e_acosl.c
+++ b/sysdeps/ieee754/ldbl-128ibm/e_acosl.c
@@ -153,6 +153,8 @@ __ieee754_acosl (long double x)
 {
   long double a, z, r, w, p, q, s, t, f2;
 
+  if (__glibc_unlikely (__isnanl (x)))
+    return x + x;
   a = __builtin_fabsl (x);
   if (a == 1.0L)
     {
diff --git a/sysdeps/ieee754/ldbl-128ibm/e_asinl.c b/sysdeps/ieee754/ldbl-128ibm/e_asinl.c
index 99a5b85..dece118 100644
--- a/sysdeps/ieee754/ldbl-128ibm/e_asinl.c
+++ b/sysdeps/ieee754/ldbl-128ibm/e_asinl.c
@@ -134,6 +134,8 @@ __ieee754_asinl (long double x)
   long double a, t, w, p, q, c, r, s;
   int flag;
 
+  if (__glibc_unlikely (__isnanl (x)))
+    return x + x;
   flag = 0;
   a = __builtin_fabsl (x);
   if (a == 1.0L)	/* |x|>= 1 */

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=6c02f0569e758cd1973797c4a46b8c74425e3b72

commit 6c02f0569e758cd1973797c4a46b8c74425e3b72
Author: Alan Modra <amodra@gmail.com>
Date:   Fri Oct 4 12:48:51 2013 +0930

    Use stdint.h types in union unaligned.
    
    	* sysdeps/powerpc/powerpc32/dl-machine.c (__process_machine_rela):
    	Use stdint types in rather than __attribute__((mode())).
    	* sysdeps/powerpc/powerpc64/dl-machine.h (elf_machine_rela): Likewise.

diff --git a/ChangeLog b/ChangeLog
index a961126..bf099c9 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,6 +1,12 @@
 2013-10-04  Alan Modra  <amodra@gmail.com>
 
 	* sysdeps/powerpc/powerpc32/dl-machine.c (__process_machine_rela):
+	Use stdint types in rather than __attribute__((mode())).
+	* sysdeps/powerpc/powerpc64/dl-machine.h (elf_machine_rela): Likewise.
+
+2013-10-04  Alan Modra  <amodra@gmail.com>
+
+	* sysdeps/powerpc/powerpc32/dl-machine.c (__process_machine_rela):
 	Correct handling of unaligned relocs for little-endian.
 	* sysdeps/powerpc/powerpc64/dl-machine.h (elf_machine_rela): Likewise.
 
diff --git a/sysdeps/powerpc/powerpc32/dl-machine.c b/sysdeps/powerpc/powerpc32/dl-machine.c
index ec64951..df8c14e 100644
--- a/sysdeps/powerpc/powerpc32/dl-machine.c
+++ b/sysdeps/powerpc/powerpc32/dl-machine.c
@@ -425,8 +425,8 @@ __process_machine_rela (struct link_map *map,
 {
   union unaligned
     {
-      unsigned u2 __attribute__ ((mode (HI)));
-      unsigned u4 __attribute__ ((mode (SI)));
+      uint16_t u2;
+      uint32_t u4;
     } __attribute__((__packed__));
 
   switch (rinfo)
diff --git a/sysdeps/powerpc/powerpc64/dl-machine.h b/sysdeps/powerpc/powerpc64/dl-machine.h
index b69a1ce..18cf157 100644
--- a/sysdeps/powerpc/powerpc64/dl-machine.h
+++ b/sysdeps/powerpc/powerpc64/dl-machine.h
@@ -563,10 +563,10 @@ elf_machine_rela (struct link_map *map,
   const Elf64_Sym *const refsym = sym;
   union unaligned
     {
-      unsigned u2 __attribute__ ((mode (HI)));
-      unsigned u4 __attribute__ ((mode (SI)));
-      unsigned u8 __attribute__ ((mode (DI)));
-    } __attribute__((__packed__));
+      uint16_t u2;
+      uint32_t u4;
+      uint64_t u8;
+    } __attribute__ ((__packed__));
 
   if (r_type == R_PPC64_RELATIVE)
     {

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=723630a980657c4c88193448f7b4b6bf09128fda

commit 723630a980657c4c88193448f7b4b6bf09128fda
Author: Alan Modra <amodra@gmail.com>
Date:   Thu Oct 3 13:51:52 2013 +0930

    Correct little-endian relocation of UADDR64,32,16.
    
    	* sysdeps/powerpc/powerpc32/dl-machine.c (__process_machine_rela):
    	Correct handling of unaligned relocs for little-endian.
    	* sysdeps/powerpc/powerpc64/dl-machine.h (elf_machine_rela): Likewise.

diff --git a/ChangeLog b/ChangeLog
index 0c727fa..a961126 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,11 @@
 2013-10-04  Alan Modra  <amodra@gmail.com>
 
+	* sysdeps/powerpc/powerpc32/dl-machine.c (__process_machine_rela):
+	Correct handling of unaligned relocs for little-endian.
+	* sysdeps/powerpc/powerpc64/dl-machine.h (elf_machine_rela): Likewise.
+
+2013-10-04  Alan Modra  <amodra@gmail.com>
+
 	* configure.in: Map powerpc64le and powerpcle to base_machine/machine.
 	* configure: Regenerate.
 	* nptl/shlib-versions: Powerpc*le starts at 2.18.
diff --git a/sysdeps/powerpc/powerpc32/dl-machine.c b/sysdeps/powerpc/powerpc32/dl-machine.c
index 188f72c..ec64951 100644
--- a/sysdeps/powerpc/powerpc32/dl-machine.c
+++ b/sysdeps/powerpc/powerpc32/dl-machine.c
@@ -423,6 +423,12 @@ __process_machine_rela (struct link_map *map,
 			Elf32_Addr const finaladdr,
 			int rinfo)
 {
+  union unaligned
+    {
+      unsigned u2 __attribute__ ((mode (HI)));
+      unsigned u4 __attribute__ ((mode (SI)));
+    } __attribute__((__packed__));
+
   switch (rinfo)
     {
     case R_PPC_NONE:
@@ -439,10 +445,7 @@ __process_machine_rela (struct link_map *map,
       return;
 
     case R_PPC_UADDR32:
-      ((char *) reloc_addr)[0] = finaladdr >> 24;
-      ((char *) reloc_addr)[1] = finaladdr >> 16;
-      ((char *) reloc_addr)[2] = finaladdr >> 8;
-      ((char *) reloc_addr)[3] = finaladdr;
+      ((union unaligned *) reloc_addr)->u4 = finaladdr;
       break;
 
     case R_PPC_ADDR24:
@@ -460,8 +463,7 @@ __process_machine_rela (struct link_map *map,
     case R_PPC_UADDR16:
       if (__builtin_expect (finaladdr > 0x7fff && finaladdr < 0xffff8000, 0))
 	_dl_reloc_overflow (map,  "R_PPC_UADDR16", reloc_addr, refsym);
-      ((char *) reloc_addr)[0] = finaladdr >> 8;
-      ((char *) reloc_addr)[1] = finaladdr;
+      ((union unaligned *) reloc_addr)->u2 = finaladdr;
       break;
 
     case R_PPC_ADDR16_LO:
diff --git a/sysdeps/powerpc/powerpc64/dl-machine.h b/sysdeps/powerpc/powerpc64/dl-machine.h
index 059fdaf..b69a1ce 100644
--- a/sysdeps/powerpc/powerpc64/dl-machine.h
+++ b/sysdeps/powerpc/powerpc64/dl-machine.h
@@ -561,6 +561,12 @@ elf_machine_rela (struct link_map *map,
   Elf64_Addr *const reloc_addr = reloc_addr_arg;
   const int r_type = ELF64_R_TYPE (reloc->r_info);
   const Elf64_Sym *const refsym = sym;
+  union unaligned
+    {
+      unsigned u2 __attribute__ ((mode (HI)));
+      unsigned u4 __attribute__ ((mode (SI)));
+      unsigned u8 __attribute__ ((mode (DI)));
+    } __attribute__((__packed__));
 
   if (r_type == R_PPC64_RELATIVE)
     {
@@ -741,23 +747,11 @@ elf_machine_rela (struct link_map *map,
       return;
 
     case R_PPC64_UADDR64:
-      /* We are big-endian.  */
-      ((char *) reloc_addr_arg)[0] = (value >> 56) & 0xff;
-      ((char *) reloc_addr_arg)[1] = (value >> 48) & 0xff;
-      ((char *) reloc_addr_arg)[2] = (value >> 40) & 0xff;
-      ((char *) reloc_addr_arg)[3] = (value >> 32) & 0xff;
-      ((char *) reloc_addr_arg)[4] = (value >> 24) & 0xff;
-      ((char *) reloc_addr_arg)[5] = (value >> 16) & 0xff;
-      ((char *) reloc_addr_arg)[6] = (value >> 8) & 0xff;
-      ((char *) reloc_addr_arg)[7] = (value >> 0) & 0xff;
+      ((union unaligned *) reloc_addr)->u8 = value;
       return;
 
     case R_PPC64_UADDR32:
-      /* We are big-endian.  */
-      ((char *) reloc_addr_arg)[0] = (value >> 24) & 0xff;
-      ((char *) reloc_addr_arg)[1] = (value >> 16) & 0xff;
-      ((char *) reloc_addr_arg)[2] = (value >> 8) & 0xff;
-      ((char *) reloc_addr_arg)[3] = (value >> 0) & 0xff;
+      ((union unaligned *) reloc_addr)->u4 = value;
       return;
 
     case R_PPC64_ADDR32:
@@ -781,10 +775,8 @@ elf_machine_rela (struct link_map *map,
     case R_PPC64_UADDR16:
       if (dont_expect ((value + 0x8000) >= 0x10000))
 	_dl_reloc_overflow (map, "R_PPC64_UADDR16", reloc_addr, refsym);
-      /* We are big-endian.  */
-      ((char *) reloc_addr_arg)[0] = (value >> 8) & 0xff;
-      ((char *) reloc_addr_arg)[1] = (value >> 0) & 0xff;
-      break;
+      ((union unaligned *) reloc_addr)->u2 = value;
+      return;
 
     case R_PPC64_ADDR16_DS:
       if (dont_expect ((value + 0x8000) >= 0x10000 || (value & 3) != 0))

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=cde0ef248c7566567e7461e58e0b91707fe2330c

commit cde0ef248c7566567e7461e58e0b91707fe2330c
Author: Alan Modra <amodra@gmail.com>
Date:   Thu Oct 3 14:03:03 2013 +0930

    PowerPC LE configury
    http://sourceware.org/ml/libc-alpha/2013-08/msg00096.html
    
    This adds the basic configury bits for powerpc64le and powerpcle.
    
    	* configure.in: Map powerpc64le and powerpcle to base_machine/machine.
    	* configure: Regenerate.
    	* nptl/shlib-versions: Powerpc*le starts at 2.18.
    	* shlib-versions: Likewise.

diff --git a/ChangeLog b/ChangeLog
index f1aaebf..0c727fa 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,12 @@
 2013-10-04  Alan Modra  <amodra@gmail.com>
 
+	* configure.in: Map powerpc64le and powerpcle to base_machine/machine.
+	* configure: Regenerate.
+	* nptl/shlib-versions: Powerpc*le starts at 2.18.
+	* shlib-versions: Likewise.
+
+2013-10-04  Alan Modra  <amodra@gmail.com>
+
 	* string/tester.c (test_memrchr): Increment reported test cycle.
 
 2013-10-04  Alan Modra  <amodra@gmail.com>
diff --git a/configure b/configure
index 1ee4c42..e8a581c 100755
--- a/configure
+++ b/configure
@@ -3969,8 +3969,8 @@ fi
 # base_machine, we don't change it.
 test -n "$base_machine" || case "$machine" in
 i[4567]86)	base_machine=i386 machine=i386/$machine ;;
-powerpc)	base_machine=powerpc machine=powerpc/powerpc32 ;;
-powerpc64)	base_machine=powerpc machine=powerpc/powerpc64 ;;
+powerpc64*)	base_machine=powerpc machine=powerpc/powerpc64 ;;
+powerpc*)	base_machine=powerpc machine=powerpc/powerpc32 ;;
 s390)           base_machine=s390 machine=s390/s390-32 ;;
 s390x)          base_machine=s390 machine=s390/s390-64 ;;
 sh3*)		base_machine=sh machine=sh/sh3 ;;
diff --git a/configure.in b/configure.in
index 769e8ef..848870b 100644
--- a/configure.in
+++ b/configure.in
@@ -587,8 +587,8 @@ changequote(,)dnl
 # base_machine, we don't change it.
 test -n "$base_machine" || case "$machine" in
 i[4567]86)	base_machine=i386 machine=i386/$machine ;;
-powerpc)	base_machine=powerpc machine=powerpc/powerpc32 ;;
-powerpc64)	base_machine=powerpc machine=powerpc/powerpc64 ;;
+powerpc64*)	base_machine=powerpc machine=powerpc/powerpc64 ;;
+powerpc*)	base_machine=powerpc machine=powerpc/powerpc32 ;;
 s390)           base_machine=s390 machine=s390/s390-32 ;;
 s390x)          base_machine=s390 machine=s390/s390-64 ;;
 sh3*)		base_machine=sh machine=sh/sh3 ;;
diff --git a/nptl/shlib-versions b/nptl/shlib-versions
index e49e7ca..495b240 100644
--- a/nptl/shlib-versions
+++ b/nptl/shlib-versions
@@ -2,4 +2,5 @@ sparc64.*-.*-linux.*	libpthread=0		GLIBC_2.2
 sh.*-.*-linux.*		libpthread=0		GLIBC_2.2
 s390x-.*-linux.*	libpthread=0		GLIBC_2.2
 powerpc64-.*-linux.*	libpthread=0		GLIBC_2.3
+powerpc.*le-.*-linux.*	libpthread=0		GLIBC_2.18
 .*-.*-linux.*		libpthread=0
diff --git a/shlib-versions b/shlib-versions
index 9344590..51f5327 100644
--- a/shlib-versions
+++ b/shlib-versions
@@ -23,6 +23,7 @@
 
 s390x-.*-linux.*        DEFAULT			GLIBC_2.2
 powerpc64-.*-linux.*	DEFAULT			GLIBC_2.3
+powerpc.*le-.*-linux.*	DEFAULT			GLIBC_2.18
 .*-.*-gnu-gnu.*		DEFAULT			GLIBC_2.2.6
 
 # Configuration		ABI			Identifier for ABI data files

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=126904dbbf11a7d6692a7286414ab93d72fe16cd

commit 126904dbbf11a7d6692a7286414ab93d72fe16cd
Author: Alan Modra <amodra@gmail.com>
Date:   Sat Aug 17 18:38:26 2013 +0930

    string/tester memrchr test
    http://sourceware.org/ml/libc-alpha/2013-08/msg00095.html
    
    I found this useful at one stage when I was seeing a huge number of
    memrchr failures all of test number 10.
    
    	* string/tester.c (test_memrchr): Increment reported test cycle.

diff --git a/ChangeLog b/ChangeLog
index eae9d39..f1aaebf 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,9 @@
 2013-10-04  Alan Modra  <amodra@gmail.com>
 
+	* string/tester.c (test_memrchr): Increment reported test cycle.
+
+2013-10-04  Alan Modra  <amodra@gmail.com>
+
 	* string/test-memcpy.c (do_one_test): When reporting errors, print
 	string address and don't overrun end of string.
 
diff --git a/string/tester.c b/string/tester.c
index 2fe520c..f1ea438 100644
--- a/string/tester.c
+++ b/string/tester.c
@@ -704,7 +704,7 @@ test_memrchr (void)
      more than 128 byte chunks: */
   {
     char buf[128 + sizeof(long)];
-    long align, len, i, pos;
+    long align, len, i, pos, n = 9;
 
     for (align = 0; align < (long) sizeof(long); ++align) {
       for (len = 0; len < (long) (sizeof(buf) - align); ++len) {
@@ -715,9 +715,9 @@ test_memrchr (void)
 #if 0
 	  printf("align %d, len %d, pos %d\n", align, len, pos);
 #endif
-	  check(memrchr(buf + align, 'x', len) == buf + align + pos, 9);
+	  check(memrchr(buf + align, 'x', len) == buf + align + pos, n++);
 	  check(memrchr(buf + align + pos + 1, 'x', len - (pos + 1)) == NULL,
-		10);
+		n++);
 	  buf[align + pos] = '-';
 	}
       }

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=b921c5bc50a863b130fda0c9e7d5f50e6a4783ee

commit b921c5bc50a863b130fda0c9e7d5f50e6a4783ee
Author: Alan Modra <amodra@gmail.com>
Date:   Sat Aug 17 18:37:58 2013 +0930

    string/test-memcpy error reporting
    http://sourceware.org/ml/libc-alpha/2013-08/msg00094.html
    
    Using plain %s here runs the risk of segfaulting when displaying the
    string.  src and dst aren't zero terminated strings.
    
    	* string/test-memcpy.c (do_one_test): When reporting errors, print
    	string address and don't overrun end of string.

diff --git a/ChangeLog b/ChangeLog
index 888c7d9..eae9d39 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,10 @@
 2013-10-04  Alan Modra  <amodra@gmail.com>
 
+	* string/test-memcpy.c (do_one_test): When reporting errors, print
+	string address and don't overrun end of string.
+
+2013-10-04  Alan Modra  <amodra@gmail.com>
+
 	* sysdeps/powerpc/powerpc64/power7/memchr.S: Replace rlwimi with
 	insrdi.  Make better use of reg selection to speed exit slightly.
 	Schedule entry path a little better.  Remove useless "are we done"
diff --git a/string/test-memcpy.c b/string/test-memcpy.c
index d121ef0..b7ebe5f 100644
--- a/string/test-memcpy.c
+++ b/string/test-memcpy.c
@@ -63,8 +63,8 @@ do_one_test (impl_t *impl, char *dst, const char *src,
 
   if (memcmp (dst, src, len) != 0)
     {
-      error (0, 0, "Wrong result in function %s dst \"%s\" src \"%s\"",
-	     impl->name, dst, src);
+      error (0, 0, "Wrong result in function %s dst %p \"%.*s\" src %p \"%.*s\" len %zu",
+	     impl->name, dst, (int) len, dst, src, (int) len, src, len);
       ret = 1;
       return;
     }

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=01f25c0e1c5f1f49df18c5f3f67c873ce1739481

commit 01f25c0e1c5f1f49df18c5f3f67c873ce1739481
Author: Alan Modra <amodra@gmail.com>
Date:   Sat Aug 17 18:48:36 2013 +0930

    PowerPC LE memchr and memrchr
    http://sourceware.org/ml/libc-alpha/2013-08/msg00105.html
    
    Like strnlen, memchr and memrchr had a number of defects fixed by this
    patch as well as adding little-endian support.  The first one I
    noticed was that the entry to the main loop needlessly checked for
    "are we done yet?" when we know the size is large enough that we can't
    be done.  The second defect I noticed was that the main loop count was
    wrong, which in turn meant that the small loop needed to handle an
    extra word.  Thirdly, there is nothing to say that the string can't
    wrap around zero, except of course that we'd normally hit a segfault
    on trying to read from address zero.  Fixing that simplified a number
    of places:
    
    -	/* Are we done already?  */
    -	addi    r9,r8,8
    -	cmpld	r9,r7
    -	bge	L(null)
    
    becomes
    
    +	cmpld	r8,r7
    +	beqlr
    
    However, the exit gets an extra test because I test for being on the
    last word then if so whether the byte offset is less than the end.
    Overall, the change is a win.
    
    Lastly, memrchr used the wrong cache hint.
    
    	* sysdeps/powerpc/powerpc64/power7/memchr.S: Replace rlwimi with
    	insrdi.  Make better use of reg selection to speed exit slightly.
    	Schedule entry path a little better.  Remove useless "are we done"
    	checks on entry to main loop.  Handle wrapping around zero address.
    	Correct main loop count.  Handle single left-over word from main
    	loop inline rather than by using loop_small.  Remove extra word
    	case in loop_small caused by wrong loop count.  Add little-endian
    	support.
    	* sysdeps/powerpc/powerpc32/power7/memchr.S: Likewise.
    	* sysdeps/powerpc/powerpc64/power7/memrchr.S: Likewise.  Use proper
    	cache hint.
    	* sysdeps/powerpc/powerpc32/power7/memrchr.S: Likewise.
    	* sysdeps/powerpc/powerpc64/power7/rawmemchr.S: Add little-endian
    	support.  Avoid rlwimi.
    	* sysdeps/powerpc/powerpc32/power7/rawmemchr.S: Likewise.

diff --git a/ChangeLog b/ChangeLog
index 99d2b70..888c7d9 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,23 @@
 2013-10-04  Alan Modra  <amodra@gmail.com>
 
+	* sysdeps/powerpc/powerpc64/power7/memchr.S: Replace rlwimi with
+	insrdi.  Make better use of reg selection to speed exit slightly.
+	Schedule entry path a little better.  Remove useless "are we done"
+	checks on entry to main loop.  Handle wrapping around zero address.
+	Correct main loop count.  Handle single left-over word from main
+	loop inline rather than by using loop_small.  Remove extra word
+	case in loop_small caused by wrong loop count.  Add little-endian
+	support.
+	* sysdeps/powerpc/powerpc32/power7/memchr.S: Likewise.
+	* sysdeps/powerpc/powerpc64/power7/memrchr.S: Likewise.  Use proper
+	cache hint.
+	* sysdeps/powerpc/powerpc32/power7/memrchr.S: Likewise.
+	* sysdeps/powerpc/powerpc64/power7/rawmemchr.S: Add little-endian
+	support.  Avoid rlwimi.
+	* sysdeps/powerpc/powerpc32/power7/rawmemchr.S: Likewise.
+
+2013-10-04  Alan Modra  <amodra@gmail.com>
+
 	* sysdeps/powerpc/powerpc64/memset.S: Replace rlwimi with
         insrdi.  Formatting.
 	* sysdeps/powerpc/powerpc64/power4/memset.S: Likewise.
diff --git a/sysdeps/powerpc/powerpc32/power7/memchr.S b/sysdeps/powerpc/powerpc32/power7/memchr.S
index 369e5e0..85754f3 100644
--- a/sysdeps/powerpc/powerpc32/power7/memchr.S
+++ b/sysdeps/powerpc/powerpc32/power7/memchr.S
@@ -25,107 +25,111 @@ ENTRY (__memchr)
 	CALL_MCOUNT
 	dcbt	0,r3
 	clrrwi  r8,r3,2
-	rlwimi	r4,r4,8,16,23
-	rlwimi	r4,r4,16,0,15
+	insrdi	r4,r4,8,48
 	add	r7,r3,r5      /* Calculate the last acceptable address.  */
+	insrdi	r4,r4,16,32
 	cmplwi	r5,16
+	li	r9, -1
+	rlwinm	r6,r3,3,27,28 /* Calculate padding.  */
+	addi	r7,r7,-1
+#ifdef __LITTLE_ENDIAN__
+	slw	r9,r9,r6
+#else
+	srw	r9,r9,r6
+#endif
 	ble	L(small_range)
 
-	cmplw	cr7,r3,r7     /* Compare the starting address (r3) with the
-				 ending address (r7).  If (r3 >= r7), the size
-				 passed in is zero or negative.  */
-	ble	cr7,L(proceed)
-
-	li	r7,-1	      /* Artificially set our ending address (r7)
-				 such that we will exit early. */
-L(proceed):
-	rlwinm	r6,r3,3,27,28 /* Calculate padding.  */
-	cmpli	cr6,r6,0      /* cr6 == Do we have padding?  */
 	lwz	r12,0(r8)     /* Load word from memory.  */
-	cmpb	r10,r12,r4    /* Check for BYTEs in WORD1.  */
-	beq	cr6,L(proceed_no_padding)
-	slw	r10,r10,r6
-	srw	r10,r10,r6
-L(proceed_no_padding):
-	cmplwi	cr7,r10,0     /* If r10 == 0, no BYTEs have been found.  */
+	cmpb	r3,r12,r4     /* Check for BYTEs in WORD1.  */
+	and	r3,r3,r9
+	clrlwi	r5,r7,30      /* Byte count - 1 in last word.  */
+	clrrwi	r7,r7,2       /* Address of last word.  */
+	cmplwi	cr7,r3,0      /* If r3 == 0, no BYTEs have been found.  */
 	bne	cr7,L(done)
 
-	/* Are we done already?  */
-	addi	r9,r8,4
-	cmplw	cr6,r9,r7
-	bge	cr6,L(null)
-
 	mtcrf   0x01,r8
 	/* Are we now aligned to a doubleword boundary?  If so, skip to
 	   the main loop.  Otherwise, go through the alignment code.  */
-
 	bt	29,L(loop_setup)
 
 	/* Handle WORD2 of pair.  */
 	lwzu	r12,4(r8)
-	cmpb	r10,r12,r4
-	cmplwi	cr7,r10,0
+	cmpb	r3,r12,r4
+	cmplwi	cr7,r3,0
 	bne	cr7,L(done)
 
-	/* Are we done already?  */
-	addi	r9,r8,4
-	cmplw	cr6,r9,r7
-	bge	cr6,L(null)
-
 L(loop_setup):
-	sub	r5,r7,r9
-	srwi	r6,r5,3	      /* Number of loop iterations.  */
+	/* The last word we want to read in the loop below is the one
+	   containing the last byte of the string, ie. the word at
+	   (s + size - 1) & ~3, or r7.  The first word read is at
+	   r8 + 4, we read 2 * cnt words, so the last word read will
+	   be at r8 + 4 + 8 * cnt - 4.  Solving for cnt gives
+	   cnt = (r7 - r8) / 8  */
+	sub	r6,r7,r8
+	srwi	r6,r6,3	      /* Number of loop iterations.  */
 	mtctr	r6            /* Setup the counter.  */
-	b	L(loop)
-	/* Main loop to look for BYTE backwards in the string.  Since
-	   it's a small loop (< 8 instructions), align it to 32-bytes.  */
-	.p2align  5
+
+	/* Main loop to look for BYTE in the string.  Since
+	   it's a small loop (8 instructions), align it to 32-bytes.  */
+	.align	5
 L(loop):
 	/* Load two words, compare and merge in a
 	   single register for speed.  This is an attempt
 	   to speed up the byte-checking process for bigger strings.  */
 	lwz	r12,4(r8)
 	lwzu	r11,8(r8)
-	cmpb	r10,r12,r4
+	cmpb	r3,r12,r4
 	cmpb	r9,r11,r4
-	or	r5,r9,r10     /* Merge everything in one word.  */
-	cmplwi	cr7,r5,0
+	or	r6,r9,r3      /* Merge everything in one word.  */
+	cmplwi	cr7,r6,0
 	bne	cr7,L(found)
 	bdnz	L(loop)
 
-	/* We're here because the counter reached 0, and that means we
-	   didn't have any matches for BYTE in the whole range.  */
-	subi	r11,r7,4
-	cmplw	cr6,r8,r11
-	blt	cr6,L(loop_small)
-	b	L(null)
+	/* We may have one more dword to read.  */
+	cmplw	r8,r7
+	beqlr
+
+	lwzu	r12,4(r8)
+	cmpb	r3,r12,r4
+	cmplwi	cr6,r3,0
+	bne	cr6,L(done)
+	blr
 
+	.align	4
+L(found):
 	/* OK, one (or both) of the words contains BYTE.  Check
 	   the first word and decrement the address in case the first
 	   word really contains BYTE.  */
-	.align	4
-L(found):
-	cmplwi	cr6,r10,0
+	cmplwi	cr6,r3,0
 	addi	r8,r8,-4
 	bne	cr6,L(done)
 
 	/* BYTE must be in the second word.  Adjust the address
-	   again and move the result of cmpb to r10 so we can calculate the
+	   again and move the result of cmpb to r3 so we can calculate the
 	   pointer.  */
 
-	mr	r10,r9
+	mr	r3,r9
 	addi	r8,r8,4
 
-	/* r10 has the output of the cmpb instruction, that is, it contains
+	/* r3 has the output of the cmpb instruction, that is, it contains
 	   0xff in the same position as BYTE in the original
 	   word from the string.  Use that to calculate the pointer.
 	   We need to make sure BYTE is *before* the end of the range.  */
 L(done):
-	cntlzw	r0,r10	      /* Count leading zeroes before the match.  */
-	srwi	r0,r0,3	      /* Convert leading zeroes to bytes.  */
+#ifdef __LITTLE_ENDIAN__
+	addi    r0,r3,-1
+	andc    r0,r0,r3
+	popcntw	r0,r0	      /* Count trailing zeros.  */
+#else
+	cntlzw	r0,r3	      /* Count leading zeros before the match.  */
+#endif
+	cmplw	r8,r7         /* Are we on the last word?  */
+	srwi	r0,r0,3	      /* Convert leading/trailing zeros to bytes.  */
 	add	r3,r8,r0
-	cmplw	r3,r7
-	bge	L(null)
+	cmplw	cr7,r0,r5     /* If on the last dword, check byte offset.  */
+	bnelr
+	blelr	cr7
+	li	r3,0
 	blr
 
 	.align	4
@@ -137,67 +141,42 @@ L(null):
 	.align	4
 L(small_range):
 	cmplwi	r5,0
-	rlwinm	r6,r3,3,27,28 /* Calculate padding.  */
-	beq	L(null)       /* This branch is for the cmplwi r5,0 above */
+	beq	L(null)
 	lwz	r12,0(r8)     /* Load word from memory.  */
-	cmplwi	cr6,r6,0      /* cr6 == Do we have padding?  */
-	cmpb	r10,r12,r4    /* Check for BYTE in DWORD1.  */
-	beq	cr6,L(small_no_padding)
-	slw	r10,r10,r6
-	srw	r10,r10,r6
-L(small_no_padding):
-	cmplwi	cr7,r10,0
+	cmpb	r3,r12,r4     /* Check for BYTE in DWORD1.  */
+	and	r3,r3,r9
+	cmplwi	cr7,r3,0
+	clrlwi	r5,r7,30      /* Byte count - 1 in last word.  */
+	clrrwi	r7,r7,2       /* Address of last word.  */
+	cmplw	r8,r7         /* Are we done already?  */
 	bne	cr7,L(done)
+	beqlr
 
-	/* Are we done already?  */
-	addi    r9,r8,4
-	cmplw	r9,r7
-	bge	L(null)
-
-L(loop_small):                /* loop_small has been unrolled.  */
 	lwzu	r12,4(r8)
-	cmpb	r10,r12,r4
-	addi	r9,r8,4
-	cmplwi	cr6,r10,0
-	cmplw	r9,r7
+	cmpb	r3,r12,r4
+	cmplwi	cr6,r3,0
+	cmplw	r8,r7
 	bne	cr6,L(done)
-	bge	L(null)
+	beqlr
 
 	lwzu	r12,4(r8)
-	cmpb	r10,r12,r4
-	addi	r9,r8,4
-	cmplwi	cr6,r10,0
-	cmplw	r9,r7
+	cmpb	r3,r12,r4
+	cmplwi	cr6,r3,0
+	cmplw	r8,r7
 	bne	cr6,L(done)
-	bge	L(null)
+	beqlr
 
 	lwzu	r12,4(r8)
-	cmpb	r10,r12,r4
-	addi	r9,r8,4
-	cmplwi	cr6,r10,0
-	cmplw	r9,r7
+	cmpb	r3,r12,r4
+	cmplwi	cr6,r3,0
+	cmplw	r8,r7
 	bne	cr6,L(done)
-	bge	L(null)
+	beqlr
 
 	lwzu	r12,4(r8)
-	cmpb	r10,r12,r4
-	addi	r9,r8,4
-	cmplwi	cr6,r10,0
-	cmplw	r9,r7
+	cmpb	r3,r12,r4
+	cmplwi	cr6,r3,0
 	bne	cr6,L(done)
-	bge	L(null)
-
-	/* For most cases we will never get here.  Under some combinations of
-	   padding + length there is a leftover word that still needs to be
-	   checked.  */
-	lwzu	r12,4(r8)
-	cmpb	r10,r12,r4
-	addi	r9,r8,4
-	cmplwi	cr6,r10,0
-	bne	cr6,L(done)
-
-	/* save a branch and exit directly */
-	li	r3,0
 	blr
 
 END (__memchr)
diff --git a/sysdeps/powerpc/powerpc32/power7/memrchr.S b/sysdeps/powerpc/powerpc32/power7/memrchr.S
index defd832..9601aa7 100644
--- a/sysdeps/powerpc/powerpc32/power7/memrchr.S
+++ b/sysdeps/powerpc/powerpc32/power7/memrchr.S
@@ -23,117 +23,131 @@
 	.machine  power7
 ENTRY (__memrchr)
 	CALL_MCOUNT
-	dcbt	0,r3
-	mr	r7,r3
-	add	r3,r7,r5      /* Calculate the last acceptable address.  */
-	cmplw	cr7,r3,r7     /* Is the address equal or less than r3?  */
+	add	r7,r3,r5      /* Calculate the last acceptable address.  */
+	neg	r0,r7
+	addi	r7,r7,-1
+	mr	r10,r3
+	clrrwi	r6,r7,7
+	li	r9,3<<5
+	dcbt	r9,r6,16      /* Stream hint, decreasing addresses.  */
 
 	/* Replicate BYTE to word.  */
-	rlwimi	r4,r4,8,16,23
-	rlwimi	r4,r4,16,0,15
-	bge	cr7,L(proceed)
-
-	li	r3,-1	      /* Make r11 the biggest if r4 <= 0.  */
-L(proceed):
+	rldimi	r4,r4,8,48
+	rldimi	r4,r4,16,32
 	li	r6,-4
-	addi	r9,r3,-1
-	clrrwi  r8,r9,2
-	addi	r8,r8,4
-	neg	r0,r3
+	li	r9,-1
 	rlwinm	r0,r0,3,27,28 /* Calculate padding.  */
-
+	clrrwi	r8,r7,2
+	srw	r9,r9,r0
 	cmplwi	r5,16
+	clrrwi	r0,r10,2
 	ble	L(small_range)
 
-	lwbrx	r12,r8,r6     /* Load reversed word from memory.  */
-	cmpb	r10,r12,r4    /* Check for BYTE in WORD1.  */
-	slw	r10,r10,r0
-	srw	r10,r10,r0
-	cmplwi	cr7,r10,0     /* If r10 == 0, no BYTEs have been found.  */
+#ifdef __LITTLE_ENDIAN__
+	lwzx	r12,0,r8
+#else
+	lwbrx	r12,0,r8      /* Load reversed word from memory.  */
+#endif
+	cmpb	r3,r12,r4     /* Check for BYTE in WORD1.  */
+	and	r3,r3,r9
+	cmplwi	cr7,r3,0      /* If r3 == 0, no BYTEs have been found.  */
 	bne	cr7,L(done)
 
-	/* Are we done already?  */
-	addi	r9,r8,-4
-	cmplw	cr6,r9,r7
-	ble	cr6,L(null)
-
 	mtcrf   0x01,r8
 	/* Are we now aligned to a doubleword boundary?  If so, skip to
 	   the main loop.  Otherwise, go through the alignment code.  */
-	mr	r8,r9
-	bt	29,L(loop_setup)
+	bf	29,L(loop_setup)
 
 	/* Handle WORD2 of pair.  */
+#ifdef __LITTLE_ENDIAN__
+	lwzx	r12,r8,r6
+#else
 	lwbrx	r12,r8,r6
-	cmpb	r10,r12,r4
-	cmplwi	cr7,r10,0
-	bne	cr7,L(done)
-
-	/* Are we done already?  */
+#endif
 	addi	r8,r8,-4
-	cmplw	cr6,r8,r7
-	ble	cr6,L(null)
+	cmpb	r3,r12,r4
+	cmplwi	cr7,r3,0
+	bne	cr7,L(done)
 
 L(loop_setup):
-	li	r0,-8
-	sub	r5,r8,r7
-	srwi	r9,r5,3	      /* Number of loop iterations.  */
+	/* The last word we want to read in the loop below is the one
+	   containing the first byte of the string, ie. the word at
+	   s & ~3, or r0.  The first word read is at r8 - 4, we
+	   read 2 * cnt words, so the last word read will be at
+	   r8 - 4 - 8 * cnt + 4.  Solving for cnt gives
+	   cnt = (r8 - r0) / 8  */
+	sub	r5,r8,r0
+	addi	r8,r8,-4
+	srwi	r9,r5,3       /* Number of loop iterations.  */
 	mtctr	r9	      /* Setup the counter.  */
-	b	L(loop)
-	/* Main loop to look for BYTE backwards in the string.  Since it's a
-	   small loop (< 8 instructions), align it to 32-bytes.  */
-	.p2align  5
+
+	/* Main loop to look for BYTE backwards in the string.
+	   FIXME: Investigate whether 32 byte align helps with this
+	   9 instruction loop.  */
+	.align	5
 L(loop):
 	/* Load two words, compare and merge in a
 	   single register for speed.  This is an attempt
 	   to speed up the byte-checking process for bigger strings.  */
 
-	lwbrx	r12,r8,r6
-	lwbrx	r11,r8,r0
-	addi	r8,r8,-4
-	cmpb	r10,r12,r4
+#ifdef __LITTLE_ENDIAN__
+	lwzx	r12,0,r8
+	lwzx	r11,r8,r6
+#else
+	lwbrx	r12,0,r8
+	lwbrx	r11,r8,r6
+#endif
+	cmpb	r3,r12,r4
 	cmpb	r9,r11,r4
-	or	r5,r9,r10     /* Merge everything in one word.  */
+	or	r5,r9,r3      /* Merge everything in one word.  */
 	cmplwi	cr7,r5,0
 	bne	cr7,L(found)
-	addi	r8,r8,-4
+	addi	r8,r8,-8
 	bdnz	L(loop)
-	/* We're here because the counter reached 0, and that means we
-	   didn't have any matches for BYTE in the whole range.  Just return
-	   the original range.  */
-	addi	r8,r8,4
-	cmplw	cr6,r8,r7
-	bgt	cr6,L(loop_small)
-	b	L(null)
 
-	/* OK, one (or both) of the words contains BYTE.  Check
-	   the first word and decrement the address in case the first
-	   word really contains BYTE.  */
+	/* We may have one more word to read.  */
+	cmplw	r8,r0
+	bnelr
+
+#ifdef __LITTLE_ENDIAN__
+	lwzx	r12,0,r8
+#else
+	lwbrx	r12,0,r8
+#endif
+	cmpb	r3,r12,r4
+	cmplwi	cr7,r3,0
+	bne	cr7,L(done)
+	blr
+
 	.align	4
 L(found):
-	cmplwi	cr6,r10,0
-	addi	r8,r8,4
+	/* OK, one (or both) of the words contains BYTE.  Check
+	   the first word.  */
+	cmplwi	cr6,r3,0
 	bne	cr6,L(done)
 
 	/* BYTE must be in the second word.  Adjust the address
-	   again and move the result of cmpb to r10 so we can calculate the
+	   again and move the result of cmpb to r3 so we can calculate the
 	   pointer.  */
 
-	mr	r10,r9
+	mr	r3,r9
 	addi	r8,r8,-4
 
-	/* r10 has the output of the cmpb instruction, that is, it contains
+	/* r3 has the output of the cmpb instruction, that is, it contains
 	   0xff in the same position as BYTE in the original
 	   word from the string.  Use that to calculate the pointer.
 	   We need to make sure BYTE is *before* the end of the
 	   range.  */
 L(done):
-	cntlzw	r0,r10	      /* Count leading zeroes before the match.  */
-	srwi	r6,r0,3	      /* Convert leading zeroes to bytes.  */
-	addi	r0,r6,1
+	cntlzw	r9,r3	      /* Count leading zeros before the match.  */
+	cmplw	r8,r0         /* Are we on the last word?  */
+	srwi	r6,r9,3	      /* Convert leading zeros to bytes.  */
+	addi	r0,r6,-3
 	sub	r3,r8,r0
-	cmplw	r3,r7
-	blt	L(null)
+	cmplw	cr7,r3,r10
+	bnelr
+	bgelr	cr7
+	li	r3,0
 	blr
 
 	.align	4
@@ -147,28 +161,35 @@ L(small_range):
 	cmplwi	r5,0
 	beq	L(null)
 
-	lwbrx	r12,r8,r6     /* Load reversed word from memory.  */
-	cmpb	r10,r12,r4    /* Check for null bytes in WORD1.  */
-	slw	r10,r10,r0
-	srw	r10,r10,r0
-	cmplwi	cr7,r10,0
+#ifdef __LITTLE_ENDIAN__
+	lwzx	r12,0,r8
+#else
+	lwbrx	r12,0,r8      /* Load reversed word from memory.  */
+#endif
+	cmpb	r3,r12,r4     /* Check for BYTE in WORD1.  */
+	and	r3,r3,r9
+	cmplwi	cr7,r3,0
 	bne	cr7,L(done)
 
+	/* Are we done already?  */
+	cmplw	r8,r0
 	addi	r8,r8,-4
-	cmplw	r8,r7
-	ble	L(null)
-	b	L(loop_small)
+	beqlr
 
-	.p2align  5
+	.align	5
 L(loop_small):
-	lwbrx	r12,r8,r6
-	cmpb	r10,r12,r4
-	cmplwi	cr6,r10,0
-	bne	cr6,L(done)
+#ifdef __LITTLE_ENDIAN__
+	lwzx	r12,0,r8
+#else
+	lwbrx	r12,0,r8
+#endif
+	cmpb	r3,r12,r4
+	cmplw	r8,r0
+	cmplwi	cr7,r3,0
+	bne	cr7,L(done)
 	addi	r8,r8,-4
-	cmplw	r8,r7
-	ble	L(null)
-	b	L(loop_small)
+	bne	L(loop_small)
+	blr
 
 END (__memrchr)
 weak_alias (__memrchr, memrchr)
diff --git a/sysdeps/powerpc/powerpc32/power7/rawmemchr.S b/sysdeps/powerpc/powerpc32/power7/rawmemchr.S
index a80c74a..c2d8c4b 100644
--- a/sysdeps/powerpc/powerpc32/power7/rawmemchr.S
+++ b/sysdeps/powerpc/powerpc32/power7/rawmemchr.S
@@ -27,16 +27,21 @@ ENTRY (__rawmemchr)
 	clrrwi	r8,r3,2	      /* Align the address to word boundary.  */
 
 	/* Replicate byte to word.  */
-	rlwimi	r4,r4,8,16,23
-	rlwimi	r4,r4,16,0,15
+	rldimi	r4,r4,8,48
+	rldimi	r4,r4,16,32
 
 	/* Now r4 has a word of c bytes.  */
 
 	rlwinm	r6,r3,3,27,28 /* Calculate padding.  */
 	lwz	r12,0(r8)     /* Load word from memory.  */
 	cmpb	r5,r12,r4     /* Compare each byte against c byte.  */
+#ifdef __LITTLE_ENDIAN__
+	srw	r5,r5,r6
+	slw	r5,r5,r6
+#else
 	slw	r5,r5,r6      /* Move left to discard ignored bits.  */
 	srw	r5,r5,r6      /* Bring the bits back as zeros.  */
+#endif
 	cmpwi	cr7,r5,0      /* If r5 == 0, no c bytes have been found.  */
 	bne	cr7,L(done)
 
@@ -90,8 +95,14 @@ L(loop):
 	   word from the string.  Use that fact to find out what is
 	   the position of the byte inside the string.  */
 L(done):
+#ifdef __LITTLE_ENDIAN__
+	addi    r0,r5,-1
+	andc    r0,r0,r5
+	popcntw	r0,r0
+#else
 	cntlzw	r0,r5	      /* Count leading zeros before the match.  */
-	srwi	r0,r0,3	      /* Convert leading zeroes to bytes.  */
+#endif
+	srwi	r0,r0,3	      /* Convert leading zeros to bytes.  */
 	add	r3,r8,r0      /* Return address of the matching char.  */
 	blr
 END (__rawmemchr)
diff --git a/sysdeps/powerpc/powerpc64/power7/memchr.S b/sysdeps/powerpc/powerpc64/power7/memchr.S
index 3416897..5076dd0 100644
--- a/sysdeps/powerpc/powerpc64/power7/memchr.S
+++ b/sysdeps/powerpc/powerpc64/power7/memchr.S
@@ -25,109 +25,112 @@ ENTRY (__memchr)
 	CALL_MCOUNT 2
 	dcbt	0,r3
 	clrrdi  r8,r3,3
-	rlwimi	r4,r4,8,16,23
-	rlwimi	r4,r4,16,0,15
+	insrdi	r4,r4,8,48
 	add	r7,r3,r5      /* Calculate the last acceptable address.  */
+	insrdi	r4,r4,16,32
 	cmpldi	r5,32
+	li	r9, -1
+	rlwinm	r6,r3,3,26,28 /* Calculate padding.  */
 	insrdi  r4,r4,32,0
+	addi	r7,r7,-1
+#ifdef __LITTLE_ENDIAN__
+	sld	r9,r9,r6
+#else
+	srd	r9,r9,r6
+#endif
 	ble	L(small_range)
 
-	cmpld	cr7,r3,r7     /* Compare the starting address (r3) with the
-				 ending address (r7).  If (r3 >= r7),
-				 the size passed in was zero or negative.  */
-	ble	cr7,L(proceed)
-
-	li	r7,-1         /* Artificially set our ending address (r7)
-				 such that we will exit early.  */
-
-L(proceed):
-	rlwinm	r6,r3,3,26,28 /* Calculate padding.  */
-	cmpldi	cr6,r6,0      /* cr6 == Do we have padding?  */
 	ld	r12,0(r8)     /* Load doubleword from memory.  */
-	cmpb	r10,r12,r4    /* Check for BYTEs in DWORD1.  */
-	beq	cr6,L(proceed_no_padding)
-	sld	r10,r10,r6
-	srd	r10,r10,r6
-L(proceed_no_padding):
-	cmpldi	cr7,r10,0     /* Does r10 indicate we got a hit?  */
+	cmpb	r3,r12,r4     /* Check for BYTEs in DWORD1.  */
+	and	r3,r3,r9
+	clrldi	r5,r7,61      /* Byte count - 1 in last dword.  */
+	clrrdi	r7,r7,3       /* Address of last doubleword.  */
+	cmpldi	cr7,r3,0      /* Does r3 indicate we got a hit?  */
 	bne	cr7,L(done)
 
-	/* See if we are at the last acceptable address yet.  */
-	addi	r9,r8,8
-	cmpld	cr6,r9,r7
-	bge	cr6,L(null)
-
 	mtcrf   0x01,r8
 	/* Are we now aligned to a quadword boundary?  If so, skip to
 	   the main loop.  Otherwise, go through the alignment code.  */
-
 	bt	28,L(loop_setup)
 
 	/* Handle DWORD2 of pair.  */
 	ldu	r12,8(r8)
-	cmpb	r10,r12,r4
-	cmpldi	cr7,r10,0
+	cmpb	r3,r12,r4
+	cmpldi	cr7,r3,0
 	bne	cr7,L(done)
 
-	/* Are we done already?  */
-	addi	r9,r8,8
-	cmpld	cr6,r9,r7
-	bge	cr6,L(null)
-
 L(loop_setup):
-	sub	r5,r7,r9
-	srdi	r6,r5,4	      /* Number of loop iterations.  */
+	/* The last dword we want to read in the loop below is the one
+	   containing the last byte of the string, ie. the dword at
+	   (s + size - 1) & ~7, or r7.  The first dword read is at
+	   r8 + 8, we read 2 * cnt dwords, so the last dword read will
+	   be at r8 + 8 + 16 * cnt - 8.  Solving for cnt gives
+	   cnt = (r7 - r8) / 16  */
+	sub	r6,r7,r8
+	srdi	r6,r6,4	      /* Number of loop iterations.  */
 	mtctr	r6            /* Setup the counter.  */
-	b	L(loop)
-	/* Main loop to look for BYTE backwards in the string.  Since
-	   it's a small loop (< 8 instructions), align it to 32-bytes.  */
-	.p2align  5
+
+	/* Main loop to look for BYTE in the string.  Since
+	   it's a small loop (8 instructions), align it to 32-bytes.  */
+	.align	5
 L(loop):
 	/* Load two doublewords, compare and merge in a
 	   single register for speed.  This is an attempt
 	   to speed up the byte-checking process for bigger strings.  */
 	ld	r12,8(r8)
 	ldu	r11,16(r8)
-	cmpb	r10,r12,r4
+	cmpb	r3,r12,r4
 	cmpb	r9,r11,r4
-	or	r5,r9,r10     /* Merge everything in one doubleword.  */
-	cmpldi	cr7,r5,0
+	or	r6,r9,r3      /* Merge everything in one doubleword.  */
+	cmpldi	cr7,r6,0
 	bne	cr7,L(found)
 	bdnz	L(loop)
 
-	/* We're here because the counter reached 0, and that means we
-	   didn't have any matches for BYTE in the whole range.  */
-	subi	r11,r7,8
-	cmpld	cr6,r8,r11
-	blt	cr6,L(loop_small)
-	b	L(null)
+	/* We may have one more dword to read.  */
+	cmpld	r8,r7
+	beqlr
 
+	ldu	r12,8(r8)
+	cmpb	r3,r12,r4
+	cmpldi	cr6,r3,0
+	bne	cr6,L(done)
+	blr
+
+	.align	4
+L(found):
 	/* OK, one (or both) of the doublewords contains BYTE.  Check
 	   the first doubleword and decrement the address in case the first
 	   doubleword really contains BYTE.  */
-	.align	4
-L(found):
-	cmpldi	cr6,r10,0
+	cmpldi	cr6,r3,0
 	addi	r8,r8,-8
 	bne	cr6,L(done)
 
 	/* BYTE must be in the second doubleword.  Adjust the address
-	   again and move the result of cmpb to r10 so we can calculate the
+	   again and move the result of cmpb to r3 so we can calculate the
 	   pointer.  */
 
-	mr	r10,r9
+	mr	r3,r9
 	addi	r8,r8,8
 
-	/* r10 has the output of the cmpb instruction, that is, it contains
+	/* r3 has the output of the cmpb instruction, that is, it contains
 	   0xff in the same position as BYTE in the original
 	   doubleword from the string.  Use that to calculate the pointer.
 	   We need to make sure BYTE is *before* the end of the range.  */
 L(done):
-	cntlzd	r0,r10	      /* Count leading zeroes before the match.  */
-	srdi	r0,r0,3	      /* Convert leading zeroes to bytes.  */
+#ifdef __LITTLE_ENDIAN__
+	addi    r0,r3,-1
+	andc    r0,r0,r3
+	popcntd	r0,r0	      /* Count trailing zeros.  */
+#else
+	cntlzd	r0,r3	      /* Count leading zeros before the match.  */
+#endif
+	cmpld	r8,r7         /* Are we on the last dword?  */
+	srdi	r0,r0,3	      /* Convert leading/trailing zeros to bytes.  */
 	add	r3,r8,r0
-	cmpld	r3,r7
-	bge	L(null)
+	cmpld	cr7,r0,r5     /* If on the last dword, check byte offset.  */
+	bnelr
+	blelr	cr7
+	li	r3,0
 	blr
 
 	.align	4
@@ -139,67 +142,44 @@ L(null):
 	.align	4
 L(small_range):
 	cmpldi	r5,0
-	rlwinm	r6,r3,3,26,28 /* Calculate padding.  */
-	beq	L(null)       /* This branch is for the cmpldi r5,0 above.  */
+	beq	L(null)
 	ld	r12,0(r8)     /* Load word from memory.  */
-	cmpldi	cr6,r6,0      /* cr6 == Do we have padding?  */
-	cmpb	r10,r12,r4    /* Check for BYTE in DWORD1.  */
-			      /* If no padding, skip the shifts.  */
-	beq	cr6,L(small_no_padding)
-	sld	r10,r10,r6
-	srd	r10,r10,r6
-L(small_no_padding):
-	cmpldi	cr7,r10,0
+	cmpb	r3,r12,r4     /* Check for BYTE in DWORD1.  */
+	and	r3,r3,r9
+	cmpldi	cr7,r3,0
+	clrldi	r5,r7,61      /* Byte count - 1 in last dword.  */
+	clrrdi	r7,r7,3       /* Address of last doubleword.  */
+	cmpld	r8,r7         /* Are we done already?  */
 	bne	cr7,L(done)
+	beqlr
 
-	/* Are we done already?  */
-	addi    r9,r8,8
-	cmpld	r9,r7
-	bge	L(null)
-	/* If we're not done, drop through into loop_small.  */
-
-L(loop_small):                /* loop_small has been unrolled.  */
 	ldu	r12,8(r8)
-	cmpb	r10,r12,r4
-	addi	r9,r8,8
-	cmpldi	cr6,r10,0
-	cmpld	r9,r7
+	cmpb	r3,r12,r4
+	cmpldi	cr6,r3,0
+	cmpld	r8,r7
 	bne	cr6,L(done)   /* Found something.  */
-	bge	L(null)       /* Hit end of string (length).  */
+	beqlr		      /* Hit end of string (length).  */
 
 	ldu	r12,8(r8)
-	cmpb	r10,r12,r4
-	addi	r9,r8,8
-	cmpldi	cr6,r10,0
-	cmpld	r9,r7
-	bne	cr6,L(done)   /* Found something.  */
-	bge	L(null)
+	cmpb	r3,r12,r4
+	cmpldi	cr6,r3,0
+	cmpld	r8,r7
+	bne	cr6,L(done)
+	beqlr
 
 	ldu	r12,8(r8)
-	subi	r11,r7,8
-	cmpb	r10,r12,r4
-	cmpldi	cr6,r10,0
-	ori	r2,r2,0       /* Force a dispatch group.  */
+	cmpb	r3,r12,r4
+	cmpldi	cr6,r3,0
+	cmpld	r8,r7
 	bne	cr6,L(done)
+	beqlr
 
-	cmpld	r8,r11        /* At end of range?  */
-	bge	L(null)
-
-	/* For most cases we will never get here.  Under some combinations of
-	   padding + length there is a leftover double that still needs to be
-	   checked.  */
 	ldu	r12,8(r8)
-	cmpb	r10,r12,r4
-	addi	r9,r8,8
-	cmpldi	cr6,r10,0
-	cmpld	r9,r7
-	bne	cr6,L(done)   /* Found something.  */
-
-	/* Save a branch and exit directly.  */
-	li	r3,0
+	cmpb	r3,r12,r4
+	cmpldi	cr6,r3,0
+	bne	cr6,L(done)
 	blr
 
-
 END (__memchr)
 weak_alias (__memchr, memchr)
 libc_hidden_builtin_def (memchr)
diff --git a/sysdeps/powerpc/powerpc64/power7/memrchr.S b/sysdeps/powerpc/powerpc64/power7/memrchr.S
index c499952..a9e86cb 100644
--- a/sysdeps/powerpc/powerpc64/power7/memrchr.S
+++ b/sysdeps/powerpc/powerpc64/power7/memrchr.S
@@ -23,118 +23,132 @@
 	.machine  power7
 ENTRY (__memrchr)
 	CALL_MCOUNT
-	dcbt	0,r3
-	mr	r7,r3
-	add	r3,r7,r5      /* Calculate the last acceptable address.  */
-	cmpld	cr7,r3,r7     /* Is the address equal or less than r3?  */
+	add	r7,r3,r5      /* Calculate the last acceptable address.  */
+	neg	r0,r7
+	addi	r7,r7,-1
+	mr	r10,r3
+	clrrdi	r6,r7,7
+	li	r9,3<<5
+	dcbt	r9,r6,16      /* Stream hint, decreasing addresses.  */
 
 	/* Replicate BYTE to doubleword.  */
-	rlwimi	r4,r4,8,16,23
-	rlwimi	r4,r4,16,0,15
+	insrdi	r4,r4,8,48
+	insrdi	r4,r4,16,32
 	insrdi  r4,r4,32,0
-	bge	cr7,L(proceed)
-
-	li	r3,-1	      /* Make r11 the biggest if r4 <= 0.  */
-L(proceed):
 	li	r6,-8
-	addi	r9,r3,-1
-	clrrdi  r8,r9,3
-	addi	r8,r8,8
-	neg	r0,r3
+	li	r9,-1
 	rlwinm	r0,r0,3,26,28 /* Calculate padding.  */
-
+	clrrdi	r8,r7,3
+	srd	r9,r9,r0
 	cmpldi	r5,32
+	clrrdi	r0,r10,3
 	ble	L(small_range)
 
-	ldbrx	r12,r8,r6     /* Load reversed doubleword from memory.  */
-	cmpb	r10,r12,r4    /* Check for BYTE in DWORD1.  */
-	sld	r10,r10,r0
-	srd	r10,r10,r0
-	cmpldi	cr7,r10,0     /* If r10 == 0, no BYTEs have been found.  */
+#ifdef __LITTLE_ENDIAN__
+	ldx	r12,0,r8
+#else
+	ldbrx	r12,0,r8      /* Load reversed doubleword from memory.  */
+#endif
+	cmpb	r3,r12,r4     /* Check for BYTE in DWORD1.  */
+	and	r3,r3,r9
+	cmpldi	cr7,r3,0      /* If r3 == 0, no BYTEs have been found.  */
 	bne	cr7,L(done)
 
-	/* Are we done already?  */
-	addi	r9,r8,-8
-	cmpld	cr6,r9,r7
-	ble	cr6,L(null)
-
 	mtcrf   0x01,r8
-	/* Are we now aligned to a doubleword boundary?  If so, skip to
+	/* Are we now aligned to a quadword boundary?  If so, skip to
 	   the main loop.  Otherwise, go through the alignment code.  */
-	mr	r8,r9
-	bt	28,L(loop_setup)
+	bf	28,L(loop_setup)
 
 	/* Handle DWORD2 of pair.  */
+#ifdef __LITTLE_ENDIAN__
+	ldx	r12,r8,r6
+#else
 	ldbrx	r12,r8,r6
-	cmpb	r10,r12,r4
-	cmpldi	cr7,r10,0
-	bne	cr7,L(done)
-
-	/* Are we done already.  */
+#endif
 	addi	r8,r8,-8
-	cmpld	cr6,r8,r7
-	ble	cr6,L(null)
+	cmpb	r3,r12,r4
+	cmpldi	cr7,r3,0
+	bne	cr7,L(done)
 
 L(loop_setup):
-	li	r0,-16
-	sub	r5,r8,r7
-	srdi	r9,r5,4	      /* Number of loop iterations.  */
+	/* The last dword we want to read in the loop below is the one
+	   containing the first byte of the string, ie. the dword at
+	   s & ~7, or r0.  The first dword read is at r8 - 8, we
+	   read 2 * cnt dwords, so the last dword read will be at
+	   r8 - 8 - 16 * cnt + 8.  Solving for cnt gives
+	   cnt = (r8 - r0) / 16  */
+	sub	r5,r8,r0
+	addi	r8,r8,-8
+	srdi	r9,r5,4       /* Number of loop iterations.  */
 	mtctr	r9	      /* Setup the counter.  */
-	b	L(loop)
-	/* Main loop to look for BYTE backwards in the string.  Since it's a
-	   small loop (< 8 instructions), align it to 32-bytes.  */
-	.p2align  5
+
+	/* Main loop to look for BYTE backwards in the string.
+	   FIXME: Investigate whether 32 byte align helps with this
+	   9 instruction loop.  */
+	.align	5
 L(loop):
 	/* Load two doublewords, compare and merge in a
 	   single register for speed.  This is an attempt
 	   to speed up the byte-checking process for bigger strings.  */
 
-	ldbrx	r12,r8,r6
-	ldbrx	r11,r8,r0
-	addi	r8,r8,-8
-	cmpb	r10,r12,r4
+#ifdef __LITTLE_ENDIAN__
+	ldx	r12,0,r8
+	ldx	r11,r8,r6
+#else
+	ldbrx	r12,0,r8
+	ldbrx	r11,r8,r6
+#endif
+	cmpb	r3,r12,r4
 	cmpb	r9,r11,r4
-	or	r5,r9,r10     /* Merge everything in one doubleword.  */
+	or	r5,r9,r3      /* Merge everything in one doubleword.  */
 	cmpldi	cr7,r5,0
 	bne	cr7,L(found)
-	addi	r8,r8,-8
+	addi	r8,r8,-16
 	bdnz	L(loop)
-	/* We're here because the counter reached 0, and that means we
-	   didn't have any matches for BYTE in the whole range.  Just return
-	   the original range.  */
-	addi	r8,r8,8
-	cmpld	cr6,r8,r7
-	bgt	cr6,L(loop_small)
-	b	L(null)
-
-	/* OK, one (or both) of the words contains BYTE.  Check
-	   the first word and decrement the address in case the first
-	   word really contains BYTE.  */
+
+	/* We may have one more word to read.  */
+	cmpld	r8,r0
+	bnelr
+
+#ifdef __LITTLE_ENDIAN__
+	ldx	r12,0,r8
+#else
+	ldbrx	r12,0,r8
+#endif
+	cmpb	r3,r12,r4
+	cmpldi	cr7,r3,0
+	bne	cr7,L(done)
+	blr
+
 	.align	4
 L(found):
-	cmpldi	cr6,r10,0
-	addi	r8,r8,8
+	/* OK, one (or both) of the dwords contains BYTE.  Check
+	   the first dword.  */
+	cmpldi	cr6,r3,0
 	bne	cr6,L(done)
 
 	/* BYTE must be in the second word.  Adjust the address
-	   again and move the result of cmpb to r10 so we can calculate the
+	   again and move the result of cmpb to r3 so we can calculate the
 	   pointer.  */
 
-	mr	r10,r9
+	mr	r3,r9
 	addi	r8,r8,-8
 
-	/* r10 has the output of the cmpb instruction, that is, it contains
-	   0xff in the same position as the BYTE in the original
+	/* r3 has the output of the cmpb instruction, that is, it contains
+	   0xff in the same position as BYTE in the original
 	   word from the string.  Use that to calculate the pointer.
 	   We need to make sure BYTE is *before* the end of the
 	   range.  */
 L(done):
-	cntlzd	r0,r10	      /* Count leading zeroes before the match.  */
-	srdi	r6,r0,3	      /* Convert leading zeroes to bytes.  */
-	addi	r0,r6,1
+	cntlzd	r9,r3	      /* Count leading zeros before the match.  */
+	cmpld	r8,r0         /* Are we on the last word?  */
+	srdi	r6,r9,3	      /* Convert leading zeros to bytes.  */
+	addi	r0,r6,-7
 	sub	r3,r8,r0
-	cmpld	r3,r7
-	blt	L(null)
+	cmpld	cr7,r3,r10
+	bnelr
+	bgelr	cr7
+	li	r3,0
 	blr
 
 	.align	4
@@ -148,29 +162,35 @@ L(small_range):
 	cmpldi	r5,0
 	beq	L(null)
 
-	ldbrx	r12,r8,r6     /* Load reversed doubleword from memory.  */
-	cmpb	r10,r12,r4    /* Check for BYTE in DWORD1.  */
-	sld	r10,r10,r0
-	srd	r10,r10,r0
-	cmpldi	cr7,r10,0
+#ifdef __LITTLE_ENDIAN__
+	ldx	r12,0,r8
+#else
+	ldbrx	r12,0,r8      /* Load reversed doubleword from memory.  */
+#endif
+	cmpb	r3,r12,r4     /* Check for BYTE in DWORD1.  */
+	and	r3,r3,r9
+	cmpldi	cr7,r3,0
 	bne	cr7,L(done)
 
 	/* Are we done already?  */
+	cmpld	r8,r0
 	addi	r8,r8,-8
-	cmpld	r8,r7
-	ble	L(null)
-	b	L(loop_small)
+	beqlr
 
-	.p2align  5
+	.align	5
 L(loop_small):
-	ldbrx	r12,r8,r6
-	cmpb	r10,r12,r4
-	cmpldi	cr6,r10,0
-	bne	cr6,L(done)
+#ifdef __LITTLE_ENDIAN__
+	ldx	r12,0,r8
+#else
+	ldbrx	r12,0,r8
+#endif
+	cmpb	r3,r12,r4
+	cmpld	r8,r0
+	cmpldi	cr7,r3,0
+	bne	cr7,L(done)
 	addi	r8,r8,-8
-	cmpld	r8,r7
-	ble	L(null)
-	b	L(loop_small)
+	bne	L(loop_small)
+	blr
 
 END (__memrchr)
 weak_alias (__memrchr, memrchr)
diff --git a/sysdeps/powerpc/powerpc64/power7/rawmemchr.S b/sysdeps/powerpc/powerpc64/power7/rawmemchr.S
index 50a33d8..547aed7 100644
--- a/sysdeps/powerpc/powerpc64/power7/rawmemchr.S
+++ b/sysdeps/powerpc/powerpc64/power7/rawmemchr.S
@@ -27,8 +27,8 @@ ENTRY (__rawmemchr)
 	clrrdi	r8,r3,3	      /* Align the address to doubleword boundary.  */
 
 	/* Replicate byte to doubleword.  */
-	rlwimi	r4,r4,8,16,23
-	rlwimi	r4,r4,16,0,15
+	insrdi	r4,r4,8,48
+	insrdi	r4,r4,16,32
 	insrdi	r4,r4,32,0
 
 	/* Now r4 has a doubleword of c bytes.  */
@@ -36,8 +36,13 @@ ENTRY (__rawmemchr)
 	rlwinm	r6,r3,3,26,28 /* Calculate padding.  */
 	ld	r12,0(r8)     /* Load doubleword from memory.  */
 	cmpb	r5,r12,r4     /* Compare each byte against c byte.  */
+#ifdef __LITTLE_ENDIAN__
+	srd	r5,r5,r6
+	sld	r5,r5,r6
+#else
 	sld	r5,r5,r6      /* Move left to discard ignored bits.  */
 	srd	r5,r5,r6      /* Bring the bits back as zeros.  */
+#endif
 	cmpdi	cr7,r5,0      /* If r5 == 0, no c bytes have been found.  */
 	bne	cr7,L(done)
 
@@ -91,8 +96,14 @@ L(loop):
 	   doubleword from the string.  Use that fact to find out what is
 	   the position of the byte inside the string.  */
 L(done):
+#ifdef __LITTLE_ENDIAN__
+	addi    r0,r5,-1
+	andc    r0,r0,r5
+	popcntd	r0,r0	      /* Count trailing zeros.  */
+#else
 	cntlzd	r0,r5	      /* Count leading zeros before the match.  */
-	srdi	r0,r0,3	      /* Convert leading zeroes to bytes.  */
+#endif
+	srdi	r0,r0,3	      /* Convert leading zeros to bytes.  */
 	add	r3,r8,r0      /* Return address of the matching char.  */
 	blr
 END (__rawmemchr)

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=62b5c6de0ec2b1a3d4779797dece796edb631e17

commit 62b5c6de0ec2b1a3d4779797dece796edb631e17
Author: Alan Modra <amodra@gmail.com>
Date:   Sat Aug 17 18:47:59 2013 +0930

    PowerPC LE memset
    http://sourceware.org/ml/libc-alpha/2013-08/msg00104.html
    
    One of the things I noticed when looking at power7 timing is that rlwimi
    is cracked and the two resulting insns have a register dependency.
    That makes it a little slower than the equivalent rldimi.
    
    	* sysdeps/powerpc/powerpc64/memset.S: Replace rlwimi with
            insrdi.  Formatting.
    	* sysdeps/powerpc/powerpc64/power4/memset.S: Likewise.
    	* sysdeps/powerpc/powerpc64/power6/memset.S: Likewise.
    	* sysdeps/powerpc/powerpc64/power7/memset.S: Likewise.
    	* sysdeps/powerpc/powerpc32/power4/memset.S: Likewise.
    	* sysdeps/powerpc/powerpc32/power6/memset.S: Likewise.
    	* sysdeps/powerpc/powerpc32/power7/memset.S: Likewise.

diff --git a/ChangeLog b/ChangeLog
index 3632248..99d2b70 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,16 @@
 2013-10-04  Alan Modra  <amodra@gmail.com>
 
+	* sysdeps/powerpc/powerpc64/memset.S: Replace rlwimi with
+        insrdi.  Formatting.
+	* sysdeps/powerpc/powerpc64/power4/memset.S: Likewise.
+	* sysdeps/powerpc/powerpc64/power6/memset.S: Likewise.
+	* sysdeps/powerpc/powerpc64/power7/memset.S: Likewise.
+	* sysdeps/powerpc/powerpc32/power4/memset.S: Likewise.
+	* sysdeps/powerpc/powerpc32/power6/memset.S: Likewise.
+	* sysdeps/powerpc/powerpc32/power7/memset.S: Likewise.
+
+2013-10-04  Alan Modra  <amodra@gmail.com>
+
 	* sysdeps/powerpc/powerpc32/power4/memcpy.S: Add little endian support.
 	* sysdeps/powerpc/powerpc32/power6/memcpy.S: Likewise.
 	* sysdeps/powerpc/powerpc32/power7/memcpy.S: Likewise.
diff --git a/sysdeps/powerpc/powerpc32/power4/memset.S b/sysdeps/powerpc/powerpc32/power4/memset.S
index c2d288b..4fd9d8c 100644
--- a/sysdeps/powerpc/powerpc32/power4/memset.S
+++ b/sysdeps/powerpc/powerpc32/power4/memset.S
@@ -50,7 +50,7 @@ L(_memset):
 
 /* Align to word boundary.  */
 	cmplwi	cr5, rLEN, 31
-	rlwimi	rCHR, rCHR, 8, 16, 23 /* Replicate byte to halfword.  */
+	insrdi	rCHR, rCHR, 8, 48     /* Replicate byte to halfword.  */
 	beq+	L(aligned)
 	mtcrf	0x01, rMEMP0
 	subfic	rALIGN, rALIGN, 4
@@ -65,7 +65,7 @@ L(g0):
 /* Handle the case of size < 31.  */
 L(aligned):
 	mtcrf	0x01, rLEN
-	rlwimi	rCHR, rCHR, 16, 0, 15 /* Replicate halfword to word.  */
+	insrdi	rCHR, rCHR, 16, 32    /* Replicate halfword to word.  */
 	ble	cr5, L(medium)
 /* Align to 32-byte boundary.  */
 	andi.	rALIGN, rMEMP, 0x1C
diff --git a/sysdeps/powerpc/powerpc32/power6/memset.S b/sysdeps/powerpc/powerpc32/power6/memset.S
index ce06630..508d560 100644
--- a/sysdeps/powerpc/powerpc32/power6/memset.S
+++ b/sysdeps/powerpc/powerpc32/power6/memset.S
@@ -48,7 +48,7 @@ L(_memset):
 	ble-	cr1, L(small)
 /* Align to word boundary.  */
 	cmplwi	cr5, rLEN, 31
-	rlwimi	rCHR, rCHR, 8, 16, 23 /* Replicate byte to halfword.  */
+	insrdi	rCHR, rCHR, 8, 48	/* Replicate byte to halfword.  */
 	beq+	L(aligned)
 	mtcrf	0x01, rMEMP0
 	subfic	rALIGN, rALIGN, 4
@@ -64,7 +64,7 @@ L(g0):
 /* Handle the case of size < 31.  */
 L(aligned):
 	mtcrf	0x01, rLEN
-	rlwimi	rCHR, rCHR, 16, 0, 15 /* Replicate halfword to word.  */
+	insrdi	rCHR, rCHR, 16, 32	/* Replicate halfword to word.  */
 	ble	cr5, L(medium)
 /* Align to 32-byte boundary.  */
 	andi.	rALIGN, rMEMP, 0x1C
diff --git a/sysdeps/powerpc/powerpc32/power7/memset.S b/sysdeps/powerpc/powerpc32/power7/memset.S
index 360ea71..aadda25 100644
--- a/sysdeps/powerpc/powerpc32/power7/memset.S
+++ b/sysdeps/powerpc/powerpc32/power7/memset.S
@@ -35,8 +35,8 @@ L(_memset):
 	cfi_offset(31,-8)
 
 	/* Replicate byte to word.  */
-	rlwimi	4,4,8,16,23
-	rlwimi	4,4,16,0,15
+	insrdi	4,4,8,48
+	insrdi	4,4,16,32
 
 	ble	cr6,L(small)	/* If length <= 8, use short copy code.  */
 
diff --git a/sysdeps/powerpc/powerpc64/memset.S b/sysdeps/powerpc/powerpc64/memset.S
index 6acf149..1027a59 100644
--- a/sysdeps/powerpc/powerpc64/memset.S
+++ b/sysdeps/powerpc/powerpc64/memset.S
@@ -55,14 +55,14 @@ L(_memset):
 
 /* Align to doubleword boundary.  */
 	cmpldi	cr5, rLEN, 31
-	rlwimi	rCHR, rCHR, 8, 16, 23 /* Replicate byte to halfword.  */
+	insrdi	rCHR, rCHR, 8, 48	/* Replicate byte to halfword.  */
 	beq+	L(aligned2)
 	mtcrf	0x01, rMEMP0
 	subfic	rALIGN, rALIGN, 8
 	cror	28,30,31		/* Detect odd word aligned.  */
 	add	rMEMP, rMEMP, rALIGN
 	sub	rLEN, rLEN, rALIGN
-	rlwimi	rCHR, rCHR, 16, 0, 15 /* Replicate halfword to word.  */
+	insrdi	rCHR, rCHR, 16, 32	/* Replicate halfword to word.  */
 	bt	29, L(g4)
 /* Process the even word of doubleword.  */
 	bf+	31, L(g2)
@@ -84,14 +84,14 @@ L(g0):
 
 /* Handle the case of size < 31.  */
 L(aligned2):
-	rlwimi	rCHR, rCHR, 16, 0, 15 /* Replicate halfword to word.  */
+	insrdi	rCHR, rCHR, 16, 32	/* Replicate halfword to word.  */
 L(aligned):
 	mtcrf	0x01, rLEN
 	ble	cr5, L(medium)
 /* Align to 32-byte boundary.  */
 	andi.	rALIGN, rMEMP, 0x18
 	subfic	rALIGN, rALIGN, 0x20
-	insrdi	rCHR,rCHR,32,0 /* Replicate word to double word. */
+	insrdi	rCHR, rCHR, 32, 0	/* Replicate word to double word. */
 	beq	L(caligned)
 	mtcrf	0x01, rALIGN
 	add	rMEMP, rMEMP, rALIGN
@@ -212,7 +212,7 @@ L(le4):
 /* Memset of 0-31 bytes.  */
 	.align 5
 L(medium):
-	insrdi	rCHR,rCHR,32,0 /* Replicate word to double word.  */
+	insrdi	rCHR, rCHR, 32, 0	/* Replicate word to double word.  */
 	cmpldi	cr1, rLEN, 16
 L(medium_tail2):
 	add	rMEMP, rMEMP, rLEN
diff --git a/sysdeps/powerpc/powerpc64/power4/memset.S b/sysdeps/powerpc/powerpc64/power4/memset.S
index dbecee8..ad0d381 100644
--- a/sysdeps/powerpc/powerpc64/power4/memset.S
+++ b/sysdeps/powerpc/powerpc64/power4/memset.S
@@ -50,14 +50,14 @@ L(_memset):
 
 /* Align to doubleword boundary.  */
 	cmpldi	cr5, rLEN, 31
-	rlwimi	rCHR, rCHR, 8, 16, 23 /* Replicate byte to halfword.  */
+	insrdi	rCHR, rCHR, 8, 48	/* Replicate byte to halfword.  */
 	beq+	L(aligned2)
 	mtcrf	0x01, rMEMP0
 	subfic	rALIGN, rALIGN, 8
 	cror	28,30,31		/* Detect odd word aligned.  */
 	add	rMEMP, rMEMP, rALIGN
 	sub	rLEN, rLEN, rALIGN
-	rlwimi	rCHR, rCHR, 16, 0, 15 /* Replicate halfword to word.  */
+	insrdi	rCHR, rCHR, 16, 32	/* Replicate halfword to word.  */
 	bt	29, L(g4)
 /* Process the even word of doubleword.  */
 	bf+	31, L(g2)
@@ -79,14 +79,14 @@ L(g0):
 
 /* Handle the case of size < 31.  */
 L(aligned2):
-	rlwimi	rCHR, rCHR, 16, 0, 15 /* Replicate halfword to word.  */
+	insrdi	rCHR, rCHR, 16, 32	/* Replicate halfword to word.  */
 L(aligned):
 	mtcrf	0x01, rLEN
 	ble	cr5, L(medium)
 /* Align to 32-byte boundary.  */
 	andi.	rALIGN, rMEMP, 0x18
 	subfic	rALIGN, rALIGN, 0x20
-	insrdi	rCHR,rCHR,32,0 /* Replicate word to double word. */
+	insrdi	rCHR, rCHR, 32, 0	/* Replicate word to double word. */
 	beq	L(caligned)
 	mtcrf	0x01, rALIGN
 	add	rMEMP, rMEMP, rALIGN
@@ -146,24 +146,24 @@ L(zloopstart):
 L(getCacheAligned):
 	cmpldi	cr1,rLEN,32
 	andi.	rTMP,rMEMP,127
-	blt		cr1,L(handletail32)
-	beq		L(cacheAligned)
+	blt	cr1,L(handletail32)
+	beq	L(cacheAligned)
 	addi	rMEMP,rMEMP,32
 	addi	rLEN,rLEN,-32
-	std		rCHR,-32(rMEMP)
-	std		rCHR,-24(rMEMP)
-	std		rCHR,-16(rMEMP)
-	std		rCHR,-8(rMEMP)
-	b		L(getCacheAligned)
+	std	rCHR,-32(rMEMP)
+	std	rCHR,-24(rMEMP)
+	std	rCHR,-16(rMEMP)
+	std	rCHR,-8(rMEMP)
+	b	L(getCacheAligned)
 
 /* Now we are aligned to the cache line and can use dcbz.  */
 L(cacheAligned):
 	cmpld	cr1,rLEN,rCLS
-	blt		cr1,L(handletail32)
+	blt	cr1,L(handletail32)
 	dcbz	0,rMEMP
 	subf	rLEN,rCLS,rLEN
-	add		rMEMP,rMEMP,rCLS
-	b		L(cacheAligned)
+	add	rMEMP,rMEMP,rCLS
+	b	L(cacheAligned)
 
 /* We are here because the cache line size was set and was not 32-bytes
    and the remainder (rLEN) is less than the actual cache line size.
@@ -200,7 +200,7 @@ L(le4):
 /* Memset of 0-31 bytes.  */
 	.align 5
 L(medium):
-	insrdi	rCHR,rCHR,32,0 /* Replicate word to double word.  */
+	insrdi	rCHR, rCHR, 32, 0	/* Replicate word to double word.  */
 	cmpldi	cr1, rLEN, 16
 L(medium_tail2):
 	add	rMEMP, rMEMP, rLEN
diff --git a/sysdeps/powerpc/powerpc64/power6/memset.S b/sysdeps/powerpc/powerpc64/power6/memset.S
index 541a45f..a3864cc 100644
--- a/sysdeps/powerpc/powerpc64/power6/memset.S
+++ b/sysdeps/powerpc/powerpc64/power6/memset.S
@@ -47,14 +47,14 @@ L(_memset):
 
 /* Align to doubleword boundary.  */
 	cmpldi	cr5, rLEN, 31
-	rlwimi	rCHR, rCHR, 8, 16, 23 /* Replicate byte to halfword.  */
+	insrdi	rCHR, rCHR, 8, 48	/* Replicate byte to halfword.  */
 	beq+	L(aligned2)
 	mtcrf	0x01, rMEMP0
 	subfic	rALIGN, rALIGN, 8
 	cror	28,30,31		/* Detect odd word aligned.  */
 	add	rMEMP, rMEMP, rALIGN
 	sub	rLEN, rLEN, rALIGN
-	rlwimi	rCHR, rCHR, 16, 0, 15 /* Replicate halfword to word.  */
+	insrdi	rCHR, rCHR, 16, 32	/* Replicate halfword to word.  */
 	bt	29, L(g4)
 /* Process the even word of doubleword.  */
 	bf+	31, L(g2)
@@ -76,14 +76,14 @@ L(g0):
 
 /* Handle the case of size < 31.  */
 L(aligned2):
-	rlwimi	rCHR, rCHR, 16, 0, 15 /* Replicate halfword to word.  */
+	insrdi	rCHR, rCHR, 16, 32	/* Replicate halfword to word.  */
 L(aligned):
 	mtcrf	0x01, rLEN
 	ble	cr5, L(medium)
 /* Align to 32-byte boundary.  */
 	andi.	rALIGN, rMEMP, 0x18
 	subfic	rALIGN, rALIGN, 0x20
-	insrdi	rCHR,rCHR,32,0 /* Replicate word to double word. */
+	insrdi	rCHR, rCHR, 32, 0	/* Replicate word to double word. */
 	beq	L(caligned)
 	mtcrf	0x01, rALIGN
 	add	rMEMP, rMEMP, rALIGN
@@ -344,7 +344,7 @@ L(le4):
 /* Memset of 0-31 bytes.  */
 	.align 5
 L(medium):
-	insrdi	rCHR,rCHR,32,0 /* Replicate word to double word.  */
+	insrdi	rCHR, rCHR, 32, 0	/* Replicate word to double word.  */
 	cmpldi	cr1, rLEN, 16
 L(medium_tail2):
 	add	rMEMP, rMEMP, rLEN
diff --git a/sysdeps/powerpc/powerpc64/power7/memset.S b/sysdeps/powerpc/powerpc64/power7/memset.S
index b24cfa1..8b081e8 100644
--- a/sysdeps/powerpc/powerpc64/power7/memset.S
+++ b/sysdeps/powerpc/powerpc64/power7/memset.S
@@ -32,8 +32,8 @@ L(_memset):
 	mr	10,3
 
 	/* Replicate byte to word.  */
-	rlwimi	4,4,8,16,23
-	rlwimi	4,4,16,0,15
+	insrdi	4,4,8,48
+	insrdi	4,4,16,32
 	ble	cr6,L(small)	/* If length <= 8, use short copy code.  */
 
 	neg	0,3
@@ -321,7 +321,7 @@ L(medium):
 	clrldi	0,0,62
 	beq	L(medium_aligned)
 
-	/* Force 4-bytes alignment for SRC.  */
+	/* Force 4-bytes alignment for DST.  */
 	mtocrf	0x01,0
 	subf	5,0,5
 1:	/* Copy 1 byte.  */

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=0455a7b91e468c01869cdbb8ac6b532e4cf4a60a

commit 0455a7b91e468c01869cdbb8ac6b532e4cf4a60a
Author: Alan Modra <amodra@gmail.com>
Date:   Sat Aug 17 18:47:22 2013 +0930

    PowerPC LE memcpy
    http://sourceware.org/ml/libc-alpha/2013-08/msg00103.html
    
    LIttle-endian support for memcpy.  I spent some time cleaning up the
    64-bit power7 memcpy, in order to avoid the extra alignment traps
    power7 takes for little-endian.  It probably would have been better
    to copy the linux kernel version of memcpy.
    
    	* sysdeps/powerpc/powerpc32/power4/memcpy.S: Add little endian support.
    	* sysdeps/powerpc/powerpc32/power6/memcpy.S: Likewise.
    	* sysdeps/powerpc/powerpc32/power7/memcpy.S: Likewise.
    	* sysdeps/powerpc/powerpc32/power7/mempcpy.S: Likewise.
    	* sysdeps/powerpc/powerpc64/memcpy.S: Likewise.
    	* sysdeps/powerpc/powerpc64/power4/memcpy.S: Likewise.
    	* sysdeps/powerpc/powerpc64/power6/memcpy.S: Likewise.
    	* sysdeps/powerpc/powerpc64/power7/memcpy.S: Likewise.
    	* sysdeps/powerpc/powerpc64/power7/mempcpy.S: Likewise.  Make better
    	use of regs.  Use power7 mtocrf.  Tidy function tails.

diff --git a/ChangeLog b/ChangeLog
index 42d88db..3632248 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,18 @@
 2013-10-04  Alan Modra  <amodra@gmail.com>
 
+	* sysdeps/powerpc/powerpc32/power4/memcpy.S: Add little endian support.
+	* sysdeps/powerpc/powerpc32/power6/memcpy.S: Likewise.
+	* sysdeps/powerpc/powerpc32/power7/memcpy.S: Likewise.
+	* sysdeps/powerpc/powerpc32/power7/mempcpy.S: Likewise.
+	* sysdeps/powerpc/powerpc64/memcpy.S: Likewise.
+	* sysdeps/powerpc/powerpc64/power4/memcpy.S: Likewise.
+	* sysdeps/powerpc/powerpc64/power6/memcpy.S: Likewise.
+	* sysdeps/powerpc/powerpc64/power7/memcpy.S: Likewise.
+	* sysdeps/powerpc/powerpc64/power7/mempcpy.S: Likewise.  Make better
+	use of regs.  Use power7 mtocrf.  Tidy function tails.
+
+2013-10-04  Alan Modra  <amodra@gmail.com>
+
 	* sysdeps/powerpc/powerpc64/power7/memcmp.S: Add little-endian support.
 	Formatting.  Consistently use rXXX register defines or rN defines.
 	Use early exit labels that avoid restoring unused non-volatile regs.
diff --git a/sysdeps/powerpc/powerpc32/power4/memcpy.S b/sysdeps/powerpc/powerpc32/power4/memcpy.S
index d914663..338d3cc 100644
--- a/sysdeps/powerpc/powerpc32/power4/memcpy.S
+++ b/sysdeps/powerpc/powerpc32/power4/memcpy.S
@@ -203,15 +203,28 @@ EALIGN (memcpy, 5, 0)
     blt   cr6,5f
     srwi  7,6,16
     bgt	  cr6,3f
+#ifdef __LITTLE_ENDIAN__
+    sth   7,0(3)
+#else
     sth   6,0(3)
+#endif
     b     7f
     .align  4
 3:
+#ifdef __LITTLE_ENDIAN__
+    rotlwi 6,6,24
+    stb   6,0(3)
+    sth   7,1(3)
+#else
     stb   7,0(3)
     sth   6,1(3)
+#endif
     b     7f
     .align  4
 5:
+#ifdef __LITTLE_ENDIAN__
+    rotlwi 6,6,8
+#endif
     stb   6,0(3)
 7:
     cmplwi	cr1,10,16
@@ -339,13 +352,23 @@ EALIGN (memcpy, 5, 0)
     bf      30,1f
 
     /* there are at least two words to copy, so copy them */
+#ifdef __LITTLE_ENDIAN__
+    srw   0,6,10
+    slw   8,7,9
+#else
     slw   0,6,10  /* shift 1st src word to left align it in R0 */
     srw   8,7,9   /* shift 2nd src word to right align it in R8 */
+#endif
     or    0,0,8   /* or them to get word to store */
     lwz   6,8(5)  /* load the 3rd src word */
     stw   0,0(4)  /* store the 1st dst word */
+#ifdef __LITTLE_ENDIAN__
+    srw   0,7,10
+    slw   8,6,9
+#else
     slw   0,7,10  /* now left align 2nd src word into R0 */
     srw   8,6,9   /* shift 3rd src word to right align it in R8 */
+#endif
     or    0,0,8   /* or them to get word to store */
     lwz   7,12(5)
     stw   0,4(4)  /* store the 2nd dst word */
@@ -353,8 +376,13 @@ EALIGN (memcpy, 5, 0)
     addi  5,5,16
     bf    31,4f
     /* there is a third word to copy, so copy it */
+#ifdef __LITTLE_ENDIAN__
+    srw   0,6,10
+    slw   8,7,9
+#else
     slw   0,6,10  /* shift 3rd src word to left align it in R0 */
     srw   8,7,9   /* shift 4th src word to right align it in R8 */
+#endif
     or    0,0,8   /* or them to get word to store */
     stw   0,0(4)  /* store 3rd dst word */
     mr    6,7
@@ -364,8 +392,13 @@ EALIGN (memcpy, 5, 0)
     b     4f
     .align 4
 1:
+#ifdef __LITTLE_ENDIAN__
+    srw     0,6,10
+    slw     8,7,9
+#else
     slw     0,6,10  /* shift 1st src word to left align it in R0 */
     srw     8,7,9   /* shift 2nd src word to right align it in R8 */
+#endif
     addi  5,5,8
     or    0,0,8   /* or them to get word to store */
     bf    31,4f
@@ -378,23 +411,43 @@ EALIGN (memcpy, 5, 0)
     .align  4
 4:
     /* copy 16 bytes at a time */
+#ifdef __LITTLE_ENDIAN__
+    srw   0,6,10
+    slw   8,7,9
+#else
     slw   0,6,10
     srw   8,7,9
+#endif
     or    0,0,8
     lwz   6,0(5)
     stw   0,0(4)
+#ifdef __LITTLE_ENDIAN__
+    srw   0,7,10
+    slw   8,6,9
+#else
     slw   0,7,10
     srw   8,6,9
+#endif
     or    0,0,8
     lwz   7,4(5)
     stw   0,4(4)
+#ifdef __LITTLE_ENDIAN__
+    srw   0,6,10
+    slw   8,7,9
+#else
     slw   0,6,10
     srw   8,7,9
+#endif
     or    0,0,8
     lwz   6,8(5)
     stw   0,8(4)
+#ifdef __LITTLE_ENDIAN__
+    srw   0,7,10
+    slw   8,6,9
+#else
     slw   0,7,10
     srw   8,6,9
+#endif
     or    0,0,8
     lwz   7,12(5)
     stw   0,12(4)
@@ -403,8 +456,13 @@ EALIGN (memcpy, 5, 0)
     bdnz+ 4b
 8:
     /* calculate and store the final word */
+#ifdef __LITTLE_ENDIAN__
+    srw   0,6,10
+    slw   8,7,9
+#else
     slw   0,6,10
     srw   8,7,9
+#endif
     or    0,0,8
     stw   0,0(4)
 3:
diff --git a/sysdeps/powerpc/powerpc32/power6/memcpy.S b/sysdeps/powerpc/powerpc32/power6/memcpy.S
index c3d55b7..9c80767 100644
--- a/sysdeps/powerpc/powerpc32/power6/memcpy.S
+++ b/sysdeps/powerpc/powerpc32/power6/memcpy.S
@@ -219,15 +219,28 @@ L(word_unaligned_short):
     blt   cr6,5f
     srwi  7,6,16
     bgt	  cr6,3f
+#ifdef __LITTLE_ENDIAN__
+    sth   7,0(3)
+#else
     sth   6,0(3)
+#endif
     b     7f
     .align  4
 3:
+#ifdef __LITTLE_ENDIAN__
+    rotlwi 6,6,24
+    stb   6,0(3)
+    sth   7,1(3)
+#else
     stb   7,0(3)
     sth   6,1(3)
+#endif
     b     7f
     .align  4
 5:
+#ifdef __LITTLE_ENDIAN__
+    rotlwi 6,6,8
+#endif
     stb   6,0(3)
 7:
     cmplwi	cr1,10,16
@@ -577,7 +590,11 @@ L(wdu1_32):
     lwz     6,-1(4)
     cmplwi  cr6,31,4
     srwi    8,31,5    /* calculate the 32 byte loop count */
+#ifdef __LITTLE_ENDIAN__
+    srwi    6,6,8
+#else
     slwi    6,6,8
+#endif
     clrlwi  31,31,27   /* The remaining bytes, < 32.  */
     blt     cr5,L(wdu1_32tail)
     mtctr   8
@@ -585,8 +602,12 @@ L(wdu1_32):
 
     lwz   8,3(4)
     lwz   7,4(4)
+#ifdef __LITTLE_ENDIAN__
+    rldimi 6,8,24,32
+#else
 /*  Equivalent to: srwi   8,8,32-8;  or    6,6,8 */
     rlwimi 6,8,8,(32-8),31
+#endif
     b      L(wdu1_loop32x)
     .align  4
 L(wdu1_loop32):
@@ -595,8 +616,12 @@ L(wdu1_loop32):
     lwz   7,4(4)
     stw   10,-8(3)
     stw   11,-4(3)
+#ifdef __LITTLE_ENDIAN__
+    rldimi 6,8,24,32
+#else
 /*  Equivalent to  srwi   8,8,32-8; or    6,6,8 */
     rlwimi 6,8,8,(32-8),31
+#endif
 L(wdu1_loop32x):
     lwz   10,8(4)
     lwz   11,12(4)
@@ -613,7 +638,11 @@ L(wdu1_loop32x):
     stw   6,16(3)
     stw   7,20(3)
     addi  3,3,32
+#ifdef __LITTLE_ENDIAN__
+    srwi  6,8,8
+#else
     slwi  6,8,8
+#endif
     bdnz+ L(wdu1_loop32)
     stw   10,-8(3)
     stw   11,-4(3)
@@ -624,8 +653,12 @@ L(wdu1_32tail):
     blt     cr6,L(wdu_4tail)
     /* calculate and store the final word */
     lwz   8,3(4)
-/*  Equivalent to: srwi   8,8,32-9;  or    6,6,8  */
+#ifdef __LITTLE_ENDIAN__
+    rldimi 6,8,24,32
+#else
+/*  Equivalent to: srwi   8,8,32-8;  or    6,6,8  */
     rlwimi 6,8,8,(32-8),31
+#endif
     b     L(wdu_32tailx)
 
 L(wdu2_32):
@@ -633,7 +666,11 @@ L(wdu2_32):
     lwz     6,-2(4)
     cmplwi  cr6,31,4
     srwi    8,31,5    /* calculate the 32 byte loop count */
+#ifdef __LITTLE_ENDIAN__
+    srwi    6,6,16
+#else
     slwi    6,6,16
+#endif
     clrlwi  31,31,27   /* The remaining bytes, < 32.  */
     blt     cr5,L(wdu2_32tail)
     mtctr   8
@@ -641,8 +678,11 @@ L(wdu2_32):
 
     lwz   8,2(4)
     lwz   7,4(4)
-/*  Equivalent to: srwi   8,8,32-8;  or    6,6,8 */
+#ifdef __LITTLE_ENDIAN__
+    rldimi 6,8,16,32
+#else
     rlwimi 6,8,16,(32-16),31
+#endif
     b      L(wdu2_loop32x)
     .align  4
 L(wdu2_loop32):
@@ -651,8 +691,11 @@ L(wdu2_loop32):
     lwz   7,4(4)
     stw   10,-8(3)
     stw   11,-4(3)
-/*  Equivalent to  srwi   8,8,32-8; or    6,6,8 */
+#ifdef __LITTLE_ENDIAN__
+    rldimi 6,8,16,32
+#else
     rlwimi 6,8,16,(32-16),31
+#endif
 L(wdu2_loop32x):
     lwz   10,8(4)
     lwz   11,12(4)
@@ -670,7 +713,11 @@ L(wdu2_loop32x):
     stw   6,16(3)
     stw   7,20(3)
     addi  3,3,32
+#ifdef __LITTLE_ENDIAN__
+    srwi  6,8,16
+#else
     slwi  6,8,16
+#endif
     bdnz+ L(wdu2_loop32)
     stw   10,-8(3)
     stw   11,-4(3)
@@ -681,8 +728,11 @@ L(wdu2_32tail):
     blt     cr6,L(wdu_4tail)
     /* calculate and store the final word */
     lwz   8,2(4)
-/*  Equivalent to: srwi   8,8,32-9;  or    6,6,8  */
+#ifdef __LITTLE_ENDIAN__
+    rldimi 6,8,16,32
+#else
     rlwimi 6,8,16,(32-16),31
+#endif
     b     L(wdu_32tailx)
 
 L(wdu3_32):
@@ -690,7 +740,11 @@ L(wdu3_32):
     lwz     6,-3(4)
     cmplwi  cr6,31,4
     srwi    8,31,5    /* calculate the 32 byte loop count */
+#ifdef __LITTLE_ENDIAN__
+    srwi    6,6,24
+#else
     slwi    6,6,24
+#endif
     clrlwi  31,31,27   /* The remaining bytes, < 32.  */
     blt     cr5,L(wdu3_32tail)
     mtctr   8
@@ -698,8 +752,11 @@ L(wdu3_32):
 
     lwz   8,1(4)
     lwz   7,4(4)
-/*  Equivalent to: srwi   8,8,32-8;  or    6,6,8 */
+#ifdef __LITTLE_ENDIAN__
+    rldimi 6,8,8,32
+#else
     rlwimi 6,8,24,(32-24),31
+#endif
     b      L(wdu3_loop32x)
     .align  4
 L(wdu3_loop32):
@@ -708,8 +765,11 @@ L(wdu3_loop32):
     lwz   7,4(4)
     stw   10,-8(3)
     stw   11,-4(3)
-/*  Equivalent to  srwi   8,8,32-8; or    6,6,8 */
+#ifdef __LITTLE_ENDIAN__
+    rldimi 6,8,8,32
+#else
     rlwimi 6,8,24,(32-24),31
+#endif
 L(wdu3_loop32x):
     lwz   10,8(4)
     lwz   11,12(4)
@@ -726,7 +786,11 @@ L(wdu3_loop32x):
     stw   6,16(3)
     stw   7,20(3)
     addi  3,3,32
+#ifdef __LITTLE_ENDIAN__
+    srwi  6,8,24
+#else
     slwi  6,8,24
+#endif
     bdnz+ L(wdu3_loop32)
     stw   10,-8(3)
     stw   11,-4(3)
@@ -737,8 +801,11 @@ L(wdu3_32tail):
     blt     cr6,L(wdu_4tail)
     /* calculate and store the final word */
     lwz   8,1(4)
-/*  Equivalent to: srwi   8,8,32-9;  or    6,6,8  */
+#ifdef __LITTLE_ENDIAN__
+    rldimi 6,8,8,32
+#else
     rlwimi 6,8,24,(32-24),31
+#endif
     b     L(wdu_32tailx)
     .align  4
 L(wdu_32tailx):
diff --git a/sysdeps/powerpc/powerpc32/power7/memcpy.S b/sysdeps/powerpc/powerpc32/power7/memcpy.S
index 7f00778..acf3c10 100644
--- a/sysdeps/powerpc/powerpc32/power7/memcpy.S
+++ b/sysdeps/powerpc/powerpc32/power7/memcpy.S
@@ -383,7 +383,7 @@ L(copy_GE_32_unaligned):
 
 	beq    L(copy_GE_32_unaligned_cont)
 
-	/* SRC is not quadword aligned, get it aligned.  */
+	/* DST is not quadword aligned, get it aligned.  */
 
 	mtcrf   0x01,0
 	subf    31,0,5
@@ -435,13 +435,21 @@ L(copy_GE_32_unaligned_cont):
 	mr      11,12
 	mtcrf   0x01,9
 	cmplwi  cr6,9,1
+#ifdef __LITTLE_ENDIAN__
+	lvsr    5,0,12
+#else
 	lvsl    5,0,12
+#endif
 	lvx     3,0,12
 	bf      31,L(setup_unaligned_loop)
 
 	/* Copy another 16 bytes to align to 32-bytes due to the loop .  */
 	lvx     4,12,6
+#ifdef __LITTLE_ENDIAN__
+	vperm   6,4,3,5
+#else
 	vperm   6,3,4,5
+#endif
 	addi    11,12,16
 	addi    10,3,16
 	stvx    6,0,3
@@ -461,11 +469,17 @@ L(unaligned_loop):
 	vector instructions though.  */
 
 	lvx	4,11,6	      /* vr4 = r11+16.  */
-	vperm   6,3,4,5	      /* Merge the correctly-aligned portions
-			      of vr3/vr4 into vr6.  */
+#ifdef __LITTLE_ENDIAN__
+	vperm   6,4,3,5
+#else
+	vperm   6,3,4,5
+#endif
 	lvx	3,11,7	      /* vr3 = r11+32.  */
-	vperm   10,4,3,5      /* Merge the correctly-aligned portions
-			      of vr3/vr4 into vr10.  */
+#ifdef __LITTLE_ENDIAN__
+	vperm   10,3,4,5
+#else
+	vperm   10,4,3,5
+#endif
 	addi    11,11,32
 	stvx    6,0,10
 	stvx    10,10,6
diff --git a/sysdeps/powerpc/powerpc32/power7/mempcpy.S b/sysdeps/powerpc/powerpc32/power7/mempcpy.S
index 5ad4edb..4610ec5 100644
--- a/sysdeps/powerpc/powerpc32/power7/mempcpy.S
+++ b/sysdeps/powerpc/powerpc32/power7/mempcpy.S
@@ -325,7 +325,7 @@ L(copy_GE_32_unaligned):
 
 	beq	L(copy_GE_32_unaligned_cont)
 
-	/* SRC is not quadword aligned, get it aligned.  */
+	/* DST is not quadword aligned, get it aligned.  */
 
 	mtcrf	0x01,0
 	subf	31,0,5
@@ -377,13 +377,21 @@ L(copy_GE_32_unaligned_cont):
 	mr	11,12
 	mtcrf	0x01,9
 	cmplwi	cr6,9,1
-	lvsl	5,0,12
+#ifdef __LITTLE_ENDIAN__
+	lvsr    5,0,12
+#else
+	lvsl    5,0,12
+#endif
 	lvx	3,0,12
 	bf	31,L(setup_unaligned_loop)
 
 	/* Copy another 16 bytes to align to 32-bytes due to the loop .  */
 	lvx	4,12,6
-	vperm	6,3,4,5
+#ifdef __LITTLE_ENDIAN__
+	vperm   6,4,3,5
+#else
+	vperm   6,3,4,5
+#endif
 	addi	11,12,16
 	addi	10,3,16
 	stvx	6,0,3
@@ -403,11 +411,17 @@ L(unaligned_loop):
 	vector instructions though.  */
 
 	lvx	4,11,6	      /* vr4 = r11+16.  */
-	vperm	6,3,4,5	      /* Merge the correctly-aligned portions
-				 of vr3/vr4 into vr6.  */
+#ifdef __LITTLE_ENDIAN__
+	vperm   6,4,3,5
+#else
+	vperm   6,3,4,5
+#endif
 	lvx	3,11,7	      /* vr3 = r11+32.  */
-	vperm	10,4,3,5      /* Merge the correctly-aligned portions
-				 of vr3/vr4 into vr10.  */
+#ifdef __LITTLE_ENDIAN__
+	vperm   10,3,4,5
+#else
+	vperm   10,4,3,5
+#endif
 	addi	11,11,32
 	stvx	6,0,10
 	stvx	10,10,6
diff --git a/sysdeps/powerpc/powerpc64/memcpy.S b/sysdeps/powerpc/powerpc64/memcpy.S
index b8c4cc8..5fc7401 100644
--- a/sysdeps/powerpc/powerpc64/memcpy.S
+++ b/sysdeps/powerpc/powerpc64/memcpy.S
@@ -212,15 +212,28 @@ EALIGN (memcpy, 5, 0)
     blt   cr6,5f
     srdi  7,6,16
     bgt	  cr6,3f
+#ifdef __LITTLE_ENDIAN__
+    sth   7,0(3)
+#else
     sth   6,0(3)
+#endif
     b     7f
     .align  4
 3:
+#ifdef __LITTLE_ENDIAN__
+    rotlwi 6,6,24
+    stb   6,0(3)
+    sth   7,1(3)
+#else
     stb   7,0(3)
     sth   6,1(3)
+#endif
     b     7f
     .align  4
 5:
+#ifdef __LITTLE_ENDIAN__
+    rotlwi 6,6,8
+#endif
     stb   6,0(3)
 7:
     cmpldi	cr1,10,16
@@ -328,7 +341,11 @@ EALIGN (memcpy, 5, 0)
     ld    7,8(5)
     subfic  9,10,64
     beq   2f
+#ifdef __LITTLE_ENDIAN__
+    srd   0,6,10
+#else
     sld   0,6,10
+#endif
     cmpldi  11,1
     mr    6,7
     addi  4,4,-8
@@ -336,15 +353,25 @@ EALIGN (memcpy, 5, 0)
     b     1f
 2:  addi  5,5,8
     .align  4
+#ifdef __LITTLE_ENDIAN__
+0:  srd   0,6,10
+    sld   8,7,9
+#else
 0:  sld   0,6,10
     srd   8,7,9
+#endif
     cmpldi  11,2
     ld    6,8(5)
     or    0,0,8
     addi  11,11,-2
     std   0,0(4)
+#ifdef __LITTLE_ENDIAN__
+    srd   0,7,10
+1:  sld   8,6,9
+#else
     sld   0,7,10
 1:  srd   8,6,9
+#endif
     or    0,0,8
     beq   8f
     ld    7,16(5)
diff --git a/sysdeps/powerpc/powerpc64/power4/memcpy.S b/sysdeps/powerpc/powerpc64/power4/memcpy.S
index 4317c7e..f9a7260 100644
--- a/sysdeps/powerpc/powerpc64/power4/memcpy.S
+++ b/sysdeps/powerpc/powerpc64/power4/memcpy.S
@@ -214,15 +214,28 @@ EALIGN (memcpy, 5, 0)
     blt   cr6,5f
     srdi  7,6,16
     bgt	  cr6,3f
+#ifdef __LITTLE_ENDIAN__
+    sth   7,0(3)
+#else
     sth   6,0(3)
+#endif
     b     7f
     .align  4
 3:
+#ifdef __LITTLE_ENDIAN__
+    rotlwi 6,6,24
+    stb   6,0(3)
+    sth   7,1(3)
+#else
     stb   7,0(3)
     sth   6,1(3)
+#endif
     b     7f
     .align  4
 5:
+#ifdef __LITTLE_ENDIAN__
+    rotlwi 6,6,8
+#endif
     stb   6,0(3)
 7:
     cmpldi	cr1,10,16
@@ -334,13 +347,23 @@ EALIGN (memcpy, 5, 0)
     bf      30,1f
 
     /* there are at least two DWs to copy */
+#ifdef __LITTLE_ENDIAN__
+    srd     0,6,10
+    sld     8,7,9
+#else
     sld     0,6,10
     srd     8,7,9
+#endif
     or      0,0,8
     ld      6,16(5)
     std     0,0(4)
+#ifdef __LITTLE_ENDIAN__
+    srd     0,7,10
+    sld     8,6,9
+#else
     sld     0,7,10
     srd     8,6,9
+#endif
     or      0,0,8
     ld      7,24(5)
     std     0,8(4)
@@ -349,8 +372,13 @@ EALIGN (memcpy, 5, 0)
     blt     cr6,8f  /* if total DWs = 3, then bypass loop */
     bf      31,4f
     /* there is a third DW to copy */
+#ifdef __LITTLE_ENDIAN__
+    srd     0,6,10
+    sld     8,7,9
+#else
     sld     0,6,10
     srd     8,7,9
+#endif
     or      0,0,8
     std     0,0(4)
     mr      6,7
@@ -361,8 +389,13 @@ EALIGN (memcpy, 5, 0)
     b       4f
     .align 4
 1:
+#ifdef __LITTLE_ENDIAN__
+    srd     0,6,10
+    sld     8,7,9
+#else
     sld     0,6,10
     srd     8,7,9
+#endif
     addi    5,5,16
     or      0,0,8
     bf      31,4f
@@ -373,23 +406,44 @@ EALIGN (memcpy, 5, 0)
     addi    4,4,8
     .align 4
 /* copy 32 bytes at a time */
-4:  sld   0,6,10
+4:
+#ifdef __LITTLE_ENDIAN__
+    srd   0,6,10
+    sld   8,7,9
+#else
+    sld   0,6,10
     srd   8,7,9
+#endif
     or    0,0,8
     ld    6,0(5)
     std   0,0(4)
+#ifdef __LITTLE_ENDIAN__
+    srd   0,7,10
+    sld   8,6,9
+#else
     sld   0,7,10
     srd   8,6,9
+#endif
     or    0,0,8
     ld    7,8(5)
     std   0,8(4)
+#ifdef __LITTLE_ENDIAN__
+    srd   0,6,10
+    sld   8,7,9
+#else
     sld   0,6,10
     srd   8,7,9
+#endif
     or    0,0,8
     ld    6,16(5)
     std   0,16(4)
+#ifdef __LITTLE_ENDIAN__
+    srd   0,7,10
+    sld   8,6,9
+#else
     sld   0,7,10
     srd   8,6,9
+#endif
     or    0,0,8
     ld    7,24(5)
     std   0,24(4)
@@ -399,8 +453,13 @@ EALIGN (memcpy, 5, 0)
     .align 4
 8:
     /* calculate and store the final DW */
+#ifdef __LITTLE_ENDIAN__
+    srd   0,6,10
+    sld   8,7,9
+#else
     sld   0,6,10
     srd   8,7,9
+#endif
     or    0,0,8
     std   0,0(4)
 3:
diff --git a/sysdeps/powerpc/powerpc64/power6/memcpy.S b/sysdeps/powerpc/powerpc64/power6/memcpy.S
index db29e2b..aa0802e 100644
--- a/sysdeps/powerpc/powerpc64/power6/memcpy.S
+++ b/sysdeps/powerpc/powerpc64/power6/memcpy.S
@@ -400,15 +400,28 @@ L(das_tail2):
     blt   cr6,5f
     srdi  7,6,16
     bgt	  cr6,3f
+#ifdef __LITTLE_ENDIAN__
+    sth   7,0(3)
+#else
     sth   6,0(3)
+#endif
     b     7f
     .align  4
 3:
+#ifdef __LITTLE_ENDIAN__
+    rotlwi 6,6,24
+    stb   6,0(3)
+    sth   7,1(3)
+#else
     stb   7,0(3)
     sth   6,1(3)
+#endif
     b     7f
     .align  4
 5:
+#ifdef __LITTLE_ENDIAN__
+    rotlwi 6,6,8
+#endif
     stb   6,0(3)
 7:
     cmpldi	cr1,10,16
@@ -595,13 +608,24 @@ L(du1_do):
     bf      30,L(du1_1dw)
 
     /* there are at least two DWs to copy */
+    /* FIXME: can combine last shift and "or" into "rldimi" */
+#ifdef __LITTLE_ENDIAN__
+    srdi     0,6, 8
+    sldi     8,7, 64-8
+#else
     sldi     0,6, 8
     srdi     8,7, 64-8
+#endif
     or      0,0,8
     ld      6,16(5)
     std     0,0(4)
+#ifdef __LITTLE_ENDIAN__
+    srdi     0,7, 8
+    sldi     8,6, 64-8
+#else
     sldi     0,7, 8
     srdi     8,6, 64-8
+#endif
     or      0,0,8
     ld      7,24(5)
     std     0,8(4)
@@ -610,8 +634,13 @@ L(du1_do):
     blt     cr6,L(du1_fini)  /* if total DWs = 3, then bypass loop */
     bf      31,L(du1_loop)
     /* there is a third DW to copy */
+#ifdef __LITTLE_ENDIAN__
+    srdi     0,6, 8
+    sldi     8,7, 64-8
+#else
     sldi     0,6, 8
     srdi     8,7, 64-8
+#endif
     or      0,0,8
     std     0,0(4)
     mr      6,7
@@ -622,8 +651,13 @@ L(du1_do):
     b       L(du1_loop)
     .align 4
 L(du1_1dw):
+#ifdef __LITTLE_ENDIAN__
+    srdi     0,6, 8
+    sldi     8,7, 64-8
+#else
     sldi     0,6, 8
     srdi     8,7, 64-8
+#endif
     addi    5,5,16
     or      0,0,8
     bf      31,L(du1_loop)
@@ -635,23 +669,43 @@ L(du1_1dw):
     .align 4
 /* copy 32 bytes at a time */
 L(du1_loop):
+#ifdef __LITTLE_ENDIAN__
+    srdi   0,6, 8
+    sldi   8,7, 64-8
+#else
     sldi   0,6, 8
     srdi   8,7, 64-8
+#endif
     or    0,0,8
     ld    6,0(5)
     std   0,0(4)
+#ifdef __LITTLE_ENDIAN__
+    srdi   0,7, 8
+    sldi   8,6, 64-8
+#else
     sldi   0,7, 8
     srdi   8,6, 64-8
+#endif
     or    0,0,8
     ld    7,8(5)
     std   0,8(4)
+#ifdef __LITTLE_ENDIAN__
+    srdi   0,6, 8
+    sldi   8,7, 64-8
+#else
     sldi   0,6, 8
     srdi   8,7, 64-8
+#endif
     or    0,0,8
     ld    6,16(5)
     std   0,16(4)
+#ifdef __LITTLE_ENDIAN__
+    srdi   0,7, 8
+    sldi   8,6, 64-8
+#else
     sldi   0,7, 8
     srdi   8,6, 64-8
+#endif
     or    0,0,8
     ld    7,24(5)
     std   0,24(4)
@@ -661,8 +715,13 @@ L(du1_loop):
     .align 4
 L(du1_fini):
     /* calculate and store the final DW */
+#ifdef __LITTLE_ENDIAN__
+    srdi   0,6, 8
+    sldi   8,7, 64-8
+#else
     sldi   0,6, 8
     srdi   8,7, 64-8
+#endif
     or    0,0,8
     std   0,0(4)
     b     L(du_done)
@@ -672,13 +731,23 @@ L(du2_do):
     bf      30,L(du2_1dw)
 
     /* there are at least two DWs to copy */
+#ifdef __LITTLE_ENDIAN__
+    srdi     0,6, 16
+    sldi     8,7, 64-16
+#else
     sldi     0,6, 16
     srdi     8,7, 64-16
+#endif
     or      0,0,8
     ld      6,16(5)
     std     0,0(4)
+#ifdef __LITTLE_ENDIAN__
+    srdi     0,7, 16
+    sldi     8,6, 64-16
+#else
     sldi     0,7, 16
     srdi     8,6, 64-16
+#endif
     or      0,0,8
     ld      7,24(5)
     std     0,8(4)
@@ -687,8 +756,13 @@ L(du2_do):
     blt     cr6,L(du2_fini)  /* if total DWs = 3, then bypass loop */
     bf      31,L(du2_loop)
     /* there is a third DW to copy */
+#ifdef __LITTLE_ENDIAN__
+    srdi     0,6, 16
+    sldi     8,7, 64-16
+#else
     sldi     0,6, 16
     srdi     8,7, 64-16
+#endif
     or      0,0,8
     std     0,0(4)
     mr      6,7
@@ -699,8 +773,13 @@ L(du2_do):
     b       L(du2_loop)
     .align 4
 L(du2_1dw):
+#ifdef __LITTLE_ENDIAN__
+    srdi     0,6, 16
+    sldi     8,7, 64-16
+#else
     sldi     0,6, 16
     srdi     8,7, 64-16
+#endif
     addi    5,5,16
     or      0,0,8
     bf      31,L(du2_loop)
@@ -712,23 +791,43 @@ L(du2_1dw):
     .align 4
 /* copy 32 bytes at a time */
 L(du2_loop):
+#ifdef __LITTLE_ENDIAN__
+    srdi   0,6, 16
+    sldi   8,7, 64-16
+#else
     sldi   0,6, 16
     srdi   8,7, 64-16
+#endif
     or    0,0,8
     ld    6,0(5)
     std   0,0(4)
+#ifdef __LITTLE_ENDIAN__
+    srdi   0,7, 16
+    sldi   8,6, 64-16
+#else
     sldi   0,7, 16
     srdi   8,6, 64-16
+#endif
     or    0,0,8
     ld    7,8(5)
     std   0,8(4)
+#ifdef __LITTLE_ENDIAN__
+    srdi   0,6, 16
+    sldi   8,7, 64-16
+#else
     sldi   0,6, 16
     srdi   8,7, 64-16
+#endif
     or    0,0,8
     ld    6,16(5)
     std   0,16(4)
+#ifdef __LITTLE_ENDIAN__
+    srdi   0,7, 16
+    sldi   8,6, 64-16
+#else
     sldi   0,7, 16
     srdi   8,6, 64-16
+#endif
     or    0,0,8
     ld    7,24(5)
     std   0,24(4)
@@ -738,8 +837,13 @@ L(du2_loop):
     .align 4
 L(du2_fini):
     /* calculate and store the final DW */
+#ifdef __LITTLE_ENDIAN__
+    srdi   0,6, 16
+    sldi   8,7, 64-16
+#else
     sldi   0,6, 16
     srdi   8,7, 64-16
+#endif
     or    0,0,8
     std   0,0(4)
     b     L(du_done)
@@ -749,13 +853,23 @@ L(du3_do):
     bf      30,L(du3_1dw)
 
     /* there are at least two DWs to copy */
+#ifdef __LITTLE_ENDIAN__
+    srdi     0,6, 24
+    sldi     8,7, 64-24
+#else
     sldi     0,6, 24
     srdi     8,7, 64-24
+#endif
     or      0,0,8
     ld      6,16(5)
     std     0,0(4)
+#ifdef __LITTLE_ENDIAN__
+    srdi     0,7, 24
+    sldi     8,6, 64-24
+#else
     sldi     0,7, 24
     srdi     8,6, 64-24
+#endif
     or      0,0,8
     ld      7,24(5)
     std     0,8(4)
@@ -764,8 +878,13 @@ L(du3_do):
     blt     cr6,L(du3_fini)  /* if total DWs = 3, then bypass loop */
     bf      31,L(du3_loop)
     /* there is a third DW to copy */
+#ifdef __LITTLE_ENDIAN__
+    srdi     0,6, 24
+    sldi     8,7, 64-24
+#else
     sldi     0,6, 24
     srdi     8,7, 64-24
+#endif
     or      0,0,8
     std     0,0(4)
     mr      6,7
@@ -776,8 +895,13 @@ L(du3_do):
     b       L(du3_loop)
     .align 4
 L(du3_1dw):
+#ifdef __LITTLE_ENDIAN__
+    srdi     0,6, 24
+    sldi     8,7, 64-24
+#else
     sldi     0,6, 24
     srdi     8,7, 64-24
+#endif
     addi    5,5,16
     or      0,0,8
     bf      31,L(du3_loop)
@@ -789,23 +913,43 @@ L(du3_1dw):
     .align 4
 /* copy 32 bytes at a time */
 L(du3_loop):
+#ifdef __LITTLE_ENDIAN__
+    srdi   0,6, 24
+    sldi   8,7, 64-24
+#else
     sldi   0,6, 24
     srdi   8,7, 64-24
+#endif
     or    0,0,8
     ld    6,0(5)
     std   0,0(4)
+#ifdef __LITTLE_ENDIAN__
+    srdi   0,7, 24
+    sldi   8,6, 64-24
+#else
     sldi   0,7, 24
     srdi   8,6, 64-24
+#endif
     or    0,0,8
     ld    7,8(5)
     std   0,8(4)
+#ifdef __LITTLE_ENDIAN__
+    srdi   0,6, 24
+    sldi   8,7, 64-24
+#else
     sldi   0,6, 24
     srdi   8,7, 64-24
+#endif
     or    0,0,8
     ld    6,16(5)
     std   0,16(4)
+#ifdef __LITTLE_ENDIAN__
+    srdi   0,7, 24
+    sldi   8,6, 64-24
+#else
     sldi   0,7, 24
     srdi   8,6, 64-24
+#endif
     or    0,0,8
     ld    7,24(5)
     std   0,24(4)
@@ -815,8 +959,13 @@ L(du3_loop):
     .align 4
 L(du3_fini):
     /* calculate and store the final DW */
+#ifdef __LITTLE_ENDIAN__
+    srdi   0,6, 24
+    sldi   8,7, 64-24
+#else
     sldi   0,6, 24
     srdi   8,7, 64-24
+#endif
     or    0,0,8
     std   0,0(4)
     b     L(du_done)
@@ -832,13 +981,23 @@ L(du4_dox):
     bf      30,L(du4_1dw)
 
     /* there are at least two DWs to copy */
+#ifdef __LITTLE_ENDIAN__
+    srdi     0,6, 32
+    sldi     8,7, 64-32
+#else
     sldi     0,6, 32
     srdi     8,7, 64-32
+#endif
     or      0,0,8
     ld      6,16(5)
     std     0,0(4)
+#ifdef __LITTLE_ENDIAN__
+    srdi     0,7, 32
+    sldi     8,6, 64-32
+#else
     sldi     0,7, 32
     srdi     8,6, 64-32
+#endif
     or      0,0,8
     ld      7,24(5)
     std     0,8(4)
@@ -847,8 +1006,13 @@ L(du4_dox):
     blt     cr6,L(du4_fini)  /* if total DWs = 3, then bypass loop */
     bf      31,L(du4_loop)
     /* there is a third DW to copy */
+#ifdef __LITTLE_ENDIAN__
+    srdi     0,6, 32
+    sldi     8,7, 64-32
+#else
     sldi     0,6, 32
     srdi     8,7, 64-32
+#endif
     or      0,0,8
     std     0,0(4)
     mr      6,7
@@ -859,8 +1023,13 @@ L(du4_dox):
     b       L(du4_loop)
     .align 4
 L(du4_1dw):
+#ifdef __LITTLE_ENDIAN__
+    srdi     0,6, 32
+    sldi     8,7, 64-32
+#else
     sldi     0,6, 32
     srdi     8,7, 64-32
+#endif
     addi    5,5,16
     or      0,0,8
     bf      31,L(du4_loop)
@@ -872,23 +1041,43 @@ L(du4_1dw):
     .align 4
 /* copy 32 bytes at a time */
 L(du4_loop):
+#ifdef __LITTLE_ENDIAN__
+    srdi   0,6, 32
+    sldi   8,7, 64-32
+#else
     sldi   0,6, 32
     srdi   8,7, 64-32
+#endif
     or    0,0,8
     ld    6,0(5)
     std   0,0(4)
+#ifdef __LITTLE_ENDIAN__
+    srdi   0,7, 32
+    sldi   8,6, 64-32
+#else
     sldi   0,7, 32
     srdi   8,6, 64-32
+#endif
     or    0,0,8
     ld    7,8(5)
     std   0,8(4)
+#ifdef __LITTLE_ENDIAN__
+    srdi   0,6, 32
+    sldi   8,7, 64-32
+#else
     sldi   0,6, 32
     srdi   8,7, 64-32
+#endif
     or    0,0,8
     ld    6,16(5)
     std   0,16(4)
+#ifdef __LITTLE_ENDIAN__
+    srdi   0,7, 32
+    sldi   8,6, 64-32
+#else
     sldi   0,7, 32
     srdi   8,6, 64-32
+#endif
     or    0,0,8
     ld    7,24(5)
     std   0,24(4)
@@ -898,8 +1087,13 @@ L(du4_loop):
     .align 4
 L(du4_fini):
     /* calculate and store the final DW */
+#ifdef __LITTLE_ENDIAN__
+    srdi   0,6, 32
+    sldi   8,7, 64-32
+#else
     sldi   0,6, 32
     srdi   8,7, 64-32
+#endif
     or    0,0,8
     std   0,0(4)
     b     L(du_done)
@@ -909,13 +1103,23 @@ L(du5_do):
     bf      30,L(du5_1dw)
 
     /* there are at least two DWs to copy */
+#ifdef __LITTLE_ENDIAN__
+    srdi     0,6, 40
+    sldi     8,7, 64-40
+#else
     sldi     0,6, 40
     srdi     8,7, 64-40
+#endif
     or      0,0,8
     ld      6,16(5)
     std     0,0(4)
+#ifdef __LITTLE_ENDIAN__
+    srdi     0,7, 40
+    sldi     8,6, 64-40
+#else
     sldi     0,7, 40
     srdi     8,6, 64-40
+#endif
     or      0,0,8
     ld      7,24(5)
     std     0,8(4)
@@ -924,8 +1128,13 @@ L(du5_do):
     blt     cr6,L(du5_fini)  /* if total DWs = 3, then bypass loop */
     bf      31,L(du5_loop)
     /* there is a third DW to copy */
+#ifdef __LITTLE_ENDIAN__
+    srdi     0,6, 40
+    sldi     8,7, 64-40
+#else
     sldi     0,6, 40
     srdi     8,7, 64-40
+#endif
     or      0,0,8
     std     0,0(4)
     mr      6,7
@@ -936,8 +1145,13 @@ L(du5_do):
     b       L(du5_loop)
     .align 4
 L(du5_1dw):
+#ifdef __LITTLE_ENDIAN__
+    srdi     0,6, 40
+    sldi     8,7, 64-40
+#else
     sldi     0,6, 40
     srdi     8,7, 64-40
+#endif
     addi    5,5,16
     or      0,0,8
     bf      31,L(du5_loop)
@@ -949,23 +1163,43 @@ L(du5_1dw):
     .align 4
 /* copy 32 bytes at a time */
 L(du5_loop):
+#ifdef __LITTLE_ENDIAN__
+    srdi   0,6, 40
+    sldi   8,7, 64-40
+#else
     sldi   0,6, 40
     srdi   8,7, 64-40
+#endif
     or    0,0,8
     ld    6,0(5)
     std   0,0(4)
+#ifdef __LITTLE_ENDIAN__
+    srdi   0,7, 40
+    sldi   8,6, 64-40
+#else
     sldi   0,7, 40
     srdi   8,6, 64-40
+#endif
     or    0,0,8
     ld    7,8(5)
     std   0,8(4)
+#ifdef __LITTLE_ENDIAN__
+    srdi   0,6, 40
+    sldi   8,7, 64-40
+#else
     sldi   0,6, 40
     srdi   8,7, 64-40
+#endif
     or    0,0,8
     ld    6,16(5)
     std   0,16(4)
+#ifdef __LITTLE_ENDIAN__
+    srdi   0,7, 40
+    sldi   8,6, 64-40
+#else
     sldi   0,7, 40
     srdi   8,6, 64-40
+#endif
     or    0,0,8
     ld    7,24(5)
     std   0,24(4)
@@ -975,8 +1209,13 @@ L(du5_loop):
     .align 4
 L(du5_fini):
     /* calculate and store the final DW */
+#ifdef __LITTLE_ENDIAN__
+    srdi   0,6, 40
+    sldi   8,7, 64-40
+#else
     sldi   0,6, 40
     srdi   8,7, 64-40
+#endif
     or    0,0,8
     std   0,0(4)
     b     L(du_done)
@@ -986,13 +1225,23 @@ L(du6_do):
     bf      30,L(du6_1dw)
 
     /* there are at least two DWs to copy */
+#ifdef __LITTLE_ENDIAN__
+    srdi     0,6, 48
+    sldi     8,7, 64-48
+#else
     sldi     0,6, 48
     srdi     8,7, 64-48
+#endif
     or      0,0,8
     ld      6,16(5)
     std     0,0(4)
+#ifdef __LITTLE_ENDIAN__
+    srdi     0,7, 48
+    sldi     8,6, 64-48
+#else
     sldi     0,7, 48
     srdi     8,6, 64-48
+#endif
     or      0,0,8
     ld      7,24(5)
     std     0,8(4)
@@ -1001,8 +1250,13 @@ L(du6_do):
     blt     cr6,L(du6_fini)  /* if total DWs = 3, then bypass loop */
     bf      31,L(du6_loop)
     /* there is a third DW to copy */
+#ifdef __LITTLE_ENDIAN__
+    srdi     0,6, 48
+    sldi     8,7, 64-48
+#else
     sldi     0,6, 48
     srdi     8,7, 64-48
+#endif
     or      0,0,8
     std     0,0(4)
     mr      6,7
@@ -1013,8 +1267,13 @@ L(du6_do):
     b       L(du6_loop)
     .align 4
 L(du6_1dw):
+#ifdef __LITTLE_ENDIAN__
+    srdi     0,6, 48
+    sldi     8,7, 64-48
+#else
     sldi     0,6, 48
     srdi     8,7, 64-48
+#endif
     addi    5,5,16
     or      0,0,8
     bf      31,L(du6_loop)
@@ -1026,23 +1285,43 @@ L(du6_1dw):
     .align 4
 /* copy 32 bytes at a time */
 L(du6_loop):
+#ifdef __LITTLE_ENDIAN__
+    srdi   0,6, 48
+    sldi   8,7, 64-48
+#else
     sldi   0,6, 48
     srdi   8,7, 64-48
+#endif
     or    0,0,8
     ld    6,0(5)
     std   0,0(4)
+#ifdef __LITTLE_ENDIAN__
+    srdi   0,7, 48
+    sldi   8,6, 64-48
+#else
     sldi   0,7, 48
     srdi   8,6, 64-48
+#endif
     or    0,0,8
     ld    7,8(5)
     std   0,8(4)
+#ifdef __LITTLE_ENDIAN__
+    srdi   0,6, 48
+    sldi   8,7, 64-48
+#else
     sldi   0,6, 48
     srdi   8,7, 64-48
+#endif
     or    0,0,8
     ld    6,16(5)
     std   0,16(4)
+#ifdef __LITTLE_ENDIAN__
+    srdi   0,7, 48
+    sldi   8,6, 64-48
+#else
     sldi   0,7, 48
     srdi   8,6, 64-48
+#endif
     or    0,0,8
     ld    7,24(5)
     std   0,24(4)
@@ -1052,8 +1331,13 @@ L(du6_loop):
     .align 4
 L(du6_fini):
     /* calculate and store the final DW */
+#ifdef __LITTLE_ENDIAN__
+    srdi   0,6, 48
+    sldi   8,7, 64-48
+#else
     sldi   0,6, 48
     srdi   8,7, 64-48
+#endif
     or    0,0,8
     std   0,0(4)
     b     L(du_done)
@@ -1063,13 +1347,23 @@ L(du7_do):
     bf      30,L(du7_1dw)
 
     /* there are at least two DWs to copy */
+#ifdef __LITTLE_ENDIAN__
+    srdi     0,6, 56
+    sldi     8,7, 64-56
+#else
     sldi     0,6, 56
     srdi     8,7, 64-56
+#endif
     or      0,0,8
     ld      6,16(5)
     std     0,0(4)
+#ifdef __LITTLE_ENDIAN__
+    srdi     0,7, 56
+    sldi     8,6, 64-56
+#else
     sldi     0,7, 56
     srdi     8,6, 64-56
+#endif
     or      0,0,8
     ld      7,24(5)
     std     0,8(4)
@@ -1078,8 +1372,13 @@ L(du7_do):
     blt     cr6,L(du7_fini)  /* if total DWs = 3, then bypass loop */
     bf      31,L(du7_loop)
     /* there is a third DW to copy */
+#ifdef __LITTLE_ENDIAN__
+    srdi     0,6, 56
+    sldi     8,7, 64-56
+#else
     sldi     0,6, 56
     srdi     8,7, 64-56
+#endif
     or      0,0,8
     std     0,0(4)
     mr      6,7
@@ -1090,8 +1389,13 @@ L(du7_do):
     b       L(du7_loop)
     .align 4
 L(du7_1dw):
+#ifdef __LITTLE_ENDIAN__
+    srdi     0,6, 56
+    sldi     8,7, 64-56
+#else
     sldi     0,6, 56
     srdi     8,7, 64-56
+#endif
     addi    5,5,16
     or      0,0,8
     bf      31,L(du7_loop)
@@ -1103,23 +1407,43 @@ L(du7_1dw):
     .align 4
 /* copy 32 bytes at a time */
 L(du7_loop):
+#ifdef __LITTLE_ENDIAN__
+    srdi   0,6, 56
+    sldi   8,7, 64-56
+#else
     sldi   0,6, 56
     srdi   8,7, 64-56
+#endif
     or    0,0,8
     ld    6,0(5)
     std   0,0(4)
+#ifdef __LITTLE_ENDIAN__
+    srdi   0,7, 56
+    sldi   8,6, 64-56
+#else
     sldi   0,7, 56
     srdi   8,6, 64-56
+#endif
     or    0,0,8
     ld    7,8(5)
     std   0,8(4)
+#ifdef __LITTLE_ENDIAN__
+    srdi   0,6, 56
+    sldi   8,7, 64-56
+#else
     sldi   0,6, 56
     srdi   8,7, 64-56
+#endif
     or    0,0,8
     ld    6,16(5)
     std   0,16(4)
+#ifdef __LITTLE_ENDIAN__
+    srdi   0,7, 56
+    sldi   8,6, 64-56
+#else
     sldi   0,7, 56
     srdi   8,6, 64-56
+#endif
     or    0,0,8
     ld    7,24(5)
     std   0,24(4)
@@ -1129,8 +1453,13 @@ L(du7_loop):
     .align 4
 L(du7_fini):
     /* calculate and store the final DW */
+#ifdef __LITTLE_ENDIAN__
+    srdi   0,6, 56
+    sldi   8,7, 64-56
+#else
     sldi   0,6, 56
     srdi   8,7, 64-56
+#endif
     or    0,0,8
     std   0,0(4)
     b     L(du_done)
diff --git a/sysdeps/powerpc/powerpc64/power7/memcpy.S b/sysdeps/powerpc/powerpc64/power7/memcpy.S
index 800a9f1..e8df75f 100644
--- a/sysdeps/powerpc/powerpc64/power7/memcpy.S
+++ b/sysdeps/powerpc/powerpc64/power7/memcpy.S
@@ -23,418 +23,361 @@
 /* __ptr_t [r3] memcpy (__ptr_t dst [r3], __ptr_t src [r4], size_t len [r5]);
    Returns 'dst'.  */
 
+#define dst 11		/* Use r11 so r3 kept unchanged.  */
+#define src 4
+#define cnt 5
+
 	.machine power7
 EALIGN (memcpy, 5, 0)
 	CALL_MCOUNT 3
 
-	cmpldi  cr1,5,31
+	cmpldi	cr1,cnt,31
 	neg	0,3
-	std	3,-16(1)
-	std	31,-8(1)
-	cfi_offset(31,-8)
 	ble	cr1, L(copy_LT_32)  /* If move < 32 bytes use short move
 				    code.  */
 
-	andi.   11,3,7	      /* Check alignment of DST.  */
-
-
-	clrldi  10,4,61       /* Check alignment of SRC.  */
-	cmpld   cr6,10,11     /* SRC and DST alignments match?  */
-	mr	12,4
-	mr	31,5
+#ifdef __LITTLE_ENDIAN__
+/* In little-endian mode, power7 takes an alignment trap on any lxvd2x
+   or stxvd2x crossing a 32-byte boundary, so ensure the aligned_copy
+   loop is only used for quadword aligned copies.  */
+	andi.	10,3,15
+	clrldi	11,4,60
+#else
+	andi.	10,3,7		/* Check alignment of DST.  */
+	clrldi	11,4,61		/* Check alignment of SRC.  */
+#endif
+	cmpld	cr6,10,11	/* SRC and DST alignments match?  */
+
+	mr	dst,3
 	bne	cr6,L(copy_GE_32_unaligned)
+	beq	L(aligned_copy)
 
-	srdi    9,5,3	      /* Number of full quadwords remaining.  */
-
-	beq    L(copy_GE_32_aligned_cont)
-
-	clrldi  0,0,61
-	mtcrf   0x01,0
-	subf    31,0,5
-
-	/* Get the SRC aligned to 8 bytes.  */
-
-1:	bf	31,2f
-	lbz	6,0(12)
-	addi    12,12,1
-	stb	6,0(3)
-	addi    3,3,1
-2:	bf      30,4f
-	lhz     6,0(12)
-	addi    12,12,2
-	sth     6,0(3)
-	addi    3,3,2
-4:	bf      29,0f
-	lwz     6,0(12)
-	addi    12,12,4
-	stw     6,0(3)
-	addi    3,3,4
-0:
-	clrldi  10,12,61      /* Check alignment of SRC again.  */
-	srdi    9,31,3	      /* Number of full doublewords remaining.  */
-
-L(copy_GE_32_aligned_cont):
-
-	clrldi  11,31,61
-	mtcrf   0x01,9
-
-	srdi    8,31,5
-	cmpldi  cr1,9,4
-	cmpldi  cr6,11,0
-	mr	11,12
-
-	/* Copy 1~3 doublewords so the main loop starts
-	at a multiple of 32 bytes.  */
+	mtocrf	0x01,0
+#ifdef __LITTLE_ENDIAN__
+	clrldi	0,0,60
+#else
+	clrldi	0,0,61
+#endif
 
-	bf	30,1f
-	ld      6,0(12)
-	ld      7,8(12)
-	addi    11,12,16
-	mtctr   8
-	std     6,0(3)
-	std     7,8(3)
-	addi    10,3,16
-	bf      31,4f
-	ld      0,16(12)
-	std     0,16(3)
-	blt     cr1,3f
-	addi    11,12,24
-	addi    10,3,24
-	b       4f
-
-	.align  4
-1:	/* Copy 1 doubleword and set the counter.  */
-	mr	10,3
-	mtctr   8
-	bf      31,4f
-	ld      6,0(12)
-	addi    11,12,8
-	std     6,0(3)
-	addi    10,3,8
-
-L(aligned_copy):
-	/* Main aligned copy loop. Copies up to 128-bytes at a time. */
-	.align  4
+/* Get the DST and SRC aligned to 8 bytes (16 for little-endian).  */
+1:
+	bf	31,2f
+	lbz	6,0(src)
+	addi	src,src,1
+	stb	6,0(dst)
+	addi	dst,dst,1
+2:
+	bf	30,4f
+	lhz	6,0(src)
+	addi	src,src,2
+	sth	6,0(dst)
+	addi	dst,dst,2
 4:
-	/* check for any 32-byte or 64-byte lumps that are outside of a
-	   nice 128-byte range.  R8 contains the number of 32-byte
-	   lumps, so drop this into the CR, and use the SO/EQ bits to help
-	   handle the 32- or 64- byte lumps.  Then handle the rest with an
-	   unrolled 128-bytes-at-a-time copy loop. */
-	mtocrf	1,8
-	li	6,16	# 16() index
-	li	7,32	# 32() index
-	li	8,48	# 48() index
-
-L(aligned_32byte):
-	/* if the SO bit (indicating a 32-byte lump) is not set, move along. */
-	bns	cr7,L(aligned_64byte)
-	lxvd2x	6,0,11
-	lxvd2x	7,11,6
-	addi	11,11,32
-	stxvd2x	6,0,10
-	stxvd2x	7,10,6
-	addi	10,10,32
-
-L(aligned_64byte):
-	/* if the EQ bit (indicating a 64-byte lump) is not set, move along. */
-	bne	cr7,L(aligned_128setup)
-	lxvd2x	6,0,11
-	lxvd2x	7,11,6
-	lxvd2x	8,11,7
-	lxvd2x	9,11,8
-	addi	11,11,64
-	stxvd2x	6,0,10
-	stxvd2x	7,10,6
-	stxvd2x	8,10,7
-	stxvd2x	9,10,8
-	addi	10,10,64
-
-L(aligned_128setup):
-	/* Set up for the 128-byte at a time copy loop.  */
-	srdi	8,31,7
-	cmpdi	8,0	# Any 4x lumps left?
-	beq	3f	# if not, move along.
-	lxvd2x	6,0,11
-	lxvd2x	7,11,6
-	mtctr	8	# otherwise, load the ctr and begin.
-	li	8,48	# 48() index
+	bf	29,8f
+	lwz	6,0(src)
+	addi	src,src,4
+	stw	6,0(dst)
+	addi	dst,dst,4
+8:
+#ifdef __LITTLE_ENDIAN__
+	bf	28,16f
+	ld	6,0(src)
+	addi	src,src,8
+	std	6,0(dst)
+	addi	dst,dst,8
+16:
+#endif
+	subf	cnt,0,cnt
+
+/* Main aligned copy loop. Copies 128 bytes at a time. */
+L(aligned_copy):
+	li	6,16
+	li	7,32
+	li	8,48
+	mtocrf	0x02,cnt
+	srdi	12,cnt,7
+	cmpdi	12,0
+	beq	L(aligned_tail)
+	lxvd2x	6,0,src
+	lxvd2x	7,src,6
+	mtctr	12
 	b	L(aligned_128loop)
 
+	.align  4
 L(aligned_128head):
 	/* for the 2nd + iteration of this loop. */
-	lxvd2x	6,0,11
-	lxvd2x	7,11,6
+	lxvd2x	6,0,src
+	lxvd2x	7,src,6
 L(aligned_128loop):
-	lxvd2x	8,11,7
-	lxvd2x	9,11,8
-	stxvd2x	6,0,10
-	addi	11,11,64
-	stxvd2x	7,10,6
-	stxvd2x	8,10,7
-	stxvd2x	9,10,8
-	lxvd2x	6,0,11
-	lxvd2x	7,11,6
-	addi	10,10,64
-	lxvd2x	8,11,7
-	lxvd2x	9,11,8
-	addi	11,11,64
-	stxvd2x	6,0,10
-	stxvd2x	7,10,6
-	stxvd2x	8,10,7
-	stxvd2x	9,10,8
-	addi	10,10,64
+	lxvd2x	8,src,7
+	lxvd2x	9,src,8
+	stxvd2x	6,0,dst
+	addi	src,src,64
+	stxvd2x	7,dst,6
+	stxvd2x	8,dst,7
+	stxvd2x	9,dst,8
+	lxvd2x	6,0,src
+	lxvd2x	7,src,6
+	addi	dst,dst,64
+	lxvd2x	8,src,7
+	lxvd2x	9,src,8
+	addi	src,src,64
+	stxvd2x	6,0,dst
+	stxvd2x	7,dst,6
+	stxvd2x	8,dst,7
+	stxvd2x	9,dst,8
+	addi	dst,dst,64
 	bdnz	L(aligned_128head)
 
-3:
-	/* Check for tail bytes.  */
-	rldicr  0,31,0,60
-	mtcrf   0x01,31
-	beq	cr6,0f
-
-.L9:
-	add	3,3,0
-	add	12,12,0
-
-	/*  At this point we have a tail of 0-7 bytes and we know that the
-	destination is doubleword-aligned.  */
-4:	/* Copy 4 bytes.  */
-	bf	29,2f
-
-	lwz     6,0(12)
-	addi    12,12,4
-	stw     6,0(3)
-	addi    3,3,4
-2:	/* Copy 2 bytes.  */
-	bf	30,1f
-
-	lhz     6,0(12)
-	addi    12,12,2
-	sth     6,0(3)
-	addi    3,3,2
-1:	/* Copy 1 byte.  */
-	bf	31,0f
-
-	lbz	6,0(12)
-	stb	6,0(3)
-0:	/* Return original DST pointer.  */
-	ld	31,-8(1)
-	ld	3,-16(1)
+L(aligned_tail):
+	mtocrf	0x01,cnt
+	bf	25,32f
+	lxvd2x	6,0,src
+	lxvd2x	7,src,6
+	lxvd2x	8,src,7
+	lxvd2x	9,src,8
+	addi	src,src,64
+	stxvd2x	6,0,dst
+	stxvd2x	7,dst,6
+	stxvd2x	8,dst,7
+	stxvd2x	9,dst,8
+	addi	dst,dst,64
+32:
+	bf	26,16f
+	lxvd2x	6,0,src
+	lxvd2x	7,src,6
+	addi	src,src,32
+	stxvd2x	6,0,dst
+	stxvd2x	7,dst,6
+	addi	dst,dst,32
+16:
+	bf	27,8f
+	lxvd2x	6,0,src
+	addi	src,src,16
+	stxvd2x	6,0,dst
+	addi	dst,dst,16
+8:
+	bf	28,4f
+	ld	6,0(src)
+	addi	src,src,8
+	std     6,0(dst)
+	addi	dst,dst,8
+4:	/* Copies 4~7 bytes.  */
+	bf	29,L(tail2)
+	lwz	6,0(src)
+	stw     6,0(dst)
+	bf      30,L(tail5)
+	lhz     7,4(src)
+	sth     7,4(dst)
+	bflr	31
+	lbz     8,6(src)
+	stb     8,6(dst)
+	/* Return original DST pointer.  */
 	blr
 
-	/* Handle copies of 0~31 bytes.  */
-	.align  4
+
+/* Handle copies of 0~31 bytes.  */
+	.align	4
 L(copy_LT_32):
-	cmpldi  cr6,5,8
-	mr	12,4
-	mtcrf   0x01,5
+	mr	dst,3
+	cmpldi	cr6,cnt,8
+	mtocrf	0x01,cnt
 	ble	cr6,L(copy_LE_8)
 
 	/* At least 9 bytes to go.  */
 	neg	8,4
-	clrrdi  11,4,2
-	andi.   0,8,3
-	cmpldi  cr1,5,16
-	mr	10,5
+	andi.	0,8,3
+	cmpldi	cr1,cnt,16
 	beq	L(copy_LT_32_aligned)
 
-	/* Force 4-bytes alignment for SRC.  */
-	mtocrf  0x01,0
-	subf    10,0,5
-2:	bf	30,1f
-
-	lhz	6,0(12)
-	addi    12,12,2
-	sth	6,0(3)
-	addi    3,3,2
-1:	bf	31,L(end_4bytes_alignment)
-
-	lbz	6,0(12)
-	addi    12,12,1
-	stb	6,0(3)
-	addi    3,3,1
-
-	.align  4
+	/* Force 4-byte alignment for SRC.  */
+	mtocrf	0x01,0
+	subf	cnt,0,cnt
+2:
+	bf	30,1f
+	lhz	6,0(src)
+	addi	src,src,2
+	sth	6,0(dst)
+	addi	dst,dst,2
+1:
+	bf	31,L(end_4bytes_alignment)
+	lbz	6,0(src)
+	addi	src,src,1
+	stb	6,0(dst)
+	addi	dst,dst,1
+
+	.align	4
 L(end_4bytes_alignment):
-	cmpldi  cr1,10,16
-	mtcrf   0x01,10
+	cmpldi	cr1,cnt,16
+	mtocrf	0x01,cnt
 
 L(copy_LT_32_aligned):
 	/* At least 6 bytes to go, and SRC is word-aligned.  */
 	blt	cr1,8f
 
 	/* Copy 16 bytes.  */
-	lwz	6,0(12)
-	lwz     7,4(12)
-	stw     6,0(3)
-	lwz     8,8(12)
-	stw     7,4(3)
-	lwz     6,12(12)
-	addi    12,12,16
-	stw     8,8(3)
-	stw     6,12(3)
-	addi    3,3,16
+	lwz	6,0(src)
+	lwz	7,4(src)
+	stw	6,0(dst)
+	lwz	8,8(src)
+	stw	7,4(dst)
+	lwz	6,12(src)
+	addi	src,src,16
+	stw	8,8(dst)
+	stw	6,12(dst)
+	addi	dst,dst,16
 8:	/* Copy 8 bytes.  */
-	bf	28,4f
+	bf	28,L(tail4)
+	lwz	6,0(src)
+	lwz	7,4(src)
+	addi	src,src,8
+	stw	6,0(dst)
+	stw	7,4(dst)
+	addi	dst,dst,8
+
+	.align	4
+/* Copies 4~7 bytes.  */
+L(tail4):
+	bf	29,L(tail2)
+	lwz	6,0(src)
+	stw	6,0(dst)
+	bf	30,L(tail5)
+	lhz	7,4(src)
+	sth	7,4(dst)
+	bflr	31
+	lbz	8,6(src)
+	stb	8,6(dst)
+	/* Return original DST pointer.  */
+	blr
 
-	lwz     6,0(12)
-	lwz     7,4(12)
-	addi    12,12,8
-	stw     6,0(3)
-	stw     7,4(3)
-	addi    3,3,8
-4:	/* Copy 4 bytes.  */
-	bf	29,2f
-
-	lwz     6,0(12)
-	addi    12,12,4
-	stw     6,0(3)
-	addi    3,3,4
-2:	/* Copy 2-3 bytes.  */
+	.align	4
+/* Copies 2~3 bytes.  */
+L(tail2):
 	bf	30,1f
-
-	lhz     6,0(12)
-	sth     6,0(3)
-	bf      31,0f
-	lbz     7,2(12)
-	stb     7,2(3)
-	ld	3,-16(1)
+	lhz	6,0(src)
+	sth	6,0(dst)
+	bflr	31
+	lbz	7,2(src)
+	stb	7,2(dst)
 	blr
 
-	.align  4
-1:	/* Copy 1 byte.  */
-	bf	31,0f
+	.align	4
+L(tail5):
+	bflr	31
+	lbz	6,4(src)
+	stb	6,4(dst)
+	blr
 
-	lbz	6,0(12)
-	stb	6,0(3)
-0:	/* Return original DST pointer.  */
-	ld	3,-16(1)
+	.align	4
+1:
+	bflr	31
+	lbz	6,0(src)
+	stb	6,0(dst)
+	/* Return original DST pointer.  */
 	blr
 
-	/* Handles copies of 0~8 bytes.  */
-	.align  4
+
+/* Handles copies of 0~8 bytes.  */
+	.align	4
 L(copy_LE_8):
-	bne	cr6,4f
+	bne	cr6,L(tail4)
 
 	/* Though we could've used ld/std here, they are still
 	slow for unaligned cases.  */
 
-	lwz	6,0(4)
-	lwz     7,4(4)
-	stw     6,0(3)
-	stw     7,4(3)
-	ld      3,-16(1)      /* Return original DST pointers.  */
+	lwz	6,0(src)
+	lwz	7,4(src)
+	stw	6,0(dst)
+	stw	7,4(dst)
 	blr
 
-	.align  4
-4:	/* Copies 4~7 bytes.  */
-	bf	29,2b
-
-	lwz	6,0(4)
-	stw     6,0(3)
-	bf      30,5f
-	lhz     7,4(4)
-	sth     7,4(3)
-	bf      31,0f
-	lbz     8,6(4)
-	stb     8,6(3)
-	ld	3,-16(1)
-	blr
-
-	.align  4
-5:	/* Copy 1 byte.  */
-	bf	31,0f
-
-	lbz	6,4(4)
-	stb	6,4(3)
-
-0:	/* Return original DST pointer.  */
-	ld	3,-16(1)
-	blr
 
-	/* Handle copies of 32+ bytes where DST is aligned (to quadword) but
-	SRC is not.  Use aligned quadword loads from SRC, shifted to realign
-	the data, allowing for aligned DST stores.  */
-	.align  4
+/* Handle copies of 32+ bytes where DST is aligned (to quadword) but
+   SRC is not.	Use aligned quadword loads from SRC, shifted to realign
+   the data, allowing for aligned DST stores.  */
+	.align	4
 L(copy_GE_32_unaligned):
-	clrldi  0,0,60	      /* Number of bytes until the 1st
-			      quadword.  */
-	andi.   11,3,15       /* Check alignment of DST (against
-			      quadwords).  */
-	srdi    9,5,4	      /* Number of full quadwords remaining.  */
+	clrldi	0,0,60	      /* Number of bytes until the 1st dst quadword.  */
+#ifndef __LITTLE_ENDIAN__
+	andi.	10,3,15	      /* Check alignment of DST (against quadwords).  */
+#endif
+	srdi	9,cnt,4	      /* Number of full quadwords remaining.  */
 
 	beq	L(copy_GE_32_unaligned_cont)
 
-	/* SRC is not quadword aligned, get it aligned.  */
+	/* DST is not quadword aligned, get it aligned.  */
 
-	mtcrf   0x01,0
-	subf    31,0,5
+	mtocrf	0x01,0
+	subf	cnt,0,cnt
 
 	/* Vector instructions work best when proper alignment (16-bytes)
 	is present.  Move 0~15 bytes as needed to get DST quadword-aligned.  */
-1:	/* Copy 1 byte.  */
+1:
 	bf	31,2f
-
-	lbz	6,0(12)
-	addi    12,12,1
-	stb	6,0(3)
-	addi    3,3,1
-2:	/* Copy 2 bytes.  */
+	lbz	6,0(src)
+	addi	src,src,1
+	stb	6,0(dst)
+	addi	dst,dst,1
+2:
 	bf	30,4f
-
-	lhz     6,0(12)
-	addi    12,12,2
-	sth     6,0(3)
-	addi    3,3,2
-4:	/* Copy 4 bytes.  */
+	lhz	6,0(src)
+	addi	src,src,2
+	sth	6,0(dst)
+	addi	dst,dst,2
+4:
 	bf	29,8f
-
-	lwz     6,0(12)
-	addi    12,12,4
-	stw     6,0(3)
-	addi    3,3,4
-8:	/* Copy 8 bytes.  */
+	lwz	6,0(src)
+	addi	src,src,4
+	stw	6,0(dst)
+	addi	dst,dst,4
+8:
 	bf	28,0f
-
-	ld	6,0(12)
-	addi    12,12,8
-	std	6,0(3)
-	addi    3,3,8
+	ld	6,0(src)
+	addi	src,src,8
+	std	6,0(dst)
+	addi	dst,dst,8
 0:
-	clrldi  10,12,60      /* Check alignment of SRC.  */
-	srdi    9,31,4	      /* Number of full quadwords remaining.  */
+	srdi	9,cnt,4	      /* Number of full quadwords remaining.  */
 
 	/* The proper alignment is present, it is OK to copy the bytes now.  */
 L(copy_GE_32_unaligned_cont):
 
 	/* Setup two indexes to speed up the indexed vector operations.  */
-	clrldi  11,31,60
-	li      6,16	      /* Index for 16-bytes offsets.  */
+	clrldi	10,cnt,60
+	li	6,16	      /* Index for 16-bytes offsets.  */
 	li	7,32	      /* Index for 32-bytes offsets.  */
-	cmpldi  cr1,11,0
-	srdi    8,31,5	      /* Setup the loop counter.  */
-	mr      10,3
-	mr      11,12
-	mtcrf   0x01,9
-	cmpldi  cr6,9,1
-	lvsl    5,0,12
-	lvx     3,0,12
-	bf      31,L(setup_unaligned_loop)
-
-	/* Copy another 16 bytes to align to 32-bytes due to the loop .  */
-	lvx     4,12,6
-	vperm   6,3,4,5
-	addi    11,12,16
-	addi    10,3,16
-	stvx    6,0,3
+	cmpldi	cr1,10,0
+	srdi	8,cnt,5	      /* Setup the loop counter.  */
+	mtocrf	0x01,9
+	cmpldi	cr6,9,1
+#ifdef __LITTLE_ENDIAN__
+	lvsr	5,0,src
+#else
+	lvsl	5,0,src
+#endif
+	lvx	3,0,src
+	li	0,0
+	bf	31,L(setup_unaligned_loop)
+
+	/* Copy another 16 bytes to align to 32-bytes due to the loop.  */
+	lvx	4,src,6
+#ifdef __LITTLE_ENDIAN__
+	vperm	6,4,3,5
+#else
+	vperm	6,3,4,5
+#endif
+	addi	src,src,16
+	stvx	6,0,dst
+	addi	dst,dst,16
 	vor	3,4,4
+	clrrdi	0,src,60
 
 L(setup_unaligned_loop):
-	mtctr   8
-	ble     cr6,L(end_unaligned_loop)
+	mtctr	8
+	ble	cr6,L(end_unaligned_loop)
 
 	/* Copy 32 bytes at a time using vector instructions.  */
-	.align  4
+	.align	4
 L(unaligned_loop):
 
 	/* Note: vr6/vr10 may contain data that was already copied,
@@ -442,62 +385,55 @@ L(unaligned_loop):
 	some portions again. This is faster than having unaligned
 	vector instructions though.  */
 
-	lvx	4,11,6	      /* vr4 = r11+16.  */
-	vperm   6,3,4,5	      /* Merge the correctly-aligned portions
-			      of vr3/vr4 into vr6.  */
-	lvx	3,11,7	      /* vr3 = r11+32.  */
-	vperm   10,4,3,5      /* Merge the correctly-aligned portions
-			      of vr3/vr4 into vr10.  */
-	addi    11,11,32
-	stvx    6,0,10
-	stvx    10,10,6
-	addi    10,10,32
-
+	lvx	4,src,6
+#ifdef __LITTLE_ENDIAN__
+	vperm	6,4,3,5
+#else
+	vperm	6,3,4,5
+#endif
+	lvx	3,src,7
+#ifdef __LITTLE_ENDIAN__
+	vperm	10,3,4,5
+#else
+	vperm	10,4,3,5
+#endif
+	addi	src,src,32
+	stvx	6,0,dst
+	stvx	10,dst,6
+	addi	dst,dst,32
 	bdnz	L(unaligned_loop)
 
-	.align  4
+	clrrdi	0,src,60
+
+	.align	4
 L(end_unaligned_loop):
 
 	/* Check for tail bytes.  */
-	rldicr  0,31,0,59
-	mtcrf   0x01,31
-	beq	cr1,0f
+	mtocrf	0x01,cnt
+	beqlr	cr1
 
-	add	3,3,0
-	add	12,12,0
+	add	src,src,0
 
 	/*  We have 1~15 tail bytes to copy, and DST is quadword aligned.  */
-8:	/* Copy 8 bytes.  */
+	/* Copy 8 bytes.  */
 	bf	28,4f
-
-	lwz	6,0(12)
-	lwz	7,4(12)
-	addi    12,12,8
-	stw	6,0(3)
-	stw	7,4(3)
-	addi    3,3,8
-4:	/* Copy 4 bytes.  */
-	bf	29,2f
-
-	lwz	6,0(12)
-	addi    12,12,4
-	stw	6,0(3)
-	addi    3,3,4
-2:	/* Copy 2~3 bytes.  */
-	bf	30,1f
-
-	lhz	6,0(12)
-	addi    12,12,2
-	sth	6,0(3)
-	addi    3,3,2
-1:	/* Copy 1 byte.  */
-	bf	31,0f
-
-	lbz	6,0(12)
-	stb	6,0(3)
-0:	/* Return original DST pointer.  */
-	ld	31,-8(1)
-	ld	3,-16(1)
+	lwz	6,0(src)
+	lwz	7,4(src)
+	addi	src,src,8
+	stw	6,0(dst)
+	stw	7,4(dst)
+	addi	dst,dst,8
+4:	/* Copy 4~7 bytes.  */
+	bf	29,L(tail2)
+	lwz	6,0(src)
+	stw	6,0(dst)
+	bf	30,L(tail5)
+	lhz	7,4(src)
+	sth	7,4(dst)
+	bflr	31
+	lbz	8,6(src)
+	stb	8,6(dst)
+	/* Return original DST pointer.  */
 	blr
 
 END_GEN_TB (memcpy,TB_TOCLESS)
diff --git a/sysdeps/powerpc/powerpc64/power7/mempcpy.S b/sysdeps/powerpc/powerpc64/power7/mempcpy.S
index f20be93..b93ab7d 100644
--- a/sysdeps/powerpc/powerpc64/power7/mempcpy.S
+++ b/sysdeps/powerpc/powerpc64/power7/mempcpy.S
@@ -365,13 +365,21 @@ L(copy_GE_32_unaligned_cont):
 	mr	11,12
 	mtcrf	0x01,9
 	cmpldi	cr6,9,1
-	lvsl	5,0,12
+#ifdef __LITTLE_ENDIAN__
+	lvsr    5,0,12
+#else
+	lvsl    5,0,12
+#endif
 	lvx	3,0,12
 	bf	31,L(setup_unaligned_loop)
 
 	/* Copy another 16 bytes to align to 32-bytes due to the loop .  */
 	lvx	4,12,6
-	vperm	6,3,4,5
+#ifdef __LITTLE_ENDIAN__
+	vperm   6,4,3,5
+#else
+	vperm   6,3,4,5
+#endif
 	addi	11,12,16
 	addi	10,3,16
 	stvx	6,0,3
@@ -391,11 +399,17 @@ L(unaligned_loop):
 	vector instructions though.  */
 
 	lvx	4,11,6	      /* vr4 = r11+16.  */
-	vperm	6,3,4,5	      /* Merge the correctly-aligned portions
-				 of vr3/vr4 into vr6.  */
+#ifdef __LITTLE_ENDIAN__
+	vperm   6,4,3,5
+#else
+	vperm   6,3,4,5
+#endif
 	lvx	3,11,7	      /* vr3 = r11+32.  */
-	vperm	10,4,3,5      /* Merge the correctly-aligned portions
-				 of vr3/vr4 into vr10.  */
+#ifdef __LITTLE_ENDIAN__
+	vperm   10,3,4,5
+#else
+	vperm   10,4,3,5
+#endif
 	addi	11,11,32
 	stvx	6,0,10
 	stvx	10,10,6

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=c3cb0a792e5a8fe6a776e3779775079b48029df2

commit c3cb0a792e5a8fe6a776e3779775079b48029df2
Author: Alan Modra <amodra@gmail.com>
Date:   Sat Aug 17 18:46:47 2013 +0930

    PowerPC LE memcmp
    http://sourceware.org/ml/libc-alpha/2013-08/msg00102.html
    
    This is a rather large patch due to formatting and renaming.  The
    formatting changes were to make it possible to compare power7 and
    power4 versions of memcmp.  Using different register defines came
    about while I was wrestling with the code, trying to find spare
    registers at one stage.  I found it much simpler if we refer to a reg
    by the same name throughout a function, so it's better if short-term
    multiple use regs like rTMP are referred to using their register
    number.  I made the cr field usage changes when attempting to reload
    rWORDn regs in the exit path to byte swap before comparing when
    little-endian.  That proved a bad idea due to the pipelining involved
    in the main loop;  Offsets to reload the regs were different first
    time around the loop..  Anyway, I left the cr field usage changes in
    place for consistency.
    
    Aside from these more-or-less cosmetic changes, I fixed a number of
    places where an early exit path restores regs unnecessarily, removed
    some dead code, and optimised one or two exits.
    
    	* sysdeps/powerpc/powerpc64/power7/memcmp.S: Add little-endian support.
    	Formatting.  Consistently use rXXX register defines or rN defines.
    	Use early exit labels that avoid restoring unused non-volatile regs.
    	Make cr field use more consistent with rWORDn compares.  Rename
    	regs used as shift registers for unaligned loop, using rN defines
    	for short lifetime/multiple use regs.
    	* sysdeps/powerpc/powerpc64/power4/memcmp.S: Likewise.
    	* sysdeps/powerpc/powerpc32/power7/memcmp.S: Likewise.  Exit with
    	addi 1,1,64 to pop stack frame.  Simplify return value code.
    	* sysdeps/powerpc/powerpc32/power4/memcmp.S: Likewise.

diff --git a/ChangeLog b/ChangeLog
index 37a85c2..42d88db 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,18 @@
 2013-10-04  Alan Modra  <amodra@gmail.com>
 
+	* sysdeps/powerpc/powerpc64/power7/memcmp.S: Add little-endian support.
+	Formatting.  Consistently use rXXX register defines or rN defines.
+	Use early exit labels that avoid restoring unused non-volatile regs.
+	Make cr field use more consistent with rWORDn compares.  Rename
+	regs used as shift registers for unaligned loop, using rN defines
+	for short lifetime/multiple use regs.
+	* sysdeps/powerpc/powerpc64/power4/memcmp.S: Likewise.
+	* sysdeps/powerpc/powerpc32/power7/memcmp.S: Likewise.  Exit with
+	addi 1,1,64 to pop stack frame.  Simplify return value code.
+	* sysdeps/powerpc/powerpc32/power4/memcmp.S: Likewise.
+
+2013-10-04  Alan Modra  <amodra@gmail.com>
+
 	* sysdeps/powerpc/powerpc64/power7/strchr.S (strchr): Add little-endian
 	support.  Correct typos, formatting.  Optimize tail.  Use insrdi
 	rather than rlwimi.
diff --git a/sysdeps/powerpc/powerpc32/power4/memcmp.S b/sysdeps/powerpc/powerpc32/power4/memcmp.S
index d7050a2..652acb9 100644
--- a/sysdeps/powerpc/powerpc32/power4/memcmp.S
+++ b/sysdeps/powerpc/powerpc32/power4/memcmp.S
@@ -1,4 +1,4 @@
-/* Optimized strcmp implementation for PowerPC64.
+/* Optimized strcmp implementation for PowerPC32.
    Copyright (C) 2003-2013 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
@@ -18,13 +18,14 @@
 
 #include <sysdep.h>
 
-/* int [r3] memcmp (const char *s1 [r3], const char *s2 [r4], size_t size [r5])  */
+/* int [r3] memcmp (const char *s1 [r3],
+		    const char *s2 [r4],
+		    size_t size [r5])  */
 
 	.machine power4
 EALIGN (memcmp, 4, 0)
 	CALL_MCOUNT
 
-#define rTMP	r0
 #define rRTN	r3
 #define rSTR1	r3	/* first string arg */
 #define rSTR2	r4	/* second string arg */
@@ -35,33 +36,32 @@ EALIGN (memcmp, 4, 0)
 #define rWORD4	r9	/* next word in s2 */
 #define rWORD5	r10	/* next word in s1 */
 #define rWORD6	r11	/* next word in s2 */
-#define rBITDIF	r12	/* bits that differ in s1 & s2 words */
 #define rWORD7	r30	/* next word in s1 */
 #define rWORD8	r31	/* next word in s2 */
 
-	xor	rTMP, rSTR2, rSTR1
+	xor	r0, rSTR2, rSTR1
 	cmplwi	cr6, rN, 0
 	cmplwi	cr1, rN, 12
-	clrlwi.	rTMP, rTMP, 30
-	clrlwi	rBITDIF, rSTR1, 30
-	cmplwi	cr5, rBITDIF, 0
+	clrlwi.	r0, r0, 30
+	clrlwi	r12, rSTR1, 30
+	cmplwi	cr5, r12, 0
 	beq-	cr6, L(zeroLength)
-	dcbt	0,rSTR1
-	dcbt	0,rSTR2
+	dcbt	0, rSTR1
+	dcbt	0, rSTR2
 /* If less than 8 bytes or not aligned, use the unaligned
    byte loop.  */
 	blt	cr1, L(bytealigned)
-        stwu    1,-64(1)
+	stwu	1, -64(r1)
 	cfi_adjust_cfa_offset(64)
-        stw     r31,48(1)
-	cfi_offset(31,(48-64))
-        stw     r30,44(1)
-	cfi_offset(30,(44-64))
+	stw	rWORD8, 48(r1)
+	cfi_offset(rWORD8, (48-64))
+	stw	rWORD7, 44(r1)
+	cfi_offset(rWORD7, (44-64))
 	bne	L(unaligned)
 /* At this point we know both strings have the same alignment and the
-   compare length is at least 8 bytes.  rBITDIF contains the low order
+   compare length is at least 8 bytes.  r12 contains the low order
    2 bits of rSTR1 and cr5 contains the result of the logical compare
-   of rBITDIF to 0.  If rBITDIF == 0 then we are already word
+   of r12 to 0.  If r12 == 0 then we are already word
    aligned and can perform the word aligned loop.
 
    Otherwise we know the two strings have the same alignment (but not
@@ -70,74 +70,95 @@ EALIGN (memcmp, 4, 0)
    eliminate bits preceding the first byte.  Since we want to join the
    normal (word aligned) compare loop, starting at the second word,
    we need to adjust the length (rN) and special case the loop
-   versioning for the first word. This insures that the loop count is
+   versioning for the first word. This ensures that the loop count is
    correct and the first word (shifted) is in the expected register pair. */
-	.align 4
+	.align	4
 L(samealignment):
 	clrrwi	rSTR1, rSTR1, 2
 	clrrwi	rSTR2, rSTR2, 2
 	beq	cr5, L(Waligned)
-	add	rN, rN, rBITDIF
-	slwi	r11, rBITDIF, 3
-	srwi	rTMP, rN, 4	 /* Divide by 16 */
-	andi.	rBITDIF, rN, 12  /* Get the word remainder */
+	add	rN, rN, r12
+	slwi	rWORD6, r12, 3
+	srwi	r0, rN, 4	/* Divide by 16 */
+	andi.	r12, rN, 12	/* Get the word remainder */
+#ifdef __LITTLE_ENDIAN__
+	lwbrx	rWORD1, 0, rSTR1
+	lwbrx	rWORD2, 0, rSTR2
+	addi	rSTR1, rSTR1, 4
+	addi	rSTR2, rSTR2, 4
+#else
 	lwz	rWORD1, 0(rSTR1)
 	lwz	rWORD2, 0(rSTR2)
-	cmplwi	cr1, rBITDIF, 8
+#endif
+	cmplwi	cr1, r12, 8
 	cmplwi	cr7, rN, 16
 	clrlwi	rN, rN, 30
 	beq	L(dPs4)
-	mtctr   rTMP	/* Power4 wants mtctr 1st in dispatch group */
+	mtctr	r0	/* Power4 wants mtctr 1st in dispatch group */
 	bgt	cr1, L(dPs3)
 	beq	cr1, L(dPs2)
 
 /* Remainder is 4 */
-	.align 3
+	.align	3
 L(dsP1):
-	slw	rWORD5, rWORD1, r11
-	slw	rWORD6, rWORD2, r11
+	slw	rWORD5, rWORD1, rWORD6
+	slw	rWORD6, rWORD2, rWORD6
 	cmplw	cr5, rWORD5, rWORD6
 	blt	cr7, L(dP1x)
 /* Do something useful in this cycle since we have to branch anyway.  */
+#ifdef __LITTLE_ENDIAN__
+	lwbrx	rWORD1, 0, rSTR1
+	lwbrx	rWORD2, 0, rSTR2
+	addi	rSTR1, rSTR1, 4
+	addi	rSTR2, rSTR2, 4
+#else
 	lwz	rWORD1, 4(rSTR1)
 	lwz	rWORD2, 4(rSTR2)
-	cmplw	cr0, rWORD1, rWORD2
+#endif
+	cmplw	cr7, rWORD1, rWORD2
 	b	L(dP1e)
 /* Remainder is 8 */
-	.align 4
+	.align	4
 L(dPs2):
-	slw	rWORD5, rWORD1, r11
-	slw	rWORD6, rWORD2, r11
+	slw	rWORD5, rWORD1, rWORD6
+	slw	rWORD6, rWORD2, rWORD6
 	cmplw	cr6, rWORD5, rWORD6
 	blt	cr7, L(dP2x)
 /* Do something useful in this cycle since we have to branch anyway.  */
+#ifdef __LITTLE_ENDIAN__
+	lwbrx	rWORD7, 0, rSTR1
+	lwbrx	rWORD8, 0, rSTR2
+	addi	rSTR1, rSTR1, 4
+	addi	rSTR2, rSTR2, 4
+#else
 	lwz	rWORD7, 4(rSTR1)
 	lwz	rWORD8, 4(rSTR2)
+#endif
 	cmplw	cr5, rWORD7, rWORD8
 	b	L(dP2e)
 /* Remainder is 12 */
-	.align 4
+	.align	4
 L(dPs3):
-	slw	rWORD3, rWORD1, r11
-	slw	rWORD4, rWORD2, r11
+	slw	rWORD3, rWORD1, rWORD6
+	slw	rWORD4, rWORD2, rWORD6
 	cmplw	cr1, rWORD3, rWORD4
 	b	L(dP3e)
 /* Count is a multiple of 16, remainder is 0 */
-	.align 4
+	.align	4
 L(dPs4):
-	mtctr   rTMP	/* Power4 wants mtctr 1st in dispatch group */
-	slw	rWORD1, rWORD1, r11
-	slw	rWORD2, rWORD2, r11
-	cmplw	cr0, rWORD1, rWORD2
+	mtctr	r0	/* Power4 wants mtctr 1st in dispatch group */
+	slw	rWORD1, rWORD1, rWORD6
+	slw	rWORD2, rWORD2, rWORD6
+	cmplw	cr7, rWORD1, rWORD2
 	b	L(dP4e)
 
 /* At this point we know both strings are word aligned and the
    compare length is at least 8 bytes.  */
-	.align 4
+	.align	4
 L(Waligned):
-	andi.	rBITDIF, rN, 12  /* Get the word remainder */
-	srwi	rTMP, rN, 4	 /* Divide by 16 */
-	cmplwi	cr1, rBITDIF, 8
+	andi.	r12, rN, 12	/* Get the word remainder */
+	srwi	r0, rN, 4	/* Divide by 16 */
+	cmplwi	cr1, r12, 8
 	cmplwi	cr7, rN, 16
 	clrlwi	rN, rN, 30
 	beq	L(dP4)
@@ -145,177 +166,352 @@ L(Waligned):
 	beq	cr1, L(dP2)
 
 /* Remainder is 4 */
-	.align 4
+	.align	4
 L(dP1):
-	mtctr   rTMP	/* Power4 wants mtctr 1st in dispatch group */
+	mtctr	r0	/* Power4 wants mtctr 1st in dispatch group */
 /* Normally we'd use rWORD7/rWORD8 here, but since we might exit early
    (8-15 byte compare), we want to use only volatile registers.  This
    means we can avoid restoring non-volatile registers since we did not
    change any on the early exit path.  The key here is the non-early
    exit path only cares about the condition code (cr5), not about which
    register pair was used.  */
+#ifdef __LITTLE_ENDIAN__
+	lwbrx	rWORD5, 0, rSTR1
+	lwbrx	rWORD6, 0, rSTR2
+	addi	rSTR1, rSTR1, 4
+	addi	rSTR2, rSTR2, 4
+#else
 	lwz	rWORD5, 0(rSTR1)
 	lwz	rWORD6, 0(rSTR2)
+#endif
 	cmplw	cr5, rWORD5, rWORD6
 	blt	cr7, L(dP1x)
+#ifdef __LITTLE_ENDIAN__
+	lwbrx	rWORD1, 0, rSTR1
+	lwbrx	rWORD2, 0, rSTR2
+	addi	rSTR1, rSTR1, 4
+	addi	rSTR2, rSTR2, 4
+#else
 	lwz	rWORD1, 4(rSTR1)
 	lwz	rWORD2, 4(rSTR2)
-	cmplw	cr0, rWORD1, rWORD2
+#endif
+	cmplw	cr7, rWORD1, rWORD2
 L(dP1e):
+#ifdef __LITTLE_ENDIAN__
+	lwbrx	rWORD3, 0, rSTR1
+	lwbrx	rWORD4, 0, rSTR2
+	addi	rSTR1, rSTR1, 4
+	addi	rSTR2, rSTR2, 4
+#else
 	lwz	rWORD3, 8(rSTR1)
 	lwz	rWORD4, 8(rSTR2)
+#endif
 	cmplw	cr1, rWORD3, rWORD4
+#ifdef __LITTLE_ENDIAN__
+	lwbrx	rWORD5, 0, rSTR1
+	lwbrx	rWORD6, 0, rSTR2
+	addi	rSTR1, rSTR1, 4
+	addi	rSTR2, rSTR2, 4
+#else
 	lwz	rWORD5, 12(rSTR1)
 	lwz	rWORD6, 12(rSTR2)
+#endif
 	cmplw	cr6, rWORD5, rWORD6
-	bne	cr5, L(dLcr5)
-	bne	cr0, L(dLcr0)
+	bne	cr5, L(dLcr5x)
+	bne	cr7, L(dLcr7x)
 
+#ifdef __LITTLE_ENDIAN__
+	lwbrx	rWORD7, 0, rSTR1
+	lwbrx	rWORD8, 0, rSTR2
+	addi	rSTR1, rSTR1, 4
+	addi	rSTR2, rSTR2, 4
+#else
 	lwzu	rWORD7, 16(rSTR1)
 	lwzu	rWORD8, 16(rSTR2)
+#endif
 	bne	cr1, L(dLcr1)
 	cmplw	cr5, rWORD7, rWORD8
 	bdnz	L(dLoop)
 	bne	cr6, L(dLcr6)
-        lwz     r30,44(1)
-        lwz     r31,48(1)
-	.align 3
+	lwz	rWORD7, 44(r1)
+	lwz	rWORD8, 48(r1)
+	.align	3
 L(dP1x):
 	slwi.	r12, rN, 3
-	bne	cr5, L(dLcr5)
+	bne	cr5, L(dLcr5x)
 	subfic	rN, r12, 32	/* Shift count is 32 - (rN * 8).  */
-        lwz     1,0(1)
+	addi	1, 1, 64
+	cfi_adjust_cfa_offset(-64)
 	bne	L(d00)
 	li	rRTN, 0
 	blr
 
 /* Remainder is 8 */
-	.align 4
+	.align	4
+	cfi_adjust_cfa_offset(64)
 L(dP2):
-	mtctr   rTMP	/* Power4 wants mtctr 1st in dispatch group */
+	mtctr	r0	/* Power4 wants mtctr 1st in dispatch group */
+#ifdef __LITTLE_ENDIAN__
+	lwbrx	rWORD5, 0, rSTR1
+	lwbrx	rWORD6, 0, rSTR2
+	addi	rSTR1, rSTR1, 4
+	addi	rSTR2, rSTR2, 4
+#else
 	lwz	rWORD5, 0(rSTR1)
 	lwz	rWORD6, 0(rSTR2)
+#endif
 	cmplw	cr6, rWORD5, rWORD6
 	blt	cr7, L(dP2x)
+#ifdef __LITTLE_ENDIAN__
+	lwbrx	rWORD7, 0, rSTR1
+	lwbrx	rWORD8, 0, rSTR2
+	addi	rSTR1, rSTR1, 4
+	addi	rSTR2, rSTR2, 4
+#else
 	lwz	rWORD7, 4(rSTR1)
 	lwz	rWORD8, 4(rSTR2)
+#endif
 	cmplw	cr5, rWORD7, rWORD8
 L(dP2e):
+#ifdef __LITTLE_ENDIAN__
+	lwbrx	rWORD1, 0, rSTR1
+	lwbrx	rWORD2, 0, rSTR2
+	addi	rSTR1, rSTR1, 4
+	addi	rSTR2, rSTR2, 4
+#else
 	lwz	rWORD1, 8(rSTR1)
 	lwz	rWORD2, 8(rSTR2)
-	cmplw	cr0, rWORD1, rWORD2
+#endif
+	cmplw	cr7, rWORD1, rWORD2
+#ifdef __LITTLE_ENDIAN__
+	lwbrx	rWORD3, 0, rSTR1
+	lwbrx	rWORD4, 0, rSTR2
+	addi	rSTR1, rSTR1, 4
+	addi	rSTR2, rSTR2, 4
+#else
 	lwz	rWORD3, 12(rSTR1)
 	lwz	rWORD4, 12(rSTR2)
+#endif
 	cmplw	cr1, rWORD3, rWORD4
+#ifndef __LITTLE_ENDIAN__
 	addi	rSTR1, rSTR1, 4
 	addi	rSTR2, rSTR2, 4
+#endif
 	bne	cr6, L(dLcr6)
 	bne	cr5, L(dLcr5)
 	b	L(dLoop2)
 /* Again we are on a early exit path (16-23 byte compare), we want to
    only use volatile registers and avoid restoring non-volatile
    registers.  */
-	.align 4
+	.align	4
 L(dP2x):
+#ifdef __LITTLE_ENDIAN__
+	lwbrx	rWORD3, 0, rSTR1
+	lwbrx	rWORD4, 0, rSTR2
+	addi	rSTR1, rSTR1, 4
+	addi	rSTR2, rSTR2, 4
+#else
 	lwz	rWORD3, 4(rSTR1)
 	lwz	rWORD4, 4(rSTR2)
-	cmplw	cr5, rWORD3, rWORD4
+#endif
+	cmplw	cr1, rWORD3, rWORD4
 	slwi.	r12, rN, 3
-	bne	cr6, L(dLcr6)
+	bne	cr6, L(dLcr6x)
+#ifndef __LITTLE_ENDIAN__
 	addi	rSTR1, rSTR1, 4
 	addi	rSTR2, rSTR2, 4
-	bne	cr5, L(dLcr5)
+#endif
+	bne	cr1, L(dLcr1x)
 	subfic	rN, r12, 32	/* Shift count is 32 - (rN * 8).  */
-        lwz     1,0(1)
+	addi	1, 1, 64
+	cfi_adjust_cfa_offset(-64)
 	bne	L(d00)
 	li	rRTN, 0
 	blr
 
 /* Remainder is 12 */
-	.align 4
+	.align	4
+	cfi_adjust_cfa_offset(64)
 L(dP3):
-	mtctr   rTMP	/* Power4 wants mtctr 1st in dispatch group */
+	mtctr	r0	/* Power4 wants mtctr 1st in dispatch group */
+#ifdef __LITTLE_ENDIAN__
+	lwbrx	rWORD3, 0, rSTR1
+	lwbrx	rWORD4, 0, rSTR2
+	addi	rSTR1, rSTR1, 4
+	addi	rSTR2, rSTR2, 4
+#else
 	lwz	rWORD3, 0(rSTR1)
 	lwz	rWORD4, 0(rSTR2)
+#endif
 	cmplw	cr1, rWORD3, rWORD4
 L(dP3e):
+#ifdef __LITTLE_ENDIAN__
+	lwbrx	rWORD5, 0, rSTR1
+	lwbrx	rWORD6, 0, rSTR2
+	addi	rSTR1, rSTR1, 4
+	addi	rSTR2, rSTR2, 4
+#else
 	lwz	rWORD5, 4(rSTR1)
 	lwz	rWORD6, 4(rSTR2)
+#endif
 	cmplw	cr6, rWORD5, rWORD6
 	blt	cr7, L(dP3x)
+#ifdef __LITTLE_ENDIAN__
+	lwbrx	rWORD7, 0, rSTR1
+	lwbrx	rWORD8, 0, rSTR2
+	addi	rSTR1, rSTR1, 4
+	addi	rSTR2, rSTR2, 4
+#else
 	lwz	rWORD7, 8(rSTR1)
 	lwz	rWORD8, 8(rSTR2)
+#endif
 	cmplw	cr5, rWORD7, rWORD8
+#ifdef __LITTLE_ENDIAN__
+	lwbrx	rWORD1, 0, rSTR1
+	lwbrx	rWORD2, 0, rSTR2
+	addi	rSTR1, rSTR1, 4
+	addi	rSTR2, rSTR2, 4
+#else
 	lwz	rWORD1, 12(rSTR1)
 	lwz	rWORD2, 12(rSTR2)
-	cmplw	cr0, rWORD1, rWORD2
+#endif
+	cmplw	cr7, rWORD1, rWORD2
+#ifndef __LITTLE_ENDIAN__
 	addi	rSTR1, rSTR1, 8
 	addi	rSTR2, rSTR2, 8
+#endif
 	bne	cr1, L(dLcr1)
 	bne	cr6, L(dLcr6)
 	b	L(dLoop1)
 /* Again we are on a early exit path (24-31 byte compare), we want to
    only use volatile registers and avoid restoring non-volatile
    registers.  */
-	.align 4
+	.align	4
 L(dP3x):
+#ifdef __LITTLE_ENDIAN__
+	lwbrx	rWORD1, 0, rSTR1
+	lwbrx	rWORD2, 0, rSTR2
+	addi	rSTR1, rSTR1, 4
+	addi	rSTR2, rSTR2, 4
+#else
 	lwz	rWORD1, 8(rSTR1)
 	lwz	rWORD2, 8(rSTR2)
-	cmplw	cr5, rWORD1, rWORD2
+#endif
+	cmplw	cr7, rWORD1, rWORD2
 	slwi.	r12, rN, 3
-	bne	cr1, L(dLcr1)
+	bne	cr1, L(dLcr1x)
+#ifndef __LITTLE_ENDIAN__
 	addi	rSTR1, rSTR1, 8
 	addi	rSTR2, rSTR2, 8
-	bne	cr6, L(dLcr6)
+#endif
+	bne	cr6, L(dLcr6x)
 	subfic	rN, r12, 32	/* Shift count is 32 - (rN * 8).  */
-	bne	cr5, L(dLcr5)
-        lwz     1,0(1)
+	bne	cr7, L(dLcr7x)
+	addi	1, 1, 64
+	cfi_adjust_cfa_offset(-64)
 	bne	L(d00)
 	li	rRTN, 0
 	blr
 
 /* Count is a multiple of 16, remainder is 0 */
-	.align 4
+	.align	4
+	cfi_adjust_cfa_offset(64)
 L(dP4):
-	mtctr   rTMP	/* Power4 wants mtctr 1st in dispatch group */
+	mtctr	r0	/* Power4 wants mtctr 1st in dispatch group */
+#ifdef __LITTLE_ENDIAN__
+	lwbrx	rWORD1, 0, rSTR1
+	lwbrx	rWORD2, 0, rSTR2
+	addi	rSTR1, rSTR1, 4
+	addi	rSTR2, rSTR2, 4
+#else
 	lwz	rWORD1, 0(rSTR1)
 	lwz	rWORD2, 0(rSTR2)
-	cmplw	cr0, rWORD1, rWORD2
+#endif
+	cmplw	cr7, rWORD1, rWORD2
 L(dP4e):
+#ifdef __LITTLE_ENDIAN__
+	lwbrx	rWORD3, 0, rSTR1
+	lwbrx	rWORD4, 0, rSTR2
+	addi	rSTR1, rSTR1, 4
+	addi	rSTR2, rSTR2, 4
+#else
 	lwz	rWORD3, 4(rSTR1)
 	lwz	rWORD4, 4(rSTR2)
+#endif
 	cmplw	cr1, rWORD3, rWORD4
+#ifdef __LITTLE_ENDIAN__
+	lwbrx	rWORD5, 0, rSTR1
+	lwbrx	rWORD6, 0, rSTR2
+	addi	rSTR1, rSTR1, 4
+	addi	rSTR2, rSTR2, 4
+#else
 	lwz	rWORD5, 8(rSTR1)
 	lwz	rWORD6, 8(rSTR2)
+#endif
 	cmplw	cr6, rWORD5, rWORD6
+#ifdef __LITTLE_ENDIAN__
+	lwbrx	rWORD7, 0, rSTR1
+	lwbrx	rWORD8, 0, rSTR2
+	addi	rSTR1, rSTR1, 4
+	addi	rSTR2, rSTR2, 4
+#else
 	lwzu	rWORD7, 12(rSTR1)
 	lwzu	rWORD8, 12(rSTR2)
+#endif
 	cmplw	cr5, rWORD7, rWORD8
-	bne	cr0, L(dLcr0)
+	bne	cr7, L(dLcr7)
 	bne	cr1, L(dLcr1)
 	bdz-	L(d24)		/* Adjust CTR as we start with +4 */
 /* This is the primary loop */
-	.align 4
+	.align	4
 L(dLoop):
+#ifdef __LITTLE_ENDIAN__
+	lwbrx	rWORD1, 0, rSTR1
+	lwbrx	rWORD2, 0, rSTR2
+	addi	rSTR1, rSTR1, 4
+	addi	rSTR2, rSTR2, 4
+#else
 	lwz	rWORD1, 4(rSTR1)
 	lwz	rWORD2, 4(rSTR2)
+#endif
 	cmplw	cr1, rWORD3, rWORD4
 	bne	cr6, L(dLcr6)
 L(dLoop1):
+#ifdef __LITTLE_ENDIAN__
+	lwbrx	rWORD3, 0, rSTR1
+	lwbrx	rWORD4, 0, rSTR2
+	addi	rSTR1, rSTR1, 4
+	addi	rSTR2, rSTR2, 4
+#else
 	lwz	rWORD3, 8(rSTR1)
 	lwz	rWORD4, 8(rSTR2)
+#endif
 	cmplw	cr6, rWORD5, rWORD6
 	bne	cr5, L(dLcr5)
 L(dLoop2):
+#ifdef __LITTLE_ENDIAN__
+	lwbrx	rWORD5, 0, rSTR1
+	lwbrx	rWORD6, 0, rSTR2
+	addi	rSTR1, rSTR1, 4
+	addi	rSTR2, rSTR2, 4
+#else
 	lwz	rWORD5, 12(rSTR1)
 	lwz	rWORD6, 12(rSTR2)
+#endif
 	cmplw	cr5, rWORD7, rWORD8
-	bne	cr0, L(dLcr0)
+	bne	cr7, L(dLcr7)
 L(dLoop3):
+#ifdef __LITTLE_ENDIAN__
+	lwbrx	rWORD7, 0, rSTR1
+	lwbrx	rWORD8, 0, rSTR2
+	addi	rSTR1, rSTR1, 4
+	addi	rSTR2, rSTR2, 4
+#else
 	lwzu	rWORD7, 16(rSTR1)
 	lwzu	rWORD8, 16(rSTR2)
+#endif
 	bne-	cr1, L(dLcr1)
-	cmplw	cr0, rWORD1, rWORD2
+	cmplw	cr7, rWORD1, rWORD2
 	bdnz+	L(dLoop)
 
 L(dL4):
@@ -325,7 +521,7 @@ L(dL4):
 	bne	cr5, L(dLcr5)
 	cmplw	cr5, rWORD7, rWORD8
 L(d44):
-	bne	cr0, L(dLcr0)
+	bne	cr7, L(dLcr7)
 L(d34):
 	bne	cr1, L(dLcr1)
 L(d24):
@@ -334,69 +530,82 @@ L(d14):
 	slwi.	r12, rN, 3
 	bne	cr5, L(dLcr5)
 L(d04):
-        lwz     r30,44(1)
-        lwz     r31,48(1)
-        lwz     1,0(1)
+	lwz	rWORD7, 44(r1)
+	lwz	rWORD8, 48(r1)
+	addi	1, 1, 64
+	cfi_adjust_cfa_offset(-64)
 	subfic	rN, r12, 32	/* Shift count is 32 - (rN * 8).  */
 	beq	L(zeroLength)
 /* At this point we have a remainder of 1 to 3 bytes to compare.  Since
    we are aligned it is safe to load the whole word, and use
-   shift right to eliminate bits beyond the compare length. */
+   shift right to eliminate bits beyond the compare length.  */
 L(d00):
+#ifdef __LITTLE_ENDIAN__
+	lwbrx	rWORD1, 0, rSTR1
+	lwbrx	rWORD2, 0, rSTR2
+	addi	rSTR1, rSTR1, 4
+	addi	rSTR2, rSTR2, 4
+#else
 	lwz	rWORD1, 4(rSTR1)
 	lwz	rWORD2, 4(rSTR2)
+#endif
 	srw	rWORD1, rWORD1, rN
 	srw	rWORD2, rWORD2, rN
-        cmplw   rWORD1,rWORD2
-        li      rRTN,0
-        beqlr
-        li      rRTN,1
-        bgtlr
-        li      rRTN,-1
-        blr
-
-	.align 4
-L(dLcr0):
-        lwz     r30,44(1)
-        lwz     r31,48(1)
+	sub	rRTN, rWORD1, rWORD2
+	blr
+
+	.align	4
+	cfi_adjust_cfa_offset(64)
+L(dLcr7):
+	lwz	rWORD7, 44(r1)
+	lwz	rWORD8, 48(r1)
+L(dLcr7x):
 	li	rRTN, 1
-        lwz     1,0(1)
-	bgtlr	cr0
+	addi	1, 1, 64
+	cfi_adjust_cfa_offset(-64)
+	bgtlr	cr7
 	li	rRTN, -1
 	blr
-	.align 4
+	.align	4
+	cfi_adjust_cfa_offset(64)
 L(dLcr1):
-        lwz     r30,44(1)
-        lwz     r31,48(1)
+	lwz	rWORD7, 44(r1)
+	lwz	rWORD8, 48(r1)
+L(dLcr1x):
 	li	rRTN, 1
-        lwz     1,0(1)
+	addi	1, 1, 64
+	cfi_adjust_cfa_offset(-64)
 	bgtlr	cr1
 	li	rRTN, -1
 	blr
-	.align 4
+	.align	4
+	cfi_adjust_cfa_offset(64)
 L(dLcr6):
-        lwz     r30,44(1)
-        lwz     r31,48(1)
+	lwz	rWORD7, 44(r1)
+	lwz	rWORD8, 48(r1)
+L(dLcr6x):
 	li	rRTN, 1
-        lwz     1,0(1)
+	addi	1, 1, 64
+	cfi_adjust_cfa_offset(-64)
 	bgtlr	cr6
 	li	rRTN, -1
 	blr
-	.align 4
+	.align	4
+	cfi_adjust_cfa_offset(64)
 L(dLcr5):
-        lwz     r30,44(1)
-        lwz     r31,48(1)
+	lwz	rWORD7, 44(r1)
+	lwz	rWORD8, 48(r1)
 L(dLcr5x):
 	li	rRTN, 1
-        lwz     1,0(1)
+	addi	1, 1, 64
+	cfi_adjust_cfa_offset(-64)
 	bgtlr	cr5
 	li	rRTN, -1
 	blr
 
-	.align 4
+	.align	4
 L(bytealigned):
-	cfi_adjust_cfa_offset(-64)
-	mtctr   rN	/* Power4 wants mtctr 1st in dispatch group */
+	mtctr	rN	/* Power4 wants mtctr 1st in dispatch group */
 
 /* We need to prime this loop.  This loop is swing modulo scheduled
    to avoid pipe delays.  The dependent instruction latencies (load to
@@ -411,7 +620,7 @@ L(bytealigned):
 	lbz	rWORD1, 0(rSTR1)
 	lbz	rWORD2, 0(rSTR2)
 	bdz-	L(b11)
-	cmplw	cr0, rWORD1, rWORD2
+	cmplw	cr7, rWORD1, rWORD2
 	lbz	rWORD3, 1(rSTR1)
 	lbz	rWORD4, 1(rSTR2)
 	bdz-	L(b12)
@@ -419,11 +628,11 @@ L(bytealigned):
 	lbzu	rWORD5, 2(rSTR1)
 	lbzu	rWORD6, 2(rSTR2)
 	bdz-	L(b13)
-	.align 4
+	.align	4
 L(bLoop):
 	lbzu	rWORD1, 1(rSTR1)
 	lbzu	rWORD2, 1(rSTR2)
-	bne-	cr0, L(bLcr0)
+	bne-	cr7, L(bLcr7)
 
 	cmplw	cr6, rWORD5, rWORD6
 	bdz-	L(b3i)
@@ -432,7 +641,7 @@ L(bLoop):
 	lbzu	rWORD4, 1(rSTR2)
 	bne-	cr1, L(bLcr1)
 
-	cmplw	cr0, rWORD1, rWORD2
+	cmplw	cr7, rWORD1, rWORD2
 	bdz-	L(b2i)
 
 	lbzu	rWORD5, 1(rSTR1)
@@ -449,23 +658,23 @@ L(bLoop):
    tested.  In this case we must complete the pending operations
    before returning.  */
 L(b1i):
-	bne-	cr0, L(bLcr0)
+	bne-	cr7, L(bLcr7)
 	bne-	cr1, L(bLcr1)
 	b	L(bx56)
-	.align 4
+	.align	4
 L(b2i):
 	bne-	cr6, L(bLcr6)
-	bne-	cr0, L(bLcr0)
+	bne-	cr7, L(bLcr7)
 	b	L(bx34)
-	.align 4
+	.align	4
 L(b3i):
 	bne-	cr1, L(bLcr1)
 	bne-	cr6, L(bLcr6)
 	b	L(bx12)
-	.align 4
-L(bLcr0):
+	.align	4
+L(bLcr7):
 	li	rRTN, 1
-	bgtlr	cr0
+	bgtlr	cr7
 	li	rRTN, -1
 	blr
 L(bLcr1):
@@ -480,36 +689,31 @@ L(bLcr6):
 	blr
 
 L(b13):
-	bne-	cr0, L(bx12)
+	bne-	cr7, L(bx12)
 	bne-	cr1, L(bx34)
 L(bx56):
 	sub	rRTN, rWORD5, rWORD6
 	blr
 	nop
 L(b12):
-	bne-	cr0, L(bx12)
+	bne-	cr7, L(bx12)
 L(bx34):
 	sub	rRTN, rWORD3, rWORD4
 	blr
-
 L(b11):
 L(bx12):
 	sub	rRTN, rWORD1, rWORD2
 	blr
-
-	.align 4
-L(zeroLengthReturn):
-
+	.align	4
 L(zeroLength):
 	li	rRTN, 0
 	blr
 
-	cfi_adjust_cfa_offset(64)
-	.align 4
+	.align	4
 /* At this point we know the strings have different alignment and the
-   compare length is at least 8 bytes.  rBITDIF contains the low order
+   compare length is at least 8 bytes.  r12 contains the low order
    2 bits of rSTR1 and cr5 contains the result of the logical compare
-   of rBITDIF to 0.  If rBITDIF == 0 then rStr1 is word aligned and can
+   of r12 to 0.  If r12 == 0 then rStr1 is word aligned and can
    perform the Wunaligned loop.
 
    Otherwise we know that rSTR1 is not aready word aligned yet.
@@ -518,79 +722,88 @@ L(zeroLength):
    eliminate bits preceding the first byte.  Since we want to join the
    normal (Wualigned) compare loop, starting at the second word,
    we need to adjust the length (rN) and special case the loop
-   versioning for the first W. This insures that the loop count is
+   versioning for the first W. This ensures that the loop count is
    correct and the first W (shifted) is in the expected resister pair.  */
 #define rSHL		r29	/* Unaligned shift left count.  */
 #define rSHR		r28	/* Unaligned shift right count.  */
-#define rB		r27	/* Left rotation temp for rWORD2.  */
-#define rD		r26	/* Left rotation temp for rWORD4.  */
-#define rF		r25	/* Left rotation temp for rWORD6.  */
-#define rH		r24	/* Left rotation temp for rWORD8.  */
-#define rA		r0	/* Right rotation temp for rWORD2.  */
-#define rC		r12	/* Right rotation temp for rWORD4.  */
-#define rE		r0	/* Right rotation temp for rWORD6.  */
-#define rG		r12	/* Right rotation temp for rWORD8.  */
+#define rWORD8_SHIFT	r27	/* Left rotation temp for rWORD2.  */
+#define rWORD2_SHIFT	r26	/* Left rotation temp for rWORD4.  */
+#define rWORD4_SHIFT	r25	/* Left rotation temp for rWORD6.  */
+#define rWORD6_SHIFT	r24	/* Left rotation temp for rWORD8.  */
+	cfi_adjust_cfa_offset(64)
 L(unaligned):
-	stw     r29,40(r1)
-	cfi_offset(r29,(40-64))
+	stw	rSHL, 40(r1)
+	cfi_offset(rSHL, (40-64))
 	clrlwi	rSHL, rSTR2, 30
-        stw     r28,36(r1)
-	cfi_offset(r28,(36-64))
+	stw	rSHR, 36(r1)
+	cfi_offset(rSHR, (36-64))
 	beq	cr5, L(Wunaligned)
-        stw     r27,32(r1)
-	cfi_offset(r27,(32-64))
+	stw	rWORD8_SHIFT, 32(r1)
+	cfi_offset(rWORD8_SHIFT, (32-64))
 /* Adjust the logical start of rSTR2 to compensate for the extra bits
    in the 1st rSTR1 W.  */
-	sub	r27, rSTR2, rBITDIF
+	sub	rWORD8_SHIFT, rSTR2, r12
 /* But do not attempt to address the W before that W that contains
    the actual start of rSTR2.  */
 	clrrwi	rSTR2, rSTR2, 2
-        stw     r26,28(r1)
-	cfi_offset(r26,(28-64))
-/* Compute the left/right shift counts for the unalign rSTR2,
+	stw	rWORD2_SHIFT, 28(r1)
+	cfi_offset(rWORD2_SHIFT, (28-64))
+/* Compute the left/right shift counts for the unaligned rSTR2,
    compensating for the logical (W aligned) start of rSTR1.  */
-	clrlwi	rSHL, r27, 30
+	clrlwi	rSHL, rWORD8_SHIFT, 30
 	clrrwi	rSTR1, rSTR1, 2
-        stw     r25,24(r1)
-	cfi_offset(r25,(24-64))
+	stw	rWORD4_SHIFT, 24(r1)
+	cfi_offset(rWORD4_SHIFT, (24-64))
 	slwi	rSHL, rSHL, 3
-	cmplw	cr5, r27, rSTR2
-	add	rN, rN, rBITDIF
-	slwi	r11, rBITDIF, 3
-        stw     r24,20(r1)
-	cfi_offset(r24,(20-64))
+	cmplw	cr5, rWORD8_SHIFT, rSTR2
+	add	rN, rN, r12
+	slwi	rWORD6, r12, 3
+	stw	rWORD6_SHIFT, 20(r1)
+	cfi_offset(rWORD6_SHIFT, (20-64))
 	subfic	rSHR, rSHL, 32
-	srwi	rTMP, rN, 4      /* Divide by 16 */
-	andi.	rBITDIF, rN, 12  /* Get the W remainder */
+	srwi	r0, rN, 4	/* Divide by 16 */
+	andi.	r12, rN, 12	/* Get the W remainder */
 /* We normally need to load 2 Ws to start the unaligned rSTR2, but in
    this special case those bits may be discarded anyway.  Also we
    must avoid loading a W where none of the bits are part of rSTR2 as
    this may cross a page boundary and cause a page fault.  */
 	li	rWORD8, 0
 	blt	cr5, L(dus0)
+#ifdef __LITTLE_ENDIAN__
+	lwbrx	rWORD8, 0, rSTR2
+	addi	rSTR2, rSTR2, 4
+#else
 	lwz	rWORD8, 0(rSTR2)
-	la	rSTR2, 4(rSTR2)
+	addi	rSTR2, rSTR2, 4
+#endif
 	slw	rWORD8, rWORD8, rSHL
 
 L(dus0):
+#ifdef __LITTLE_ENDIAN__
+	lwbrx	rWORD1, 0, rSTR1
+	lwbrx	rWORD2, 0, rSTR2
+	addi	rSTR1, rSTR1, 4
+	addi	rSTR2, rSTR2, 4
+#else
 	lwz	rWORD1, 0(rSTR1)
 	lwz	rWORD2, 0(rSTR2)
-	cmplwi	cr1, rBITDIF, 8
+#endif
+	cmplwi	cr1, r12, 8
 	cmplwi	cr7, rN, 16
-	srw	rG, rWORD2, rSHR
+	srw	r12, rWORD2, rSHR
 	clrlwi	rN, rN, 30
 	beq	L(duPs4)
-	mtctr   rTMP	/* Power4 wants mtctr 1st in dispatch group */
-	or	rWORD8, rG, rWORD8
+	mtctr	r0	/* Power4 wants mtctr 1st in dispatch group */
+	or	rWORD8, r12, rWORD8
 	bgt	cr1, L(duPs3)
 	beq	cr1, L(duPs2)
 
 /* Remainder is 4 */
-	.align 4
+	.align	4
 L(dusP1):
-	slw	rB, rWORD2, rSHL
-	slw	rWORD7, rWORD1, r11
-	slw	rWORD8, rWORD8, r11
+	slw	rWORD8_SHIFT, rWORD2, rSHL
+	slw	rWORD7, rWORD1, rWORD6
+	slw	rWORD8, rWORD8, rWORD6
 	bge	cr7, L(duP1e)
 /* At this point we exit early with the first word compare
    complete and remainder of 0 to 3 bytes.  See L(du14) for details on
@@ -600,95 +813,133 @@ L(dusP1):
 	bne	cr5, L(duLcr5)
 	cmplw	cr7, rN, rSHR
 	beq	L(duZeroReturn)
-	li	rA, 0
+	li	r0, 0
 	ble	cr7, L(dutrim)
+#ifdef __LITTLE_ENDIAN__
+	lwbrx	rWORD2, 0, rSTR2
+	addi	rSTR2, rSTR2, 4
+#else
 	lwz	rWORD2, 4(rSTR2)
-	srw	rA, rWORD2, rSHR
+#endif
+	srw	r0, rWORD2, rSHR
 	b	L(dutrim)
 /* Remainder is 8 */
-	.align 4
+	.align	4
 L(duPs2):
-	slw	rH, rWORD2, rSHL
-	slw	rWORD5, rWORD1, r11
-	slw	rWORD6, rWORD8, r11
+	slw	rWORD6_SHIFT, rWORD2, rSHL
+	slw	rWORD5, rWORD1, rWORD6
+	slw	rWORD6, rWORD8, rWORD6
 	b	L(duP2e)
 /* Remainder is 12 */
-	.align 4
+	.align	4
 L(duPs3):
-	slw	rF, rWORD2, rSHL
-	slw	rWORD3, rWORD1, r11
-	slw	rWORD4, rWORD8, r11
+	slw	rWORD4_SHIFT, rWORD2, rSHL
+	slw	rWORD3, rWORD1, rWORD6
+	slw	rWORD4, rWORD8, rWORD6
 	b	L(duP3e)
 /* Count is a multiple of 16, remainder is 0 */
-	.align 4
+	.align	4
 L(duPs4):
-	mtctr   rTMP	/* Power4 wants mtctr 1st in dispatch group */
-	or	rWORD8, rG, rWORD8
-	slw	rD, rWORD2, rSHL
-	slw	rWORD1, rWORD1, r11
-	slw	rWORD2, rWORD8, r11
+	mtctr	r0	/* Power4 wants mtctr 1st in dispatch group */
+	or	rWORD8, r12, rWORD8
+	slw	rWORD2_SHIFT, rWORD2, rSHL
+	slw	rWORD1, rWORD1, rWORD6
+	slw	rWORD2, rWORD8, rWORD6
 	b	L(duP4e)
 
 /* At this point we know rSTR1 is word aligned and the
    compare length is at least 8 bytes.  */
-	.align 4
+	.align	4
 L(Wunaligned):
-        stw     r27,32(r1)
-	cfi_offset(r27,(32-64))
+	stw	rWORD8_SHIFT, 32(r1)
+	cfi_offset(rWORD8_SHIFT, (32-64))
 	clrrwi	rSTR2, rSTR2, 2
-        stw     r26,28(r1)
-	cfi_offset(r26,(28-64))
-	srwi	rTMP, rN, 4	 /* Divide by 16 */
-        stw     r25,24(r1)
-	cfi_offset(r25,(24-64))
-	andi.	rBITDIF, rN, 12  /* Get the W remainder */
-        stw     r24,20(r1)
-	cfi_offset(r24,(20-64))
+	stw	rWORD2_SHIFT, 28(r1)
+	cfi_offset(rWORD2_SHIFT, (28-64))
+	srwi	r0, rN, 4	/* Divide by 16 */
+	stw	rWORD4_SHIFT, 24(r1)
+	cfi_offset(rWORD4_SHIFT, (24-64))
+	andi.	r12, rN, 12	/* Get the W remainder */
+	stw	rWORD6_SHIFT, 20(r1)
+	cfi_offset(rWORD6_SHIFT, (20-64))
 	slwi	rSHL, rSHL, 3
+#ifdef __LITTLE_ENDIAN__
+	lwbrx	rWORD6, 0, rSTR2
+	addi	rSTR2, rSTR2, 4
+	lwbrx	rWORD8, 0, rSTR2
+	addi	rSTR2, rSTR2, 4
+#else
 	lwz	rWORD6, 0(rSTR2)
 	lwzu	rWORD8, 4(rSTR2)
-	cmplwi	cr1, rBITDIF, 8
+#endif
+	cmplwi	cr1, r12, 8
 	cmplwi	cr7, rN, 16
 	clrlwi	rN, rN, 30
 	subfic	rSHR, rSHL, 32
-	slw	rH, rWORD6, rSHL
+	slw	rWORD6_SHIFT, rWORD6, rSHL
 	beq	L(duP4)
-	mtctr   rTMP	/* Power4 wants mtctr 1st in dispatch group */
+	mtctr	r0	/* Power4 wants mtctr 1st in dispatch group */
 	bgt	cr1, L(duP3)
 	beq	cr1, L(duP2)
 
 /* Remainder is 4 */
-	.align 4
+	.align	4
 L(duP1):
-	srw	rG, rWORD8, rSHR
+	srw	r12, rWORD8, rSHR
+#ifdef __LITTLE_ENDIAN__
+	lwbrx	rWORD7, 0, rSTR1
+	addi	rSTR1, rSTR1, 4
+#else
 	lwz	rWORD7, 0(rSTR1)
-	slw	rB, rWORD8, rSHL
-	or	rWORD8, rG, rH
+#endif
+	slw	rWORD8_SHIFT, rWORD8, rSHL
+	or	rWORD8, r12, rWORD6_SHIFT
 	blt	cr7, L(duP1x)
 L(duP1e):
+#ifdef __LITTLE_ENDIAN__
+	lwbrx	rWORD1, 0, rSTR1
+	lwbrx	rWORD2, 0, rSTR2
+	addi	rSTR1, rSTR1, 4
+	addi	rSTR2, rSTR2, 4
+#else
 	lwz	rWORD1, 4(rSTR1)
 	lwz	rWORD2, 4(rSTR2)
+#endif
 	cmplw	cr5, rWORD7, rWORD8
-	srw	rA, rWORD2, rSHR
-	slw	rD, rWORD2, rSHL
-	or	rWORD2, rA, rB
+	srw	r0, rWORD2, rSHR
+	slw	rWORD2_SHIFT, rWORD2, rSHL
+	or	rWORD2, r0, rWORD8_SHIFT
+#ifdef __LITTLE_ENDIAN__
+	lwbrx	rWORD3, 0, rSTR1
+	lwbrx	rWORD4, 0, rSTR2
+	addi	rSTR1, rSTR1, 4
+	addi	rSTR2, rSTR2, 4
+#else
 	lwz	rWORD3, 8(rSTR1)
 	lwz	rWORD4, 8(rSTR2)
-	cmplw	cr0, rWORD1, rWORD2
-	srw	rC, rWORD4, rSHR
-	slw	rF, rWORD4, rSHL
+#endif
+	cmplw	cr7, rWORD1, rWORD2
+	srw	r12, rWORD4, rSHR
+	slw	rWORD4_SHIFT, rWORD4, rSHL
 	bne	cr5, L(duLcr5)
-	or	rWORD4, rC, rD
+	or	rWORD4, r12, rWORD2_SHIFT
+#ifdef __LITTLE_ENDIAN__
+	lwbrx	rWORD5, 0, rSTR1
+	lwbrx	rWORD6, 0, rSTR2
+	addi	rSTR1, rSTR1, 4
+	addi	rSTR2, rSTR2, 4
+#else
 	lwz	rWORD5, 12(rSTR1)
 	lwz	rWORD6, 12(rSTR2)
+#endif
 	cmplw	cr1, rWORD3, rWORD4
-	srw	rE, rWORD6, rSHR
-	slw	rH, rWORD6, rSHL
-	bne	cr0, L(duLcr0)
-	or	rWORD6, rE, rF
+	srw	r0, rWORD6, rSHR
+	slw	rWORD6_SHIFT, rWORD6, rSHL
+	bne	cr7, L(duLcr7)
+	or	rWORD6, r0, rWORD4_SHIFT
 	cmplw	cr6, rWORD5, rWORD6
 	b	L(duLoop3)
-	.align 4
+	.align	4
 /* At this point we exit early with the first word compare
    complete and remainder of 0 to 3 bytes.  See L(du14) for details on
    how we handle the remaining bytes.  */
@@ -698,186 +949,321 @@ L(duP1x):
 	bne	cr5, L(duLcr5)
 	cmplw	cr7, rN, rSHR
 	beq	L(duZeroReturn)
-	li	rA, 0
+	li	r0, 0
 	ble	cr7, L(dutrim)
-	ld	rWORD2, 8(rSTR2)
-	srw	rA, rWORD2, rSHR
+#ifdef __LITTLE_ENDIAN__
+	lwbrx	rWORD2, 0, rSTR2
+	addi	rSTR2, rSTR2, 4
+#else
+	lwz	rWORD2, 8(rSTR2)
+#endif
+	srw	r0, rWORD2, rSHR
 	b	L(dutrim)
 /* Remainder is 8 */
-	.align 4
+	.align	4
 L(duP2):
-	srw	rE, rWORD8, rSHR
+	srw	r0, rWORD8, rSHR
+#ifdef __LITTLE_ENDIAN__
+	lwbrx	rWORD5, 0, rSTR1
+	addi	rSTR1, rSTR1, 4
+#else
 	lwz	rWORD5, 0(rSTR1)
-	or	rWORD6, rE, rH
-	slw	rH, rWORD8, rSHL
+#endif
+	or	rWORD6, r0, rWORD6_SHIFT
+	slw	rWORD6_SHIFT, rWORD8, rSHL
 L(duP2e):
+#ifdef __LITTLE_ENDIAN__
+	lwbrx	rWORD7, 0, rSTR1
+	lwbrx	rWORD8, 0, rSTR2
+	addi	rSTR1, rSTR1, 4
+	addi	rSTR2, rSTR2, 4
+#else
 	lwz	rWORD7, 4(rSTR1)
 	lwz	rWORD8, 4(rSTR2)
+#endif
 	cmplw	cr6, rWORD5, rWORD6
-	srw	rG, rWORD8, rSHR
-	slw	rB, rWORD8, rSHL
-	or	rWORD8, rG, rH
+	srw	r12, rWORD8, rSHR
+	slw	rWORD8_SHIFT, rWORD8, rSHL
+	or	rWORD8, r12, rWORD6_SHIFT
 	blt	cr7, L(duP2x)
+#ifdef __LITTLE_ENDIAN__
+	lwbrx	rWORD1, 0, rSTR1
+	lwbrx	rWORD2, 0, rSTR2
+	addi	rSTR1, rSTR1, 4
+	addi	rSTR2, rSTR2, 4
+#else
 	lwz	rWORD1, 8(rSTR1)
 	lwz	rWORD2, 8(rSTR2)
+#endif
 	cmplw	cr5, rWORD7, rWORD8
 	bne	cr6, L(duLcr6)
-	srw	rA, rWORD2, rSHR
-	slw	rD, rWORD2, rSHL
-	or	rWORD2, rA, rB
+	srw	r0, rWORD2, rSHR
+	slw	rWORD2_SHIFT, rWORD2, rSHL
+	or	rWORD2, r0, rWORD8_SHIFT
+#ifdef __LITTLE_ENDIAN__
+	lwbrx	rWORD3, 0, rSTR1
+	lwbrx	rWORD4, 0, rSTR2
+	addi	rSTR1, rSTR1, 4
+	addi	rSTR2, rSTR2, 4
+#else
 	lwz	rWORD3, 12(rSTR1)
 	lwz	rWORD4, 12(rSTR2)
-	cmplw	cr0, rWORD1, rWORD2
+#endif
+	cmplw	cr7, rWORD1, rWORD2
 	bne	cr5, L(duLcr5)
-	srw	rC, rWORD4, rSHR
-	slw	rF, rWORD4, rSHL
-	or	rWORD4, rC, rD
+	srw	r12, rWORD4, rSHR
+	slw	rWORD4_SHIFT, rWORD4, rSHL
+	or	rWORD4, r12, rWORD2_SHIFT
+#ifndef __LITTLE_ENDIAN__
 	addi	rSTR1, rSTR1, 4
 	addi	rSTR2, rSTR2, 4
+#endif
 	cmplw	cr1, rWORD3, rWORD4
 	b	L(duLoop2)
-	.align 4
+	.align	4
 L(duP2x):
 	cmplw	cr5, rWORD7, rWORD8
+#ifndef __LITTLE_ENDIAN__
 	addi	rSTR1, rSTR1, 4
 	addi	rSTR2, rSTR2, 4
+#endif
 	bne	cr6, L(duLcr6)
 	slwi.	rN, rN, 3
 	bne	cr5, L(duLcr5)
 	cmplw	cr7, rN, rSHR
 	beq	L(duZeroReturn)
-	li	rA, 0
+	li	r0, 0
 	ble	cr7, L(dutrim)
+#ifdef __LITTLE_ENDIAN__
+	lwbrx	rWORD2, 0, rSTR2
+	addi	rSTR2, rSTR2, 4
+#else
 	lwz	rWORD2, 4(rSTR2)
-	srw	rA, rWORD2, rSHR
+#endif
+	srw	r0, rWORD2, rSHR
 	b	L(dutrim)
 
 /* Remainder is 12 */
-	.align 4
+	.align	4
 L(duP3):
-	srw	rC, rWORD8, rSHR
+	srw	r12, rWORD8, rSHR
+#ifdef __LITTLE_ENDIAN__
+	lwbrx	rWORD3, 0, rSTR1
+	addi	rSTR1, rSTR1, 4
+#else
 	lwz	rWORD3, 0(rSTR1)
-	slw	rF, rWORD8, rSHL
-	or	rWORD4, rC, rH
+#endif
+	slw	rWORD4_SHIFT, rWORD8, rSHL
+	or	rWORD4, r12, rWORD6_SHIFT
 L(duP3e):
+#ifdef __LITTLE_ENDIAN__
+	lwbrx	rWORD5, 0, rSTR1
+	lwbrx	rWORD6, 0, rSTR2
+	addi	rSTR1, rSTR1, 4
+	addi	rSTR2, rSTR2, 4
+#else
 	lwz	rWORD5, 4(rSTR1)
 	lwz	rWORD6, 4(rSTR2)
+#endif
 	cmplw	cr1, rWORD3, rWORD4
-	srw	rE, rWORD6, rSHR
-	slw	rH, rWORD6, rSHL
-	or	rWORD6, rE, rF
+	srw	r0, rWORD6, rSHR
+	slw	rWORD6_SHIFT, rWORD6, rSHL
+	or	rWORD6, r0, rWORD4_SHIFT
+#ifdef __LITTLE_ENDIAN__
+	lwbrx	rWORD7, 0, rSTR1
+	lwbrx	rWORD8, 0, rSTR2
+	addi	rSTR1, rSTR1, 4
+	addi	rSTR2, rSTR2, 4
+#else
 	lwz	rWORD7, 8(rSTR1)
 	lwz	rWORD8, 8(rSTR2)
+#endif
 	cmplw	cr6, rWORD5, rWORD6
 	bne	cr1, L(duLcr1)
-	srw	rG, rWORD8, rSHR
-	slw	rB, rWORD8, rSHL
-	or	rWORD8, rG, rH
+	srw	r12, rWORD8, rSHR
+	slw	rWORD8_SHIFT, rWORD8, rSHL
+	or	rWORD8, r12, rWORD6_SHIFT
 	blt	cr7, L(duP3x)
+#ifdef __LITTLE_ENDIAN__
+	lwbrx	rWORD1, 0, rSTR1
+	lwbrx	rWORD2, 0, rSTR2
+	addi	rSTR1, rSTR1, 4
+	addi	rSTR2, rSTR2, 4
+#else
 	lwz	rWORD1, 12(rSTR1)
 	lwz	rWORD2, 12(rSTR2)
+#endif
 	cmplw	cr5, rWORD7, rWORD8
 	bne	cr6, L(duLcr6)
-	srw	rA, rWORD2, rSHR
-	slw	rD, rWORD2, rSHL
-	or	rWORD2, rA, rB
+	srw	r0, rWORD2, rSHR
+	slw	rWORD2_SHIFT, rWORD2, rSHL
+	or	rWORD2, r0, rWORD8_SHIFT
+#ifndef __LITTLE_ENDIAN__
 	addi	rSTR1, rSTR1, 8
 	addi	rSTR2, rSTR2, 8
-	cmplw	cr0, rWORD1, rWORD2
+#endif
+	cmplw	cr7, rWORD1, rWORD2
 	b	L(duLoop1)
-	.align 4
+	.align	4
 L(duP3x):
+#ifndef __LITTLE_ENDIAN__
 	addi	rSTR1, rSTR1, 8
 	addi	rSTR2, rSTR2, 8
+#endif
+#if 0
+/* Huh?  We've already branched on cr1!  */
 	bne	cr1, L(duLcr1)
+#endif
 	cmplw	cr5, rWORD7, rWORD8
 	bne	cr6, L(duLcr6)
 	slwi.	rN, rN, 3
 	bne	cr5, L(duLcr5)
 	cmplw	cr7, rN, rSHR
 	beq	L(duZeroReturn)
-	li	rA, 0
+	li	r0, 0
 	ble	cr7, L(dutrim)
+#ifdef __LITTLE_ENDIAN__
+	lwbrx	rWORD2, 0, rSTR2
+	addi	rSTR2, rSTR2, 4
+#else
 	lwz	rWORD2, 4(rSTR2)
-	srw	rA, rWORD2, rSHR
+#endif
+	srw	r0, rWORD2, rSHR
 	b	L(dutrim)
 
 /* Count is a multiple of 16, remainder is 0 */
-	.align 4
+	.align	4
 L(duP4):
-	mtctr   rTMP	/* Power4 wants mtctr 1st in dispatch group */
-	srw	rA, rWORD8, rSHR
+	mtctr	r0	/* Power4 wants mtctr 1st in dispatch group */
+	srw	r0, rWORD8, rSHR
+#ifdef __LITTLE_ENDIAN__
+	lwbrx	rWORD1, 0, rSTR1
+	addi	rSTR1, rSTR1, 4
+#else
 	lwz	rWORD1, 0(rSTR1)
-	slw	rD, rWORD8, rSHL
-	or	rWORD2, rA, rH
+#endif
+	slw	rWORD2_SHIFT, rWORD8, rSHL
+	or	rWORD2, r0, rWORD6_SHIFT
 L(duP4e):
+#ifdef __LITTLE_ENDIAN__
+	lwbrx	rWORD3, 0, rSTR1
+	lwbrx	rWORD4, 0, rSTR2
+	addi	rSTR1, rSTR1, 4
+	addi	rSTR2, rSTR2, 4
+#else
 	lwz	rWORD3, 4(rSTR1)
 	lwz	rWORD4, 4(rSTR2)
-	cmplw	cr0, rWORD1, rWORD2
-	srw	rC, rWORD4, rSHR
-	slw	rF, rWORD4, rSHL
-	or	rWORD4, rC, rD
+#endif
+	cmplw	cr7, rWORD1, rWORD2
+	srw	r12, rWORD4, rSHR
+	slw	rWORD4_SHIFT, rWORD4, rSHL
+	or	rWORD4, r12, rWORD2_SHIFT
+#ifdef __LITTLE_ENDIAN__
+	lwbrx	rWORD5, 0, rSTR1
+	lwbrx	rWORD6, 0, rSTR2
+	addi	rSTR1, rSTR1, 4
+	addi	rSTR2, rSTR2, 4
+#else
 	lwz	rWORD5, 8(rSTR1)
 	lwz	rWORD6, 8(rSTR2)
+#endif
 	cmplw	cr1, rWORD3, rWORD4
-	bne	cr0, L(duLcr0)
-	srw	rE, rWORD6, rSHR
-	slw	rH, rWORD6, rSHL
-	or	rWORD6, rE, rF
+	bne	cr7, L(duLcr7)
+	srw	r0, rWORD6, rSHR
+	slw	rWORD6_SHIFT, rWORD6, rSHL
+	or	rWORD6, r0, rWORD4_SHIFT
+#ifdef __LITTLE_ENDIAN__
+	lwbrx	rWORD7, 0, rSTR1
+	lwbrx	rWORD8, 0, rSTR2
+	addi	rSTR1, rSTR1, 4
+	addi	rSTR2, rSTR2, 4
+#else
 	lwzu	rWORD7, 12(rSTR1)
 	lwzu	rWORD8, 12(rSTR2)
+#endif
 	cmplw	cr6, rWORD5, rWORD6
 	bne	cr1, L(duLcr1)
-	srw	rG, rWORD8, rSHR
-	slw	rB, rWORD8, rSHL
-	or	rWORD8, rG, rH
+	srw	r12, rWORD8, rSHR
+	slw	rWORD8_SHIFT, rWORD8, rSHL
+	or	rWORD8, r12, rWORD6_SHIFT
 	cmplw	cr5, rWORD7, rWORD8
 	bdz-	L(du24)		/* Adjust CTR as we start with +4 */
 /* This is the primary loop */
-	.align 4
+	.align	4
 L(duLoop):
+#ifdef __LITTLE_ENDIAN__
+	lwbrx	rWORD1, 0, rSTR1
+	lwbrx	rWORD2, 0, rSTR2
+	addi	rSTR1, rSTR1, 4
+	addi	rSTR2, rSTR2, 4
+#else
 	lwz	rWORD1, 4(rSTR1)
 	lwz	rWORD2, 4(rSTR2)
+#endif
 	cmplw	cr1, rWORD3, rWORD4
 	bne	cr6, L(duLcr6)
-	srw	rA, rWORD2, rSHR
-	slw	rD, rWORD2, rSHL
-	or	rWORD2, rA, rB
+	srw	r0, rWORD2, rSHR
+	slw	rWORD2_SHIFT, rWORD2, rSHL
+	or	rWORD2, r0, rWORD8_SHIFT
 L(duLoop1):
+#ifdef __LITTLE_ENDIAN__
+	lwbrx	rWORD3, 0, rSTR1
+	lwbrx	rWORD4, 0, rSTR2
+	addi	rSTR1, rSTR1, 4
+	addi	rSTR2, rSTR2, 4
+#else
 	lwz	rWORD3, 8(rSTR1)
 	lwz	rWORD4, 8(rSTR2)
+#endif
 	cmplw	cr6, rWORD5, rWORD6
 	bne	cr5, L(duLcr5)
-	srw	rC, rWORD4, rSHR
-	slw	rF, rWORD4, rSHL
-	or	rWORD4, rC, rD
+	srw	r12, rWORD4, rSHR
+	slw	rWORD4_SHIFT, rWORD4, rSHL
+	or	rWORD4, r12, rWORD2_SHIFT
 L(duLoop2):
+#ifdef __LITTLE_ENDIAN__
+	lwbrx	rWORD5, 0, rSTR1
+	lwbrx	rWORD6, 0, rSTR2
+	addi	rSTR1, rSTR1, 4
+	addi	rSTR2, rSTR2, 4
+#else
 	lwz	rWORD5, 12(rSTR1)
 	lwz	rWORD6, 12(rSTR2)
+#endif
 	cmplw	cr5, rWORD7, rWORD8
-	bne	cr0, L(duLcr0)
-	srw	rE, rWORD6, rSHR
-	slw	rH, rWORD6, rSHL
-	or	rWORD6, rE, rF
+	bne	cr7, L(duLcr7)
+	srw	r0, rWORD6, rSHR
+	slw	rWORD6_SHIFT, rWORD6, rSHL
+	or	rWORD6, r0, rWORD4_SHIFT
 L(duLoop3):
+#ifdef __LITTLE_ENDIAN__
+	lwbrx	rWORD7, 0, rSTR1
+	lwbrx	rWORD8, 0, rSTR2
+	addi	rSTR1, rSTR1, 4
+	addi	rSTR2, rSTR2, 4
+#else
 	lwzu	rWORD7, 16(rSTR1)
 	lwzu	rWORD8, 16(rSTR2)
-	cmplw	cr0, rWORD1, rWORD2
+#endif
+	cmplw	cr7, rWORD1, rWORD2
 	bne-	cr1, L(duLcr1)
-	srw	rG, rWORD8, rSHR
-	slw	rB, rWORD8, rSHL
-	or	rWORD8, rG, rH
+	srw	r12, rWORD8, rSHR
+	slw	rWORD8_SHIFT, rWORD8, rSHL
+	or	rWORD8, r12, rWORD6_SHIFT
 	bdnz+	L(duLoop)
 
 L(duL4):
+#if 0
+/* Huh?  We've already branched on cr1!  */
 	bne	cr1, L(duLcr1)
+#endif
 	cmplw	cr1, rWORD3, rWORD4
 	bne	cr6, L(duLcr6)
 	cmplw	cr6, rWORD5, rWORD6
 	bne	cr5, L(duLcr5)
 	cmplw	cr5, rWORD7, rWORD8
 L(du44):
-	bne	cr0, L(duLcr0)
+	bne	cr7, L(duLcr7)
 L(du34):
 	bne	cr1, L(duLcr1)
 L(du24):
@@ -887,95 +1273,101 @@ L(du14):
 	bne	cr5, L(duLcr5)
 /* At this point we have a remainder of 1 to 3 bytes to compare.  We use
    shift right to eliminate bits beyond the compare length.
+   This allows the use of word subtract to compute the final result.
 
    However it may not be safe to load rWORD2 which may be beyond the
    string length. So we compare the bit length of the remainder to
    the right shift count (rSHR). If the bit count is less than or equal
    we do not need to load rWORD2 (all significant bits are already in
-   rB).  */
+   rWORD8_SHIFT).  */
 	cmplw	cr7, rN, rSHR
 	beq	L(duZeroReturn)
-	li	rA, 0
+	li	r0, 0
 	ble	cr7, L(dutrim)
+#ifdef __LITTLE_ENDIAN__
+	lwbrx	rWORD2, 0, rSTR2
+	addi	rSTR2, rSTR2, 4
+#else
 	lwz	rWORD2, 4(rSTR2)
-	srw	rA, rWORD2, rSHR
-	.align 4
+#endif
+	srw	r0, rWORD2, rSHR
+	.align	4
 L(dutrim):
+#ifdef __LITTLE_ENDIAN__
+	lwbrx	rWORD1, 0, rSTR1
+#else
 	lwz	rWORD1, 4(rSTR1)
-        lwz     r31,48(1)
+#endif
+	lwz	rWORD8, 48(r1)
 	subfic	rN, rN, 32	/* Shift count is 32 - (rN * 8).  */
-	or	rWORD2, rA, rB
-        lwz     r30,44(1)
-        lwz     r29,40(r1)
+	or	rWORD2, r0, rWORD8_SHIFT
+	lwz	rWORD7, 44(r1)
+	lwz	rSHL, 40(r1)
 	srw	rWORD1, rWORD1, rN
 	srw	rWORD2, rWORD2, rN
-        lwz     r28,36(r1)
-        lwz     r27,32(r1)
-        cmplw   rWORD1,rWORD2
-        li      rRTN,0
-        beq     L(dureturn26)
-        li      rRTN,1
-        bgt     L(dureturn26)
-        li      rRTN,-1
-	b    L(dureturn26)
-	.align 4
-L(duLcr0):
-        lwz     r31,48(1)
-        lwz     r30,44(1)
+	lwz	rSHR, 36(r1)
+	lwz	rWORD8_SHIFT, 32(r1)
+	sub	rRTN, rWORD1, rWORD2
+	b	L(dureturn26)
+	.align	4
+L(duLcr7):
+	lwz	rWORD8, 48(r1)
+	lwz	rWORD7, 44(r1)
 	li	rRTN, 1
-	bgt	cr0, L(dureturn29)
-	lwz     r29,40(r1)
-        lwz     r28,36(r1)
+	bgt	cr7, L(dureturn29)
+	lwz	rSHL, 40(r1)
+	lwz	rSHR, 36(r1)
 	li	rRTN, -1
 	b	L(dureturn27)
-	.align 4
+	.align	4
 L(duLcr1):
-        lwz     r31,48(1)
-        lwz     r30,44(1)
+	lwz	rWORD8, 48(r1)
+	lwz	rWORD7, 44(r1)
 	li	rRTN, 1
 	bgt	cr1, L(dureturn29)
-        lwz     r29,40(r1)
-        lwz     r28,36(r1)
+	lwz	rSHL, 40(r1)
+	lwz	rSHR, 36(r1)
 	li	rRTN, -1
 	b	L(dureturn27)
-	.align 4
+	.align	4
 L(duLcr6):
-        lwz     r31,48(1)
-        lwz     r30,44(1)
+	lwz	rWORD8, 48(r1)
+	lwz	rWORD7, 44(r1)
 	li	rRTN, 1
 	bgt	cr6, L(dureturn29)
-        lwz     r29,40(r1)
-        lwz     r28,36(r1)
+	lwz	rSHL, 40(r1)
+	lwz	rSHR, 36(r1)
 	li	rRTN, -1
 	b	L(dureturn27)
-	.align 4
+	.align	4
 L(duLcr5):
-        lwz     r31,48(1)
-        lwz     r30,44(1)
+	lwz	rWORD8, 48(r1)
+	lwz	rWORD7, 44(r1)
 	li	rRTN, 1
 	bgt	cr5, L(dureturn29)
-        lwz     r29,40(r1)
-        lwz     r28,36(r1)
+	lwz	rSHL, 40(r1)
+	lwz	rSHR, 36(r1)
 	li	rRTN, -1
 	b	L(dureturn27)
 	.align	3
 L(duZeroReturn):
-	li	rRTN,0
+	li	rRTN, 0
 	.align	4
 L(dureturn):
-        lwz     r31,48(1)
-        lwz     r30,44(1)
+	lwz	rWORD8, 48(r1)
+	lwz	rWORD7, 44(r1)
 L(dureturn29):
-        lwz     r29,40(r1)
-        lwz     r28,36(r1)
+	lwz	rSHL, 40(r1)
+	lwz	rSHR, 36(r1)
 L(dureturn27):
-        lwz     r27,32(r1)
+	lwz	rWORD8_SHIFT, 32(r1)
 L(dureturn26):
-        lwz     r26,28(r1)
+	lwz	rWORD2_SHIFT, 28(r1)
 L(dureturn25):
-        lwz     r25,24(r1)
-        lwz     r24,20(r1)
-        lwz     1,0(1)
+	lwz	rWORD4_SHIFT, 24(r1)
+	lwz	rWORD6_SHIFT, 20(r1)
+	addi	1, 1, 64
+	cfi_adjust_cfa_offset(-64)
 	blr
 END (memcmp)
 
diff --git a/sysdeps/powerpc/powerpc32/power7/memcmp.S b/sysdeps/powerpc/powerpc32/power7/memcmp.S
index f764b7c..ea001da 100644
--- a/sysdeps/powerpc/powerpc32/power7/memcmp.S
+++ b/sysdeps/powerpc/powerpc32/power7/memcmp.S
@@ -23,10 +23,9 @@
 		    size_t size [r5])  */
 
 	.machine power7
-EALIGN (memcmp,4,0)
+EALIGN (memcmp, 4, 0)
 	CALL_MCOUNT
 
-#define rTMP	r0
 #define rRTN	r3
 #define rSTR1	r3	/* first string arg */
 #define rSTR2	r4	/* second string arg */
@@ -37,35 +36,32 @@ EALIGN (memcmp,4,0)
 #define rWORD4	r9	/* next word in s2 */
 #define rWORD5	r10	/* next word in s1 */
 #define rWORD6	r11	/* next word in s2 */
-#define rBITDIF	r12	/* bits that differ in s1 & s2 words */
 #define rWORD7	r30	/* next word in s1 */
 #define rWORD8	r31	/* next word in s2 */
 
-	xor	rTMP,rSTR2,rSTR1
-	cmplwi	cr6,rN,0
-	cmplwi	cr1,rN,12
-	clrlwi.	rTMP,rTMP,30
-	clrlwi	rBITDIF,rSTR1,30
-	cmplwi	cr5,rBITDIF,0
-	beq-	cr6,L(zeroLength)
-	dcbt	0,rSTR1
-	dcbt	0,rSTR2
-
-	/* If less than 8 bytes or not aligned, use the unaligned
-	   byte loop.  */
-
-	blt	cr1,L(bytealigned)
-	stwu	1,-64(1)
+	xor	r0, rSTR2, rSTR1
+	cmplwi	cr6, rN, 0
+	cmplwi	cr1, rN, 12
+	clrlwi.	r0, r0, 30
+	clrlwi	r12, rSTR1, 30
+	cmplwi	cr5, r12, 0
+	beq-	cr6, L(zeroLength)
+	dcbt	0, rSTR1
+	dcbt	0, rSTR2
+/* If less than 8 bytes or not aligned, use the unaligned
+   byte loop.  */
+	blt	cr1, L(bytealigned)
+	stwu	1, -64(r1)
 	cfi_adjust_cfa_offset(64)
-	stw	r31,48(1)
-	cfi_offset(31,(48-64))
-	stw	r30,44(1)
-	cfi_offset(30,(44-64))
+	stw	rWORD8, 48(r1)
+	cfi_offset(rWORD8, (48-64))
+	stw	rWORD7, 44(r1)
+	cfi_offset(rWORD7, (44-64))
 	bne	L(unaligned)
 /* At this point we know both strings have the same alignment and the
-   compare length is at least 8 bytes.  rBITDIF contains the low order
+   compare length is at least 8 bytes.  r12 contains the low order
    2 bits of rSTR1 and cr5 contains the result of the logical compare
-   of rBITDIF to 0.  If rBITDIF == 0 then we are already word
+   of r12 to 0.  If r12 == 0 then we are already word
    aligned and can perform the word aligned loop.
 
    Otherwise we know the two strings have the same alignment (but not
@@ -74,332 +70,541 @@ EALIGN (memcmp,4,0)
    eliminate bits preceding the first byte.  Since we want to join the
    normal (word aligned) compare loop, starting at the second word,
    we need to adjust the length (rN) and special case the loop
-   versioning for the first word. This insures that the loop count is
+   versioning for the first word. This ensures that the loop count is
    correct and the first word (shifted) is in the expected register pair. */
 	.align	4
 L(samealignment):
-	clrrwi	rSTR1,rSTR1,2
-	clrrwi	rSTR2,rSTR2,2
-	beq	cr5,L(Waligned)
-	add	rN,rN,rBITDIF
-	slwi	r11,rBITDIF,3
-	srwi	rTMP,rN,4	/* Divide by 16 */
-	andi.	rBITDIF,rN,12	/* Get the word remainder */
-	lwz	rWORD1,0(rSTR1)
-	lwz	rWORD2,0(rSTR2)
-	cmplwi	cr1,rBITDIF,8
-	cmplwi	cr7,rN,16
-	clrlwi	rN,rN,30
+	clrrwi	rSTR1, rSTR1, 2
+	clrrwi	rSTR2, rSTR2, 2
+	beq	cr5, L(Waligned)
+	add	rN, rN, r12
+	slwi	rWORD6, r12, 3
+	srwi	r0, rN, 4	/* Divide by 16 */
+	andi.	r12, rN, 12	/* Get the word remainder */
+#ifdef __LITTLE_ENDIAN__
+	lwbrx	rWORD1, 0, rSTR1
+	lwbrx	rWORD2, 0, rSTR2
+	addi	rSTR1, rSTR1, 4
+	addi	rSTR2, rSTR2, 4
+#else
+	lwz	rWORD1, 0(rSTR1)
+	lwz	rWORD2, 0(rSTR2)
+#endif
+	cmplwi	cr1, r12, 8
+	cmplwi	cr7, rN, 16
+	clrlwi	rN, rN, 30
 	beq	L(dPs4)
-	mtctr	rTMP
-	bgt	cr1,L(dPs3)
-	beq	cr1,L(dPs2)
+	mtctr	r0
+	bgt	cr1, L(dPs3)
+	beq	cr1, L(dPs2)
 
 /* Remainder is 4 */
 	.align	3
 L(dsP1):
-	slw	rWORD5,rWORD1,r11
-	slw	rWORD6,rWORD2,r11
-	cmplw	cr5,rWORD5,rWORD6
-	blt	cr7,L(dP1x)
+	slw	rWORD5, rWORD1, rWORD6
+	slw	rWORD6, rWORD2, rWORD6
+	cmplw	cr5, rWORD5, rWORD6
+	blt	cr7, L(dP1x)
 /* Do something useful in this cycle since we have to branch anyway.  */
-	lwz	rWORD1,4(rSTR1)
-	lwz	rWORD2,4(rSTR2)
-	cmplw	cr0,rWORD1,rWORD2
+#ifdef __LITTLE_ENDIAN__
+	lwbrx	rWORD1, 0, rSTR1
+	lwbrx	rWORD2, 0, rSTR2
+	addi	rSTR1, rSTR1, 4
+	addi	rSTR2, rSTR2, 4
+#else
+	lwz	rWORD1, 4(rSTR1)
+	lwz	rWORD2, 4(rSTR2)
+#endif
+	cmplw	cr7, rWORD1, rWORD2
 	b	L(dP1e)
 /* Remainder is 8 */
 	.align	4
 L(dPs2):
-	slw	rWORD5,rWORD1,r11
-	slw	rWORD6,rWORD2,r11
-	cmplw	cr6,rWORD5,rWORD6
-	blt	cr7,L(dP2x)
+	slw	rWORD5, rWORD1, rWORD6
+	slw	rWORD6, rWORD2, rWORD6
+	cmplw	cr6, rWORD5, rWORD6
+	blt	cr7, L(dP2x)
 /* Do something useful in this cycle since we have to branch anyway.  */
-	lwz	rWORD7,4(rSTR1)
-	lwz	rWORD8,4(rSTR2)
-	cmplw	cr5,rWORD7,rWORD8
+#ifdef __LITTLE_ENDIAN__
+	lwbrx	rWORD7, 0, rSTR1
+	lwbrx	rWORD8, 0, rSTR2
+	addi	rSTR1, rSTR1, 4
+	addi	rSTR2, rSTR2, 4
+#else
+	lwz	rWORD7, 4(rSTR1)
+	lwz	rWORD8, 4(rSTR2)
+#endif
+	cmplw	cr5, rWORD7, rWORD8
 	b	L(dP2e)
 /* Remainder is 12 */
 	.align	4
 L(dPs3):
-	slw	rWORD3,rWORD1,r11
-	slw	rWORD4,rWORD2,r11
-	cmplw	cr1,rWORD3,rWORD4
+	slw	rWORD3, rWORD1, rWORD6
+	slw	rWORD4, rWORD2, rWORD6
+	cmplw	cr1, rWORD3, rWORD4
 	b	L(dP3e)
 /* Count is a multiple of 16, remainder is 0 */
 	.align	4
 L(dPs4):
-	mtctr	rTMP
-	slw	rWORD1,rWORD1,r11
-	slw	rWORD2,rWORD2,r11
-	cmplw	cr0,rWORD1,rWORD2
+	mtctr	r0
+	slw	rWORD1, rWORD1, rWORD6
+	slw	rWORD2, rWORD2, rWORD6
+	cmplw	cr7, rWORD1, rWORD2
 	b	L(dP4e)
 
 /* At this point we know both strings are word aligned and the
    compare length is at least 8 bytes.  */
 	.align	4
 L(Waligned):
-	andi.	rBITDIF,rN,12	/* Get the word remainder */
-	srwi	rTMP,rN,4	/* Divide by 16 */
-	cmplwi	cr1,rBITDIF,8
-	cmplwi	cr7,rN,16
-	clrlwi	rN,rN,30
+	andi.	r12, rN, 12	/* Get the word remainder */
+	srwi	r0, rN, 4	/* Divide by 16 */
+	cmplwi	cr1, r12, 8
+	cmplwi	cr7, rN, 16
+	clrlwi	rN, rN, 30
 	beq	L(dP4)
-	bgt	cr1,L(dP3)
-	beq	cr1,L(dP2)
+	bgt	cr1, L(dP3)
+	beq	cr1, L(dP2)
 
 /* Remainder is 4 */
 	.align	4
 L(dP1):
-	mtctr	rTMP
+	mtctr	r0
 /* Normally we'd use rWORD7/rWORD8 here, but since we might exit early
    (8-15 byte compare), we want to use only volatile registers.  This
    means we can avoid restoring non-volatile registers since we did not
    change any on the early exit path.  The key here is the non-early
    exit path only cares about the condition code (cr5), not about which
    register pair was used.  */
-	lwz	rWORD5,0(rSTR1)
-	lwz	rWORD6,0(rSTR2)
-	cmplw	cr5,rWORD5,rWORD6
-	blt	cr7,L(dP1x)
-	lwz	rWORD1,4(rSTR1)
-	lwz	rWORD2,4(rSTR2)
-	cmplw	cr0,rWORD1,rWORD2
+#ifdef __LITTLE_ENDIAN__
+	lwbrx	rWORD5, 0, rSTR1
+	lwbrx	rWORD6, 0, rSTR2
+	addi	rSTR1, rSTR1, 4
+	addi	rSTR2, rSTR2, 4
+#else
+	lwz	rWORD5, 0(rSTR1)
+	lwz	rWORD6, 0(rSTR2)
+#endif
+	cmplw	cr5, rWORD5, rWORD6
+	blt	cr7, L(dP1x)
+#ifdef __LITTLE_ENDIAN__
+	lwbrx	rWORD1, 0, rSTR1
+	lwbrx	rWORD2, 0, rSTR2
+	addi	rSTR1, rSTR1, 4
+	addi	rSTR2, rSTR2, 4
+#else
+	lwz	rWORD1, 4(rSTR1)
+	lwz	rWORD2, 4(rSTR2)
+#endif
+	cmplw	cr7, rWORD1, rWORD2
 L(dP1e):
-	lwz	rWORD3,8(rSTR1)
-	lwz	rWORD4,8(rSTR2)
-	cmplw	cr1,rWORD3,rWORD4
-	lwz	rWORD5,12(rSTR1)
-	lwz	rWORD6,12(rSTR2)
-	cmplw	cr6,rWORD5,rWORD6
-	bne	cr5,L(dLcr5)
-	bne	cr0,L(dLcr0)
-
-	lwzu	rWORD7,16(rSTR1)
-	lwzu	rWORD8,16(rSTR2)
-	bne	cr1,L(dLcr1)
-	cmplw	cr5,rWORD7,rWORD8
+#ifdef __LITTLE_ENDIAN__
+	lwbrx	rWORD3, 0, rSTR1
+	lwbrx	rWORD4, 0, rSTR2
+	addi	rSTR1, rSTR1, 4
+	addi	rSTR2, rSTR2, 4
+#else
+	lwz	rWORD3, 8(rSTR1)
+	lwz	rWORD4, 8(rSTR2)
+#endif
+	cmplw	cr1, rWORD3, rWORD4
+#ifdef __LITTLE_ENDIAN__
+	lwbrx	rWORD5, 0, rSTR1
+	lwbrx	rWORD6, 0, rSTR2
+	addi	rSTR1, rSTR1, 4
+	addi	rSTR2, rSTR2, 4
+#else
+	lwz	rWORD5, 12(rSTR1)
+	lwz	rWORD6, 12(rSTR2)
+#endif
+	cmplw	cr6, rWORD5, rWORD6
+	bne	cr5, L(dLcr5x)
+	bne	cr7, L(dLcr7x)
+
+#ifdef __LITTLE_ENDIAN__
+	lwbrx	rWORD7, 0, rSTR1
+	lwbrx	rWORD8, 0, rSTR2
+	addi	rSTR1, rSTR1, 4
+	addi	rSTR2, rSTR2, 4
+#else
+	lwzu	rWORD7, 16(rSTR1)
+	lwzu	rWORD8, 16(rSTR2)
+#endif
+	bne	cr1, L(dLcr1)
+	cmplw	cr5, rWORD7, rWORD8
 	bdnz	L(dLoop)
-	bne	cr6,L(dLcr6)
-	lwz	r30,44(1)
-	lwz	r31,48(1)
+	bne	cr6, L(dLcr6)
+	lwz	rWORD7, 44(r1)
+	lwz	rWORD8, 48(r1)
 	.align	3
 L(dP1x):
-	slwi.	r12,rN,3
-	bne	cr5,L(dLcr5)
-	subfic	rN,r12,32	/* Shift count is 32 - (rN * 8).  */
-	lwz	1,0(1)
+	slwi.	r12, rN, 3
+	bne	cr5, L(dLcr5x)
+	subfic	rN, r12, 32	/* Shift count is 32 - (rN * 8).  */
+	addi	r1, r1, 64
+	cfi_adjust_cfa_offset(-64)
 	bne	L(d00)
-	li	rRTN,0
+	li	rRTN, 0
 	blr
 
 /* Remainder is 8 */
 	.align	4
+	cfi_adjust_cfa_offset(64)
 L(dP2):
-	mtctr	rTMP
-	lwz	rWORD5,0(rSTR1)
-	lwz	rWORD6,0(rSTR2)
-	cmplw	cr6,rWORD5,rWORD6
-	blt	cr7,L(dP2x)
-	lwz	rWORD7,4(rSTR1)
-	lwz	rWORD8,4(rSTR2)
-	cmplw	cr5,rWORD7,rWORD8
+	mtctr	r0
+#ifdef __LITTLE_ENDIAN__
+	lwbrx	rWORD5, 0, rSTR1
+	lwbrx	rWORD6, 0, rSTR2
+	addi	rSTR1, rSTR1, 4
+	addi	rSTR2, rSTR2, 4
+#else
+	lwz	rWORD5, 0(rSTR1)
+	lwz	rWORD6, 0(rSTR2)
+#endif
+	cmplw	cr6, rWORD5, rWORD6
+	blt	cr7, L(dP2x)
+#ifdef __LITTLE_ENDIAN__
+	lwbrx	rWORD7, 0, rSTR1
+	lwbrx	rWORD8, 0, rSTR2
+	addi	rSTR1, rSTR1, 4
+	addi	rSTR2, rSTR2, 4
+#else
+	lwz	rWORD7, 4(rSTR1)
+	lwz	rWORD8, 4(rSTR2)
+#endif
+	cmplw	cr5, rWORD7, rWORD8
 L(dP2e):
-	lwz	rWORD1,8(rSTR1)
-	lwz	rWORD2,8(rSTR2)
-	cmplw	cr0,rWORD1,rWORD2
-	lwz	rWORD3,12(rSTR1)
-	lwz	rWORD4,12(rSTR2)
-	cmplw	cr1,rWORD3,rWORD4
-	addi	rSTR1,rSTR1,4
-	addi	rSTR2,rSTR2,4
-	bne	cr6,L(dLcr6)
-	bne	cr5,L(dLcr5)
+#ifdef __LITTLE_ENDIAN__
+	lwbrx	rWORD1, 0, rSTR1
+	lwbrx	rWORD2, 0, rSTR2
+	addi	rSTR1, rSTR1, 4
+	addi	rSTR2, rSTR2, 4
+#else
+	lwz	rWORD1, 8(rSTR1)
+	lwz	rWORD2, 8(rSTR2)
+#endif
+	cmplw	cr7, rWORD1, rWORD2
+#ifdef __LITTLE_ENDIAN__
+	lwbrx	rWORD3, 0, rSTR1
+	lwbrx	rWORD4, 0, rSTR2
+	addi	rSTR1, rSTR1, 4
+	addi	rSTR2, rSTR2, 4
+#else
+	lwz	rWORD3, 12(rSTR1)
+	lwz	rWORD4, 12(rSTR2)
+#endif
+	cmplw	cr1, rWORD3, rWORD4
+#ifndef __LITTLE_ENDIAN__
+	addi	rSTR1, rSTR1, 4
+	addi	rSTR2, rSTR2, 4
+#endif
+	bne	cr6, L(dLcr6)
+	bne	cr5, L(dLcr5)
 	b	L(dLoop2)
 /* Again we are on a early exit path (16-23 byte compare), we want to
    only use volatile registers and avoid restoring non-volatile
    registers.  */
 	.align	4
 L(dP2x):
-	lwz	rWORD3,4(rSTR1)
-	lwz	rWORD4,4(rSTR2)
-	cmplw	cr5,rWORD3,rWORD4
-	slwi.	r12,rN,3
-	bne	cr6,L(dLcr6)
-	addi	rSTR1,rSTR1,4
-	addi	rSTR2,rSTR2,4
-	bne	cr5,L(dLcr5)
-	subfic	rN,r12,32	/* Shift count is 32 - (rN * 8).  */
-	lwz	1,0(1)
+#ifdef __LITTLE_ENDIAN__
+	lwbrx	rWORD3, 0, rSTR1
+	lwbrx	rWORD4, 0, rSTR2
+	addi	rSTR1, rSTR1, 4
+	addi	rSTR2, rSTR2, 4
+#else
+	lwz	rWORD3, 4(rSTR1)
+	lwz	rWORD4, 4(rSTR2)
+#endif
+	cmplw	cr1, rWORD3, rWORD4
+	slwi.	r12, rN, 3
+	bne	cr6, L(dLcr6x)
+#ifndef __LITTLE_ENDIAN__
+	addi	rSTR1, rSTR1, 4
+	addi	rSTR2, rSTR2, 4
+#endif
+	bne	cr1, L(dLcr1x)
+	subfic	rN, r12, 32	/* Shift count is 32 - (rN * 8).  */
+	addi	r1, r1, 64
+	cfi_adjust_cfa_offset(-64)
 	bne	L(d00)
-	li	rRTN,0
+	li	rRTN, 0
 	blr
 
 /* Remainder is 12 */
 	.align	4
+	cfi_adjust_cfa_offset(64)
 L(dP3):
-	mtctr	rTMP
-	lwz	rWORD3,0(rSTR1)
-	lwz	rWORD4,0(rSTR2)
-	cmplw	cr1,rWORD3,rWORD4
+	mtctr	r0
+#ifdef __LITTLE_ENDIAN__
+	lwbrx	rWORD3, 0, rSTR1
+	lwbrx	rWORD4, 0, rSTR2
+	addi	rSTR1, rSTR1, 4
+	addi	rSTR2, rSTR2, 4
+#else
+	lwz	rWORD3, 0(rSTR1)
+	lwz	rWORD4, 0(rSTR2)
+#endif
+	cmplw	cr1, rWORD3, rWORD4
 L(dP3e):
-	lwz	rWORD5,4(rSTR1)
-	lwz	rWORD6,4(rSTR2)
-	cmplw	cr6,rWORD5,rWORD6
-	blt	cr7,L(dP3x)
-	lwz	rWORD7,8(rSTR1)
-	lwz	rWORD8,8(rSTR2)
-	cmplw	cr5,rWORD7,rWORD8
-	lwz	rWORD1,12(rSTR1)
-	lwz	rWORD2,12(rSTR2)
-	cmplw	cr0,rWORD1,rWORD2
-	addi	rSTR1,rSTR1,8
-	addi	rSTR2,rSTR2,8
-	bne	cr1,L(dLcr1)
-	bne	cr6,L(dLcr6)
+#ifdef __LITTLE_ENDIAN__
+	lwbrx	rWORD5, 0, rSTR1
+	lwbrx	rWORD6, 0, rSTR2
+	addi	rSTR1, rSTR1, 4
+	addi	rSTR2, rSTR2, 4
+#else
+	lwz	rWORD5, 4(rSTR1)
+	lwz	rWORD6, 4(rSTR2)
+#endif
+	cmplw	cr6, rWORD5, rWORD6
+	blt	cr7, L(dP3x)
+#ifdef __LITTLE_ENDIAN__
+	lwbrx	rWORD7, 0, rSTR1
+	lwbrx	rWORD8, 0, rSTR2
+	addi	rSTR1, rSTR1, 4
+	addi	rSTR2, rSTR2, 4
+#else
+	lwz	rWORD7, 8(rSTR1)
+	lwz	rWORD8, 8(rSTR2)
+#endif
+	cmplw	cr5, rWORD7, rWORD8
+#ifdef __LITTLE_ENDIAN__
+	lwbrx	rWORD1, 0, rSTR1
+	lwbrx	rWORD2, 0, rSTR2
+	addi	rSTR1, rSTR1, 4
+	addi	rSTR2, rSTR2, 4
+#else
+	lwz	rWORD1, 12(rSTR1)
+	lwz	rWORD2, 12(rSTR2)
+#endif
+	cmplw	cr7, rWORD1, rWORD2
+#ifndef __LITTLE_ENDIAN__
+	addi	rSTR1, rSTR1, 8
+	addi	rSTR2, rSTR2, 8
+#endif
+	bne	cr1, L(dLcr1)
+	bne	cr6, L(dLcr6)
 	b	L(dLoop1)
 /* Again we are on a early exit path (24-31 byte compare), we want to
    only use volatile registers and avoid restoring non-volatile
    registers.  */
 	.align	4
 L(dP3x):
-	lwz	rWORD1,8(rSTR1)
-	lwz	rWORD2,8(rSTR2)
-	cmplw	cr5,rWORD1,rWORD2
-	slwi.	r12,rN,3
-	bne	cr1,L(dLcr1)
-	addi	rSTR1,rSTR1,8
-	addi	rSTR2,rSTR2,8
-	bne	cr6,L(dLcr6)
-	subfic	rN,r12,32	/* Shift count is 32 - (rN * 8).  */
-	bne	cr5,L(dLcr5)
-	lwz	1,0(1)
+#ifdef __LITTLE_ENDIAN__
+	lwbrx	rWORD1, 0, rSTR1
+	lwbrx	rWORD2, 0, rSTR2
+	addi	rSTR1, rSTR1, 4
+	addi	rSTR2, rSTR2, 4
+#else
+	lwz	rWORD1, 8(rSTR1)
+	lwz	rWORD2, 8(rSTR2)
+#endif
+	cmplw	cr7, rWORD1, rWORD2
+	slwi.	r12, rN, 3
+	bne	cr1, L(dLcr1x)
+#ifndef __LITTLE_ENDIAN__
+	addi	rSTR1, rSTR1, 8
+	addi	rSTR2, rSTR2, 8
+#endif
+	bne	cr6, L(dLcr6x)
+	subfic	rN, r12, 32	/* Shift count is 32 - (rN * 8).  */
+	bne	cr7, L(dLcr7x)
+	addi	r1, r1, 64
+	cfi_adjust_cfa_offset(-64)
 	bne	L(d00)
-	li	rRTN,0
+	li	rRTN, 0
 	blr
 
 /* Count is a multiple of 16, remainder is 0 */
 	.align	4
+	cfi_adjust_cfa_offset(64)
 L(dP4):
-	mtctr	rTMP
-	lwz	rWORD1,0(rSTR1)
-	lwz	rWORD2,0(rSTR2)
-	cmplw	cr0,rWORD1,rWORD2
+	mtctr	r0
+#ifdef __LITTLE_ENDIAN__
+	lwbrx	rWORD1, 0, rSTR1
+	lwbrx	rWORD2, 0, rSTR2
+	addi	rSTR1, rSTR1, 4
+	addi	rSTR2, rSTR2, 4
+#else
+	lwz	rWORD1, 0(rSTR1)
+	lwz	rWORD2, 0(rSTR2)
+#endif
+	cmplw	cr7, rWORD1, rWORD2
 L(dP4e):
-	lwz	rWORD3,4(rSTR1)
-	lwz	rWORD4,4(rSTR2)
-	cmplw	cr1,rWORD3,rWORD4
-	lwz	rWORD5,8(rSTR1)
-	lwz	rWORD6,8(rSTR2)
-	cmplw	cr6,rWORD5,rWORD6
-	lwzu	rWORD7,12(rSTR1)
-	lwzu	rWORD8,12(rSTR2)
-	cmplw	cr5,rWORD7,rWORD8
-	bne	cr0,L(dLcr0)
-	bne	cr1,L(dLcr1)
+#ifdef __LITTLE_ENDIAN__
+	lwbrx	rWORD3, 0, rSTR1
+	lwbrx	rWORD4, 0, rSTR2
+	addi	rSTR1, rSTR1, 4
+	addi	rSTR2, rSTR2, 4
+#else
+	lwz	rWORD3, 4(rSTR1)
+	lwz	rWORD4, 4(rSTR2)
+#endif
+	cmplw	cr1, rWORD3, rWORD4
+#ifdef __LITTLE_ENDIAN__
+	lwbrx	rWORD5, 0, rSTR1
+	lwbrx	rWORD6, 0, rSTR2
+	addi	rSTR1, rSTR1, 4
+	addi	rSTR2, rSTR2, 4
+#else
+	lwz	rWORD5, 8(rSTR1)
+	lwz	rWORD6, 8(rSTR2)
+#endif
+	cmplw	cr6, rWORD5, rWORD6
+#ifdef __LITTLE_ENDIAN__
+	lwbrx	rWORD7, 0, rSTR1
+	lwbrx	rWORD8, 0, rSTR2
+	addi	rSTR1, rSTR1, 4
+	addi	rSTR2, rSTR2, 4
+#else
+	lwzu	rWORD7, 12(rSTR1)
+	lwzu	rWORD8, 12(rSTR2)
+#endif
+	cmplw	cr5, rWORD7, rWORD8
+	bne	cr7, L(dLcr7)
+	bne	cr1, L(dLcr1)
 	bdz-	L(d24)		/* Adjust CTR as we start with +4 */
 /* This is the primary loop */
 	.align	4
 L(dLoop):
-	lwz	rWORD1,4(rSTR1)
-	lwz	rWORD2,4(rSTR2)
-	cmplw	cr1,rWORD3,rWORD4
-	bne	cr6,L(dLcr6)
+#ifdef __LITTLE_ENDIAN__
+	lwbrx	rWORD1, 0, rSTR1
+	lwbrx	rWORD2, 0, rSTR2
+	addi	rSTR1, rSTR1, 4
+	addi	rSTR2, rSTR2, 4
+#else
+	lwz	rWORD1, 4(rSTR1)
+	lwz	rWORD2, 4(rSTR2)
+#endif
+	cmplw	cr1, rWORD3, rWORD4
+	bne	cr6, L(dLcr6)
 L(dLoop1):
-	lwz	rWORD3,8(rSTR1)
-	lwz	rWORD4,8(rSTR2)
-	cmplw	cr6,rWORD5,rWORD6
-	bne	cr5,L(dLcr5)
+#ifdef __LITTLE_ENDIAN__
+	lwbrx	rWORD3, 0, rSTR1
+	lwbrx	rWORD4, 0, rSTR2
+	addi	rSTR1, rSTR1, 4
+	addi	rSTR2, rSTR2, 4
+#else
+	lwz	rWORD3, 8(rSTR1)
+	lwz	rWORD4, 8(rSTR2)
+#endif
+	cmplw	cr6, rWORD5, rWORD6
+	bne	cr5, L(dLcr5)
 L(dLoop2):
-	lwz	rWORD5,12(rSTR1)
-	lwz	rWORD6,12(rSTR2)
-	cmplw	cr5,rWORD7,rWORD8
-	bne	cr0,L(dLcr0)
+#ifdef __LITTLE_ENDIAN__
+	lwbrx	rWORD5, 0, rSTR1
+	lwbrx	rWORD6, 0, rSTR2
+	addi	rSTR1, rSTR1, 4
+	addi	rSTR2, rSTR2, 4
+#else
+	lwz	rWORD5, 12(rSTR1)
+	lwz	rWORD6, 12(rSTR2)
+#endif
+	cmplw	cr5, rWORD7, rWORD8
+	bne	cr7, L(dLcr7)
 L(dLoop3):
-	lwzu	rWORD7,16(rSTR1)
-	lwzu	rWORD8,16(rSTR2)
-	bne	cr1,L(dLcr1)
-	cmplw	cr0,rWORD1,rWORD2
+#ifdef __LITTLE_ENDIAN__
+	lwbrx	rWORD7, 0, rSTR1
+	lwbrx	rWORD8, 0, rSTR2
+	addi	rSTR1, rSTR1, 4
+	addi	rSTR2, rSTR2, 4
+#else
+	lwzu	rWORD7, 16(rSTR1)
+	lwzu	rWORD8, 16(rSTR2)
+#endif
+	bne	cr1, L(dLcr1)
+	cmplw	cr7, rWORD1, rWORD2
 	bdnz	L(dLoop)
 
 L(dL4):
-	cmplw	cr1,rWORD3,rWORD4
-	bne	cr6,L(dLcr6)
-	cmplw	cr6,rWORD5,rWORD6
-	bne	cr5,L(dLcr5)
-	cmplw	cr5,rWORD7,rWORD8
+	cmplw	cr1, rWORD3, rWORD4
+	bne	cr6, L(dLcr6)
+	cmplw	cr6, rWORD5, rWORD6
+	bne	cr5, L(dLcr5)
+	cmplw	cr5, rWORD7, rWORD8
 L(d44):
-	bne	cr0,L(dLcr0)
+	bne	cr7, L(dLcr7)
 L(d34):
-	bne	cr1,L(dLcr1)
+	bne	cr1, L(dLcr1)
 L(d24):
-	bne	cr6,L(dLcr6)
+	bne	cr6, L(dLcr6)
 L(d14):
-	slwi.	r12,rN,3
-	bne	cr5,L(dLcr5)
+	slwi.	r12, rN, 3
+	bne	cr5, L(dLcr5)
 L(d04):
-	lwz	r30,44(1)
-	lwz	r31,48(1)
-	lwz	1,0(1)
-	subfic	rN,r12,32	/* Shift count is 32 - (rN * 8).  */
+	lwz	rWORD7, 44(r1)
+	lwz	rWORD8, 48(r1)
+	addi	r1, r1, 64
+	cfi_adjust_cfa_offset(-64)
+	subfic	rN, r12, 32	/* Shift count is 32 - (rN * 8).  */
 	beq	L(zeroLength)
 /* At this point we have a remainder of 1 to 3 bytes to compare.  Since
    we are aligned it is safe to load the whole word, and use
-   shift right to eliminate bits beyond the compare length. */
+   shift right to eliminate bits beyond the compare length.  */
 L(d00):
-	lwz	rWORD1,4(rSTR1)
-	lwz	rWORD2,4(rSTR2)
-	srw	rWORD1,rWORD1,rN
-	srw	rWORD2,rWORD2,rN
-	cmplw	rWORD1,rWORD2
-	li	rRTN,0
-	beqlr
-	li	rRTN,1
-	bgtlr
-	li	rRTN,-1
+#ifdef __LITTLE_ENDIAN__
+	lwbrx	rWORD1, 0, rSTR1
+	lwbrx	rWORD2, 0, rSTR2
+	addi	rSTR1, rSTR1, 4
+	addi	rSTR2, rSTR2, 4
+#else
+	lwz	rWORD1, 4(rSTR1)
+	lwz	rWORD2, 4(rSTR2)
+#endif
+	srw	rWORD1, rWORD1, rN
+	srw	rWORD2, rWORD2, rN
+	sub	rRTN, rWORD1, rWORD2
 	blr
 
 	.align	4
-L(dLcr0):
-	lwz	r30,44(1)
-	lwz	r31,48(1)
-	li	rRTN,1
-	lwz	1,0(1)
-	bgtlr	cr0
-	li	rRTN,-1
+	cfi_adjust_cfa_offset(64)
+L(dLcr7):
+	lwz	rWORD7, 44(r1)
+	lwz	rWORD8, 48(r1)
+L(dLcr7x):
+	li	rRTN, 1
+	addi	r1, r1, 64
+	cfi_adjust_cfa_offset(-64)
+	bgtlr	cr7
+	li	rRTN, -1
 	blr
 	.align	4
+	cfi_adjust_cfa_offset(64)
 L(dLcr1):
-	lwz	r30,44(1)
-	lwz	r31,48(1)
-	li	rRTN,1
-	lwz	1,0(1)
+	lwz	rWORD7, 44(r1)
+	lwz	rWORD8, 48(r1)
+L(dLcr1x):
+	li	rRTN, 1
+	addi	r1, r1, 64
+	cfi_adjust_cfa_offset(-64)
 	bgtlr	cr1
-	li	rRTN,-1
+	li	rRTN, -1
 	blr
 	.align	4
+	cfi_adjust_cfa_offset(64)
 L(dLcr6):
-	lwz	r30,44(1)
-	lwz	r31,48(1)
-	li	rRTN,1
-	lwz	1,0(1)
+	lwz	rWORD7, 44(r1)
+	lwz	rWORD8, 48(r1)
+L(dLcr6x):
+	li	rRTN, 1
+	addi	r1, r1, 64
+	cfi_adjust_cfa_offset(-64)
 	bgtlr	cr6
-	li	rRTN,-1
+	li	rRTN, -1
 	blr
 	.align	4
+	cfi_adjust_cfa_offset(64)
 L(dLcr5):
-	lwz	r30,44(1)
-	lwz	r31,48(1)
+	lwz	rWORD7, 44(r1)
+	lwz	rWORD8, 48(r1)
 L(dLcr5x):
-	li	rRTN,1
-	lwz	1,0(1)
+	li	rRTN, 1
+	addi	r1, r1, 64
+	cfi_adjust_cfa_offset(-64)
 	bgtlr	cr5
-	li	rRTN,-1
+	li	rRTN, -1
 	blr
 
 	.align	4
 L(bytealigned):
-	cfi_adjust_cfa_offset(-64)
 	mtctr	rN
 
 /* We need to prime this loop.  This loop is swing modulo scheduled
@@ -411,38 +616,39 @@ L(bytealigned):
 
    So we must precondition some registers and condition codes so that
    we don't exit the loop early on the first iteration.  */
-	lbz	rWORD1,0(rSTR1)
-	lbz	rWORD2,0(rSTR2)
+
+	lbz	rWORD1, 0(rSTR1)
+	lbz	rWORD2, 0(rSTR2)
 	bdz	L(b11)
-	cmplw	cr0,rWORD1,rWORD2
-	lbz	rWORD3,1(rSTR1)
-	lbz	rWORD4,1(rSTR2)
+	cmplw	cr7, rWORD1, rWORD2
+	lbz	rWORD3, 1(rSTR1)
+	lbz	rWORD4, 1(rSTR2)
 	bdz	L(b12)
-	cmplw	cr1,rWORD3,rWORD4
-	lbzu	rWORD5,2(rSTR1)
-	lbzu	rWORD6,2(rSTR2)
+	cmplw	cr1, rWORD3, rWORD4
+	lbzu	rWORD5, 2(rSTR1)
+	lbzu	rWORD6, 2(rSTR2)
 	bdz	L(b13)
 	.align	4
 L(bLoop):
-	lbzu	rWORD1,1(rSTR1)
-	lbzu	rWORD2,1(rSTR2)
-	bne	cr0,L(bLcr0)
+	lbzu	rWORD1, 1(rSTR1)
+	lbzu	rWORD2, 1(rSTR2)
+	bne	cr7, L(bLcr7)
 
-	cmplw	cr6,rWORD5,rWORD6
+	cmplw	cr6, rWORD5, rWORD6
 	bdz	L(b3i)
 
-	lbzu	rWORD3,1(rSTR1)
-	lbzu	rWORD4,1(rSTR2)
-	bne	cr1,L(bLcr1)
+	lbzu	rWORD3, 1(rSTR1)
+	lbzu	rWORD4, 1(rSTR2)
+	bne	cr1, L(bLcr1)
 
-	cmplw	cr0,rWORD1,rWORD2
+	cmplw	cr7, rWORD1, rWORD2
 	bdz	L(b2i)
 
-	lbzu	rWORD5,1(rSTR1)
-	lbzu	rWORD6,1(rSTR2)
-	bne	cr6,L(bLcr6)
+	lbzu	rWORD5, 1(rSTR1)
+	lbzu	rWORD6, 1(rSTR2)
+	bne	cr6, L(bLcr6)
 
-	cmplw	cr1,rWORD3,rWORD4
+	cmplw	cr1, rWORD3, rWORD4
 	bdnz	L(bLoop)
 
 /* We speculatively loading bytes before we have tested the previous
@@ -452,67 +658,62 @@ L(bLoop):
    tested.  In this case we must complete the pending operations
    before returning.  */
 L(b1i):
-	bne	cr0,L(bLcr0)
-	bne	cr1,L(bLcr1)
+	bne	cr7, L(bLcr7)
+	bne	cr1, L(bLcr1)
 	b	L(bx56)
 	.align	4
 L(b2i):
-	bne	cr6,L(bLcr6)
-	bne	cr0,L(bLcr0)
+	bne	cr6, L(bLcr6)
+	bne	cr7, L(bLcr7)
 	b	L(bx34)
 	.align	4
 L(b3i):
-	bne	cr1,L(bLcr1)
-	bne	cr6,L(bLcr6)
+	bne	cr1, L(bLcr1)
+	bne	cr6, L(bLcr6)
 	b	L(bx12)
 	.align	4
-L(bLcr0):
-	li	rRTN,1
-	bgtlr	cr0
-	li	rRTN,-1
+L(bLcr7):
+	li	rRTN, 1
+	bgtlr	cr7
+	li	rRTN, -1
 	blr
 L(bLcr1):
-	li	rRTN,1
+	li	rRTN, 1
 	bgtlr	cr1
-	li	rRTN,-1
+	li	rRTN, -1
 	blr
 L(bLcr6):
-	li	rRTN,1
+	li	rRTN, 1
 	bgtlr	cr6
-	li	rRTN,-1
+	li	rRTN, -1
 	blr
 
 L(b13):
-	bne	cr0,L(bx12)
-	bne	cr1,L(bx34)
+	bne	cr7, L(bx12)
+	bne	cr1, L(bx34)
 L(bx56):
-	sub	rRTN,rWORD5,rWORD6
+	sub	rRTN, rWORD5, rWORD6
 	blr
 	nop
 L(b12):
-	bne	cr0,L(bx12)
+	bne	cr7, L(bx12)
 L(bx34):
-	sub	rRTN,rWORD3,rWORD4
+	sub	rRTN, rWORD3, rWORD4
 	blr
-
 L(b11):
 L(bx12):
-	sub	rRTN,rWORD1,rWORD2
+	sub	rRTN, rWORD1, rWORD2
 	blr
-
 	.align	4
-L(zeroLengthReturn):
-
 L(zeroLength):
-	li	rRTN,0
+	li	rRTN, 0
 	blr
 
-	cfi_adjust_cfa_offset(64)
 	.align	4
 /* At this point we know the strings have different alignment and the
-   compare length is at least 8 bytes.  rBITDIF contains the low order
+   compare length is at least 8 bytes.  r12 contains the low order
    2 bits of rSTR1 and cr5 contains the result of the logical compare
-   of rBITDIF to 0.  If rBITDIF == 0 then rStr1 is word aligned and can
+   of r12 to 0.  If r12 == 0 then rStr1 is word aligned and can
    perform the Wunaligned loop.
 
    Otherwise we know that rSTR1 is not aready word aligned yet.
@@ -521,465 +722,654 @@ L(zeroLength):
    eliminate bits preceding the first byte.  Since we want to join the
    normal (Wualigned) compare loop, starting at the second word,
    we need to adjust the length (rN) and special case the loop
-   versioning for the first W. This insures that the loop count is
+   versioning for the first W. This ensures that the loop count is
    correct and the first W (shifted) is in the expected resister pair.  */
 #define rSHL		r29	/* Unaligned shift left count.  */
 #define rSHR		r28	/* Unaligned shift right count.  */
-#define rB		r27	/* Left rotation temp for rWORD2.  */
-#define rD		r26	/* Left rotation temp for rWORD4.  */
-#define rF		r25	/* Left rotation temp for rWORD6.  */
-#define rH		r24	/* Left rotation temp for rWORD8.  */
-#define rA		r0	/* Right rotation temp for rWORD2.  */
-#define rC		r12	/* Right rotation temp for rWORD4.  */
-#define rE		r0	/* Right rotation temp for rWORD6.  */
-#define rG		r12	/* Right rotation temp for rWORD8.  */
+#define rWORD8_SHIFT	r27	/* Left rotation temp for rWORD2.  */
+#define rWORD2_SHIFT	r26	/* Left rotation temp for rWORD4.  */
+#define rWORD4_SHIFT	r25	/* Left rotation temp for rWORD6.  */
+#define rWORD6_SHIFT	r24	/* Left rotation temp for rWORD8.  */
+	cfi_adjust_cfa_offset(64)
 L(unaligned):
-	stw	r29,40(r1)
-	cfi_offset(r29,(40-64))
-	clrlwi	rSHL,rSTR2,30
-	stw	r28,36(r1)
-	cfi_offset(r28,(36-64))
-	beq	cr5,L(Wunaligned)
-	stw	r27,32(r1)
-	cfi_offset(r27,(32-64))
+	stw	rSHL, 40(r1)
+	cfi_offset(rSHL, (40-64))
+	clrlwi	rSHL, rSTR2, 30
+	stw	rSHR, 36(r1)
+	cfi_offset(rSHR, (36-64))
+	beq	cr5, L(Wunaligned)
+	stw	rWORD8_SHIFT, 32(r1)
+	cfi_offset(rWORD8_SHIFT, (32-64))
 /* Adjust the logical start of rSTR2 to compensate for the extra bits
    in the 1st rSTR1 W.  */
-	sub	r27,rSTR2,rBITDIF
+	sub	rWORD8_SHIFT, rSTR2, r12
 /* But do not attempt to address the W before that W that contains
    the actual start of rSTR2.  */
-	clrrwi	rSTR2,rSTR2,2
-	stw	r26,28(r1)
-	cfi_offset(r26,(28-64))
-/* Compute the left/right shift counts for the unalign rSTR2,
+	clrrwi	rSTR2, rSTR2, 2
+	stw	rWORD2_SHIFT, 28(r1)
+	cfi_offset(rWORD2_SHIFT, (28-64))
+/* Compute the left/right shift counts for the unaligned rSTR2,
    compensating for the logical (W aligned) start of rSTR1.  */
-	clrlwi	rSHL,r27,30
-	clrrwi	rSTR1,rSTR1,2
-	stw	r25,24(r1)
-	cfi_offset(r25,(24-64))
-	slwi	rSHL,rSHL,3
-	cmplw	cr5,r27,rSTR2
-	add	rN,rN,rBITDIF
-	slwi	r11,rBITDIF,3
-	stw	r24,20(r1)
-	cfi_offset(r24,(20-64))
-	subfic	rSHR,rSHL,32
-	srwi	rTMP,rN,4	/* Divide by 16 */
-	andi.	rBITDIF,rN,12	/* Get the W remainder */
+	clrlwi	rSHL, rWORD8_SHIFT, 30
+	clrrwi	rSTR1, rSTR1, 2
+	stw	rWORD4_SHIFT, 24(r1)
+	cfi_offset(rWORD4_SHIFT, (24-64))
+	slwi	rSHL, rSHL, 3
+	cmplw	cr5, rWORD8_SHIFT, rSTR2
+	add	rN, rN, r12
+	slwi	rWORD6, r12, 3
+	stw	rWORD6_SHIFT, 20(r1)
+	cfi_offset(rWORD6_SHIFT, (20-64))
+	subfic	rSHR, rSHL, 32
+	srwi	r0, rN, 4	/* Divide by 16 */
+	andi.	r12, rN, 12	/* Get the W remainder */
 /* We normally need to load 2 Ws to start the unaligned rSTR2, but in
    this special case those bits may be discarded anyway.  Also we
    must avoid loading a W where none of the bits are part of rSTR2 as
    this may cross a page boundary and cause a page fault.  */
-	li	rWORD8,0
-	blt	cr5,L(dus0)
-	lwz	rWORD8,0(rSTR2)
-	la	rSTR2,4(rSTR2)
-	slw	rWORD8,rWORD8,rSHL
+	li	rWORD8, 0
+	blt	cr5, L(dus0)
+#ifdef __LITTLE_ENDIAN__
+	lwbrx	rWORD8, 0, rSTR2
+	addi	rSTR2, rSTR2, 4
+#else
+	lwz	rWORD8, 0(rSTR2)
+	addi	rSTR2, rSTR2, 4
+#endif
+	slw	rWORD8, rWORD8, rSHL
 
 L(dus0):
-	lwz	rWORD1,0(rSTR1)
-	lwz	rWORD2,0(rSTR2)
-	cmplwi	cr1,rBITDIF,8
-	cmplwi	cr7,rN,16
-	srw	rG,rWORD2,rSHR
-	clrlwi	rN,rN,30
+#ifdef __LITTLE_ENDIAN__
+	lwbrx	rWORD1, 0, rSTR1
+	lwbrx	rWORD2, 0, rSTR2
+	addi	rSTR1, rSTR1, 4
+	addi	rSTR2, rSTR2, 4
+#else
+	lwz	rWORD1, 0(rSTR1)
+	lwz	rWORD2, 0(rSTR2)
+#endif
+	cmplwi	cr1, r12, 8
+	cmplwi	cr7, rN, 16
+	srw	r12, rWORD2, rSHR
+	clrlwi	rN, rN, 30
 	beq	L(duPs4)
-	mtctr	rTMP
-	or	rWORD8,rG,rWORD8
-	bgt	cr1,L(duPs3)
-	beq	cr1,L(duPs2)
+	mtctr	r0
+	or	rWORD8, r12, rWORD8
+	bgt	cr1, L(duPs3)
+	beq	cr1, L(duPs2)
 
 /* Remainder is 4 */
 	.align	4
 L(dusP1):
-	slw	rB,rWORD2,rSHL
-	slw	rWORD7,rWORD1,r11
-	slw	rWORD8,rWORD8,r11
-	bge	cr7,L(duP1e)
+	slw	rWORD8_SHIFT, rWORD2, rSHL
+	slw	rWORD7, rWORD1, rWORD6
+	slw	rWORD8, rWORD8, rWORD6
+	bge	cr7, L(duP1e)
 /* At this point we exit early with the first word compare
    complete and remainder of 0 to 3 bytes.  See L(du14) for details on
    how we handle the remaining bytes.  */
-	cmplw	cr5,rWORD7,rWORD8
-	slwi.	rN,rN,3
-	bne	cr5,L(duLcr5)
-	cmplw	cr7,rN,rSHR
+	cmplw	cr5, rWORD7, rWORD8
+	slwi.	rN, rN, 3
+	bne	cr5, L(duLcr5)
+	cmplw	cr7, rN, rSHR
 	beq	L(duZeroReturn)
-	li	rA,0
-	ble	cr7,L(dutrim)
-	lwz	rWORD2,4(rSTR2)
-	srw	rA,rWORD2,rSHR
+	li	r0, 0
+	ble	cr7, L(dutrim)
+#ifdef __LITTLE_ENDIAN__
+	lwbrx	rWORD2, 0, rSTR2
+	addi	rSTR2, rSTR2, 4
+#else
+	lwz	rWORD2, 4(rSTR2)
+#endif
+	srw	r0, rWORD2, rSHR
 	b	L(dutrim)
 /* Remainder is 8 */
 	.align	4
 L(duPs2):
-	slw	rH,rWORD2,rSHL
-	slw	rWORD5,rWORD1,r11
-	slw	rWORD6,rWORD8,r11
+	slw	rWORD6_SHIFT, rWORD2, rSHL
+	slw	rWORD5, rWORD1, rWORD6
+	slw	rWORD6, rWORD8, rWORD6
 	b	L(duP2e)
 /* Remainder is 12 */
 	.align	4
 L(duPs3):
-	slw	rF,rWORD2,rSHL
-	slw	rWORD3,rWORD1,r11
-	slw	rWORD4,rWORD8,r11
+	slw	rWORD4_SHIFT, rWORD2, rSHL
+	slw	rWORD3, rWORD1, rWORD6
+	slw	rWORD4, rWORD8, rWORD6
 	b	L(duP3e)
 /* Count is a multiple of 16, remainder is 0 */
 	.align	4
 L(duPs4):
-	mtctr	rTMP
-	or	rWORD8,rG,rWORD8
-	slw	rD,rWORD2,rSHL
-	slw	rWORD1,rWORD1,r11
-	slw	rWORD2,rWORD8,r11
+	mtctr	r0
+	or	rWORD8, r12, rWORD8
+	slw	rWORD2_SHIFT, rWORD2, rSHL
+	slw	rWORD1, rWORD1, rWORD6
+	slw	rWORD2, rWORD8, rWORD6
 	b	L(duP4e)
 
 /* At this point we know rSTR1 is word aligned and the
    compare length is at least 8 bytes.  */
 	.align	4
 L(Wunaligned):
-	stw	r27,32(r1)
-	cfi_offset(r27,(32-64))
-	clrrwi	rSTR2,rSTR2,2
-	stw	r26,28(r1)
-	cfi_offset(r26,(28-64))
-	srwi	rTMP,rN,4	/* Divide by 16 */
-	stw	r25,24(r1)
-	cfi_offset(r25,(24-64))
-	andi.	rBITDIF,rN,12	/* Get the W remainder */
-	stw	r24,20(r1)
-	cfi_offset(r24,(24-64))
-	slwi	rSHL,rSHL,3
-	lwz	rWORD6,0(rSTR2)
-	lwzu	rWORD8,4(rSTR2)
-	cmplwi	cr1,rBITDIF,8
-	cmplwi	cr7,rN,16
-	clrlwi	rN,rN,30
-	subfic	rSHR,rSHL,32
-	slw	rH,rWORD6,rSHL
+	stw	rWORD8_SHIFT, 32(r1)
+	cfi_offset(rWORD8_SHIFT, (32-64))
+	clrrwi	rSTR2, rSTR2, 2
+	stw	rWORD2_SHIFT, 28(r1)
+	cfi_offset(rWORD2_SHIFT, (28-64))
+	srwi	r0, rN, 4	/* Divide by 16 */
+	stw	rWORD4_SHIFT, 24(r1)
+	cfi_offset(rWORD4_SHIFT, (24-64))
+	andi.	r12, rN, 12	/* Get the W remainder */
+	stw	rWORD6_SHIFT, 20(r1)
+	cfi_offset(rWORD6_SHIFT, (20-64))
+	slwi	rSHL, rSHL, 3
+#ifdef __LITTLE_ENDIAN__
+	lwbrx	rWORD6, 0, rSTR2
+	addi	rSTR2, rSTR2, 4
+	lwbrx	rWORD8, 0, rSTR2
+	addi	rSTR2, rSTR2, 4
+#else
+	lwz	rWORD6, 0(rSTR2)
+	lwzu	rWORD8, 4(rSTR2)
+#endif
+	cmplwi	cr1, r12, 8
+	cmplwi	cr7, rN, 16
+	clrlwi	rN, rN, 30
+	subfic	rSHR, rSHL, 32
+	slw	rWORD6_SHIFT, rWORD6, rSHL
 	beq	L(duP4)
-	mtctr	rTMP
-	bgt	cr1,L(duP3)
-	beq	cr1,L(duP2)
+	mtctr	r0
+	bgt	cr1, L(duP3)
+	beq	cr1, L(duP2)
 
 /* Remainder is 4 */
 	.align	4
 L(duP1):
-	srw	rG,rWORD8,rSHR
-	lwz	rWORD7,0(rSTR1)
-	slw	rB,rWORD8,rSHL
-	or	rWORD8,rG,rH
-	blt	cr7,L(duP1x)
+	srw	r12, rWORD8, rSHR
+#ifdef __LITTLE_ENDIAN__
+	lwbrx	rWORD7, 0, rSTR1
+	addi	rSTR1, rSTR1, 4
+#else
+	lwz	rWORD7, 0(rSTR1)
+#endif
+	slw	rWORD8_SHIFT, rWORD8, rSHL
+	or	rWORD8, r12, rWORD6_SHIFT
+	blt	cr7, L(duP1x)
 L(duP1e):
-	lwz	rWORD1,4(rSTR1)
-	lwz	rWORD2,4(rSTR2)
-	cmplw	cr5,rWORD7,rWORD8
-	srw	rA,rWORD2,rSHR
-	slw	rD,rWORD2,rSHL
-	or	rWORD2,rA,rB
-	lwz	rWORD3,8(rSTR1)
-	lwz	rWORD4,8(rSTR2)
-	cmplw	cr0,rWORD1,rWORD2
-	srw	rC,rWORD4,rSHR
-	slw	rF,rWORD4,rSHL
-	bne	cr5,L(duLcr5)
-	or	rWORD4,rC,rD
-	lwz	rWORD5,12(rSTR1)
-	lwz	rWORD6,12(rSTR2)
-	cmplw	cr1,rWORD3,rWORD4
-	srw	rE,rWORD6,rSHR
-	slw	rH,rWORD6,rSHL
-	bne	cr0,L(duLcr0)
-	or	rWORD6,rE,rF
-	cmplw	cr6,rWORD5,rWORD6
+#ifdef __LITTLE_ENDIAN__
+	lwbrx	rWORD1, 0, rSTR1
+	lwbrx	rWORD2, 0, rSTR2
+	addi	rSTR1, rSTR1, 4
+	addi	rSTR2, rSTR2, 4
+#else
+	lwz	rWORD1, 4(rSTR1)
+	lwz	rWORD2, 4(rSTR2)
+#endif
+	cmplw	cr5, rWORD7, rWORD8
+	srw	r0, rWORD2, rSHR
+	slw	rWORD2_SHIFT, rWORD2, rSHL
+	or	rWORD2, r0, rWORD8_SHIFT
+#ifdef __LITTLE_ENDIAN__
+	lwbrx	rWORD3, 0, rSTR1
+	lwbrx	rWORD4, 0, rSTR2
+	addi	rSTR1, rSTR1, 4
+	addi	rSTR2, rSTR2, 4
+#else
+	lwz	rWORD3, 8(rSTR1)
+	lwz	rWORD4, 8(rSTR2)
+#endif
+	cmplw	cr7, rWORD1, rWORD2
+	srw	r12, rWORD4, rSHR
+	slw	rWORD4_SHIFT, rWORD4, rSHL
+	bne	cr5, L(duLcr5)
+	or	rWORD4, r12, rWORD2_SHIFT
+#ifdef __LITTLE_ENDIAN__
+	lwbrx	rWORD5, 0, rSTR1
+	lwbrx	rWORD6, 0, rSTR2
+	addi	rSTR1, rSTR1, 4
+	addi	rSTR2, rSTR2, 4
+#else
+	lwz	rWORD5, 12(rSTR1)
+	lwz	rWORD6, 12(rSTR2)
+#endif
+	cmplw	cr1, rWORD3, rWORD4
+	srw	r0, rWORD6, rSHR
+	slw	rWORD6_SHIFT, rWORD6, rSHL
+	bne	cr7, L(duLcr7)
+	or	rWORD6, r0, rWORD4_SHIFT
+	cmplw	cr6, rWORD5, rWORD6
 	b	L(duLoop3)
 	.align	4
 /* At this point we exit early with the first word compare
    complete and remainder of 0 to 3 bytes.  See L(du14) for details on
    how we handle the remaining bytes.  */
 L(duP1x):
-	cmplw	cr5,rWORD7,rWORD8
-	slwi.	rN,rN,3
-	bne	cr5,L(duLcr5)
-	cmplw	cr7,rN,rSHR
+	cmplw	cr5, rWORD7, rWORD8
+	slwi.	rN, rN, 3
+	bne	cr5, L(duLcr5)
+	cmplw	cr7, rN, rSHR
 	beq	L(duZeroReturn)
-	li	rA,0
-	ble	cr7,L(dutrim)
-	ld	rWORD2,8(rSTR2)
-	srw	rA,rWORD2,rSHR
+	li	r0, 0
+	ble	cr7, L(dutrim)
+#ifdef __LITTLE_ENDIAN__
+	lwbrx	rWORD2, 0, rSTR2
+	addi	rSTR2, rSTR2, 4
+#else
+	lwz	rWORD2, 8(rSTR2)
+#endif
+	srw	r0, rWORD2, rSHR
 	b	L(dutrim)
 /* Remainder is 8 */
 	.align	4
 L(duP2):
-	srw	rE,rWORD8,rSHR
-	lwz	rWORD5,0(rSTR1)
-	or	rWORD6,rE,rH
-	slw	rH,rWORD8,rSHL
+	srw	r0, rWORD8, rSHR
+#ifdef __LITTLE_ENDIAN__
+	lwbrx	rWORD5, 0, rSTR1
+	addi	rSTR1, rSTR1, 4
+#else
+	lwz	rWORD5, 0(rSTR1)
+#endif
+	or	rWORD6, r0, rWORD6_SHIFT
+	slw	rWORD6_SHIFT, rWORD8, rSHL
 L(duP2e):
-	lwz	rWORD7,4(rSTR1)
-	lwz	rWORD8,4(rSTR2)
-	cmplw	cr6,rWORD5,rWORD6
-	srw	rG,rWORD8,rSHR
-	slw	rB,rWORD8,rSHL
-	or	rWORD8,rG,rH
-	blt	cr7,L(duP2x)
-	lwz	rWORD1,8(rSTR1)
-	lwz	rWORD2,8(rSTR2)
-	cmplw	cr5,rWORD7,rWORD8
-	bne	cr6,L(duLcr6)
-	srw	rA,rWORD2,rSHR
-	slw	rD,rWORD2,rSHL
-	or	rWORD2,rA,rB
-	lwz	rWORD3,12(rSTR1)
-	lwz	rWORD4,12(rSTR2)
-	cmplw	cr0,rWORD1,rWORD2
-	bne	cr5,L(duLcr5)
-	srw	rC,rWORD4,rSHR
-	slw	rF,rWORD4,rSHL
-	or	rWORD4,rC,rD
-	addi	rSTR1,rSTR1,4
-	addi	rSTR2,rSTR2,4
-	cmplw	cr1,rWORD3,rWORD4
+#ifdef __LITTLE_ENDIAN__
+	lwbrx	rWORD7, 0, rSTR1
+	lwbrx	rWORD8, 0, rSTR2
+	addi	rSTR1, rSTR1, 4
+	addi	rSTR2, rSTR2, 4
+#else
+	lwz	rWORD7, 4(rSTR1)
+	lwz	rWORD8, 4(rSTR2)
+#endif
+	cmplw	cr6, rWORD5, rWORD6
+	srw	r12, rWORD8, rSHR
+	slw	rWORD8_SHIFT, rWORD8, rSHL
+	or	rWORD8, r12, rWORD6_SHIFT
+	blt	cr7, L(duP2x)
+#ifdef __LITTLE_ENDIAN__
+	lwbrx	rWORD1, 0, rSTR1
+	lwbrx	rWORD2, 0, rSTR2
+	addi	rSTR1, rSTR1, 4
+	addi	rSTR2, rSTR2, 4
+#else
+	lwz	rWORD1, 8(rSTR1)
+	lwz	rWORD2, 8(rSTR2)
+#endif
+	cmplw	cr5, rWORD7, rWORD8
+	bne	cr6, L(duLcr6)
+	srw	r0, rWORD2, rSHR
+	slw	rWORD2_SHIFT, rWORD2, rSHL
+	or	rWORD2, r0, rWORD8_SHIFT
+#ifdef __LITTLE_ENDIAN__
+	lwbrx	rWORD3, 0, rSTR1
+	lwbrx	rWORD4, 0, rSTR2
+	addi	rSTR1, rSTR1, 4
+	addi	rSTR2, rSTR2, 4
+#else
+	lwz	rWORD3, 12(rSTR1)
+	lwz	rWORD4, 12(rSTR2)
+#endif
+	cmplw	cr7, rWORD1, rWORD2
+	bne	cr5, L(duLcr5)
+	srw	r12, rWORD4, rSHR
+	slw	rWORD4_SHIFT, rWORD4, rSHL
+	or	rWORD4, r12, rWORD2_SHIFT
+#ifndef __LITTLE_ENDIAN__
+	addi	rSTR1, rSTR1, 4
+	addi	rSTR2, rSTR2, 4
+#endif
+	cmplw	cr1, rWORD3, rWORD4
 	b	L(duLoop2)
 	.align	4
 L(duP2x):
-	cmplw	cr5,rWORD7,rWORD8
-	addi	rSTR1,rSTR1,4
-	addi	rSTR2,rSTR2,4
-	bne	cr6,L(duLcr6)
-	slwi.	rN,rN,3
-	bne	cr5,L(duLcr5)
-	cmplw	cr7,rN,rSHR
+	cmplw	cr5, rWORD7, rWORD8
+#ifndef __LITTLE_ENDIAN__
+	addi	rSTR1, rSTR1, 4
+	addi	rSTR2, rSTR2, 4
+#endif
+	bne	cr6, L(duLcr6)
+	slwi.	rN, rN, 3
+	bne	cr5, L(duLcr5)
+	cmplw	cr7, rN, rSHR
 	beq	L(duZeroReturn)
-	li	rA,0
-	ble	cr7,L(dutrim)
-	lwz	rWORD2,4(rSTR2)
-	srw	rA,rWORD2,rSHR
+	li	r0, 0
+	ble	cr7, L(dutrim)
+#ifdef __LITTLE_ENDIAN__
+	lwbrx	rWORD2, 0, rSTR2
+	addi	rSTR2, rSTR2, 4
+#else
+	lwz	rWORD2, 4(rSTR2)
+#endif
+	srw	r0, rWORD2, rSHR
 	b	L(dutrim)
 
 /* Remainder is 12 */
 	.align	4
 L(duP3):
-	srw	rC,rWORD8,rSHR
-	lwz	rWORD3,0(rSTR1)
-	slw	rF,rWORD8,rSHL
-	or	rWORD4,rC,rH
+	srw	r12, rWORD8, rSHR
+#ifdef __LITTLE_ENDIAN__
+	lwbrx	rWORD3, 0, rSTR1
+	addi	rSTR1, rSTR1, 4
+#else
+	lwz	rWORD3, 0(rSTR1)
+#endif
+	slw	rWORD4_SHIFT, rWORD8, rSHL
+	or	rWORD4, r12, rWORD6_SHIFT
 L(duP3e):
-	lwz	rWORD5,4(rSTR1)
-	lwz	rWORD6,4(rSTR2)
-	cmplw	cr1,rWORD3,rWORD4
-	srw	rE,rWORD6,rSHR
-	slw	rH,rWORD6,rSHL
-	or	rWORD6,rE,rF
-	lwz	rWORD7,8(rSTR1)
-	lwz	rWORD8,8(rSTR2)
-	cmplw	cr6,rWORD5,rWORD6
-	bne	cr1,L(duLcr1)
-	srw	rG,rWORD8,rSHR
-	slw	rB,rWORD8,rSHL
-	or	rWORD8,rG,rH
-	blt	cr7,L(duP3x)
-	lwz	rWORD1,12(rSTR1)
-	lwz	rWORD2,12(rSTR2)
-	cmplw	cr5,rWORD7,rWORD8
-	bne	cr6,L(duLcr6)
-	srw	rA,rWORD2,rSHR
-	slw	rD,rWORD2,rSHL
-	or	rWORD2,rA,rB
-	addi	rSTR1,rSTR1,8
-	addi	rSTR2,rSTR2,8
-	cmplw	cr0,rWORD1,rWORD2
+#ifdef __LITTLE_ENDIAN__
+	lwbrx	rWORD5, 0, rSTR1
+	lwbrx	rWORD6, 0, rSTR2
+	addi	rSTR1, rSTR1, 4
+	addi	rSTR2, rSTR2, 4
+#else
+	lwz	rWORD5, 4(rSTR1)
+	lwz	rWORD6, 4(rSTR2)
+#endif
+	cmplw	cr1, rWORD3, rWORD4
+	srw	r0, rWORD6, rSHR
+	slw	rWORD6_SHIFT, rWORD6, rSHL
+	or	rWORD6, r0, rWORD4_SHIFT
+#ifdef __LITTLE_ENDIAN__
+	lwbrx	rWORD7, 0, rSTR1
+	lwbrx	rWORD8, 0, rSTR2
+	addi	rSTR1, rSTR1, 4
+	addi	rSTR2, rSTR2, 4
+#else
+	lwz	rWORD7, 8(rSTR1)
+	lwz	rWORD8, 8(rSTR2)
+#endif
+	cmplw	cr6, rWORD5, rWORD6
+	bne	cr1, L(duLcr1)
+	srw	r12, rWORD8, rSHR
+	slw	rWORD8_SHIFT, rWORD8, rSHL
+	or	rWORD8, r12, rWORD6_SHIFT
+	blt	cr7, L(duP3x)
+#ifdef __LITTLE_ENDIAN__
+	lwbrx	rWORD1, 0, rSTR1
+	lwbrx	rWORD2, 0, rSTR2
+	addi	rSTR1, rSTR1, 4
+	addi	rSTR2, rSTR2, 4
+#else
+	lwz	rWORD1, 12(rSTR1)
+	lwz	rWORD2, 12(rSTR2)
+#endif
+	cmplw	cr5, rWORD7, rWORD8
+	bne	cr6, L(duLcr6)
+	srw	r0, rWORD2, rSHR
+	slw	rWORD2_SHIFT, rWORD2, rSHL
+	or	rWORD2, r0, rWORD8_SHIFT
+#ifndef __LITTLE_ENDIAN__
+	addi	rSTR1, rSTR1, 8
+	addi	rSTR2, rSTR2, 8
+#endif
+	cmplw	cr7, rWORD1, rWORD2
 	b	L(duLoop1)
 	.align	4
 L(duP3x):
-	addi	rSTR1,rSTR1,8
-	addi	rSTR2,rSTR2,8
-	bne	cr1,L(duLcr1)
-	cmplw	cr5,rWORD7,rWORD8
-	bne	cr6,L(duLcr6)
-	slwi.	rN,rN,3
-	bne	cr5,L(duLcr5)
-	cmplw	cr7,rN,rSHR
+#ifndef __LITTLE_ENDIAN__
+	addi	rSTR1, rSTR1, 8
+	addi	rSTR2, rSTR2, 8
+#endif
+#if 0
+/* Huh?  We've already branched on cr1!  */
+	bne	cr1, L(duLcr1)
+#endif
+	cmplw	cr5, rWORD7, rWORD8
+	bne	cr6, L(duLcr6)
+	slwi.	rN, rN, 3
+	bne	cr5, L(duLcr5)
+	cmplw	cr7, rN, rSHR
 	beq	L(duZeroReturn)
-	li	rA,0
-	ble	cr7,L(dutrim)
-	lwz	rWORD2,4(rSTR2)
-	srw	rA,rWORD2,rSHR
+	li	r0, 0
+	ble	cr7, L(dutrim)
+#ifdef __LITTLE_ENDIAN__
+	lwbrx	rWORD2, 0, rSTR2
+	addi	rSTR2, rSTR2, 4
+#else
+	lwz	rWORD2, 4(rSTR2)
+#endif
+	srw	r0, rWORD2, rSHR
 	b	L(dutrim)
 
 /* Count is a multiple of 16, remainder is 0 */
 	.align	4
 L(duP4):
-	mtctr	rTMP
-	srw	rA,rWORD8,rSHR
-	lwz	rWORD1,0(rSTR1)
-	slw	rD,rWORD8,rSHL
-	or	rWORD2,rA,rH
+	mtctr	r0
+	srw	r0, rWORD8, rSHR
+#ifdef __LITTLE_ENDIAN__
+	lwbrx	rWORD1, 0, rSTR1
+	addi	rSTR1, rSTR1, 4
+#else
+	lwz	rWORD1, 0(rSTR1)
+#endif
+	slw	rWORD2_SHIFT, rWORD8, rSHL
+	or	rWORD2, r0, rWORD6_SHIFT
 L(duP4e):
-	lwz	rWORD3,4(rSTR1)
-	lwz	rWORD4,4(rSTR2)
-	cmplw	cr0,rWORD1,rWORD2
-	srw	rC,rWORD4,rSHR
-	slw	rF,rWORD4,rSHL
-	or	rWORD4,rC,rD
-	lwz	rWORD5,8(rSTR1)
-	lwz	rWORD6,8(rSTR2)
-	cmplw	cr1,rWORD3,rWORD4
-	bne	cr0,L(duLcr0)
-	srw	rE,rWORD6,rSHR
-	slw	rH,rWORD6,rSHL
-	or	rWORD6,rE,rF
-	lwzu	rWORD7,12(rSTR1)
-	lwzu	rWORD8,12(rSTR2)
-	cmplw	cr6,rWORD5,rWORD6
-	bne	cr1,L(duLcr1)
-	srw	rG,rWORD8,rSHR
-	slw	rB,rWORD8,rSHL
-	or	rWORD8,rG,rH
-	cmplw	cr5,rWORD7,rWORD8
+#ifdef __LITTLE_ENDIAN__
+	lwbrx	rWORD3, 0, rSTR1
+	lwbrx	rWORD4, 0, rSTR2
+	addi	rSTR1, rSTR1, 4
+	addi	rSTR2, rSTR2, 4
+#else
+	lwz	rWORD3, 4(rSTR1)
+	lwz	rWORD4, 4(rSTR2)
+#endif
+	cmplw	cr7, rWORD1, rWORD2
+	srw	r12, rWORD4, rSHR
+	slw	rWORD4_SHIFT, rWORD4, rSHL
+	or	rWORD4, r12, rWORD2_SHIFT
+#ifdef __LITTLE_ENDIAN__
+	lwbrx	rWORD5, 0, rSTR1
+	lwbrx	rWORD6, 0, rSTR2
+	addi	rSTR1, rSTR1, 4
+	addi	rSTR2, rSTR2, 4
+#else
+	lwz	rWORD5, 8(rSTR1)
+	lwz	rWORD6, 8(rSTR2)
+#endif
+	cmplw	cr1, rWORD3, rWORD4
+	bne	cr7, L(duLcr7)
+	srw	r0, rWORD6, rSHR
+	slw	rWORD6_SHIFT, rWORD6, rSHL
+	or	rWORD6, r0, rWORD4_SHIFT
+#ifdef __LITTLE_ENDIAN__
+	lwbrx	rWORD7, 0, rSTR1
+	lwbrx	rWORD8, 0, rSTR2
+	addi	rSTR1, rSTR1, 4
+	addi	rSTR2, rSTR2, 4
+#else
+	lwzu	rWORD7, 12(rSTR1)
+	lwzu	rWORD8, 12(rSTR2)
+#endif
+	cmplw	cr6, rWORD5, rWORD6
+	bne	cr1, L(duLcr1)
+	srw	r12, rWORD8, rSHR
+	slw	rWORD8_SHIFT, rWORD8, rSHL
+	or	rWORD8, r12, rWORD6_SHIFT
+	cmplw	cr5, rWORD7, rWORD8
 	bdz	L(du24)		/* Adjust CTR as we start with +4 */
 /* This is the primary loop */
 	.align	4
 L(duLoop):
-	lwz	rWORD1,4(rSTR1)
-	lwz	rWORD2,4(rSTR2)
-	cmplw	cr1,rWORD3,rWORD4
-	bne	cr6,L(duLcr6)
-	srw	rA,rWORD2,rSHR
-	slw	rD,rWORD2,rSHL
-	or	rWORD2,rA,rB
+#ifdef __LITTLE_ENDIAN__
+	lwbrx	rWORD1, 0, rSTR1
+	lwbrx	rWORD2, 0, rSTR2
+	addi	rSTR1, rSTR1, 4
+	addi	rSTR2, rSTR2, 4
+#else
+	lwz	rWORD1, 4(rSTR1)
+	lwz	rWORD2, 4(rSTR2)
+#endif
+	cmplw	cr1, rWORD3, rWORD4
+	bne	cr6, L(duLcr6)
+	srw	r0, rWORD2, rSHR
+	slw	rWORD2_SHIFT, rWORD2, rSHL
+	or	rWORD2, r0, rWORD8_SHIFT
 L(duLoop1):
-	lwz	rWORD3,8(rSTR1)
-	lwz	rWORD4,8(rSTR2)
-	cmplw	cr6,rWORD5,rWORD6
-	bne	cr5,L(duLcr5)
-	srw	rC,rWORD4,rSHR
-	slw	rF,rWORD4,rSHL
-	or	rWORD4,rC,rD
+#ifdef __LITTLE_ENDIAN__
+	lwbrx	rWORD3, 0, rSTR1
+	lwbrx	rWORD4, 0, rSTR2
+	addi	rSTR1, rSTR1, 4
+	addi	rSTR2, rSTR2, 4
+#else
+	lwz	rWORD3, 8(rSTR1)
+	lwz	rWORD4, 8(rSTR2)
+#endif
+	cmplw	cr6, rWORD5, rWORD6
+	bne	cr5, L(duLcr5)
+	srw	r12, rWORD4, rSHR
+	slw	rWORD4_SHIFT, rWORD4, rSHL
+	or	rWORD4, r12, rWORD2_SHIFT
 L(duLoop2):
-	lwz	rWORD5,12(rSTR1)
-	lwz	rWORD6,12(rSTR2)
-	cmplw	cr5,rWORD7,rWORD8
-	bne	cr0,L(duLcr0)
-	srw	rE,rWORD6,rSHR
-	slw	rH,rWORD6,rSHL
-	or	rWORD6,rE,rF
+#ifdef __LITTLE_ENDIAN__
+	lwbrx	rWORD5, 0, rSTR1
+	lwbrx	rWORD6, 0, rSTR2
+	addi	rSTR1, rSTR1, 4
+	addi	rSTR2, rSTR2, 4
+#else
+	lwz	rWORD5, 12(rSTR1)
+	lwz	rWORD6, 12(rSTR2)
+#endif
+	cmplw	cr5, rWORD7, rWORD8
+	bne	cr7, L(duLcr7)
+	srw	r0, rWORD6, rSHR
+	slw	rWORD6_SHIFT, rWORD6, rSHL
+	or	rWORD6, r0, rWORD4_SHIFT
 L(duLoop3):
-	lwzu	rWORD7,16(rSTR1)
-	lwzu	rWORD8,16(rSTR2)
-	cmplw	cr0,rWORD1,rWORD2
-	bne	cr1,L(duLcr1)
-	srw	rG,rWORD8,rSHR
-	slw	rB,rWORD8,rSHL
-	or	rWORD8,rG,rH
+#ifdef __LITTLE_ENDIAN__
+	lwbrx	rWORD7, 0, rSTR1
+	lwbrx	rWORD8, 0, rSTR2
+	addi	rSTR1, rSTR1, 4
+	addi	rSTR2, rSTR2, 4
+#else
+	lwzu	rWORD7, 16(rSTR1)
+	lwzu	rWORD8, 16(rSTR2)
+#endif
+	cmplw	cr7, rWORD1, rWORD2
+	bne	cr1, L(duLcr1)
+	srw	r12, rWORD8, rSHR
+	slw	rWORD8_SHIFT, rWORD8, rSHL
+	or	rWORD8, r12, rWORD6_SHIFT
 	bdnz	L(duLoop)
 
 L(duL4):
-	bne	cr1,L(duLcr1)
-	cmplw	cr1,rWORD3,rWORD4
-	bne	cr6,L(duLcr6)
-	cmplw	cr6,rWORD5,rWORD6
-	bne	cr5,L(duLcr5)
-	cmplw	cr5,rWORD7,rWORD8
+#if 0
+/* Huh?  We've already branched on cr1!  */
+	bne	cr1, L(duLcr1)
+#endif
+	cmplw	cr1, rWORD3, rWORD4
+	bne	cr6, L(duLcr6)
+	cmplw	cr6, rWORD5, rWORD6
+	bne	cr5, L(duLcr5)
+	cmplw	cr5, rWORD7, rWORD8
 L(du44):
-	bne	cr0,L(duLcr0)
+	bne	cr7, L(duLcr7)
 L(du34):
-	bne	cr1,L(duLcr1)
+	bne	cr1, L(duLcr1)
 L(du24):
-	bne	cr6,L(duLcr6)
+	bne	cr6, L(duLcr6)
 L(du14):
-	slwi.	rN,rN,3
-	bne	cr5,L(duLcr5)
+	slwi.	rN, rN, 3
+	bne	cr5, L(duLcr5)
 /* At this point we have a remainder of 1 to 3 bytes to compare.  We use
    shift right to eliminate bits beyond the compare length.
+   This allows the use of word subtract to compute the final result.
 
    However it may not be safe to load rWORD2 which may be beyond the
    string length. So we compare the bit length of the remainder to
    the right shift count (rSHR). If the bit count is less than or equal
    we do not need to load rWORD2 (all significant bits are already in
-   rB).  */
-	cmplw	cr7,rN,rSHR
+   rWORD8_SHIFT).  */
+	cmplw	cr7, rN, rSHR
 	beq	L(duZeroReturn)
-	li	rA,0
-	ble	cr7,L(dutrim)
-	lwz	rWORD2,4(rSTR2)
-	srw	rA,rWORD2,rSHR
+	li	r0, 0
+	ble	cr7, L(dutrim)
+#ifdef __LITTLE_ENDIAN__
+	lwbrx	rWORD2, 0, rSTR2
+	addi	rSTR2, rSTR2, 4
+#else
+	lwz	rWORD2, 4(rSTR2)
+#endif
+	srw	r0, rWORD2, rSHR
 	.align	4
 L(dutrim):
-	lwz	rWORD1,4(rSTR1)
-	lwz	r31,48(1)
-	subfic	rN,rN,32	/* Shift count is 32 - (rN * 8).  */
-	or	rWORD2,rA,rB
-	lwz	r30,44(1)
-	lwz	r29,40(r1)
-	srw	rWORD1,rWORD1,rN
-	srw	rWORD2,rWORD2,rN
-	lwz	r28,36(r1)
-	lwz	r27,32(r1)
-	cmplw	rWORD1,rWORD2
-	li	rRTN,0
-	beq	L(dureturn26)
-	li	rRTN,1
-	bgt	L(dureturn26)
-	li	rRTN,-1
+#ifdef __LITTLE_ENDIAN__
+	lwbrx	rWORD1, 0, rSTR1
+#else
+	lwz	rWORD1, 4(rSTR1)
+#endif
+	lwz	rWORD8, 48(r1)
+	subfic	rN, rN, 32	/* Shift count is 32 - (rN * 8).  */
+	or	rWORD2, r0, rWORD8_SHIFT
+	lwz	rWORD7, 44(r1)
+	lwz	rSHL, 40(r1)
+	srw	rWORD1, rWORD1, rN
+	srw	rWORD2, rWORD2, rN
+	lwz	rSHR, 36(r1)
+	lwz	rWORD8_SHIFT, 32(r1)
+	sub	rRTN, rWORD1, rWORD2
 	b	L(dureturn26)
 	.align	4
-L(duLcr0):
-	lwz	r31,48(1)
-	lwz	r30,44(1)
-	li	rRTN,1
-	bgt	cr0,L(dureturn29)
-	lwz	r29,40(r1)
-	lwz	r28,36(r1)
-	li	rRTN,-1
+L(duLcr7):
+	lwz	rWORD8, 48(r1)
+	lwz	rWORD7, 44(r1)
+	li	rRTN, 1
+	bgt	cr7, L(dureturn29)
+	lwz	rSHL, 40(r1)
+	lwz	rSHR, 36(r1)
+	li	rRTN, -1
 	b	L(dureturn27)
 	.align	4
 L(duLcr1):
-	lwz	r31,48(1)
-	lwz	r30,44(1)
-	li	rRTN,1
-	bgt	cr1,L(dureturn29)
-	lwz	r29,40(r1)
-	lwz	r28,36(r1)
-	li	rRTN,-1
+	lwz	rWORD8, 48(r1)
+	lwz	rWORD7, 44(r1)
+	li	rRTN, 1
+	bgt	cr1, L(dureturn29)
+	lwz	rSHL, 40(r1)
+	lwz	rSHR, 36(r1)
+	li	rRTN, -1
 	b	L(dureturn27)
 	.align	4
 L(duLcr6):
-	lwz	r31,48(1)
-	lwz	r30,44(1)
-	li	rRTN,1
-	bgt	cr6,L(dureturn29)
-	lwz	r29,40(r1)
-	lwz	r28,36(r1)
-	li	rRTN,-1
+	lwz	rWORD8, 48(r1)
+	lwz	rWORD7, 44(r1)
+	li	rRTN, 1
+	bgt	cr6, L(dureturn29)
+	lwz	rSHL, 40(r1)
+	lwz	rSHR, 36(r1)
+	li	rRTN, -1
 	b	L(dureturn27)
 	.align	4
 L(duLcr5):
-	lwz	r31,48(1)
-	lwz	r30,44(1)
-	li	rRTN,1
-	bgt	cr5,L(dureturn29)
-	lwz	r29,40(r1)
-	lwz	r28,36(r1)
-	li	rRTN,-1
+	lwz	rWORD8, 48(r1)
+	lwz	rWORD7, 44(r1)
+	li	rRTN, 1
+	bgt	cr5, L(dureturn29)
+	lwz	rSHL, 40(r1)
+	lwz	rSHR, 36(r1)
+	li	rRTN, -1
 	b	L(dureturn27)
 	.align	3
 L(duZeroReturn):
-	li	rRTN,0
+	li	rRTN, 0
 	.align	4
 L(dureturn):
-	lwz	r31,48(1)
-	lwz	r30,44(1)
+	lwz	rWORD8, 48(r1)
+	lwz	rWORD7, 44(r1)
 L(dureturn29):
-	lwz	r29,40(r1)
-	lwz	r28,36(r1)
+	lwz	rSHL, 40(r1)
+	lwz	rSHR, 36(r1)
 L(dureturn27):
-	lwz	r27,32(r1)
+	lwz	rWORD8_SHIFT, 32(r1)
 L(dureturn26):
-	lwz	r26,28(r1)
+	lwz	rWORD2_SHIFT, 28(r1)
 L(dureturn25):
-	lwz	r25,24(r1)
-	lwz	r24,20(r1)
-	lwz	1,0(1)
+	lwz	rWORD4_SHIFT, 24(r1)
+	lwz	rWORD6_SHIFT, 20(r1)
+	addi	r1, r1, 64
+	cfi_adjust_cfa_offset(-64)
 	blr
 END (memcmp)
+
 libc_hidden_builtin_def (memcmp)
-weak_alias (memcmp,bcmp)
+weak_alias (memcmp, bcmp)
diff --git a/sysdeps/powerpc/powerpc64/power4/memcmp.S b/sysdeps/powerpc/powerpc64/power4/memcmp.S
index 69caedc..80d67c9 100644
--- a/sysdeps/powerpc/powerpc64/power4/memcmp.S
+++ b/sysdeps/powerpc/powerpc64/power4/memcmp.S
@@ -1,4 +1,4 @@
-/* Optimized strcmp implementation for PowerPC64.
+/* Optimized memcmp implementation for PowerPC64.
    Copyright (C) 2003-2013 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
@@ -18,13 +18,14 @@
 
 #include <sysdep.h>
 
-/* int [r3] memcmp (const char *s1 [r3], const char *s2 [r4], size_t size [r5])  */
+/* int [r3] memcmp (const char *s1 [r3],
+		    const char *s2 [r4],
+		    size_t size [r5])  */
 
 	.machine power4
 EALIGN (memcmp, 4, 0)
 	CALL_MCOUNT 3
 
-#define rTMP	r0
 #define rRTN	r3
 #define rSTR1	r3	/* first string arg */
 #define rSTR2	r4	/* second string arg */
@@ -35,107 +36,127 @@ EALIGN (memcmp, 4, 0)
 #define rWORD4	r9	/* next word in s2 */
 #define rWORD5	r10	/* next word in s1 */
 #define rWORD6	r11	/* next word in s2 */
-#define rBITDIF	r12	/* bits that differ in s1 & s2 words */
 #define rWORD7	r30	/* next word in s1 */
 #define rWORD8	r31	/* next word in s2 */
 
-	xor	rTMP, rSTR2, rSTR1
+	xor	r0, rSTR2, rSTR1
 	cmpldi	cr6, rN, 0
 	cmpldi	cr1, rN, 12
-	clrldi.	rTMP, rTMP, 61
-	clrldi	rBITDIF, rSTR1, 61
-	cmpldi	cr5, rBITDIF, 0
+	clrldi.	r0, r0, 61
+	clrldi	r12, rSTR1, 61
+	cmpldi	cr5, r12, 0
 	beq-	cr6, L(zeroLength)
-	dcbt	0,rSTR1
-	dcbt	0,rSTR2
+	dcbt	0, rSTR1
+	dcbt	0, rSTR2
 /* If less than 8 bytes or not aligned, use the unaligned
    byte loop.  */
 	blt	cr1, L(bytealigned)
-	std	rWORD8,-8(r1)
-	cfi_offset(rWORD8,-8)
-	std	rWORD7,-16(r1)
-	cfi_offset(rWORD7,-16)
+	std	rWORD8, -8(r1)
+	cfi_offset(rWORD8, -8)
+	std	rWORD7, -16(r1)
+	cfi_offset(rWORD7, -16)
 	bne	L(unaligned)
 /* At this point we know both strings have the same alignment and the
-   compare length is at least 8 bytes.  rBITDIF contains the low order
+   compare length is at least 8 bytes.  r12 contains the low order
    3 bits of rSTR1 and cr5 contains the result of the logical compare
-   of rBITDIF to 0.  If rBITDIF == 0 then we are already double word
-   aligned and can perform the DWaligned loop.
+   of r12 to 0.  If r12 == 0 then we are already double word
+   aligned and can perform the DW aligned loop.
 
    Otherwise we know the two strings have the same alignment (but not
-   yet DW).  So we can force the string addresses to the next lower DW
-   boundary and special case this first DW word using shift left to
+   yet DW).  So we force the string addresses to the next lower DW
+   boundary and special case this first DW using shift left to
    eliminate bits preceding the first byte.  Since we want to join the
-   normal (DWaligned) compare loop, starting at the second double word,
+   normal (DW aligned) compare loop, starting at the second double word,
    we need to adjust the length (rN) and special case the loop
-   versioning for the first DW. This insures that the loop count is
-   correct and the first DW (shifted) is in the expected resister pair.  */
-	.align 4
+   versioning for the first DW. This ensures that the loop count is
+   correct and the first DW (shifted) is in the expected register pair.  */
+	.align	4
 L(samealignment):
 	clrrdi	rSTR1, rSTR1, 3
 	clrrdi	rSTR2, rSTR2, 3
 	beq	cr5, L(DWaligned)
-	add	rN, rN, rBITDIF
-	sldi	r11, rBITDIF, 3
-	srdi	rTMP, rN, 5	/* Divide by 32 */
-	andi.	rBITDIF, rN, 24	/* Get the DW remainder */
+	add	rN, rN, r12
+	sldi	rWORD6, r12, 3
+	srdi	r0, rN, 5	/* Divide by 32 */
+	andi.	r12, rN, 24	/* Get the DW remainder */
+#ifdef __LITTLE_ENDIAN__
+	ldbrx	rWORD1, 0, rSTR1
+	ldbrx	rWORD2, 0, rSTR2
+	addi	rSTR1, rSTR1, 8
+	addi	rSTR2, rSTR2, 8
+#else
 	ld	rWORD1, 0(rSTR1)
 	ld	rWORD2, 0(rSTR2)
-	cmpldi	cr1, rBITDIF, 16
+#endif
+	cmpldi	cr1, r12, 16
 	cmpldi	cr7, rN, 32
 	clrldi	rN, rN, 61
 	beq	L(dPs4)
-	mtctr   rTMP	/* Power4 wants mtctr 1st in dispatch group */
+	mtctr	r0	/* Power4 wants mtctr 1st in dispatch group */
 	bgt	cr1, L(dPs3)
 	beq	cr1, L(dPs2)
 
 /* Remainder is 8 */
-	.align 3
+	.align	3
 L(dsP1):
-	sld	rWORD5, rWORD1, r11
-	sld	rWORD6, rWORD2, r11
+	sld	rWORD5, rWORD1, rWORD6
+	sld	rWORD6, rWORD2, rWORD6
 	cmpld	cr5, rWORD5, rWORD6
 	blt	cr7, L(dP1x)
 /* Do something useful in this cycle since we have to branch anyway.  */
+#ifdef __LITTLE_ENDIAN__
+	ldbrx	rWORD1, 0, rSTR1
+	ldbrx	rWORD2, 0, rSTR2
+	addi	rSTR1, rSTR1, 8
+	addi	rSTR2, rSTR2, 8
+#else
 	ld	rWORD1, 8(rSTR1)
 	ld	rWORD2, 8(rSTR2)
-	cmpld	cr0, rWORD1, rWORD2
+#endif
+	cmpld	cr7, rWORD1, rWORD2
 	b	L(dP1e)
 /* Remainder is 16 */
-	.align 4
+	.align	4
 L(dPs2):
-	sld	rWORD5, rWORD1, r11
-	sld	rWORD6, rWORD2, r11
+	sld	rWORD5, rWORD1, rWORD6
+	sld	rWORD6, rWORD2, rWORD6
 	cmpld	cr6, rWORD5, rWORD6
 	blt	cr7, L(dP2x)
 /* Do something useful in this cycle since we have to branch anyway.  */
+#ifdef __LITTLE_ENDIAN__
+	ldbrx	rWORD7, 0, rSTR1
+	ldbrx	rWORD8, 0, rSTR2
+	addi	rSTR1, rSTR1, 8
+	addi	rSTR2, rSTR2, 8
+#else
 	ld	rWORD7, 8(rSTR1)
 	ld	rWORD8, 8(rSTR2)
+#endif
 	cmpld	cr5, rWORD7, rWORD8
 	b	L(dP2e)
 /* Remainder is 24 */
-	.align 4
+	.align	4
 L(dPs3):
-	sld	rWORD3, rWORD1, r11
-	sld	rWORD4, rWORD2, r11
+	sld	rWORD3, rWORD1, rWORD6
+	sld	rWORD4, rWORD2, rWORD6
 	cmpld	cr1, rWORD3, rWORD4
 	b	L(dP3e)
 /* Count is a multiple of 32, remainder is 0 */
-	.align 4
+	.align	4
 L(dPs4):
-	mtctr   rTMP	/* Power4 wants mtctr 1st in dispatch group */
-	sld	rWORD1, rWORD1, r11
-	sld	rWORD2, rWORD2, r11
-	cmpld	cr0, rWORD1, rWORD2
+	mtctr	r0	/* Power4 wants mtctr 1st in dispatch group */
+	sld	rWORD1, rWORD1, rWORD6
+	sld	rWORD2, rWORD2, rWORD6
+	cmpld	cr7, rWORD1, rWORD2
 	b	L(dP4e)
 
 /* At this point we know both strings are double word aligned and the
    compare length is at least 8 bytes.  */
-	.align 4
+	.align	4
 L(DWaligned):
-	andi.	rBITDIF, rN, 24	/* Get the DW remainder */
-	srdi	rTMP, rN, 5	/* Divide by 32 */
-	cmpldi	cr1, rBITDIF, 16
+	andi.	r12, rN, 24	/* Get the DW remainder */
+	srdi	r0, rN, 5	/* Divide by 32 */
+	cmpldi	cr1, r12, 16
 	cmpldi	cr7, rN, 32
 	clrldi	rN, rN, 61
 	beq	L(dP4)
@@ -143,174 +164,343 @@ L(DWaligned):
 	beq	cr1, L(dP2)
 
 /* Remainder is 8 */
-	.align 4
+	.align	4
 L(dP1):
-	mtctr   rTMP	/* Power4 wants mtctr 1st in dispatch group */
+	mtctr	r0	/* Power4 wants mtctr 1st in dispatch group */
 /* Normally we'd use rWORD7/rWORD8 here, but since we might exit early
    (8-15 byte compare), we want to use only volatile registers.  This
    means we can avoid restoring non-volatile registers since we did not
    change any on the early exit path.  The key here is the non-early
    exit path only cares about the condition code (cr5), not about which
    register pair was used.  */
+#ifdef __LITTLE_ENDIAN__
+	ldbrx	rWORD5, 0, rSTR1
+	ldbrx	rWORD6, 0, rSTR2
+	addi	rSTR1, rSTR1, 8
+	addi	rSTR2, rSTR2, 8
+#else
 	ld	rWORD5, 0(rSTR1)
 	ld	rWORD6, 0(rSTR2)
+#endif
 	cmpld	cr5, rWORD5, rWORD6
 	blt	cr7, L(dP1x)
+#ifdef __LITTLE_ENDIAN__
+	ldbrx	rWORD1, 0, rSTR1
+	ldbrx	rWORD2, 0, rSTR2
+	addi	rSTR1, rSTR1, 8
+	addi	rSTR2, rSTR2, 8
+#else
 	ld	rWORD1, 8(rSTR1)
 	ld	rWORD2, 8(rSTR2)
-	cmpld	cr0, rWORD1, rWORD2
+#endif
+	cmpld	cr7, rWORD1, rWORD2
 L(dP1e):
+#ifdef __LITTLE_ENDIAN__
+	ldbrx	rWORD3, 0, rSTR1
+	ldbrx	rWORD4, 0, rSTR2
+	addi	rSTR1, rSTR1, 8
+	addi	rSTR2, rSTR2, 8
+#else
 	ld	rWORD3, 16(rSTR1)
 	ld	rWORD4, 16(rSTR2)
+#endif
 	cmpld	cr1, rWORD3, rWORD4
+#ifdef __LITTLE_ENDIAN__
+	ldbrx	rWORD5, 0, rSTR1
+	ldbrx	rWORD6, 0, rSTR2
+	addi	rSTR1, rSTR1, 8
+	addi	rSTR2, rSTR2, 8
+#else
 	ld	rWORD5, 24(rSTR1)
 	ld	rWORD6, 24(rSTR2)
+#endif
 	cmpld	cr6, rWORD5, rWORD6
-	bne	cr5, L(dLcr5)
-	bne	cr0, L(dLcr0)
+	bne	cr5, L(dLcr5x)
+	bne	cr7, L(dLcr7x)
 
+#ifdef __LITTLE_ENDIAN__
+	ldbrx	rWORD7, 0, rSTR1
+	ldbrx	rWORD8, 0, rSTR2
+	addi	rSTR1, rSTR1, 8
+	addi	rSTR2, rSTR2, 8
+#else
 	ldu	rWORD7, 32(rSTR1)
 	ldu	rWORD8, 32(rSTR2)
+#endif
 	bne	cr1, L(dLcr1)
 	cmpld	cr5, rWORD7, rWORD8
 	bdnz	L(dLoop)
 	bne	cr6, L(dLcr6)
-	ld	rWORD8,-8(r1)
-	ld	rWORD7,-16(r1)
-	.align 3
+	ld	rWORD8, -8(r1)
+	ld	rWORD7, -16(r1)
+	.align	3
 L(dP1x):
 	sldi.	r12, rN, 3
-	bne	cr5, L(dLcr5)
+	bne	cr5, L(dLcr5x)
 	subfic	rN, r12, 64	/* Shift count is 64 - (rN * 8).  */
 	bne	L(d00)
 	li	rRTN, 0
 	blr
 
 /* Remainder is 16 */
-	.align 4
+	.align	4
 L(dP2):
-	mtctr   rTMP	/* Power4 wants mtctr 1st in dispatch group */
+	mtctr	r0	/* Power4 wants mtctr 1st in dispatch group */
+#ifdef __LITTLE_ENDIAN__
+	ldbrx	rWORD5, 0, rSTR1
+	ldbrx	rWORD6, 0, rSTR2
+	addi	rSTR1, rSTR1, 8
+	addi	rSTR2, rSTR2, 8
+#else
 	ld	rWORD5, 0(rSTR1)
 	ld	rWORD6, 0(rSTR2)
+#endif
 	cmpld	cr6, rWORD5, rWORD6
 	blt	cr7, L(dP2x)
+#ifdef __LITTLE_ENDIAN__
+	ldbrx	rWORD7, 0, rSTR1
+	ldbrx	rWORD8, 0, rSTR2
+	addi	rSTR1, rSTR1, 8
+	addi	rSTR2, rSTR2, 8
+#else
 	ld	rWORD7, 8(rSTR1)
 	ld	rWORD8, 8(rSTR2)
+#endif
 	cmpld	cr5, rWORD7, rWORD8
 L(dP2e):
+#ifdef __LITTLE_ENDIAN__
+	ldbrx	rWORD1, 0, rSTR1
+	ldbrx	rWORD2, 0, rSTR2
+	addi	rSTR1, rSTR1, 8
+	addi	rSTR2, rSTR2, 8
+#else
 	ld	rWORD1, 16(rSTR1)
 	ld	rWORD2, 16(rSTR2)
-	cmpld	cr0, rWORD1, rWORD2
+#endif
+	cmpld	cr7, rWORD1, rWORD2
+#ifdef __LITTLE_ENDIAN__
+	ldbrx	rWORD3, 0, rSTR1
+	ldbrx	rWORD4, 0, rSTR2
+	addi	rSTR1, rSTR1, 8
+	addi	rSTR2, rSTR2, 8
+#else
 	ld	rWORD3, 24(rSTR1)
 	ld	rWORD4, 24(rSTR2)
+#endif
 	cmpld	cr1, rWORD3, rWORD4
+#ifndef __LITTLE_ENDIAN__
 	addi	rSTR1, rSTR1, 8
 	addi	rSTR2, rSTR2, 8
+#endif
 	bne	cr6, L(dLcr6)
 	bne	cr5, L(dLcr5)
 	b	L(dLoop2)
 /* Again we are on a early exit path (16-23 byte compare), we want to
    only use volatile registers and avoid restoring non-volatile
    registers.  */
-	.align 4
+	.align	4
 L(dP2x):
+#ifdef __LITTLE_ENDIAN__
+	ldbrx	rWORD3, 0, rSTR1
+	ldbrx	rWORD4, 0, rSTR2
+	addi	rSTR1, rSTR1, 8
+	addi	rSTR2, rSTR2, 8
+#else
 	ld	rWORD3, 8(rSTR1)
 	ld	rWORD4, 8(rSTR2)
-	cmpld	cr5, rWORD3, rWORD4
+#endif
+	cmpld	cr1, rWORD3, rWORD4
 	sldi.	r12, rN, 3
-	bne	cr6, L(dLcr6)
+	bne	cr6, L(dLcr6x)
+#ifndef __LITTLE_ENDIAN__
 	addi	rSTR1, rSTR1, 8
 	addi	rSTR2, rSTR2, 8
-	bne	cr5, L(dLcr5)
+#endif
+	bne	cr1, L(dLcr1x)
 	subfic	rN, r12, 64	/* Shift count is 64 - (rN * 8).  */
 	bne	L(d00)
 	li	rRTN, 0
 	blr
 
 /* Remainder is 24 */
-	.align 4
+	.align	4
 L(dP3):
-	mtctr   rTMP	/* Power4 wants mtctr 1st in dispatch group */
+	mtctr	r0	/* Power4 wants mtctr 1st in dispatch group */
+#ifdef __LITTLE_ENDIAN__
+	ldbrx	rWORD3, 0, rSTR1
+	ldbrx	rWORD4, 0, rSTR2
+	addi	rSTR1, rSTR1, 8
+	addi	rSTR2, rSTR2, 8
+#else
 	ld	rWORD3, 0(rSTR1)
 	ld	rWORD4, 0(rSTR2)
+#endif
 	cmpld	cr1, rWORD3, rWORD4
 L(dP3e):
+#ifdef __LITTLE_ENDIAN__
+	ldbrx	rWORD5, 0, rSTR1
+	ldbrx	rWORD6, 0, rSTR2
+	addi	rSTR1, rSTR1, 8
+	addi	rSTR2, rSTR2, 8
+#else
 	ld	rWORD5, 8(rSTR1)
 	ld	rWORD6, 8(rSTR2)
+#endif
 	cmpld	cr6, rWORD5, rWORD6
 	blt	cr7, L(dP3x)
+#ifdef __LITTLE_ENDIAN__
+	ldbrx	rWORD7, 0, rSTR1
+	ldbrx	rWORD8, 0, rSTR2
+	addi	rSTR1, rSTR1, 8
+	addi	rSTR2, rSTR2, 8
+#else
 	ld	rWORD7, 16(rSTR1)
 	ld	rWORD8, 16(rSTR2)
+#endif
 	cmpld	cr5, rWORD7, rWORD8
+#ifdef __LITTLE_ENDIAN__
+	ldbrx	rWORD1, 0, rSTR1
+	ldbrx	rWORD2, 0, rSTR2
+	addi	rSTR1, rSTR1, 8
+	addi	rSTR2, rSTR2, 8
+#else
 	ld	rWORD1, 24(rSTR1)
 	ld	rWORD2, 24(rSTR2)
-	cmpld	cr0, rWORD1, rWORD2
+#endif
+	cmpld	cr7, rWORD1, rWORD2
+#ifndef __LITTLE_ENDIAN__
 	addi	rSTR1, rSTR1, 16
 	addi	rSTR2, rSTR2, 16
+#endif
 	bne	cr1, L(dLcr1)
 	bne	cr6, L(dLcr6)
 	b	L(dLoop1)
 /* Again we are on a early exit path (24-31 byte compare), we want to
    only use volatile registers and avoid restoring non-volatile
    registers.  */
-	.align 4
+	.align	4
 L(dP3x):
+#ifdef __LITTLE_ENDIAN__
+	ldbrx	rWORD1, 0, rSTR1
+	ldbrx	rWORD2, 0, rSTR2
+	addi	rSTR1, rSTR1, 8
+	addi	rSTR2, rSTR2, 8
+#else
 	ld	rWORD1, 16(rSTR1)
 	ld	rWORD2, 16(rSTR2)
-	cmpld	cr5, rWORD1, rWORD2
+#endif
+	cmpld	cr7, rWORD1, rWORD2
 	sldi.	r12, rN, 3
-	bne	cr1, L(dLcr1)
+	bne	cr1, L(dLcr1x)
+#ifndef __LITTLE_ENDIAN__
 	addi	rSTR1, rSTR1, 16
 	addi	rSTR2, rSTR2, 16
-	bne	cr6, L(dLcr6)
+#endif
+	bne	cr6, L(dLcr6x)
 	subfic	rN, r12, 64	/* Shift count is 64 - (rN * 8).  */
-	bne	cr5, L(dLcr5)
+	bne	cr7, L(dLcr7x)
 	bne	L(d00)
 	li	rRTN, 0
 	blr
 
 /* Count is a multiple of 32, remainder is 0 */
-	.align 4
+	.align	4
 L(dP4):
-	mtctr   rTMP	/* Power4 wants mtctr 1st in dispatch group */
+	mtctr	r0	/* Power4 wants mtctr 1st in dispatch group */
+#ifdef __LITTLE_ENDIAN__
+	ldbrx	rWORD1, 0, rSTR1
+	ldbrx	rWORD2, 0, rSTR2
+	addi	rSTR1, rSTR1, 8
+	addi	rSTR2, rSTR2, 8
+#else
 	ld	rWORD1, 0(rSTR1)
 	ld	rWORD2, 0(rSTR2)
-	cmpld	cr0, rWORD1, rWORD2
+#endif
+	cmpld	cr7, rWORD1, rWORD2
 L(dP4e):
+#ifdef __LITTLE_ENDIAN__
+	ldbrx	rWORD3, 0, rSTR1
+	ldbrx	rWORD4, 0, rSTR2
+	addi	rSTR1, rSTR1, 8
+	addi	rSTR2, rSTR2, 8
+#else
 	ld	rWORD3, 8(rSTR1)
 	ld	rWORD4, 8(rSTR2)
+#endif
 	cmpld	cr1, rWORD3, rWORD4
+#ifdef __LITTLE_ENDIAN__
+	ldbrx	rWORD5, 0, rSTR1
+	ldbrx	rWORD6, 0, rSTR2
+	addi	rSTR1, rSTR1, 8
+	addi	rSTR2, rSTR2, 8
+#else
 	ld	rWORD5, 16(rSTR1)
 	ld	rWORD6, 16(rSTR2)
+#endif
 	cmpld	cr6, rWORD5, rWORD6
+#ifdef __LITTLE_ENDIAN__
+	ldbrx	rWORD7, 0, rSTR1
+	ldbrx	rWORD8, 0, rSTR2
+	addi	rSTR1, rSTR1, 8
+	addi	rSTR2, rSTR2, 8
+#else
 	ldu	rWORD7, 24(rSTR1)
 	ldu	rWORD8, 24(rSTR2)
+#endif
 	cmpld	cr5, rWORD7, rWORD8
-	bne	cr0, L(dLcr0)
+	bne	cr7, L(dLcr7)
 	bne	cr1, L(dLcr1)
 	bdz-	L(d24)		/* Adjust CTR as we start with +4 */
 /* This is the primary loop */
-	.align 4
+	.align	4
 L(dLoop):
+#ifdef __LITTLE_ENDIAN__
+	ldbrx	rWORD1, 0, rSTR1
+	ldbrx	rWORD2, 0, rSTR2
+	addi	rSTR1, rSTR1, 8
+	addi	rSTR2, rSTR2, 8
+#else
 	ld	rWORD1, 8(rSTR1)
 	ld	rWORD2, 8(rSTR2)
+#endif
 	cmpld	cr1, rWORD3, rWORD4
 	bne	cr6, L(dLcr6)
 L(dLoop1):
+#ifdef __LITTLE_ENDIAN__
+	ldbrx	rWORD3, 0, rSTR1
+	ldbrx	rWORD4, 0, rSTR2
+	addi	rSTR1, rSTR1, 8
+	addi	rSTR2, rSTR2, 8
+#else
 	ld	rWORD3, 16(rSTR1)
 	ld	rWORD4, 16(rSTR2)
+#endif
 	cmpld	cr6, rWORD5, rWORD6
 	bne	cr5, L(dLcr5)
 L(dLoop2):
+#ifdef __LITTLE_ENDIAN__
+	ldbrx	rWORD5, 0, rSTR1
+	ldbrx	rWORD6, 0, rSTR2
+	addi	rSTR1, rSTR1, 8
+	addi	rSTR2, rSTR2, 8
+#else
 	ld	rWORD5, 24(rSTR1)
 	ld	rWORD6, 24(rSTR2)
+#endif
 	cmpld	cr5, rWORD7, rWORD8
-	bne	cr0, L(dLcr0)
+	bne	cr7, L(dLcr7)
 L(dLoop3):
+#ifdef __LITTLE_ENDIAN__
+	ldbrx	rWORD7, 0, rSTR1
+	ldbrx	rWORD8, 0, rSTR2
+	addi	rSTR1, rSTR1, 8
+	addi	rSTR2, rSTR2, 8
+#else
 	ldu	rWORD7, 32(rSTR1)
 	ldu	rWORD8, 32(rSTR2)
+#endif
 	bne-	cr1, L(dLcr1)
-	cmpld	cr0, rWORD1, rWORD2
+	cmpld	cr7, rWORD1, rWORD2
 	bdnz+	L(dLoop)
 
 L(dL4):
@@ -320,7 +510,7 @@ L(dL4):
 	bne	cr5, L(dLcr5)
 	cmpld	cr5, rWORD7, rWORD8
 L(d44):
-	bne	cr0, L(dLcr0)
+	bne	cr7, L(dLcr7)
 L(d34):
 	bne	cr1, L(dLcr1)
 L(d24):
@@ -329,60 +519,74 @@ L(d14):
 	sldi.	r12, rN, 3
 	bne	cr5, L(dLcr5)
 L(d04):
-	ld	rWORD8,-8(r1)
-	ld	rWORD7,-16(r1)
+	ld	rWORD8, -8(r1)
+	ld	rWORD7, -16(r1)
 	subfic	rN, r12, 64	/* Shift count is 64 - (rN * 8).  */
 	beq	L(zeroLength)
 /* At this point we have a remainder of 1 to 7 bytes to compare.  Since
    we are aligned it is safe to load the whole double word, and use
    shift right double to eliminate bits beyond the compare length.  */
 L(d00):
+#ifdef __LITTLE_ENDIAN__
+	ldbrx	rWORD1, 0, rSTR1
+	ldbrx	rWORD2, 0, rSTR2
+	addi	rSTR1, rSTR1, 8
+	addi	rSTR2, rSTR2, 8
+#else
 	ld	rWORD1, 8(rSTR1)
 	ld	rWORD2, 8(rSTR2)
+#endif
 	srd	rWORD1, rWORD1, rN
 	srd	rWORD2, rWORD2, rN
-	cmpld	cr5, rWORD1, rWORD2
- 	bne	cr5, L(dLcr5x)
+	cmpld	cr7, rWORD1, rWORD2
+	bne	cr7, L(dLcr7x)
 	li	rRTN, 0
 	blr
-	.align 4
-L(dLcr0):
-	ld	rWORD8,-8(r1)
-	ld	rWORD7,-16(r1)
+
+	.align	4
+L(dLcr7):
+	ld	rWORD8, -8(r1)
+	ld	rWORD7, -16(r1)
+L(dLcr7x):
 	li	rRTN, 1
-	bgtlr	cr0
+	bgtlr	cr7
 	li	rRTN, -1
 	blr
-	.align 4
+	.align	4
 L(dLcr1):
-	ld	rWORD8,-8(r1)
-	ld	rWORD7,-16(r1)
+	ld	rWORD8, -8(r1)
+	ld	rWORD7, -16(r1)
+L(dLcr1x):
 	li	rRTN, 1
 	bgtlr	cr1
 	li	rRTN, -1
 	blr
-	.align 4
+	.align	4
 L(dLcr6):
-	ld	rWORD8,-8(r1)
-	ld	rWORD7,-16(r1)
+	ld	rWORD8, -8(r1)
+	ld	rWORD7, -16(r1)
+L(dLcr6x):
 	li	rRTN, 1
 	bgtlr	cr6
 	li	rRTN, -1
 	blr
-	.align 4
+	.align	4
 L(dLcr5):
-	ld	rWORD8,-8(r1)
-	ld	rWORD7,-16(r1)
+	ld	rWORD8, -8(r1)
+	ld	rWORD7, -16(r1)
 L(dLcr5x):
 	li	rRTN, 1
 	bgtlr	cr5
 	li	rRTN, -1
 	blr
 
-	.align 4
+	.align	4
 L(bytealigned):
-	mtctr   rN	/* Power4 wants mtctr 1st in dispatch group */
+	mtctr	rN	/* Power4 wants mtctr 1st in dispatch group */
+#if 0
+/* Huh?  We've already branched on cr6!  */
 	beq-	cr6, L(zeroLength)
+#endif
 
 /* We need to prime this loop.  This loop is swing modulo scheduled
    to avoid pipe delays.  The dependent instruction latencies (load to
@@ -397,7 +601,7 @@ L(bytealigned):
 	lbz	rWORD1, 0(rSTR1)
 	lbz	rWORD2, 0(rSTR2)
 	bdz-	L(b11)
-	cmpld	cr0, rWORD1, rWORD2
+	cmpld	cr7, rWORD1, rWORD2
 	lbz	rWORD3, 1(rSTR1)
 	lbz	rWORD4, 1(rSTR2)
 	bdz-	L(b12)
@@ -405,11 +609,11 @@ L(bytealigned):
 	lbzu	rWORD5, 2(rSTR1)
 	lbzu	rWORD6, 2(rSTR2)
 	bdz-	L(b13)
-	.align 4
+	.align	4
 L(bLoop):
 	lbzu	rWORD1, 1(rSTR1)
 	lbzu	rWORD2, 1(rSTR2)
-	bne-	cr0, L(bLcr0)
+	bne-	cr7, L(bLcr7)
 
 	cmpld	cr6, rWORD5, rWORD6
 	bdz-	L(b3i)
@@ -418,7 +622,7 @@ L(bLoop):
 	lbzu	rWORD4, 1(rSTR2)
 	bne-	cr1, L(bLcr1)
 
-	cmpld	cr0, rWORD1, rWORD2
+	cmpld	cr7, rWORD1, rWORD2
 	bdz-	L(b2i)
 
 	lbzu	rWORD5, 1(rSTR1)
@@ -435,23 +639,23 @@ L(bLoop):
    tested.  In this case we must complete the pending operations
    before returning.  */
 L(b1i):
-	bne-	cr0, L(bLcr0)
+	bne-	cr7, L(bLcr7)
 	bne-	cr1, L(bLcr1)
 	b	L(bx56)
-	.align 4
+	.align	4
 L(b2i):
 	bne-	cr6, L(bLcr6)
-	bne-	cr0, L(bLcr0)
+	bne-	cr7, L(bLcr7)
 	b	L(bx34)
-	.align 4
+	.align	4
 L(b3i):
 	bne-	cr1, L(bLcr1)
 	bne-	cr6, L(bLcr6)
 	b	L(bx12)
-	.align 4
-L(bLcr0):
+	.align	4
+L(bLcr7):
 	li	rRTN, 1
-	bgtlr	cr0
+	bgtlr	cr7
 	li	rRTN, -1
 	blr
 L(bLcr1):
@@ -466,14 +670,14 @@ L(bLcr6):
 	blr
 
 L(b13):
-	bne-	cr0, L(bx12)
+	bne-	cr7, L(bx12)
 	bne-	cr1, L(bx34)
 L(bx56):
 	sub	rRTN, rWORD5, rWORD6
 	blr
 	nop
 L(b12):
-	bne-	cr0, L(bx12)
+	bne-	cr7, L(bx12)
 L(bx34):
 	sub	rRTN, rWORD3, rWORD4
 	blr
@@ -481,101 +685,106 @@ L(b11):
 L(bx12):
 	sub	rRTN, rWORD1, rWORD2
 	blr
-	.align 4
-L(zeroLengthReturn):
-	ld	rWORD8,-8(r1)
-	ld	rWORD7,-16(r1)
+	.align	4
 L(zeroLength):
 	li	rRTN, 0
 	blr
 
-	.align 4
+	.align	4
 /* At this point we know the strings have different alignment and the
-   compare length is at least 8 bytes.  rBITDIF contains the low order
+   compare length is at least 8 bytes.  r12 contains the low order
    3 bits of rSTR1 and cr5 contains the result of the logical compare
-   of rBITDIF to 0.  If rBITDIF == 0 then rStr1 is double word
+   of r12 to 0.  If r12 == 0 then rStr1 is double word
    aligned and can perform the DWunaligned loop.
 
    Otherwise we know that rSTR1 is not already DW aligned yet.
    So we can force the string addresses to the next lower DW
-   boundary and special case this first DW word using shift left to
+   boundary and special case this first DW using shift left to
    eliminate bits preceding the first byte.  Since we want to join the
    normal (DWaligned) compare loop, starting at the second double word,
    we need to adjust the length (rN) and special case the loop
-   versioning for the first DW. This insures that the loop count is
+   versioning for the first DW. This ensures that the loop count is
    correct and the first DW (shifted) is in the expected resister pair.  */
-#define rSHL	r29	/* Unaligned shift left count.  */
-#define rSHR	r28	/* Unaligned shift right count.  */
-#define rB		r27	/* Left rotation temp for rWORD2.  */
-#define rD		r26	/* Left rotation temp for rWORD4.  */
-#define rF		r25	/* Left rotation temp for rWORD6.  */
-#define rH		r24	/* Left rotation temp for rWORD8.  */
-#define rA		r0	/* Right rotation temp for rWORD2.  */
-#define rC		r12	/* Right rotation temp for rWORD4.  */
-#define rE		r0	/* Right rotation temp for rWORD6.  */
-#define rG		r12	/* Right rotation temp for rWORD8.  */
+#define rSHL		r29	/* Unaligned shift left count.  */
+#define rSHR		r28	/* Unaligned shift right count.  */
+#define rWORD8_SHIFT	r27	/* Left rotation temp for rWORD2.  */
+#define rWORD2_SHIFT	r26	/* Left rotation temp for rWORD4.  */
+#define rWORD4_SHIFT	r25	/* Left rotation temp for rWORD6.  */
+#define rWORD6_SHIFT	r24	/* Left rotation temp for rWORD8.  */
 L(unaligned):
-	std	r29,-24(r1)
-	cfi_offset(r29,-24)
+	std	rSHL, -24(r1)
+	cfi_offset(rSHL, -24)
 	clrldi	rSHL, rSTR2, 61
 	beq-	cr6, L(duzeroLength)
-	std	r28,-32(r1)
-	cfi_offset(r28,-32)
+	std	rSHR, -32(r1)
+	cfi_offset(rSHR, -32)
 	beq	cr5, L(DWunaligned)
-	std	r27,-40(r1)
-	cfi_offset(r27,-40)
-/* Adjust the logical start of rSTR2 ro compensate for the extra bits
+	std	rWORD8_SHIFT, -40(r1)
+	cfi_offset(rWORD8_SHIFT, -40)
+/* Adjust the logical start of rSTR2 to compensate for the extra bits
    in the 1st rSTR1 DW.  */
-	sub	r27, rSTR2, rBITDIF
+	sub	rWORD8_SHIFT, rSTR2, r12
 /* But do not attempt to address the DW before that DW that contains
    the actual start of rSTR2.  */
 	clrrdi	rSTR2, rSTR2, 3
-	std	r26,-48(r1)
-	cfi_offset(r26,-48)
-/* Compute the left/right shift counts for the unalign rSTR2,
+	std	rWORD2_SHIFT, -48(r1)
+	cfi_offset(rWORD2_SHIFT, -48)
+/* Compute the left/right shift counts for the unaligned rSTR2,
    compensating for the logical (DW aligned) start of rSTR1.  */
-	clrldi	rSHL, r27, 61
+	clrldi	rSHL, rWORD8_SHIFT, 61
 	clrrdi	rSTR1, rSTR1, 3
-	std	r25,-56(r1)
-	cfi_offset(r25,-56)
+	std	rWORD4_SHIFT, -56(r1)
+	cfi_offset(rWORD4_SHIFT, -56)
 	sldi	rSHL, rSHL, 3
-	cmpld	cr5, r27, rSTR2
-	add	rN, rN, rBITDIF
-	sldi	r11, rBITDIF, 3
-	std	r24,-64(r1)
-	cfi_offset(r24,-64)
+	cmpld	cr5, rWORD8_SHIFT, rSTR2
+	add	rN, rN, r12
+	sldi	rWORD6, r12, 3
+	std	rWORD6_SHIFT, -64(r1)
+	cfi_offset(rWORD6_SHIFT, -64)
 	subfic	rSHR, rSHL, 64
-	srdi	rTMP, rN, 5	/* Divide by 32 */
-	andi.	rBITDIF, rN, 24	/* Get the DW remainder */
+	srdi	r0, rN, 5	/* Divide by 32 */
+	andi.	r12, rN, 24	/* Get the DW remainder */
 /* We normally need to load 2 DWs to start the unaligned rSTR2, but in
    this special case those bits may be discarded anyway.  Also we
    must avoid loading a DW where none of the bits are part of rSTR2 as
    this may cross a page boundary and cause a page fault.  */
 	li	rWORD8, 0
 	blt	cr5, L(dus0)
+#ifdef __LITTLE_ENDIAN__
+	ldbrx	rWORD8, 0, rSTR2
+	addi	rSTR2, rSTR2, 8
+#else
 	ld	rWORD8, 0(rSTR2)
-	la	rSTR2, 8(rSTR2)
+	addi	rSTR2, rSTR2, 8
+#endif
 	sld	rWORD8, rWORD8, rSHL
 
 L(dus0):
+#ifdef __LITTLE_ENDIAN__
+	ldbrx	rWORD1, 0, rSTR1
+	ldbrx	rWORD2, 0, rSTR2
+	addi	rSTR1, rSTR1, 8
+	addi	rSTR2, rSTR2, 8
+#else
 	ld	rWORD1, 0(rSTR1)
 	ld	rWORD2, 0(rSTR2)
-	cmpldi	cr1, rBITDIF, 16
+#endif
+	cmpldi	cr1, r12, 16
 	cmpldi	cr7, rN, 32
-	srd	rG, rWORD2, rSHR
+	srd	r12, rWORD2, rSHR
 	clrldi	rN, rN, 61
 	beq	L(duPs4)
-	mtctr   rTMP	/* Power4 wants mtctr 1st in dispatch group */
-	or	rWORD8, rG, rWORD8
+	mtctr	r0	/* Power4 wants mtctr 1st in dispatch group */
+	or	rWORD8, r12, rWORD8
 	bgt	cr1, L(duPs3)
 	beq	cr1, L(duPs2)
 
 /* Remainder is 8 */
-	.align 4
+	.align	4
 L(dusP1):
-	sld	rB, rWORD2, rSHL
-	sld	rWORD7, rWORD1, r11
-	sld	rWORD8, rWORD8, r11
+	sld	rWORD8_SHIFT, rWORD2, rSHL
+	sld	rWORD7, rWORD1, rWORD6
+	sld	rWORD8, rWORD8, rWORD6
 	bge	cr7, L(duP1e)
 /* At this point we exit early with the first double word compare
    complete and remainder of 0 to 7 bytes.  See L(du14) for details on
@@ -585,95 +794,133 @@ L(dusP1):
 	bne	cr5, L(duLcr5)
 	cmpld	cr7, rN, rSHR
 	beq	L(duZeroReturn)
-	li	rA, 0
+	li	r0, 0
 	ble	cr7, L(dutrim)
+#ifdef __LITTLE_ENDIAN__
+	ldbrx	rWORD2, 0, rSTR2
+	addi	rSTR2, rSTR2, 8
+#else
 	ld	rWORD2, 8(rSTR2)
-	srd	rA, rWORD2, rSHR
+#endif
+	srd	r0, rWORD2, rSHR
 	b	L(dutrim)
 /* Remainder is 16 */
-	.align 4
+	.align	4
 L(duPs2):
-	sld	rH, rWORD2, rSHL
-	sld	rWORD5, rWORD1, r11
-	sld	rWORD6, rWORD8, r11
+	sld	rWORD6_SHIFT, rWORD2, rSHL
+	sld	rWORD5, rWORD1, rWORD6
+	sld	rWORD6, rWORD8, rWORD6
 	b	L(duP2e)
 /* Remainder is 24 */
-	.align 4
+	.align	4
 L(duPs3):
-	sld	rF, rWORD2, rSHL
-	sld	rWORD3, rWORD1, r11
-	sld	rWORD4, rWORD8, r11
+	sld	rWORD4_SHIFT, rWORD2, rSHL
+	sld	rWORD3, rWORD1, rWORD6
+	sld	rWORD4, rWORD8, rWORD6
 	b	L(duP3e)
 /* Count is a multiple of 32, remainder is 0 */
-	.align 4
+	.align	4
 L(duPs4):
-	mtctr   rTMP	/* Power4 wants mtctr 1st in dispatch group */
-	or	rWORD8, rG, rWORD8
-	sld	rD, rWORD2, rSHL
-	sld	rWORD1, rWORD1, r11
-	sld	rWORD2, rWORD8, r11
+	mtctr	r0	/* Power4 wants mtctr 1st in dispatch group */
+	or	rWORD8, r12, rWORD8
+	sld	rWORD2_SHIFT, rWORD2, rSHL
+	sld	rWORD1, rWORD1, rWORD6
+	sld	rWORD2, rWORD8, rWORD6
 	b	L(duP4e)
 
 /* At this point we know rSTR1 is double word aligned and the
    compare length is at least 8 bytes.  */
-	.align 4
+	.align	4
 L(DWunaligned):
-	std	r27,-40(r1)
-	cfi_offset(r27,-40)
+	std	rWORD8_SHIFT, -40(r1)
+	cfi_offset(rWORD8_SHIFT, -40)
 	clrrdi	rSTR2, rSTR2, 3
-	std	r26,-48(r1)
-	cfi_offset(r26,-48)
-	srdi	rTMP, rN, 5	/* Divide by 32 */
-	std	r25,-56(r1)
-	cfi_offset(r25,-56)
-	andi.	rBITDIF, rN, 24	/* Get the DW remainder */
-	std	r24,-64(r1)
-	cfi_offset(r24,-64)
+	std	rWORD2_SHIFT, -48(r1)
+	cfi_offset(rWORD2_SHIFT, -48)
+	srdi	r0, rN, 5	/* Divide by 32 */
+	std	rWORD4_SHIFT, -56(r1)
+	cfi_offset(rWORD4_SHIFT, -56)
+	andi.	r12, rN, 24	/* Get the DW remainder */
+	std	rWORD6_SHIFT, -64(r1)
+	cfi_offset(rWORD6_SHIFT, -64)
 	sldi	rSHL, rSHL, 3
+#ifdef __LITTLE_ENDIAN__
+	ldbrx	rWORD6, 0, rSTR2
+	addi	rSTR2, rSTR2, 8
+	ldbrx	rWORD8, 0, rSTR2
+	addi	rSTR2, rSTR2, 8
+#else
 	ld	rWORD6, 0(rSTR2)
 	ldu	rWORD8, 8(rSTR2)
-	cmpldi	cr1, rBITDIF, 16
+#endif
+	cmpldi	cr1, r12, 16
 	cmpldi	cr7, rN, 32
 	clrldi	rN, rN, 61
 	subfic	rSHR, rSHL, 64
-	sld	rH, rWORD6, rSHL
+	sld	rWORD6_SHIFT, rWORD6, rSHL
 	beq	L(duP4)
-	mtctr   rTMP	/* Power4 wants mtctr 1st in dispatch group */
+	mtctr	r0	/* Power4 wants mtctr 1st in dispatch group */
 	bgt	cr1, L(duP3)
 	beq	cr1, L(duP2)
 
 /* Remainder is 8 */
-	.align 4
+	.align	4
 L(duP1):
-	srd	rG, rWORD8, rSHR
+	srd	r12, rWORD8, rSHR
+#ifdef __LITTLE_ENDIAN__
+	ldbrx	rWORD7, 0, rSTR1
+	addi	rSTR1, rSTR1, 8
+#else
 	ld	rWORD7, 0(rSTR1)
-	sld	rB, rWORD8, rSHL
-	or	rWORD8, rG, rH
+#endif
+	sld	rWORD8_SHIFT, rWORD8, rSHL
+	or	rWORD8, r12, rWORD6_SHIFT
 	blt	cr7, L(duP1x)
 L(duP1e):
+#ifdef __LITTLE_ENDIAN__
+	ldbrx	rWORD1, 0, rSTR1
+	ldbrx	rWORD2, 0, rSTR2
+	addi	rSTR1, rSTR1, 8
+	addi	rSTR2, rSTR2, 8
+#else
 	ld	rWORD1, 8(rSTR1)
 	ld	rWORD2, 8(rSTR2)
+#endif
 	cmpld	cr5, rWORD7, rWORD8
-	srd	rA, rWORD2, rSHR
-	sld	rD, rWORD2, rSHL
-	or	rWORD2, rA, rB
+	srd	r0, rWORD2, rSHR
+	sld	rWORD2_SHIFT, rWORD2, rSHL
+	or	rWORD2, r0, rWORD8_SHIFT
+#ifdef __LITTLE_ENDIAN__
+	ldbrx	rWORD3, 0, rSTR1
+	ldbrx	rWORD4, 0, rSTR2
+	addi	rSTR1, rSTR1, 8
+	addi	rSTR2, rSTR2, 8
+#else
 	ld	rWORD3, 16(rSTR1)
 	ld	rWORD4, 16(rSTR2)
-	cmpld	cr0, rWORD1, rWORD2
-	srd	rC, rWORD4, rSHR
-	sld	rF, rWORD4, rSHL
+#endif
+	cmpld	cr7, rWORD1, rWORD2
+	srd	r12, rWORD4, rSHR
+	sld	rWORD4_SHIFT, rWORD4, rSHL
 	bne	cr5, L(duLcr5)
-	or	rWORD4, rC, rD
+	or	rWORD4, r12, rWORD2_SHIFT
+#ifdef __LITTLE_ENDIAN__
+	ldbrx	rWORD5, 0, rSTR1
+	ldbrx	rWORD6, 0, rSTR2
+	addi	rSTR1, rSTR1, 8
+	addi	rSTR2, rSTR2, 8
+#else
 	ld	rWORD5, 24(rSTR1)
 	ld	rWORD6, 24(rSTR2)
+#endif
 	cmpld	cr1, rWORD3, rWORD4
-	srd	rE, rWORD6, rSHR
-	sld	rH, rWORD6, rSHL
-	bne	cr0, L(duLcr0)
-	or	rWORD6, rE, rF
+	srd	r0, rWORD6, rSHR
+	sld	rWORD6_SHIFT, rWORD6, rSHL
+	bne	cr7, L(duLcr7)
+	or	rWORD6, r0, rWORD4_SHIFT
 	cmpld	cr6, rWORD5, rWORD6
 	b	L(duLoop3)
-	.align 4
+	.align	4
 /* At this point we exit early with the first double word compare
    complete and remainder of 0 to 7 bytes.  See L(du14) for details on
    how we handle the remaining bytes.  */
@@ -683,186 +930,321 @@ L(duP1x):
 	bne	cr5, L(duLcr5)
 	cmpld	cr7, rN, rSHR
 	beq	L(duZeroReturn)
-	li	rA, 0
+	li	r0, 0
 	ble	cr7, L(dutrim)
+#ifdef __LITTLE_ENDIAN__
+	ldbrx	rWORD2, 0, rSTR2
+	addi	rSTR2, rSTR2, 8
+#else
 	ld	rWORD2, 8(rSTR2)
-	srd	rA, rWORD2, rSHR
+#endif
+	srd	r0, rWORD2, rSHR
 	b	L(dutrim)
 /* Remainder is 16 */
-	.align 4
+	.align	4
 L(duP2):
-	srd	rE, rWORD8, rSHR
+	srd	r0, rWORD8, rSHR
+#ifdef __LITTLE_ENDIAN__
+	ldbrx	rWORD5, 0, rSTR1
+	addi	rSTR1, rSTR1, 8
+#else
 	ld	rWORD5, 0(rSTR1)
-	or	rWORD6, rE, rH
-	sld	rH, rWORD8, rSHL
+#endif
+	or	rWORD6, r0, rWORD6_SHIFT
+	sld	rWORD6_SHIFT, rWORD8, rSHL
 L(duP2e):
+#ifdef __LITTLE_ENDIAN__
+	ldbrx	rWORD7, 0, rSTR1
+	ldbrx	rWORD8, 0, rSTR2
+	addi	rSTR1, rSTR1, 8
+	addi	rSTR2, rSTR2, 8
+#else
 	ld	rWORD7, 8(rSTR1)
 	ld	rWORD8, 8(rSTR2)
+#endif
 	cmpld	cr6, rWORD5, rWORD6
-	srd	rG, rWORD8, rSHR
-	sld	rB, rWORD8, rSHL
-	or	rWORD8, rG, rH
+	srd	r12, rWORD8, rSHR
+	sld	rWORD8_SHIFT, rWORD8, rSHL
+	or	rWORD8, r12, rWORD6_SHIFT
 	blt	cr7, L(duP2x)
+#ifdef __LITTLE_ENDIAN__
+	ldbrx	rWORD1, 0, rSTR1
+	ldbrx	rWORD2, 0, rSTR2
+	addi	rSTR1, rSTR1, 8
+	addi	rSTR2, rSTR2, 8
+#else
 	ld	rWORD1, 16(rSTR1)
 	ld	rWORD2, 16(rSTR2)
+#endif
 	cmpld	cr5, rWORD7, rWORD8
 	bne	cr6, L(duLcr6)
-	srd	rA, rWORD2, rSHR
-	sld	rD, rWORD2, rSHL
-	or	rWORD2, rA, rB
+	srd	r0, rWORD2, rSHR
+	sld	rWORD2_SHIFT, rWORD2, rSHL
+	or	rWORD2, r0, rWORD8_SHIFT
+#ifdef __LITTLE_ENDIAN__
+	ldbrx	rWORD3, 0, rSTR1
+	ldbrx	rWORD4, 0, rSTR2
+	addi	rSTR1, rSTR1, 8
+	addi	rSTR2, rSTR2, 8
+#else
 	ld	rWORD3, 24(rSTR1)
 	ld	rWORD4, 24(rSTR2)
-	cmpld	cr0, rWORD1, rWORD2
+#endif
+	cmpld	cr7, rWORD1, rWORD2
 	bne	cr5, L(duLcr5)
-	srd	rC, rWORD4, rSHR
-	sld	rF, rWORD4, rSHL
-	or	rWORD4, rC, rD
+	srd	r12, rWORD4, rSHR
+	sld	rWORD4_SHIFT, rWORD4, rSHL
+	or	rWORD4, r12, rWORD2_SHIFT
+#ifndef __LITTLE_ENDIAN__
 	addi	rSTR1, rSTR1, 8
 	addi	rSTR2, rSTR2, 8
+#endif
 	cmpld	cr1, rWORD3, rWORD4
 	b	L(duLoop2)
-	.align 4
+	.align	4
 L(duP2x):
 	cmpld	cr5, rWORD7, rWORD8
+#ifndef __LITTLE_ENDIAN__
 	addi	rSTR1, rSTR1, 8
 	addi	rSTR2, rSTR2, 8
+#endif
 	bne	cr6, L(duLcr6)
 	sldi.	rN, rN, 3
 	bne	cr5, L(duLcr5)
 	cmpld	cr7, rN, rSHR
 	beq	L(duZeroReturn)
-	li	rA, 0
+	li	r0, 0
 	ble	cr7, L(dutrim)
+#ifdef __LITTLE_ENDIAN__
+	ldbrx	rWORD2, 0, rSTR2
+	addi	rSTR2, rSTR2, 8
+#else
 	ld	rWORD2, 8(rSTR2)
-	srd	rA, rWORD2, rSHR
+#endif
+	srd	r0, rWORD2, rSHR
 	b	L(dutrim)
 
 /* Remainder is 24 */
-	.align 4
+	.align	4
 L(duP3):
-	srd	rC, rWORD8, rSHR
+	srd	r12, rWORD8, rSHR
+#ifdef __LITTLE_ENDIAN__
+	ldbrx	rWORD3, 0, rSTR1
+	addi	rSTR1, rSTR1, 8
+#else
 	ld	rWORD3, 0(rSTR1)
-	sld	rF, rWORD8, rSHL
-	or	rWORD4, rC, rH
+#endif
+	sld	rWORD4_SHIFT, rWORD8, rSHL
+	or	rWORD4, r12, rWORD6_SHIFT
 L(duP3e):
+#ifdef __LITTLE_ENDIAN__
+	ldbrx	rWORD5, 0, rSTR1
+	ldbrx	rWORD6, 0, rSTR2
+	addi	rSTR1, rSTR1, 8
+	addi	rSTR2, rSTR2, 8
+#else
 	ld	rWORD5, 8(rSTR1)
 	ld	rWORD6, 8(rSTR2)
+#endif
 	cmpld	cr1, rWORD3, rWORD4
-	srd	rE, rWORD6, rSHR
-	sld	rH, rWORD6, rSHL
-	or	rWORD6, rE, rF
+	srd	r0, rWORD6, rSHR
+	sld	rWORD6_SHIFT, rWORD6, rSHL
+	or	rWORD6, r0, rWORD4_SHIFT
+#ifdef __LITTLE_ENDIAN__
+	ldbrx	rWORD7, 0, rSTR1
+	ldbrx	rWORD8, 0, rSTR2
+	addi	rSTR1, rSTR1, 8
+	addi	rSTR2, rSTR2, 8
+#else
 	ld	rWORD7, 16(rSTR1)
 	ld	rWORD8, 16(rSTR2)
+#endif
 	cmpld	cr6, rWORD5, rWORD6
 	bne	cr1, L(duLcr1)
-	srd	rG, rWORD8, rSHR
-	sld	rB, rWORD8, rSHL
-	or	rWORD8, rG, rH
+	srd	r12, rWORD8, rSHR
+	sld	rWORD8_SHIFT, rWORD8, rSHL
+	or	rWORD8, r12, rWORD6_SHIFT
 	blt	cr7, L(duP3x)
+#ifdef __LITTLE_ENDIAN__
+	ldbrx	rWORD1, 0, rSTR1
+	ldbrx	rWORD2, 0, rSTR2
+	addi	rSTR1, rSTR1, 8
+	addi	rSTR2, rSTR2, 8
+#else
 	ld	rWORD1, 24(rSTR1)
 	ld	rWORD2, 24(rSTR2)
+#endif
 	cmpld	cr5, rWORD7, rWORD8
 	bne	cr6, L(duLcr6)
-	srd	rA, rWORD2, rSHR
-	sld	rD, rWORD2, rSHL
-	or	rWORD2, rA, rB
+	srd	r0, rWORD2, rSHR
+	sld	rWORD2_SHIFT, rWORD2, rSHL
+	or	rWORD2, r0, rWORD8_SHIFT
+#ifndef __LITTLE_ENDIAN__
 	addi	rSTR1, rSTR1, 16
 	addi	rSTR2, rSTR2, 16
-	cmpld	cr0, rWORD1, rWORD2
+#endif
+	cmpld	cr7, rWORD1, rWORD2
 	b	L(duLoop1)
-	.align 4
+	.align	4
 L(duP3x):
+#ifndef __LITTLE_ENDIAN__
 	addi	rSTR1, rSTR1, 16
 	addi	rSTR2, rSTR2, 16
+#endif
+#if 0
+/* Huh?  We've already branched on cr1!  */
 	bne	cr1, L(duLcr1)
+#endif
 	cmpld	cr5, rWORD7, rWORD8
 	bne	cr6, L(duLcr6)
 	sldi.	rN, rN, 3
 	bne	cr5, L(duLcr5)
 	cmpld	cr7, rN, rSHR
 	beq	L(duZeroReturn)
-	li	rA, 0
+	li	r0, 0
 	ble	cr7, L(dutrim)
+#ifdef __LITTLE_ENDIAN__
+	ldbrx	rWORD2, 0, rSTR2
+	addi	rSTR2, rSTR2, 8
+#else
 	ld	rWORD2, 8(rSTR2)
-	srd	rA, rWORD2, rSHR
+#endif
+	srd	r0, rWORD2, rSHR
 	b	L(dutrim)
 
 /* Count is a multiple of 32, remainder is 0 */
-	.align 4
+	.align	4
 L(duP4):
-	mtctr   rTMP	/* Power4 wants mtctr 1st in dispatch group */
-	srd	rA, rWORD8, rSHR
+	mtctr	r0	/* Power4 wants mtctr 1st in dispatch group */
+	srd	r0, rWORD8, rSHR
+#ifdef __LITTLE_ENDIAN__
+	ldbrx	rWORD1, 0, rSTR1
+	addi	rSTR1, rSTR1, 8
+#else
 	ld	rWORD1, 0(rSTR1)
-	sld	rD, rWORD8, rSHL
-	or	rWORD2, rA, rH
+#endif
+	sld	rWORD2_SHIFT, rWORD8, rSHL
+	or	rWORD2, r0, rWORD6_SHIFT
 L(duP4e):
+#ifdef __LITTLE_ENDIAN__
+	ldbrx	rWORD3, 0, rSTR1
+	ldbrx	rWORD4, 0, rSTR2
+	addi	rSTR1, rSTR1, 8
+	addi	rSTR2, rSTR2, 8
+#else
 	ld	rWORD3, 8(rSTR1)
 	ld	rWORD4, 8(rSTR2)
-	cmpld	cr0, rWORD1, rWORD2
-	srd	rC, rWORD4, rSHR
-	sld	rF, rWORD4, rSHL
-	or	rWORD4, rC, rD
+#endif
+	cmpld	cr7, rWORD1, rWORD2
+	srd	r12, rWORD4, rSHR
+	sld	rWORD4_SHIFT, rWORD4, rSHL
+	or	rWORD4, r12, rWORD2_SHIFT
+#ifdef __LITTLE_ENDIAN__
+	ldbrx	rWORD5, 0, rSTR1
+	ldbrx	rWORD6, 0, rSTR2
+	addi	rSTR1, rSTR1, 8
+	addi	rSTR2, rSTR2, 8
+#else
 	ld	rWORD5, 16(rSTR1)
 	ld	rWORD6, 16(rSTR2)
+#endif
 	cmpld	cr1, rWORD3, rWORD4
-	bne	cr0, L(duLcr0)
-	srd	rE, rWORD6, rSHR
-	sld	rH, rWORD6, rSHL
-	or	rWORD6, rE, rF
+	bne	cr7, L(duLcr7)
+	srd	r0, rWORD6, rSHR
+	sld	rWORD6_SHIFT, rWORD6, rSHL
+	or	rWORD6, r0, rWORD4_SHIFT
+#ifdef __LITTLE_ENDIAN__
+	ldbrx	rWORD7, 0, rSTR1
+	ldbrx	rWORD8, 0, rSTR2
+	addi	rSTR1, rSTR1, 8
+	addi	rSTR2, rSTR2, 8
+#else
 	ldu	rWORD7, 24(rSTR1)
 	ldu	rWORD8, 24(rSTR2)
+#endif
 	cmpld	cr6, rWORD5, rWORD6
 	bne	cr1, L(duLcr1)
-	srd	rG, rWORD8, rSHR
-	sld	rB, rWORD8, rSHL
-	or	rWORD8, rG, rH
+	srd	r12, rWORD8, rSHR
+	sld	rWORD8_SHIFT, rWORD8, rSHL
+	or	rWORD8, r12, rWORD6_SHIFT
 	cmpld	cr5, rWORD7, rWORD8
 	bdz-	L(du24)		/* Adjust CTR as we start with +4 */
 /* This is the primary loop */
-	.align 4
+	.align	4
 L(duLoop):
+#ifdef __LITTLE_ENDIAN__
+	ldbrx	rWORD1, 0, rSTR1
+	ldbrx	rWORD2, 0, rSTR2
+	addi	rSTR1, rSTR1, 8
+	addi	rSTR2, rSTR2, 8
+#else
 	ld	rWORD1, 8(rSTR1)
 	ld	rWORD2, 8(rSTR2)
+#endif
 	cmpld	cr1, rWORD3, rWORD4
 	bne	cr6, L(duLcr6)
-	srd	rA, rWORD2, rSHR
-	sld	rD, rWORD2, rSHL
-	or	rWORD2, rA, rB
+	srd	r0, rWORD2, rSHR
+	sld	rWORD2_SHIFT, rWORD2, rSHL
+	or	rWORD2, r0, rWORD8_SHIFT
 L(duLoop1):
+#ifdef __LITTLE_ENDIAN__
+	ldbrx	rWORD3, 0, rSTR1
+	ldbrx	rWORD4, 0, rSTR2
+	addi	rSTR1, rSTR1, 8
+	addi	rSTR2, rSTR2, 8
+#else
 	ld	rWORD3, 16(rSTR1)
 	ld	rWORD4, 16(rSTR2)
+#endif
 	cmpld	cr6, rWORD5, rWORD6
 	bne	cr5, L(duLcr5)
-	srd	rC, rWORD4, rSHR
-	sld	rF, rWORD4, rSHL
-	or	rWORD4, rC, rD
+	srd	r12, rWORD4, rSHR
+	sld	rWORD4_SHIFT, rWORD4, rSHL
+	or	rWORD4, r12, rWORD2_SHIFT
 L(duLoop2):
+#ifdef __LITTLE_ENDIAN__
+	ldbrx	rWORD5, 0, rSTR1
+	ldbrx	rWORD6, 0, rSTR2
+	addi	rSTR1, rSTR1, 8
+	addi	rSTR2, rSTR2, 8
+#else
 	ld	rWORD5, 24(rSTR1)
 	ld	rWORD6, 24(rSTR2)
+#endif
 	cmpld	cr5, rWORD7, rWORD8
-	bne	cr0, L(duLcr0)
-	srd	rE, rWORD6, rSHR
-	sld	rH, rWORD6, rSHL
-	or	rWORD6, rE, rF
+	bne	cr7, L(duLcr7)
+	srd	r0, rWORD6, rSHR
+	sld	rWORD6_SHIFT, rWORD6, rSHL
+	or	rWORD6, r0, rWORD4_SHIFT
 L(duLoop3):
+#ifdef __LITTLE_ENDIAN__
+	ldbrx	rWORD7, 0, rSTR1
+	ldbrx	rWORD8, 0, rSTR2
+	addi	rSTR1, rSTR1, 8
+	addi	rSTR2, rSTR2, 8
+#else
 	ldu	rWORD7, 32(rSTR1)
 	ldu	rWORD8, 32(rSTR2)
-	cmpld	cr0, rWORD1, rWORD2
+#endif
+	cmpld	cr7, rWORD1, rWORD2
 	bne-	cr1, L(duLcr1)
-	srd	rG, rWORD8, rSHR
-	sld	rB, rWORD8, rSHL
-	or	rWORD8, rG, rH
+	srd	r12, rWORD8, rSHR
+	sld	rWORD8_SHIFT, rWORD8, rSHL
+	or	rWORD8, r12, rWORD6_SHIFT
 	bdnz+	L(duLoop)
 
 L(duL4):
+#if 0
+/* Huh?  We've already branched on cr1!  */
 	bne	cr1, L(duLcr1)
+#endif
 	cmpld	cr1, rWORD3, rWORD4
 	bne	cr6, L(duLcr6)
 	cmpld	cr6, rWORD5, rWORD6
 	bne	cr5, L(duLcr5)
 	cmpld	cr5, rWORD7, rWORD8
 L(du44):
-	bne	cr0, L(duLcr0)
+	bne	cr7, L(duLcr7)
 L(du34):
 	bne	cr1, L(duLcr1)
 L(du24):
@@ -872,103 +1254,110 @@ L(du14):
 	bne	cr5, L(duLcr5)
 /* At this point we have a remainder of 1 to 7 bytes to compare.  We use
    shift right double to eliminate bits beyond the compare length.
-   This allows the use of double word subtract to compute the final
-   result.
 
    However it may not be safe to load rWORD2 which may be beyond the
    string length. So we compare the bit length of the remainder to
    the right shift count (rSHR). If the bit count is less than or equal
    we do not need to load rWORD2 (all significant bits are already in
-   rB).  */
+   rWORD8_SHIFT).  */
 	cmpld	cr7, rN, rSHR
 	beq	L(duZeroReturn)
-	li	rA, 0
+	li	r0, 0
 	ble	cr7, L(dutrim)
+#ifdef __LITTLE_ENDIAN__
+	ldbrx	rWORD2, 0, rSTR2
+	addi	rSTR2, rSTR2, 8
+#else
 	ld	rWORD2, 8(rSTR2)
-	srd	rA, rWORD2, rSHR
-	.align 4
+#endif
+	srd	r0, rWORD2, rSHR
+	.align	4
 L(dutrim):
+#ifdef __LITTLE_ENDIAN__
+	ldbrx	rWORD1, 0, rSTR1
+#else
 	ld	rWORD1, 8(rSTR1)
-	ld	rWORD8,-8(r1)
+#endif
+	ld	rWORD8, -8(r1)
 	subfic	rN, rN, 64	/* Shift count is 64 - (rN * 8).  */
-	or	rWORD2, rA, rB
-	ld	rWORD7,-16(r1)
-	ld	r29,-24(r1)
+	or	rWORD2, r0, rWORD8_SHIFT
+	ld	rWORD7, -16(r1)
+	ld	rSHL, -24(r1)
 	srd	rWORD1, rWORD1, rN
 	srd	rWORD2, rWORD2, rN
-	ld	r28,-32(r1)
-	ld	r27,-40(r1)
+	ld	rSHR, -32(r1)
+	ld	rWORD8_SHIFT, -40(r1)
 	li	rRTN, 0
-	cmpld	cr0, rWORD1, rWORD2
-	ld	r26,-48(r1)
-	ld	r25,-56(r1)
- 	beq	cr0, L(dureturn24)
+	cmpld	cr7, rWORD1, rWORD2
+	ld	rWORD2_SHIFT, -48(r1)
+	ld	rWORD4_SHIFT, -56(r1)
+	beq	cr7, L(dureturn24)
 	li	rRTN, 1
-	ld	r24,-64(r1)
-	bgtlr	cr0
+	ld	rWORD6_SHIFT, -64(r1)
+	bgtlr	cr7
 	li	rRTN, -1
 	blr
-	.align 4
-L(duLcr0):
-	ld	rWORD8,-8(r1)
-	ld	rWORD7,-16(r1)
+	.align	4
+L(duLcr7):
+	ld	rWORD8, -8(r1)
+	ld	rWORD7, -16(r1)
 	li	rRTN, 1
-	bgt	cr0, L(dureturn29)
-	ld	r29,-24(r1)
-	ld	r28,-32(r1)
+	bgt	cr7, L(dureturn29)
+	ld	rSHL, -24(r1)
+	ld	rSHR, -32(r1)
 	li	rRTN, -1
 	b	L(dureturn27)
-	.align 4
+	.align	4
 L(duLcr1):
-	ld	rWORD8,-8(r1)
-	ld	rWORD7,-16(r1)
+	ld	rWORD8, -8(r1)
+	ld	rWORD7, -16(r1)
 	li	rRTN, 1
 	bgt	cr1, L(dureturn29)
-	ld	r29,-24(r1)
-	ld	r28,-32(r1)
+	ld	rSHL, -24(r1)
+	ld	rSHR, -32(r1)
 	li	rRTN, -1
 	b	L(dureturn27)
-	.align 4
+	.align	4
 L(duLcr6):
-	ld	rWORD8,-8(r1)
-	ld	rWORD7,-16(r1)
+	ld	rWORD8, -8(r1)
+	ld	rWORD7, -16(r1)
 	li	rRTN, 1
 	bgt	cr6, L(dureturn29)
-	ld	r29,-24(r1)
-	ld	r28,-32(r1)
+	ld	rSHL, -24(r1)
+	ld	rSHR, -32(r1)
 	li	rRTN, -1
 	b	L(dureturn27)
-	.align 4
+	.align	4
 L(duLcr5):
-	ld	rWORD8,-8(r1)
-	ld	rWORD7,-16(r1)
+	ld	rWORD8, -8(r1)
+	ld	rWORD7, -16(r1)
 	li	rRTN, 1
 	bgt	cr5, L(dureturn29)
-	ld	r29,-24(r1)
-	ld	r28,-32(r1)
+	ld	rSHL, -24(r1)
+	ld	rSHR, -32(r1)
 	li	rRTN, -1
 	b	L(dureturn27)
 	.align	3
 L(duZeroReturn):
-	li	rRTN,0
+	li	rRTN, 0
 	.align	4
 L(dureturn):
-	ld	rWORD8,-8(r1)
-	ld	rWORD7,-16(r1)
+	ld	rWORD8, -8(r1)
+	ld	rWORD7, -16(r1)
 L(dureturn29):
-	ld	r29,-24(r1)
-	ld	r28,-32(r1)
+	ld	rSHL, -24(r1)
+	ld	rSHR, -32(r1)
 L(dureturn27):
-	ld	r27,-40(r1)
+	ld	rWORD8_SHIFT, -40(r1)
 L(dureturn26):
-	ld	r26,-48(r1)
+	ld	rWORD2_SHIFT, -48(r1)
 L(dureturn25):
-	ld	r25,-56(r1)
+	ld	rWORD4_SHIFT, -56(r1)
 L(dureturn24):
-	ld	r24,-64(r1)
+	ld	rWORD6_SHIFT, -64(r1)
 	blr
 L(duzeroLength):
-	li	rRTN,0
+	li	rRTN, 0
 	blr
 
 END (memcmp)
diff --git a/sysdeps/powerpc/powerpc64/power7/memcmp.S b/sysdeps/powerpc/powerpc64/power7/memcmp.S
index f190c64..6851cdc 100644
--- a/sysdeps/powerpc/powerpc64/power7/memcmp.S
+++ b/sysdeps/powerpc/powerpc64/power7/memcmp.S
@@ -23,10 +23,9 @@
 		    size_t size [r5])  */
 
 	.machine power7
-EALIGN (memcmp,4,0)
+EALIGN (memcmp, 4, 0)
 	CALL_MCOUNT 3
 
-#define rTMP	r0
 #define rRTN	r3
 #define rSTR1	r3	/* first string arg */
 #define rSTR2	r4	/* second string arg */
@@ -37,354 +36,557 @@ EALIGN (memcmp,4,0)
 #define rWORD4	r9	/* next word in s2 */
 #define rWORD5	r10	/* next word in s1 */
 #define rWORD6	r11	/* next word in s2 */
-#define rBITDIF	r12	/* bits that differ in s1 & s2 words */
 #define rWORD7	r30	/* next word in s1 */
 #define rWORD8	r31	/* next word in s2 */
 
-	xor	rTMP,rSTR2,rSTR1
-	cmpldi	cr6,rN,0
-	cmpldi	cr1,rN,12
-	clrldi.	rTMP,rTMP,61
-	clrldi	rBITDIF,rSTR1,61
-	cmpldi	cr5,rBITDIF,0
-	beq-	cr6,L(zeroLength)
-	dcbt	0,rSTR1
-	dcbt	0,rSTR2
+	xor	r0, rSTR2, rSTR1
+	cmpldi	cr6, rN, 0
+	cmpldi	cr1, rN, 12
+	clrldi.	r0, r0, 61
+	clrldi	r12, rSTR1, 61
+	cmpldi	cr5, r12, 0
+	beq-	cr6, L(zeroLength)
+	dcbt	0, rSTR1
+	dcbt	0, rSTR2
 /* If less than 8 bytes or not aligned, use the unaligned
    byte loop.  */
-	blt	cr1,L(bytealigned)
-	std	rWORD8,-8(r1)
-	cfi_offset(rWORD8,-8)
-	std	rWORD7,-16(r1)
-	cfi_offset(rWORD7,-16)
+	blt	cr1, L(bytealigned)
+	std	rWORD8, -8(r1)
+	cfi_offset(rWORD8, -8)
+	std	rWORD7, -16(r1)
+	cfi_offset(rWORD7, -16)
 	bne	L(unaligned)
 /* At this point we know both strings have the same alignment and the
-   compare length is at least 8 bytes.  rBITDIF contains the low order
+   compare length is at least 8 bytes.  r12 contains the low order
    3 bits of rSTR1 and cr5 contains the result of the logical compare
-   of rBITDIF to 0.  If rBITDIF == 0 then we are already double word
-   aligned and can perform the DWaligned loop.
+   of r12 to 0.  If r12 == 0 then we are already double word
+   aligned and can perform the DW aligned loop.
 
    Otherwise we know the two strings have the same alignment (but not
-   yet DW).  So we can force the string addresses to the next lower DW
-   boundary and special case this first DW word using shift left to
+   yet DW).  So we force the string addresses to the next lower DW
+   boundary and special case this first DW using shift left to
    eliminate bits preceding the first byte.  Since we want to join the
-   normal (DWaligned) compare loop, starting at the second double word,
+   normal (DW aligned) compare loop, starting at the second double word,
    we need to adjust the length (rN) and special case the loop
-   versioning for the first DW. This insures that the loop count is
-   correct and the first DW (shifted) is in the expected resister pair.  */
+   versioning for the first DW. This ensures that the loop count is
+   correct and the first DW (shifted) is in the expected register pair.  */
 	.align	4
 L(samealignment):
-	clrrdi	rSTR1,rSTR1,3
-	clrrdi	rSTR2,rSTR2,3
-	beq	cr5,L(DWaligned)
-	add	rN,rN,rBITDIF
-	sldi	r11,rBITDIF,3
-	srdi	rTMP,rN,5	/* Divide by 32 */
-	andi.	rBITDIF,rN,24	/* Get the DW remainder */
-	ld	rWORD1,0(rSTR1)
-	ld	rWORD2,0(rSTR2)
-	cmpldi	cr1,rBITDIF,16
-	cmpldi	cr7,rN,32
-	clrldi	rN,rN,61
+	clrrdi	rSTR1, rSTR1, 3
+	clrrdi	rSTR2, rSTR2, 3
+	beq	cr5, L(DWaligned)
+	add	rN, rN, r12
+	sldi	rWORD6, r12, 3
+	srdi	r0, rN, 5	/* Divide by 32 */
+	andi.	r12, rN, 24	/* Get the DW remainder */
+#ifdef __LITTLE_ENDIAN__
+	ldbrx	rWORD1, 0, rSTR1
+	ldbrx	rWORD2, 0, rSTR2
+	addi	rSTR1, rSTR1, 8
+	addi	rSTR2, rSTR2, 8
+#else
+	ld	rWORD1, 0(rSTR1)
+	ld	rWORD2, 0(rSTR2)
+#endif
+	cmpldi	cr1, r12, 16
+	cmpldi	cr7, rN, 32
+	clrldi	rN, rN, 61
 	beq	L(dPs4)
-	mtctr	rTMP
-	bgt	cr1,L(dPs3)
-	beq	cr1,L(dPs2)
+	mtctr	r0
+	bgt	cr1, L(dPs3)
+	beq	cr1, L(dPs2)
 
 /* Remainder is 8 */
 	.align	3
 L(dsP1):
-	sld	rWORD5,rWORD1,r11
-	sld	rWORD6,rWORD2,r11
-	cmpld	cr5,rWORD5,rWORD6
-	blt	cr7,L(dP1x)
+	sld	rWORD5, rWORD1, rWORD6
+	sld	rWORD6, rWORD2, rWORD6
+	cmpld	cr5, rWORD5, rWORD6
+	blt	cr7, L(dP1x)
 /* Do something useful in this cycle since we have to branch anyway.  */
-	ld	rWORD1,8(rSTR1)
-	ld	rWORD2,8(rSTR2)
-	cmpld	cr0,rWORD1,rWORD2
+#ifdef __LITTLE_ENDIAN__
+	ldbrx	rWORD1, 0, rSTR1
+	ldbrx	rWORD2, 0, rSTR2
+	addi	rSTR1, rSTR1, 8
+	addi	rSTR2, rSTR2, 8
+#else
+	ld	rWORD1, 8(rSTR1)
+	ld	rWORD2, 8(rSTR2)
+#endif
+	cmpld	cr7, rWORD1, rWORD2
 	b	L(dP1e)
 /* Remainder is 16 */
 	.align	4
 L(dPs2):
-	sld	rWORD5,rWORD1,r11
-	sld	rWORD6,rWORD2,r11
-	cmpld	cr6,rWORD5,rWORD6
-	blt	cr7,L(dP2x)
+	sld	rWORD5, rWORD1, rWORD6
+	sld	rWORD6, rWORD2, rWORD6
+	cmpld	cr6, rWORD5, rWORD6
+	blt	cr7, L(dP2x)
 /* Do something useful in this cycle since we have to branch anyway.  */
-	ld	rWORD7,8(rSTR1)
-	ld	rWORD8,8(rSTR2)
-	cmpld	cr5,rWORD7,rWORD8
+#ifdef __LITTLE_ENDIAN__
+	ldbrx	rWORD7, 0, rSTR1
+	ldbrx	rWORD8, 0, rSTR2
+	addi	rSTR1, rSTR1, 8
+	addi	rSTR2, rSTR2, 8
+#else
+	ld	rWORD7, 8(rSTR1)
+	ld	rWORD8, 8(rSTR2)
+#endif
+	cmpld	cr5, rWORD7, rWORD8
 	b	L(dP2e)
 /* Remainder is 24 */
 	.align	4
 L(dPs3):
-	sld	rWORD3,rWORD1,r11
-	sld	rWORD4,rWORD2,r11
-	cmpld	cr1,rWORD3,rWORD4
+	sld	rWORD3, rWORD1, rWORD6
+	sld	rWORD4, rWORD2, rWORD6
+	cmpld	cr1, rWORD3, rWORD4
 	b	L(dP3e)
 /* Count is a multiple of 32, remainder is 0 */
 	.align	4
 L(dPs4):
-	mtctr	rTMP
-	sld	rWORD1,rWORD1,r11
-	sld	rWORD2,rWORD2,r11
-	cmpld	cr0,rWORD1,rWORD2
+	mtctr	r0
+	sld	rWORD1, rWORD1, rWORD6
+	sld	rWORD2, rWORD2, rWORD6
+	cmpld	cr7, rWORD1, rWORD2
 	b	L(dP4e)
 
 /* At this point we know both strings are double word aligned and the
    compare length is at least 8 bytes.  */
 	.align	4
 L(DWaligned):
-	andi.	rBITDIF,rN,24	/* Get the DW remainder */
-	srdi	rTMP,rN,5	/* Divide by 32 */
-	cmpldi	cr1,rBITDIF,16
-	cmpldi	cr7,rN,32
-	clrldi	rN,rN,61
+	andi.	r12, rN, 24	/* Get the DW remainder */
+	srdi	r0, rN, 5	/* Divide by 32 */
+	cmpldi	cr1, r12, 16
+	cmpldi	cr7, rN, 32
+	clrldi	rN, rN, 61
 	beq	L(dP4)
-	bgt	cr1,L(dP3)
-	beq	cr1,L(dP2)
+	bgt	cr1, L(dP3)
+	beq	cr1, L(dP2)
 
 /* Remainder is 8 */
 	.align	4
 L(dP1):
-	mtctr	rTMP
+	mtctr	r0
 /* Normally we'd use rWORD7/rWORD8 here, but since we might exit early
    (8-15 byte compare), we want to use only volatile registers.  This
    means we can avoid restoring non-volatile registers since we did not
    change any on the early exit path.  The key here is the non-early
    exit path only cares about the condition code (cr5), not about which
    register pair was used.  */
-	ld	rWORD5,0(rSTR1)
-	ld	rWORD6,0(rSTR2)
-	cmpld	cr5,rWORD5,rWORD6
-	blt	cr7,L(dP1x)
-	ld	rWORD1,8(rSTR1)
-	ld	rWORD2,8(rSTR2)
-	cmpld	cr0,rWORD1,rWORD2
+#ifdef __LITTLE_ENDIAN__
+	ldbrx	rWORD5, 0, rSTR1
+	ldbrx	rWORD6, 0, rSTR2
+	addi	rSTR1, rSTR1, 8
+	addi	rSTR2, rSTR2, 8
+#else
+	ld	rWORD5, 0(rSTR1)
+	ld	rWORD6, 0(rSTR2)
+#endif
+	cmpld	cr5, rWORD5, rWORD6
+	blt	cr7, L(dP1x)
+#ifdef __LITTLE_ENDIAN__
+	ldbrx	rWORD1, 0, rSTR1
+	ldbrx	rWORD2, 0, rSTR2
+	addi	rSTR1, rSTR1, 8
+	addi	rSTR2, rSTR2, 8
+#else
+	ld	rWORD1, 8(rSTR1)
+	ld	rWORD2, 8(rSTR2)
+#endif
+	cmpld	cr7, rWORD1, rWORD2
 L(dP1e):
-	ld	rWORD3,16(rSTR1)
-	ld	rWORD4,16(rSTR2)
-	cmpld	cr1,rWORD3,rWORD4
-	ld	rWORD5,24(rSTR1)
-	ld	rWORD6,24(rSTR2)
-	cmpld	cr6,rWORD5,rWORD6
-	bne	cr5,L(dLcr5)
-	bne	cr0,L(dLcr0)
-
-	ldu	rWORD7,32(rSTR1)
-	ldu	rWORD8,32(rSTR2)
-	bne	cr1,L(dLcr1)
-	cmpld	cr5,rWORD7,rWORD8
+#ifdef __LITTLE_ENDIAN__
+	ldbrx	rWORD3, 0, rSTR1
+	ldbrx	rWORD4, 0, rSTR2
+	addi	rSTR1, rSTR1, 8
+	addi	rSTR2, rSTR2, 8
+#else
+	ld	rWORD3, 16(rSTR1)
+	ld	rWORD4, 16(rSTR2)
+#endif
+	cmpld	cr1, rWORD3, rWORD4
+#ifdef __LITTLE_ENDIAN__
+	ldbrx	rWORD5, 0, rSTR1
+	ldbrx	rWORD6, 0, rSTR2
+	addi	rSTR1, rSTR1, 8
+	addi	rSTR2, rSTR2, 8
+#else
+	ld	rWORD5, 24(rSTR1)
+	ld	rWORD6, 24(rSTR2)
+#endif
+	cmpld	cr6, rWORD5, rWORD6
+	bne	cr5, L(dLcr5x)
+	bne	cr7, L(dLcr7x)
+
+#ifdef __LITTLE_ENDIAN__
+	ldbrx	rWORD7, 0, rSTR1
+	ldbrx	rWORD8, 0, rSTR2
+	addi	rSTR1, rSTR1, 8
+	addi	rSTR2, rSTR2, 8
+#else
+	ldu	rWORD7, 32(rSTR1)
+	ldu	rWORD8, 32(rSTR2)
+#endif
+	bne	cr1, L(dLcr1)
+	cmpld	cr5, rWORD7, rWORD8
 	bdnz	L(dLoop)
-	bne	cr6,L(dLcr6)
-	ld	rWORD8,-8(r1)
-	ld	rWORD7,-16(r1)
+	bne	cr6, L(dLcr6)
+	ld	rWORD8, -8(r1)
+	ld	rWORD7, -16(r1)
 	.align	3
 L(dP1x):
-	sldi.	r12,rN,3
-	bne	cr5,L(dLcr5)
-	subfic	rN,r12,64	/* Shift count is 64 - (rN * 8).  */
+	sldi.	r12, rN, 3
+	bne	cr5, L(dLcr5x)
+	subfic	rN, r12, 64	/* Shift count is 64 - (rN * 8).  */
 	bne	L(d00)
-	li	rRTN,0
+	li	rRTN, 0
 	blr
 
 /* Remainder is 16 */
 	.align	4
 L(dP2):
-	mtctr	rTMP
-	ld	rWORD5,0(rSTR1)
-	ld	rWORD6,0(rSTR2)
-	cmpld	cr6,rWORD5,rWORD6
-	blt	cr7,L(dP2x)
-	ld	rWORD7,8(rSTR1)
-	ld	rWORD8,8(rSTR2)
-	cmpld	cr5,rWORD7,rWORD8
+	mtctr	r0
+#ifdef __LITTLE_ENDIAN__
+	ldbrx	rWORD5, 0, rSTR1
+	ldbrx	rWORD6, 0, rSTR2
+	addi	rSTR1, rSTR1, 8
+	addi	rSTR2, rSTR2, 8
+#else
+	ld	rWORD5, 0(rSTR1)
+	ld	rWORD6, 0(rSTR2)
+#endif
+	cmpld	cr6, rWORD5, rWORD6
+	blt	cr7, L(dP2x)
+#ifdef __LITTLE_ENDIAN__
+	ldbrx	rWORD7, 0, rSTR1
+	ldbrx	rWORD8, 0, rSTR2
+	addi	rSTR1, rSTR1, 8
+	addi	rSTR2, rSTR2, 8
+#else
+	ld	rWORD7, 8(rSTR1)
+	ld	rWORD8, 8(rSTR2)
+#endif
+	cmpld	cr5, rWORD7, rWORD8
 L(dP2e):
-	ld	rWORD1,16(rSTR1)
-	ld	rWORD2,16(rSTR2)
-	cmpld	cr0,rWORD1,rWORD2
-	ld	rWORD3,24(rSTR1)
-	ld	rWORD4,24(rSTR2)
-	cmpld	cr1,rWORD3,rWORD4
-	addi	rSTR1,rSTR1,8
-	addi	rSTR2,rSTR2,8
-	bne	cr6,L(dLcr6)
-	bne	cr5,L(dLcr5)
+#ifdef __LITTLE_ENDIAN__
+	ldbrx	rWORD1, 0, rSTR1
+	ldbrx	rWORD2, 0, rSTR2
+	addi	rSTR1, rSTR1, 8
+	addi	rSTR2, rSTR2, 8
+#else
+	ld	rWORD1, 16(rSTR1)
+	ld	rWORD2, 16(rSTR2)
+#endif
+	cmpld	cr7, rWORD1, rWORD2
+#ifdef __LITTLE_ENDIAN__
+	ldbrx	rWORD3, 0, rSTR1
+	ldbrx	rWORD4, 0, rSTR2
+	addi	rSTR1, rSTR1, 8
+	addi	rSTR2, rSTR2, 8
+#else
+	ld	rWORD3, 24(rSTR1)
+	ld	rWORD4, 24(rSTR2)
+#endif
+	cmpld	cr1, rWORD3, rWORD4
+#ifndef __LITTLE_ENDIAN__
+	addi	rSTR1, rSTR1, 8
+	addi	rSTR2, rSTR2, 8
+#endif
+	bne	cr6, L(dLcr6)
+	bne	cr5, L(dLcr5)
 	b	L(dLoop2)
 /* Again we are on a early exit path (16-23 byte compare), we want to
    only use volatile registers and avoid restoring non-volatile
    registers.  */
 	.align	4
 L(dP2x):
-	ld	rWORD3,8(rSTR1)
-	ld	rWORD4,8(rSTR2)
-	cmpld	cr5,rWORD3,rWORD4
-	sldi.	r12,rN,3
-	bne	cr6,L(dLcr6)
-	addi	rSTR1,rSTR1,8
-	addi	rSTR2,rSTR2,8
-	bne	cr5,L(dLcr5)
-	subfic	rN,r12,64	/* Shift count is 64 - (rN * 8).  */
+#ifdef __LITTLE_ENDIAN__
+	ldbrx	rWORD3, 0, rSTR1
+	ldbrx	rWORD4, 0, rSTR2
+	addi	rSTR1, rSTR1, 8
+	addi	rSTR2, rSTR2, 8
+#else
+	ld	rWORD3, 8(rSTR1)
+	ld	rWORD4, 8(rSTR2)
+#endif
+	cmpld	cr1, rWORD3, rWORD4
+	sldi.	r12, rN, 3
+	bne	cr6, L(dLcr6x)
+#ifndef __LITTLE_ENDIAN__
+	addi	rSTR1, rSTR1, 8
+	addi	rSTR2, rSTR2, 8
+#endif
+	bne	cr1, L(dLcr1x)
+	subfic	rN, r12, 64	/* Shift count is 64 - (rN * 8).  */
 	bne	L(d00)
-	li	rRTN,0
+	li	rRTN, 0
 	blr
 
 /* Remainder is 24 */
 	.align	4
 L(dP3):
-	mtctr	rTMP
-	ld	rWORD3,0(rSTR1)
-	ld	rWORD4,0(rSTR2)
-	cmpld	cr1,rWORD3,rWORD4
+	mtctr	r0
+#ifdef __LITTLE_ENDIAN__
+	ldbrx	rWORD3, 0, rSTR1
+	ldbrx	rWORD4, 0, rSTR2
+	addi	rSTR1, rSTR1, 8
+	addi	rSTR2, rSTR2, 8
+#else
+	ld	rWORD3, 0(rSTR1)
+	ld	rWORD4, 0(rSTR2)
+#endif
+	cmpld	cr1, rWORD3, rWORD4
 L(dP3e):
-	ld	rWORD5,8(rSTR1)
-	ld	rWORD6,8(rSTR2)
-	cmpld	cr6,rWORD5,rWORD6
-	blt	cr7,L(dP3x)
-	ld	rWORD7,16(rSTR1)
-	ld	rWORD8,16(rSTR2)
-	cmpld	cr5,rWORD7,rWORD8
-	ld	rWORD1,24(rSTR1)
-	ld	rWORD2,24(rSTR2)
-	cmpld	cr0,rWORD1,rWORD2
-	addi	rSTR1,rSTR1,16
-	addi	rSTR2,rSTR2,16
-	bne	cr1,L(dLcr1)
-	bne	cr6,L(dLcr6)
+#ifdef __LITTLE_ENDIAN__
+	ldbrx	rWORD5, 0, rSTR1
+	ldbrx	rWORD6, 0, rSTR2
+	addi	rSTR1, rSTR1, 8
+	addi	rSTR2, rSTR2, 8
+#else
+	ld	rWORD5, 8(rSTR1)
+	ld	rWORD6, 8(rSTR2)
+#endif
+	cmpld	cr6, rWORD5, rWORD6
+	blt	cr7, L(dP3x)
+#ifdef __LITTLE_ENDIAN__
+	ldbrx	rWORD7, 0, rSTR1
+	ldbrx	rWORD8, 0, rSTR2
+	addi	rSTR1, rSTR1, 8
+	addi	rSTR2, rSTR2, 8
+#else
+	ld	rWORD7, 16(rSTR1)
+	ld	rWORD8, 16(rSTR2)
+#endif
+	cmpld	cr5, rWORD7, rWORD8
+#ifdef __LITTLE_ENDIAN__
+	ldbrx	rWORD1, 0, rSTR1
+	ldbrx	rWORD2, 0, rSTR2
+	addi	rSTR1, rSTR1, 8
+	addi	rSTR2, rSTR2, 8
+#else
+	ld	rWORD1, 24(rSTR1)
+	ld	rWORD2, 24(rSTR2)
+#endif
+	cmpld	cr7, rWORD1, rWORD2
+#ifndef __LITTLE_ENDIAN__
+	addi	rSTR1, rSTR1, 16
+	addi	rSTR2, rSTR2, 16
+#endif
+	bne	cr1, L(dLcr1)
+	bne	cr6, L(dLcr6)
 	b	L(dLoop1)
 /* Again we are on a early exit path (24-31 byte compare), we want to
    only use volatile registers and avoid restoring non-volatile
    registers.  */
 	.align	4
 L(dP3x):
-	ld	rWORD1,16(rSTR1)
-	ld	rWORD2,16(rSTR2)
-	cmpld	cr5,rWORD1,rWORD2
-	sldi.	r12,rN,3
-	bne	cr1,L(dLcr1)
-	addi	rSTR1,rSTR1,16
-	addi	rSTR2,rSTR2,16
-	bne	cr6,L(dLcr6)
-	subfic	rN,r12,64	/* Shift count is 64 - (rN * 8).  */
-	bne	cr5,L(dLcr5)
+#ifdef __LITTLE_ENDIAN__
+	ldbrx	rWORD1, 0, rSTR1
+	ldbrx	rWORD2, 0, rSTR2
+	addi	rSTR1, rSTR1, 8
+	addi	rSTR2, rSTR2, 8
+#else
+	ld	rWORD1, 16(rSTR1)
+	ld	rWORD2, 16(rSTR2)
+#endif
+	cmpld	cr7, rWORD1, rWORD2
+	sldi.	r12, rN, 3
+	bne	cr1, L(dLcr1x)
+#ifndef __LITTLE_ENDIAN__
+	addi	rSTR1, rSTR1, 16
+	addi	rSTR2, rSTR2, 16
+#endif
+	bne	cr6, L(dLcr6x)
+	subfic	rN, r12, 64	/* Shift count is 64 - (rN * 8).  */
+	bne	cr7, L(dLcr7x)
 	bne	L(d00)
-	li	rRTN,0
+	li	rRTN, 0
 	blr
 
 /* Count is a multiple of 32, remainder is 0 */
 	.align	4
 L(dP4):
-	mtctr	rTMP
-	ld	rWORD1,0(rSTR1)
-	ld	rWORD2,0(rSTR2)
-	cmpld	cr0,rWORD1,rWORD2
+	mtctr	r0
+#ifdef __LITTLE_ENDIAN__
+	ldbrx	rWORD1, 0, rSTR1
+	ldbrx	rWORD2, 0, rSTR2
+	addi	rSTR1, rSTR1, 8
+	addi	rSTR2, rSTR2, 8
+#else
+	ld	rWORD1, 0(rSTR1)
+	ld	rWORD2, 0(rSTR2)
+#endif
+	cmpld	cr7, rWORD1, rWORD2
 L(dP4e):
-	ld	rWORD3,8(rSTR1)
-	ld	rWORD4,8(rSTR2)
-	cmpld	cr1,rWORD3,rWORD4
-	ld	rWORD5,16(rSTR1)
-	ld	rWORD6,16(rSTR2)
-	cmpld	cr6,rWORD5,rWORD6
-	ldu	rWORD7,24(rSTR1)
-	ldu	rWORD8,24(rSTR2)
-	cmpld	cr5,rWORD7,rWORD8
-	bne	cr0,L(dLcr0)
-	bne	cr1,L(dLcr1)
+#ifdef __LITTLE_ENDIAN__
+	ldbrx	rWORD3, 0, rSTR1
+	ldbrx	rWORD4, 0, rSTR2
+	addi	rSTR1, rSTR1, 8
+	addi	rSTR2, rSTR2, 8
+#else
+	ld	rWORD3, 8(rSTR1)
+	ld	rWORD4, 8(rSTR2)
+#endif
+	cmpld	cr1, rWORD3, rWORD4
+#ifdef __LITTLE_ENDIAN__
+	ldbrx	rWORD5, 0, rSTR1
+	ldbrx	rWORD6, 0, rSTR2
+	addi	rSTR1, rSTR1, 8
+	addi	rSTR2, rSTR2, 8
+#else
+	ld	rWORD5, 16(rSTR1)
+	ld	rWORD6, 16(rSTR2)
+#endif
+	cmpld	cr6, rWORD5, rWORD6
+#ifdef __LITTLE_ENDIAN__
+	ldbrx	rWORD7, 0, rSTR1
+	ldbrx	rWORD8, 0, rSTR2
+	addi	rSTR1, rSTR1, 8
+	addi	rSTR2, rSTR2, 8
+#else
+	ldu	rWORD7, 24(rSTR1)
+	ldu	rWORD8, 24(rSTR2)
+#endif
+	cmpld	cr5, rWORD7, rWORD8
+	bne	cr7, L(dLcr7)
+	bne	cr1, L(dLcr1)
 	bdz-	L(d24)		/* Adjust CTR as we start with +4 */
 /* This is the primary loop */
 	.align	4
 L(dLoop):
-	ld	rWORD1,8(rSTR1)
-	ld	rWORD2,8(rSTR2)
-	cmpld	cr1,rWORD3,rWORD4
-	bne	cr6,L(dLcr6)
+#ifdef __LITTLE_ENDIAN__
+	ldbrx	rWORD1, 0, rSTR1
+	ldbrx	rWORD2, 0, rSTR2
+	addi	rSTR1, rSTR1, 8
+	addi	rSTR2, rSTR2, 8
+#else
+	ld	rWORD1, 8(rSTR1)
+	ld	rWORD2, 8(rSTR2)
+#endif
+	cmpld	cr1, rWORD3, rWORD4
+	bne	cr6, L(dLcr6)
 L(dLoop1):
-	ld	rWORD3,16(rSTR1)
-	ld	rWORD4,16(rSTR2)
-	cmpld	cr6,rWORD5,rWORD6
-	bne	cr5,L(dLcr5)
+#ifdef __LITTLE_ENDIAN__
+	ldbrx	rWORD3, 0, rSTR1
+	ldbrx	rWORD4, 0, rSTR2
+	addi	rSTR1, rSTR1, 8
+	addi	rSTR2, rSTR2, 8
+#else
+	ld	rWORD3, 16(rSTR1)
+	ld	rWORD4, 16(rSTR2)
+#endif
+	cmpld	cr6, rWORD5, rWORD6
+	bne	cr5, L(dLcr5)
 L(dLoop2):
-	ld	rWORD5,24(rSTR1)
-	ld	rWORD6,24(rSTR2)
-	cmpld	cr5,rWORD7,rWORD8
-	bne	cr0,L(dLcr0)
+#ifdef __LITTLE_ENDIAN__
+	ldbrx	rWORD5, 0, rSTR1
+	ldbrx	rWORD6, 0, rSTR2
+	addi	rSTR1, rSTR1, 8
+	addi	rSTR2, rSTR2, 8
+#else
+	ld	rWORD5, 24(rSTR1)
+	ld	rWORD6, 24(rSTR2)
+#endif
+	cmpld	cr5, rWORD7, rWORD8
+	bne	cr7, L(dLcr7)
 L(dLoop3):
-	ldu	rWORD7,32(rSTR1)
-	ldu	rWORD8,32(rSTR2)
-	bne	cr1,L(dLcr1)
-	cmpld	cr0,rWORD1,rWORD2
+#ifdef __LITTLE_ENDIAN__
+	ldbrx	rWORD7, 0, rSTR1
+	ldbrx	rWORD8, 0, rSTR2
+	addi	rSTR1, rSTR1, 8
+	addi	rSTR2, rSTR2, 8
+#else
+	ldu	rWORD7, 32(rSTR1)
+	ldu	rWORD8, 32(rSTR2)
+#endif
+	bne	cr1, L(dLcr1)
+	cmpld	cr7, rWORD1, rWORD2
 	bdnz	L(dLoop)
 
 L(dL4):
-	cmpld	cr1,rWORD3,rWORD4
-	bne	cr6,L(dLcr6)
-	cmpld	cr6,rWORD5,rWORD6
-	bne	cr5,L(dLcr5)
-	cmpld	cr5,rWORD7,rWORD8
+	cmpld	cr1, rWORD3, rWORD4
+	bne	cr6, L(dLcr6)
+	cmpld	cr6, rWORD5, rWORD6
+	bne	cr5, L(dLcr5)
+	cmpld	cr5, rWORD7, rWORD8
 L(d44):
-	bne	cr0,L(dLcr0)
+	bne	cr7, L(dLcr7)
 L(d34):
-	bne	cr1,L(dLcr1)
+	bne	cr1, L(dLcr1)
 L(d24):
-	bne	cr6,L(dLcr6)
+	bne	cr6, L(dLcr6)
 L(d14):
-	sldi.	r12,rN,3
-	bne	cr5,L(dLcr5)
+	sldi.	r12, rN, 3
+	bne	cr5, L(dLcr5)
 L(d04):
-	ld	rWORD8,-8(r1)
-	ld	rWORD7,-16(r1)
-	subfic	rN,r12,64	/* Shift count is 64 - (rN * 8).  */
+	ld	rWORD8, -8(r1)
+	ld	rWORD7, -16(r1)
+	subfic	rN, r12, 64	/* Shift count is 64 - (rN * 8).  */
 	beq	L(zeroLength)
 /* At this point we have a remainder of 1 to 7 bytes to compare.  Since
    we are aligned it is safe to load the whole double word, and use
    shift right double to eliminate bits beyond the compare length.  */
 L(d00):
-	ld	rWORD1,8(rSTR1)
-	ld	rWORD2,8(rSTR2)
-	srd	rWORD1,rWORD1,rN
-	srd	rWORD2,rWORD2,rN
-	cmpld	cr5,rWORD1,rWORD2
-	bne	cr5,L(dLcr5x)
-	li	rRTN,0
+#ifdef __LITTLE_ENDIAN__
+	ldbrx	rWORD1, 0, rSTR1
+	ldbrx	rWORD2, 0, rSTR2
+	addi	rSTR1, rSTR1, 8
+	addi	rSTR2, rSTR2, 8
+#else
+	ld	rWORD1, 8(rSTR1)
+	ld	rWORD2, 8(rSTR2)
+#endif
+	srd	rWORD1, rWORD1, rN
+	srd	rWORD2, rWORD2, rN
+	cmpld	cr7, rWORD1, rWORD2
+	bne	cr7, L(dLcr7x)
+	li	rRTN, 0
 	blr
+
 	.align	4
-L(dLcr0):
-	ld	rWORD8,-8(r1)
-	ld	rWORD7,-16(r1)
-	li	rRTN,1
-	bgtlr	cr0
-	li	rRTN,-1
+L(dLcr7):
+	ld	rWORD8, -8(r1)
+	ld	rWORD7, -16(r1)
+L(dLcr7x):
+	li	rRTN, 1
+	bgtlr	cr7
+	li	rRTN, -1
 	blr
 	.align	4
 L(dLcr1):
-	ld	rWORD8,-8(r1)
-	ld	rWORD7,-16(r1)
-	li	rRTN,1
+	ld	rWORD8, -8(r1)
+	ld	rWORD7, -16(r1)
+L(dLcr1x):
+	li	rRTN, 1
 	bgtlr	cr1
-	li	rRTN,-1
+	li	rRTN, -1
 	blr
 	.align	4
 L(dLcr6):
-	ld	rWORD8,-8(r1)
-	ld	rWORD7,-16(r1)
-	li	rRTN,1
+	ld	rWORD8, -8(r1)
+	ld	rWORD7, -16(r1)
+L(dLcr6x):
+	li	rRTN, 1
 	bgtlr	cr6
-	li	rRTN,-1
+	li	rRTN, -1
 	blr
 	.align	4
 L(dLcr5):
-	ld	rWORD8,-8(r1)
-	ld	rWORD7,-16(r1)
+	ld	rWORD8, -8(r1)
+	ld	rWORD7, -16(r1)
 L(dLcr5x):
-	li	rRTN,1
+	li	rRTN, 1
 	bgtlr	cr5
-	li	rRTN,-1
+	li	rRTN, -1
 	blr
 
 	.align	4
 L(bytealigned):
 	mtctr	rN
-	beq	cr6,L(zeroLength)
+#if 0
+/* Huh?  We've already branched on cr6!  */
+	beq	cr6, L(zeroLength)
+#endif
 
 /* We need to prime this loop.  This loop is swing modulo scheduled
    to avoid pipe delays.  The dependent instruction latencies (load to
@@ -396,38 +598,38 @@ L(bytealigned):
    So we must precondition some registers and condition codes so that
    we don't exit the loop early on the first iteration.  */
 
-	lbz	rWORD1,0(rSTR1)
-	lbz	rWORD2,0(rSTR2)
+	lbz	rWORD1, 0(rSTR1)
+	lbz	rWORD2, 0(rSTR2)
 	bdz	L(b11)
-	cmpld	cr0,rWORD1,rWORD2
-	lbz	rWORD3,1(rSTR1)
-	lbz	rWORD4,1(rSTR2)
+	cmpld	cr7, rWORD1, rWORD2
+	lbz	rWORD3, 1(rSTR1)
+	lbz	rWORD4, 1(rSTR2)
 	bdz	L(b12)
-	cmpld	cr1,rWORD3,rWORD4
-	lbzu	rWORD5,2(rSTR1)
-	lbzu	rWORD6,2(rSTR2)
+	cmpld	cr1, rWORD3, rWORD4
+	lbzu	rWORD5, 2(rSTR1)
+	lbzu	rWORD6, 2(rSTR2)
 	bdz	L(b13)
 	.align	4
 L(bLoop):
-	lbzu	rWORD1,1(rSTR1)
-	lbzu	rWORD2,1(rSTR2)
-	bne	cr0,L(bLcr0)
+	lbzu	rWORD1, 1(rSTR1)
+	lbzu	rWORD2, 1(rSTR2)
+	bne	cr7, L(bLcr7)
 
-	cmpld	cr6,rWORD5,rWORD6
+	cmpld	cr6, rWORD5, rWORD6
 	bdz	L(b3i)
 
-	lbzu	rWORD3,1(rSTR1)
-	lbzu	rWORD4,1(rSTR2)
-	bne	cr1,L(bLcr1)
+	lbzu	rWORD3, 1(rSTR1)
+	lbzu	rWORD4, 1(rSTR2)
+	bne	cr1, L(bLcr1)
 
-	cmpld	cr0,rWORD1,rWORD2
+	cmpld	cr7, rWORD1, rWORD2
 	bdz	L(b2i)
 
-	lbzu	rWORD5,1(rSTR1)
-	lbzu	rWORD6,1(rSTR2)
-	bne	cr6,L(bLcr6)
+	lbzu	rWORD5, 1(rSTR1)
+	lbzu	rWORD6, 1(rSTR2)
+	bne	cr6, L(bLcr6)
 
-	cmpld	cr1,rWORD3,rWORD4
+	cmpld	cr1, rWORD3, rWORD4
 	bdnz	L(bLoop)
 
 /* We speculatively loading bytes before we have tested the previous
@@ -437,542 +639,727 @@ L(bLoop):
    tested.  In this case we must complete the pending operations
    before returning.  */
 L(b1i):
-	bne	cr0,L(bLcr0)
-	bne	cr1,L(bLcr1)
+	bne	cr7, L(bLcr7)
+	bne	cr1, L(bLcr1)
 	b	L(bx56)
 	.align	4
 L(b2i):
-	bne	cr6,L(bLcr6)
-	bne	cr0,L(bLcr0)
+	bne	cr6, L(bLcr6)
+	bne	cr7, L(bLcr7)
 	b	L(bx34)
 	.align	4
 L(b3i):
-	bne	cr1,L(bLcr1)
-	bne	cr6,L(bLcr6)
+	bne	cr1, L(bLcr1)
+	bne	cr6, L(bLcr6)
 	b	L(bx12)
 	.align	4
-L(bLcr0):
-	li	rRTN,1
-	bgtlr	cr0
-	li	rRTN,-1
+L(bLcr7):
+	li	rRTN, 1
+	bgtlr	cr7
+	li	rRTN, -1
 	blr
 L(bLcr1):
-	li	rRTN,1
+	li	rRTN, 1
 	bgtlr	cr1
-	li	rRTN,-1
+	li	rRTN, -1
 	blr
 L(bLcr6):
-	li	rRTN,1
+	li	rRTN, 1
 	bgtlr	cr6
-	li	rRTN,-1
+	li	rRTN, -1
 	blr
 
 L(b13):
-	bne	cr0,L(bx12)
-	bne	cr1,L(bx34)
+	bne	cr7, L(bx12)
+	bne	cr1, L(bx34)
 L(bx56):
-	sub	rRTN,rWORD5,rWORD6
+	sub	rRTN, rWORD5, rWORD6
 	blr
 	nop
 L(b12):
-	bne	cr0,L(bx12)
+	bne	cr7, L(bx12)
 L(bx34):
-	sub	rRTN,rWORD3,rWORD4
+	sub	rRTN, rWORD3, rWORD4
 	blr
 L(b11):
 L(bx12):
-	sub	rRTN,rWORD1,rWORD2
+	sub	rRTN, rWORD1, rWORD2
 	blr
 	.align	4
-L(zeroLengthReturn):
-	ld	rWORD8,-8(r1)
-	ld	rWORD7,-16(r1)
 L(zeroLength):
-	li	rRTN,0
+	li	rRTN, 0
 	blr
 
 	.align	4
 /* At this point we know the strings have different alignment and the
-   compare length is at least 8 bytes.  rBITDIF contains the low order
+   compare length is at least 8 bytes.  r12 contains the low order
    3 bits of rSTR1 and cr5 contains the result of the logical compare
-   of rBITDIF to 0.  If rBITDIF == 0 then rStr1 is double word
+   of r12 to 0.  If r12 == 0 then rStr1 is double word
    aligned and can perform the DWunaligned loop.
 
    Otherwise we know that rSTR1 is not already DW aligned yet.
    So we can force the string addresses to the next lower DW
-   boundary and special case this first DW word using shift left to
+   boundary and special case this first DW using shift left to
    eliminate bits preceding the first byte.  Since we want to join the
    normal (DWaligned) compare loop, starting at the second double word,
    we need to adjust the length (rN) and special case the loop
-   versioning for the first DW. This insures that the loop count is
+   versioning for the first DW. This ensures that the loop count is
    correct and the first DW (shifted) is in the expected resister pair.  */
-#define rSHL	r29	/* Unaligned shift left count.  */
-#define rSHR	r28	/* Unaligned shift right count.  */
-#define rB		r27	/* Left rotation temp for rWORD2.  */
-#define rD		r26	/* Left rotation temp for rWORD4.  */
-#define rF		r25	/* Left rotation temp for rWORD6.  */
-#define rH		r24	/* Left rotation temp for rWORD8.  */
-#define rA		r0	/* Right rotation temp for rWORD2.  */
-#define rC		r12	/* Right rotation temp for rWORD4.  */
-#define rE		r0	/* Right rotation temp for rWORD6.  */
-#define rG		r12	/* Right rotation temp for rWORD8.  */
+#define rSHL		r29	/* Unaligned shift left count.  */
+#define rSHR		r28	/* Unaligned shift right count.  */
+#define rWORD8_SHIFT	r27	/* Left rotation temp for rWORD2.  */
+#define rWORD2_SHIFT	r26	/* Left rotation temp for rWORD4.  */
+#define rWORD4_SHIFT	r25	/* Left rotation temp for rWORD6.  */
+#define rWORD6_SHIFT	r24	/* Left rotation temp for rWORD8.  */
 L(unaligned):
-	std	r29,-24(r1)
-	cfi_offset(r29,-24)
-	clrldi	rSHL,rSTR2,61
-	beq	cr6,L(duzeroLength)
-	std	r28,-32(r1)
-	cfi_offset(r28,-32)
-	beq	cr5,L(DWunaligned)
-	std	r27,-40(r1)
-	cfi_offset(r27,-40)
-/* Adjust the logical start of rSTR2 ro compensate for the extra bits
+	std	rSHL, -24(r1)
+	cfi_offset(rSHL, -24)
+	clrldi	rSHL, rSTR2, 61
+	beq	cr6, L(duzeroLength)
+	std	rSHR, -32(r1)
+	cfi_offset(rSHR, -32)
+	beq	cr5, L(DWunaligned)
+	std	rWORD8_SHIFT, -40(r1)
+	cfi_offset(rWORD8_SHIFT, -40)
+/* Adjust the logical start of rSTR2 to compensate for the extra bits
    in the 1st rSTR1 DW.  */
-	sub	r27,rSTR2,rBITDIF
+	sub	rWORD8_SHIFT, rSTR2, r12
 /* But do not attempt to address the DW before that DW that contains
    the actual start of rSTR2.  */
-	clrrdi	rSTR2,rSTR2,3
-	std	r26,-48(r1)
-	cfi_offset(r26,-48)
+	clrrdi	rSTR2, rSTR2, 3
+	std	rWORD2_SHIFT, -48(r1)
+	cfi_offset(rWORD2_SHIFT, -48)
 /* Compute the left/right shift counts for the unaligned rSTR2,
    compensating for the logical (DW aligned) start of rSTR1.  */
-	clrldi	rSHL,r27,61
-	clrrdi	rSTR1,rSTR1,3
-	std	r25,-56(r1)
-	cfi_offset(r25,-56)
-	sldi	rSHL,rSHL,3
-	cmpld	cr5,r27,rSTR2
-	add	rN,rN,rBITDIF
-	sldi	r11,rBITDIF,3
-	std	r24,-64(r1)
-	cfi_offset(r24,-64)
-	subfic	rSHR,rSHL,64
-	srdi	rTMP,rN,5	/* Divide by 32 */
-	andi.	rBITDIF,rN,24	/* Get the DW remainder */
+	clrldi	rSHL, rWORD8_SHIFT, 61
+	clrrdi	rSTR1, rSTR1, 3
+	std	rWORD4_SHIFT, -56(r1)
+	cfi_offset(rWORD4_SHIFT, -56)
+	sldi	rSHL, rSHL, 3
+	cmpld	cr5, rWORD8_SHIFT, rSTR2
+	add	rN, rN, r12
+	sldi	rWORD6, r12, 3
+	std	rWORD6_SHIFT, -64(r1)
+	cfi_offset(rWORD6_SHIFT, -64)
+	subfic	rSHR, rSHL, 64
+	srdi	r0, rN, 5	/* Divide by 32 */
+	andi.	r12, rN, 24	/* Get the DW remainder */
 /* We normally need to load 2 DWs to start the unaligned rSTR2, but in
    this special case those bits may be discarded anyway.  Also we
    must avoid loading a DW where none of the bits are part of rSTR2 as
    this may cross a page boundary and cause a page fault.  */
-	li	rWORD8,0
-	blt	cr5,L(dus0)
-	ld	rWORD8,0(rSTR2)
-	la	rSTR2,8(rSTR2)
-	sld	rWORD8,rWORD8,rSHL
+	li	rWORD8, 0
+	blt	cr5, L(dus0)
+#ifdef __LITTLE_ENDIAN__
+	ldbrx	rWORD8, 0, rSTR2
+	addi	rSTR2, rSTR2, 8
+#else
+	ld	rWORD8, 0(rSTR2)
+	addi	rSTR2, rSTR2, 8
+#endif
+	sld	rWORD8, rWORD8, rSHL
 
 L(dus0):
-	ld	rWORD1,0(rSTR1)
-	ld	rWORD2,0(rSTR2)
-	cmpldi	cr1,rBITDIF,16
-	cmpldi	cr7,rN,32
-	srd	rG,rWORD2,rSHR
-	clrldi	rN,rN,61
+#ifdef __LITTLE_ENDIAN__
+	ldbrx	rWORD1, 0, rSTR1
+	ldbrx	rWORD2, 0, rSTR2
+	addi	rSTR1, rSTR1, 8
+	addi	rSTR2, rSTR2, 8
+#else
+	ld	rWORD1, 0(rSTR1)
+	ld	rWORD2, 0(rSTR2)
+#endif
+	cmpldi	cr1, r12, 16
+	cmpldi	cr7, rN, 32
+	srd	r12, rWORD2, rSHR
+	clrldi	rN, rN, 61
 	beq	L(duPs4)
-	mtctr	rTMP
-	or	rWORD8,rG,rWORD8
-	bgt	cr1,L(duPs3)
-	beq	cr1,L(duPs2)
+	mtctr	r0
+	or	rWORD8, r12, rWORD8
+	bgt	cr1, L(duPs3)
+	beq	cr1, L(duPs2)
 
 /* Remainder is 8 */
 	.align	4
 L(dusP1):
-	sld	rB,rWORD2,rSHL
-	sld	rWORD7,rWORD1,r11
-	sld	rWORD8,rWORD8,r11
-	bge	cr7,L(duP1e)
+	sld	rWORD8_SHIFT, rWORD2, rSHL
+	sld	rWORD7, rWORD1, rWORD6
+	sld	rWORD8, rWORD8, rWORD6
+	bge	cr7, L(duP1e)
 /* At this point we exit early with the first double word compare
    complete and remainder of 0 to 7 bytes.  See L(du14) for details on
    how we handle the remaining bytes.  */
-	cmpld	cr5,rWORD7,rWORD8
-	sldi.	rN,rN,3
-	bne	cr5,L(duLcr5)
-	cmpld	cr7,rN,rSHR
+	cmpld	cr5, rWORD7, rWORD8
+	sldi.	rN, rN, 3
+	bne	cr5, L(duLcr5)
+	cmpld	cr7, rN, rSHR
 	beq	L(duZeroReturn)
-	li	rA,0
-	ble	cr7,L(dutrim)
-	ld	rWORD2,8(rSTR2)
-	srd	rA,rWORD2,rSHR
+	li	r0, 0
+	ble	cr7, L(dutrim)
+#ifdef __LITTLE_ENDIAN__
+	ldbrx	rWORD2, 0, rSTR2
+	addi	rSTR2, rSTR2, 8
+#else
+	ld	rWORD2, 8(rSTR2)
+#endif
+	srd	r0, rWORD2, rSHR
 	b	L(dutrim)
 /* Remainder is 16 */
 	.align	4
 L(duPs2):
-	sld	rH,rWORD2,rSHL
-	sld	rWORD5,rWORD1,r11
-	sld	rWORD6,rWORD8,r11
+	sld	rWORD6_SHIFT, rWORD2, rSHL
+	sld	rWORD5, rWORD1, rWORD6
+	sld	rWORD6, rWORD8, rWORD6
 	b	L(duP2e)
 /* Remainder is 24 */
 	.align	4
 L(duPs3):
-	sld	rF,rWORD2,rSHL
-	sld	rWORD3,rWORD1,r11
-	sld	rWORD4,rWORD8,r11
+	sld	rWORD4_SHIFT, rWORD2, rSHL
+	sld	rWORD3, rWORD1, rWORD6
+	sld	rWORD4, rWORD8, rWORD6
 	b	L(duP3e)
 /* Count is a multiple of 32, remainder is 0 */
 	.align	4
 L(duPs4):
-	mtctr	rTMP
-	or	rWORD8,rG,rWORD8
-	sld	rD,rWORD2,rSHL
-	sld	rWORD1,rWORD1,r11
-	sld	rWORD2,rWORD8,r11
+	mtctr	r0
+	or	rWORD8, r12, rWORD8
+	sld	rWORD2_SHIFT, rWORD2, rSHL
+	sld	rWORD1, rWORD1, rWORD6
+	sld	rWORD2, rWORD8, rWORD6
 	b	L(duP4e)
 
 /* At this point we know rSTR1 is double word aligned and the
    compare length is at least 8 bytes.  */
 	.align	4
 L(DWunaligned):
-	std	r27,-40(r1)
-	cfi_offset(r27,-40)
-	clrrdi	rSTR2,rSTR2,3
-	std	r26,-48(r1)
-	cfi_offset(r26,-48)
-	srdi	rTMP,rN,5	/* Divide by 32 */
-	std	r25,-56(r1)
-	cfi_offset(r25,-56)
-	andi.	rBITDIF,rN,24	/* Get the DW remainder */
-	std	r24,-64(r1)
-	cfi_offset(r24,-64)
-	sldi	rSHL,rSHL,3
-	ld	rWORD6,0(rSTR2)
-	ldu	rWORD8,8(rSTR2)
-	cmpldi	cr1,rBITDIF,16
-	cmpldi	cr7,rN,32
-	clrldi	rN,rN,61
-	subfic	rSHR,rSHL,64
-	sld	rH,rWORD6,rSHL
+	std	rWORD8_SHIFT, -40(r1)
+	cfi_offset(rWORD8_SHIFT, -40)
+	clrrdi	rSTR2, rSTR2, 3
+	std	rWORD2_SHIFT, -48(r1)
+	cfi_offset(rWORD2_SHIFT, -48)
+	srdi	r0, rN, 5	/* Divide by 32 */
+	std	rWORD4_SHIFT, -56(r1)
+	cfi_offset(rWORD4_SHIFT, -56)
+	andi.	r12, rN, 24	/* Get the DW remainder */
+	std	rWORD6_SHIFT, -64(r1)
+	cfi_offset(rWORD6_SHIFT, -64)
+	sldi	rSHL, rSHL, 3
+#ifdef __LITTLE_ENDIAN__
+	ldbrx	rWORD6, 0, rSTR2
+	addi	rSTR2, rSTR2, 8
+	ldbrx	rWORD8, 0, rSTR2
+	addi	rSTR2, rSTR2, 8
+#else
+	ld	rWORD6, 0(rSTR2)
+	ldu	rWORD8, 8(rSTR2)
+#endif
+	cmpldi	cr1, r12, 16
+	cmpldi	cr7, rN, 32
+	clrldi	rN, rN, 61
+	subfic	rSHR, rSHL, 64
+	sld	rWORD6_SHIFT, rWORD6, rSHL
 	beq	L(duP4)
-	mtctr	rTMP
-	bgt	cr1,L(duP3)
-	beq	cr1,L(duP2)
+	mtctr	r0
+	bgt	cr1, L(duP3)
+	beq	cr1, L(duP2)
 
 /* Remainder is 8 */
 	.align	4
 L(duP1):
-	srd	rG,rWORD8,rSHR
-	ld	rWORD7,0(rSTR1)
-	sld	rB,rWORD8,rSHL
-	or	rWORD8,rG,rH
-	blt	cr7,L(duP1x)
+	srd	r12, rWORD8, rSHR
+#ifdef __LITTLE_ENDIAN__
+	ldbrx	rWORD7, 0, rSTR1
+	addi	rSTR1, rSTR1, 8
+#else
+	ld	rWORD7, 0(rSTR1)
+#endif
+	sld	rWORD8_SHIFT, rWORD8, rSHL
+	or	rWORD8, r12, rWORD6_SHIFT
+	blt	cr7, L(duP1x)
 L(duP1e):
-	ld	rWORD1,8(rSTR1)
-	ld	rWORD2,8(rSTR2)
-	cmpld	cr5,rWORD7,rWORD8
-	srd	rA,rWORD2,rSHR
-	sld	rD,rWORD2,rSHL
-	or	rWORD2,rA,rB
-	ld	rWORD3,16(rSTR1)
-	ld	rWORD4,16(rSTR2)
-	cmpld	cr0,rWORD1,rWORD2
-	srd	rC,rWORD4,rSHR
-	sld	rF,rWORD4,rSHL
-	bne	cr5,L(duLcr5)
-	or	rWORD4,rC,rD
-	ld	rWORD5,24(rSTR1)
-	ld	rWORD6,24(rSTR2)
-	cmpld	cr1,rWORD3,rWORD4
-	srd	rE,rWORD6,rSHR
-	sld	rH,rWORD6,rSHL
-	bne	cr0,L(duLcr0)
-	or	rWORD6,rE,rF
-	cmpld	cr6,rWORD5,rWORD6
+#ifdef __LITTLE_ENDIAN__
+	ldbrx	rWORD1, 0, rSTR1
+	ldbrx	rWORD2, 0, rSTR2
+	addi	rSTR1, rSTR1, 8
+	addi	rSTR2, rSTR2, 8
+#else
+	ld	rWORD1, 8(rSTR1)
+	ld	rWORD2, 8(rSTR2)
+#endif
+	cmpld	cr5, rWORD7, rWORD8
+	srd	r0, rWORD2, rSHR
+	sld	rWORD2_SHIFT, rWORD2, rSHL
+	or	rWORD2, r0, rWORD8_SHIFT
+#ifdef __LITTLE_ENDIAN__
+	ldbrx	rWORD3, 0, rSTR1
+	ldbrx	rWORD4, 0, rSTR2
+	addi	rSTR1, rSTR1, 8
+	addi	rSTR2, rSTR2, 8
+#else
+	ld	rWORD3, 16(rSTR1)
+	ld	rWORD4, 16(rSTR2)
+#endif
+	cmpld	cr7, rWORD1, rWORD2
+	srd	r12, rWORD4, rSHR
+	sld	rWORD4_SHIFT, rWORD4, rSHL
+	bne	cr5, L(duLcr5)
+	or	rWORD4, r12, rWORD2_SHIFT
+#ifdef __LITTLE_ENDIAN__
+	ldbrx	rWORD5, 0, rSTR1
+	ldbrx	rWORD6, 0, rSTR2
+	addi	rSTR1, rSTR1, 8
+	addi	rSTR2, rSTR2, 8
+#else
+	ld	rWORD5, 24(rSTR1)
+	ld	rWORD6, 24(rSTR2)
+#endif
+	cmpld	cr1, rWORD3, rWORD4
+	srd	r0, rWORD6, rSHR
+	sld	rWORD6_SHIFT, rWORD6, rSHL
+	bne	cr7, L(duLcr7)
+	or	rWORD6, r0, rWORD4_SHIFT
+	cmpld	cr6, rWORD5, rWORD6
 	b	L(duLoop3)
 	.align	4
 /* At this point we exit early with the first double word compare
    complete and remainder of 0 to 7 bytes.  See L(du14) for details on
    how we handle the remaining bytes.  */
 L(duP1x):
-	cmpld	cr5,rWORD7,rWORD8
-	sldi.	rN,rN,3
-	bne	cr5,L(duLcr5)
-	cmpld	cr7,rN,rSHR
+	cmpld	cr5, rWORD7, rWORD8
+	sldi.	rN, rN, 3
+	bne	cr5, L(duLcr5)
+	cmpld	cr7, rN, rSHR
 	beq	L(duZeroReturn)
-	li	rA,0
-	ble	cr7,L(dutrim)
-	ld	rWORD2,8(rSTR2)
-	srd	rA,rWORD2,rSHR
+	li	r0, 0
+	ble	cr7, L(dutrim)
+#ifdef __LITTLE_ENDIAN__
+	ldbrx	rWORD2, 0, rSTR2
+	addi	rSTR2, rSTR2, 8
+#else
+	ld	rWORD2, 8(rSTR2)
+#endif
+	srd	r0, rWORD2, rSHR
 	b	L(dutrim)
 /* Remainder is 16 */
 	.align	4
 L(duP2):
-	srd	rE,rWORD8,rSHR
-	ld	rWORD5,0(rSTR1)
-	or	rWORD6,rE,rH
-	sld	rH,rWORD8,rSHL
+	srd	r0, rWORD8, rSHR
+#ifdef __LITTLE_ENDIAN__
+	ldbrx	rWORD5, 0, rSTR1
+	addi	rSTR1, rSTR1, 8
+#else
+	ld	rWORD5, 0(rSTR1)
+#endif
+	or	rWORD6, r0, rWORD6_SHIFT
+	sld	rWORD6_SHIFT, rWORD8, rSHL
 L(duP2e):
-	ld	rWORD7,8(rSTR1)
-	ld	rWORD8,8(rSTR2)
-	cmpld	cr6,rWORD5,rWORD6
-	srd	rG,rWORD8,rSHR
-	sld	rB,rWORD8,rSHL
-	or	rWORD8,rG,rH
-	blt	cr7,L(duP2x)
-	ld	rWORD1,16(rSTR1)
-	ld	rWORD2,16(rSTR2)
-	cmpld	cr5,rWORD7,rWORD8
-	bne	cr6,L(duLcr6)
-	srd	rA,rWORD2,rSHR
-	sld	rD,rWORD2,rSHL
-	or	rWORD2,rA,rB
-	ld	rWORD3,24(rSTR1)
-	ld	rWORD4,24(rSTR2)
-	cmpld	cr0,rWORD1,rWORD2
-	bne	cr5,L(duLcr5)
-	srd	rC,rWORD4,rSHR
-	sld	rF,rWORD4,rSHL
-	or	rWORD4,rC,rD
-	addi	rSTR1,rSTR1,8
-	addi	rSTR2,rSTR2,8
-	cmpld	cr1,rWORD3,rWORD4
+#ifdef __LITTLE_ENDIAN__
+	ldbrx	rWORD7, 0, rSTR1
+	ldbrx	rWORD8, 0, rSTR2
+	addi	rSTR1, rSTR1, 8
+	addi	rSTR2, rSTR2, 8
+#else
+	ld	rWORD7, 8(rSTR1)
+	ld	rWORD8, 8(rSTR2)
+#endif
+	cmpld	cr6, rWORD5, rWORD6
+	srd	r12, rWORD8, rSHR
+	sld	rWORD8_SHIFT, rWORD8, rSHL
+	or	rWORD8, r12, rWORD6_SHIFT
+	blt	cr7, L(duP2x)
+#ifdef __LITTLE_ENDIAN__
+	ldbrx	rWORD1, 0, rSTR1
+	ldbrx	rWORD2, 0, rSTR2
+	addi	rSTR1, rSTR1, 8
+	addi	rSTR2, rSTR2, 8
+#else
+	ld	rWORD1, 16(rSTR1)
+	ld	rWORD2, 16(rSTR2)
+#endif
+	cmpld	cr5, rWORD7, rWORD8
+	bne	cr6, L(duLcr6)
+	srd	r0, rWORD2, rSHR
+	sld	rWORD2_SHIFT, rWORD2, rSHL
+	or	rWORD2, r0, rWORD8_SHIFT
+#ifdef __LITTLE_ENDIAN__
+	ldbrx	rWORD3, 0, rSTR1
+	ldbrx	rWORD4, 0, rSTR2
+	addi	rSTR1, rSTR1, 8
+	addi	rSTR2, rSTR2, 8
+#else
+	ld	rWORD3, 24(rSTR1)
+	ld	rWORD4, 24(rSTR2)
+#endif
+	cmpld	cr7, rWORD1, rWORD2
+	bne	cr5, L(duLcr5)
+	srd	r12, rWORD4, rSHR
+	sld	rWORD4_SHIFT, rWORD4, rSHL
+	or	rWORD4, r12, rWORD2_SHIFT
+#ifndef __LITTLE_ENDIAN__
+	addi	rSTR1, rSTR1, 8
+	addi	rSTR2, rSTR2, 8
+#endif
+	cmpld	cr1, rWORD3, rWORD4
 	b	L(duLoop2)
 	.align	4
 L(duP2x):
-	cmpld	cr5,rWORD7,rWORD8
-	addi	rSTR1,rSTR1,8
-	addi	rSTR2,rSTR2,8
-	bne	cr6,L(duLcr6)
-	sldi.	rN,rN,3
-	bne	cr5,L(duLcr5)
-	cmpld	cr7,rN,rSHR
+	cmpld	cr5, rWORD7, rWORD8
+#ifndef __LITTLE_ENDIAN__
+	addi	rSTR1, rSTR1, 8
+	addi	rSTR2, rSTR2, 8
+#endif
+	bne	cr6, L(duLcr6)
+	sldi.	rN, rN, 3
+	bne	cr5, L(duLcr5)
+	cmpld	cr7, rN, rSHR
 	beq	L(duZeroReturn)
-	li	rA,0
-	ble	cr7,L(dutrim)
-	ld	rWORD2,8(rSTR2)
-	srd	rA,rWORD2,rSHR
+	li	r0, 0
+	ble	cr7, L(dutrim)
+#ifdef __LITTLE_ENDIAN__
+	ldbrx	rWORD2, 0, rSTR2
+	addi	rSTR2, rSTR2, 8
+#else
+	ld	rWORD2, 8(rSTR2)
+#endif
+	srd	r0, rWORD2, rSHR
 	b	L(dutrim)
 
 /* Remainder is 24 */
 	.align	4
 L(duP3):
-	srd	rC,rWORD8,rSHR
-	ld	rWORD3,0(rSTR1)
-	sld	rF,rWORD8,rSHL
-	or	rWORD4,rC,rH
+	srd	r12, rWORD8, rSHR
+#ifdef __LITTLE_ENDIAN__
+	ldbrx	rWORD3, 0, rSTR1
+	addi	rSTR1, rSTR1, 8
+#else
+	ld	rWORD3, 0(rSTR1)
+#endif
+	sld	rWORD4_SHIFT, rWORD8, rSHL
+	or	rWORD4, r12, rWORD6_SHIFT
 L(duP3e):
-	ld	rWORD5,8(rSTR1)
-	ld	rWORD6,8(rSTR2)
-	cmpld	cr1,rWORD3,rWORD4
-	srd	rE,rWORD6,rSHR
-	sld	rH,rWORD6,rSHL
-	or	rWORD6,rE,rF
-	ld	rWORD7,16(rSTR1)
-	ld	rWORD8,16(rSTR2)
-	cmpld	cr6,rWORD5,rWORD6
-	bne	cr1,L(duLcr1)
-	srd	rG,rWORD8,rSHR
-	sld	rB,rWORD8,rSHL
-	or	rWORD8,rG,rH
-	blt	cr7,L(duP3x)
-	ld	rWORD1,24(rSTR1)
-	ld	rWORD2,24(rSTR2)
-	cmpld	cr5,rWORD7,rWORD8
-	bne	cr6,L(duLcr6)
-	srd	rA,rWORD2,rSHR
-	sld	rD,rWORD2,rSHL
-	or	rWORD2,rA,rB
-	addi	rSTR1,rSTR1,16
-	addi	rSTR2,rSTR2,16
-	cmpld	cr0,rWORD1,rWORD2
+#ifdef __LITTLE_ENDIAN__
+	ldbrx	rWORD5, 0, rSTR1
+	ldbrx	rWORD6, 0, rSTR2
+	addi	rSTR1, rSTR1, 8
+	addi	rSTR2, rSTR2, 8
+#else
+	ld	rWORD5, 8(rSTR1)
+	ld	rWORD6, 8(rSTR2)
+#endif
+	cmpld	cr1, rWORD3, rWORD4
+	srd	r0, rWORD6, rSHR
+	sld	rWORD6_SHIFT, rWORD6, rSHL
+	or	rWORD6, r0, rWORD4_SHIFT
+#ifdef __LITTLE_ENDIAN__
+	ldbrx	rWORD7, 0, rSTR1
+	ldbrx	rWORD8, 0, rSTR2
+	addi	rSTR1, rSTR1, 8
+	addi	rSTR2, rSTR2, 8
+#else
+	ld	rWORD7, 16(rSTR1)
+	ld	rWORD8, 16(rSTR2)
+#endif
+	cmpld	cr6, rWORD5, rWORD6
+	bne	cr1, L(duLcr1)
+	srd	r12, rWORD8, rSHR
+	sld	rWORD8_SHIFT, rWORD8, rSHL
+	or	rWORD8, r12, rWORD6_SHIFT
+	blt	cr7, L(duP3x)
+#ifdef __LITTLE_ENDIAN__
+	ldbrx	rWORD1, 0, rSTR1
+	ldbrx	rWORD2, 0, rSTR2
+	addi	rSTR1, rSTR1, 8
+	addi	rSTR2, rSTR2, 8
+#else
+	ld	rWORD1, 24(rSTR1)
+	ld	rWORD2, 24(rSTR2)
+#endif
+	cmpld	cr5, rWORD7, rWORD8
+	bne	cr6, L(duLcr6)
+	srd	r0, rWORD2, rSHR
+	sld	rWORD2_SHIFT, rWORD2, rSHL
+	or	rWORD2, r0, rWORD8_SHIFT
+#ifndef __LITTLE_ENDIAN__
+	addi	rSTR1, rSTR1, 16
+	addi	rSTR2, rSTR2, 16
+#endif
+	cmpld	cr7, rWORD1, rWORD2
 	b	L(duLoop1)
 	.align	4
 L(duP3x):
-	addi	rSTR1,rSTR1,16
-	addi	rSTR2,rSTR2,16
-	bne	cr1,L(duLcr1)
-	cmpld	cr5,rWORD7,rWORD8
-	bne	cr6,L(duLcr6)
-	sldi.	rN,rN,3
-	bne	cr5,L(duLcr5)
-	cmpld	cr7,rN,rSHR
+#ifndef __LITTLE_ENDIAN__
+	addi	rSTR1, rSTR1, 16
+	addi	rSTR2, rSTR2, 16
+#endif
+#if 0
+/* Huh?  We've already branched on cr1!  */
+	bne	cr1, L(duLcr1)
+#endif
+	cmpld	cr5, rWORD7, rWORD8
+	bne	cr6, L(duLcr6)
+	sldi.	rN, rN, 3
+	bne	cr5, L(duLcr5)
+	cmpld	cr7, rN, rSHR
 	beq	L(duZeroReturn)
-	li	rA,0
-	ble	cr7,L(dutrim)
-	ld	rWORD2,8(rSTR2)
-	srd	rA,rWORD2,rSHR
+	li	r0, 0
+	ble	cr7, L(dutrim)
+#ifdef __LITTLE_ENDIAN__
+	ldbrx	rWORD2, 0, rSTR2
+	addi	rSTR2, rSTR2, 8
+#else
+	ld	rWORD2, 8(rSTR2)
+#endif
+	srd	r0, rWORD2, rSHR
 	b	L(dutrim)
 
 /* Count is a multiple of 32, remainder is 0 */
 	.align	4
 L(duP4):
-	mtctr	rTMP
-	srd	rA,rWORD8,rSHR
-	ld	rWORD1,0(rSTR1)
-	sld	rD,rWORD8,rSHL
-	or	rWORD2,rA,rH
+	mtctr	r0
+	srd	r0, rWORD8, rSHR
+#ifdef __LITTLE_ENDIAN__
+	ldbrx	rWORD1, 0, rSTR1
+	addi	rSTR1, rSTR1, 8
+#else
+	ld	rWORD1, 0(rSTR1)
+#endif
+	sld	rWORD2_SHIFT, rWORD8, rSHL
+	or	rWORD2, r0, rWORD6_SHIFT
 L(duP4e):
-	ld	rWORD3,8(rSTR1)
-	ld	rWORD4,8(rSTR2)
-	cmpld	cr0,rWORD1,rWORD2
-	srd	rC,rWORD4,rSHR
-	sld	rF,rWORD4,rSHL
-	or	rWORD4,rC,rD
-	ld	rWORD5,16(rSTR1)
-	ld	rWORD6,16(rSTR2)
-	cmpld	cr1,rWORD3,rWORD4
-	bne	cr0,L(duLcr0)
-	srd	rE,rWORD6,rSHR
-	sld	rH,rWORD6,rSHL
-	or	rWORD6,rE,rF
-	ldu	rWORD7,24(rSTR1)
-	ldu	rWORD8,24(rSTR2)
-	cmpld	cr6,rWORD5,rWORD6
-	bne	cr1,L(duLcr1)
-	srd	rG,rWORD8,rSHR
-	sld	rB,rWORD8,rSHL
-	or	rWORD8,rG,rH
-	cmpld	cr5,rWORD7,rWORD8
+#ifdef __LITTLE_ENDIAN__
+	ldbrx	rWORD3, 0, rSTR1
+	ldbrx	rWORD4, 0, rSTR2
+	addi	rSTR1, rSTR1, 8
+	addi	rSTR2, rSTR2, 8
+#else
+	ld	rWORD3, 8(rSTR1)
+	ld	rWORD4, 8(rSTR2)
+#endif
+	cmpld	cr7, rWORD1, rWORD2
+	srd	r12, rWORD4, rSHR
+	sld	rWORD4_SHIFT, rWORD4, rSHL
+	or	rWORD4, r12, rWORD2_SHIFT
+#ifdef __LITTLE_ENDIAN__
+	ldbrx	rWORD5, 0, rSTR1
+	ldbrx	rWORD6, 0, rSTR2
+	addi	rSTR1, rSTR1, 8
+	addi	rSTR2, rSTR2, 8
+#else
+	ld	rWORD5, 16(rSTR1)
+	ld	rWORD6, 16(rSTR2)
+#endif
+	cmpld	cr1, rWORD3, rWORD4
+	bne	cr7, L(duLcr7)
+	srd	r0, rWORD6, rSHR
+	sld	rWORD6_SHIFT, rWORD6, rSHL
+	or	rWORD6, r0, rWORD4_SHIFT
+#ifdef __LITTLE_ENDIAN__
+	ldbrx	rWORD7, 0, rSTR1
+	ldbrx	rWORD8, 0, rSTR2
+	addi	rSTR1, rSTR1, 8
+	addi	rSTR2, rSTR2, 8
+#else
+	ldu	rWORD7, 24(rSTR1)
+	ldu	rWORD8, 24(rSTR2)
+#endif
+	cmpld	cr6, rWORD5, rWORD6
+	bne	cr1, L(duLcr1)
+	srd	r12, rWORD8, rSHR
+	sld	rWORD8_SHIFT, rWORD8, rSHL
+	or	rWORD8, r12, rWORD6_SHIFT
+	cmpld	cr5, rWORD7, rWORD8
 	bdz	L(du24)		/* Adjust CTR as we start with +4 */
 /* This is the primary loop */
 	.align	4
 L(duLoop):
-	ld	rWORD1,8(rSTR1)
-	ld	rWORD2,8(rSTR2)
-	cmpld	cr1,rWORD3,rWORD4
-	bne	cr6,L(duLcr6)
-	srd	rA,rWORD2,rSHR
-	sld	rD,rWORD2,rSHL
-	or	rWORD2,rA,rB
+#ifdef __LITTLE_ENDIAN__
+	ldbrx	rWORD1, 0, rSTR1
+	ldbrx	rWORD2, 0, rSTR2
+	addi	rSTR1, rSTR1, 8
+	addi	rSTR2, rSTR2, 8
+#else
+	ld	rWORD1, 8(rSTR1)
+	ld	rWORD2, 8(rSTR2)
+#endif
+	cmpld	cr1, rWORD3, rWORD4
+	bne	cr6, L(duLcr6)
+	srd	r0, rWORD2, rSHR
+	sld	rWORD2_SHIFT, rWORD2, rSHL
+	or	rWORD2, r0, rWORD8_SHIFT
 L(duLoop1):
-	ld	rWORD3,16(rSTR1)
-	ld	rWORD4,16(rSTR2)
-	cmpld	cr6,rWORD5,rWORD6
-	bne	cr5,L(duLcr5)
-	srd	rC,rWORD4,rSHR
-	sld	rF,rWORD4,rSHL
-	or	rWORD4,rC,rD
+#ifdef __LITTLE_ENDIAN__
+	ldbrx	rWORD3, 0, rSTR1
+	ldbrx	rWORD4, 0, rSTR2
+	addi	rSTR1, rSTR1, 8
+	addi	rSTR2, rSTR2, 8
+#else
+	ld	rWORD3, 16(rSTR1)
+	ld	rWORD4, 16(rSTR2)
+#endif
+	cmpld	cr6, rWORD5, rWORD6
+	bne	cr5, L(duLcr5)
+	srd	r12, rWORD4, rSHR
+	sld	rWORD4_SHIFT, rWORD4, rSHL
+	or	rWORD4, r12, rWORD2_SHIFT
 L(duLoop2):
-	ld	rWORD5,24(rSTR1)
-	ld	rWORD6,24(rSTR2)
-	cmpld	cr5,rWORD7,rWORD8
-	bne	cr0,L(duLcr0)
-	srd	rE,rWORD6,rSHR
-	sld	rH,rWORD6,rSHL
-	or	rWORD6,rE,rF
+#ifdef __LITTLE_ENDIAN__
+	ldbrx	rWORD5, 0, rSTR1
+	ldbrx	rWORD6, 0, rSTR2
+	addi	rSTR1, rSTR1, 8
+	addi	rSTR2, rSTR2, 8
+#else
+	ld	rWORD5, 24(rSTR1)
+	ld	rWORD6, 24(rSTR2)
+#endif
+	cmpld	cr5, rWORD7, rWORD8
+	bne	cr7, L(duLcr7)
+	srd	r0, rWORD6, rSHR
+	sld	rWORD6_SHIFT, rWORD6, rSHL
+	or	rWORD6, r0, rWORD4_SHIFT
 L(duLoop3):
-	ldu	rWORD7,32(rSTR1)
-	ldu	rWORD8,32(rSTR2)
-	cmpld	cr0,rWORD1,rWORD2
-	bne-	cr1,L(duLcr1)
-	srd	rG,rWORD8,rSHR
-	sld	rB,rWORD8,rSHL
-	or	rWORD8,rG,rH
+#ifdef __LITTLE_ENDIAN__
+	ldbrx	rWORD7, 0, rSTR1
+	ldbrx	rWORD8, 0, rSTR2
+	addi	rSTR1, rSTR1, 8
+	addi	rSTR2, rSTR2, 8
+#else
+	ldu	rWORD7, 32(rSTR1)
+	ldu	rWORD8, 32(rSTR2)
+#endif
+	cmpld	cr7, rWORD1, rWORD2
+	bne	cr1, L(duLcr1)
+	srd	r12, rWORD8, rSHR
+	sld	rWORD8_SHIFT, rWORD8, rSHL
+	or	rWORD8, r12, rWORD6_SHIFT
 	bdnz	L(duLoop)
 
 L(duL4):
-	bne	cr1,L(duLcr1)
-	cmpld	cr1,rWORD3,rWORD4
-	bne	cr6,L(duLcr6)
-	cmpld	cr6,rWORD5,rWORD6
-	bne	cr5,L(duLcr5)
-	cmpld	cr5,rWORD7,rWORD8
+#if 0
+/* Huh?  We've already branched on cr1!  */
+	bne	cr1, L(duLcr1)
+#endif
+	cmpld	cr1, rWORD3, rWORD4
+	bne	cr6, L(duLcr6)
+	cmpld	cr6, rWORD5, rWORD6
+	bne	cr5, L(duLcr5)
+	cmpld	cr5, rWORD7, rWORD8
 L(du44):
-	bne	cr0,L(duLcr0)
+	bne	cr7, L(duLcr7)
 L(du34):
-	bne	cr1,L(duLcr1)
+	bne	cr1, L(duLcr1)
 L(du24):
-	bne	cr6,L(duLcr6)
+	bne	cr6, L(duLcr6)
 L(du14):
-	sldi.	rN,rN,3
-	bne	cr5,L(duLcr5)
+	sldi.	rN, rN, 3
+	bne	cr5, L(duLcr5)
 /* At this point we have a remainder of 1 to 7 bytes to compare.  We use
    shift right double to eliminate bits beyond the compare length.
-   This allows the use of double word subtract to compute the final
-   result.
 
    However it may not be safe to load rWORD2 which may be beyond the
    string length. So we compare the bit length of the remainder to
    the right shift count (rSHR). If the bit count is less than or equal
    we do not need to load rWORD2 (all significant bits are already in
-   rB).  */
-	cmpld	cr7,rN,rSHR
+   rWORD8_SHIFT).  */
+	cmpld	cr7, rN, rSHR
 	beq	L(duZeroReturn)
-	li	rA,0
-	ble	cr7,L(dutrim)
-	ld	rWORD2,8(rSTR2)
-	srd	rA,rWORD2,rSHR
+	li	r0, 0
+	ble	cr7, L(dutrim)
+#ifdef __LITTLE_ENDIAN__
+	ldbrx	rWORD2, 0, rSTR2
+	addi	rSTR2, rSTR2, 8
+#else
+	ld	rWORD2, 8(rSTR2)
+#endif
+	srd	r0, rWORD2, rSHR
 	.align	4
 L(dutrim):
-	ld	rWORD1,8(rSTR1)
-	ld	rWORD8,-8(r1)
-	subfic	rN,rN,64	/* Shift count is 64 - (rN * 8).  */
-	or	rWORD2,rA,rB
-	ld	rWORD7,-16(r1)
-	ld	r29,-24(r1)
-	srd	rWORD1,rWORD1,rN
-	srd	rWORD2,rWORD2,rN
-	ld	r28,-32(r1)
-	ld	r27,-40(r1)
-	li	rRTN,0
-	cmpld	cr0,rWORD1,rWORD2
-	ld	r26,-48(r1)
-	ld	r25,-56(r1)
-	beq	cr0,L(dureturn24)
-	li	rRTN,1
-	ld	r24,-64(r1)
-	bgtlr	cr0
-	li	rRTN,-1
+#ifdef __LITTLE_ENDIAN__
+	ldbrx	rWORD1, 0, rSTR1
+#else
+	ld	rWORD1, 8(rSTR1)
+#endif
+	ld	rWORD8, -8(r1)
+	subfic	rN, rN, 64	/* Shift count is 64 - (rN * 8).  */
+	or	rWORD2, r0, rWORD8_SHIFT
+	ld	rWORD7, -16(r1)
+	ld	rSHL, -24(r1)
+	srd	rWORD1, rWORD1, rN
+	srd	rWORD2, rWORD2, rN
+	ld	rSHR, -32(r1)
+	ld	rWORD8_SHIFT, -40(r1)
+	li	rRTN, 0
+	cmpld	cr7, rWORD1, rWORD2
+	ld	rWORD2_SHIFT, -48(r1)
+	ld	rWORD4_SHIFT, -56(r1)
+	beq	cr7, L(dureturn24)
+	li	rRTN, 1
+	ld	rWORD6_SHIFT, -64(r1)
+	bgtlr	cr7
+	li	rRTN, -1
 	blr
 	.align	4
-L(duLcr0):
-	ld	rWORD8,-8(r1)
-	ld	rWORD7,-16(r1)
-	li	rRTN,1
-	bgt	cr0,L(dureturn29)
-	ld	r29,-24(r1)
-	ld	r28,-32(r1)
-	li	rRTN,-1
+L(duLcr7):
+	ld	rWORD8, -8(r1)
+	ld	rWORD7, -16(r1)
+	li	rRTN, 1
+	bgt	cr7, L(dureturn29)
+	ld	rSHL, -24(r1)
+	ld	rSHR, -32(r1)
+	li	rRTN, -1
 	b	L(dureturn27)
 	.align	4
 L(duLcr1):
-	ld	rWORD8,-8(r1)
-	ld	rWORD7,-16(r1)
-	li	rRTN,1
-	bgt	cr1,L(dureturn29)
-	ld	r29,-24(r1)
-	ld	r28,-32(r1)
-	li	rRTN,-1
+	ld	rWORD8, -8(r1)
+	ld	rWORD7, -16(r1)
+	li	rRTN, 1
+	bgt	cr1, L(dureturn29)
+	ld	rSHL, -24(r1)
+	ld	rSHR, -32(r1)
+	li	rRTN, -1
 	b	L(dureturn27)
 	.align	4
 L(duLcr6):
-	ld	rWORD8,-8(r1)
-	ld	rWORD7,-16(r1)
-	li	rRTN,1
-	bgt	cr6,L(dureturn29)
-	ld	r29,-24(r1)
-	ld	r28,-32(r1)
-	li	rRTN,-1
+	ld	rWORD8, -8(r1)
+	ld	rWORD7, -16(r1)
+	li	rRTN, 1
+	bgt	cr6, L(dureturn29)
+	ld	rSHL, -24(r1)
+	ld	rSHR, -32(r1)
+	li	rRTN, -1
 	b	L(dureturn27)
 	.align	4
 L(duLcr5):
-	ld	rWORD8,-8(r1)
-	ld	rWORD7,-16(r1)
-	li	rRTN,1
-	bgt	cr5,L(dureturn29)
-	ld	r29,-24(r1)
-	ld	r28,-32(r1)
-	li	rRTN,-1
+	ld	rWORD8, -8(r1)
+	ld	rWORD7, -16(r1)
+	li	rRTN, 1
+	bgt	cr5, L(dureturn29)
+	ld	rSHL, -24(r1)
+	ld	rSHR, -32(r1)
+	li	rRTN, -1
 	b	L(dureturn27)
 	.align	3
 L(duZeroReturn):
-	li	rRTN,0
+	li	rRTN, 0
 	.align	4
 L(dureturn):
-	ld	rWORD8,-8(r1)
-	ld	rWORD7,-16(r1)
+	ld	rWORD8, -8(r1)
+	ld	rWORD7, -16(r1)
 L(dureturn29):
-	ld	r29,-24(r1)
-	ld	r28,-32(r1)
+	ld	rSHL, -24(r1)
+	ld	rSHR, -32(r1)
 L(dureturn27):
-	ld	r27,-40(r1)
+	ld	rWORD8_SHIFT, -40(r1)
 L(dureturn26):
-	ld	r26,-48(r1)
+	ld	rWORD2_SHIFT, -48(r1)
 L(dureturn25):
-	ld	r25,-56(r1)
+	ld	rWORD4_SHIFT, -56(r1)
 L(dureturn24):
-	ld	r24,-64(r1)
+	ld	rWORD6_SHIFT, -64(r1)
 	blr
 L(duzeroLength):
-	li	rRTN,0
+	li	rRTN, 0
 	blr
 
 END (memcmp)
 libc_hidden_builtin_def (memcmp)
-weak_alias (memcmp,bcmp)
+weak_alias (memcmp, bcmp)

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=509b04bf435e5411bb89f95f8d4df673c3ffcf66

commit 509b04bf435e5411bb89f95f8d4df673c3ffcf66
Author: Alan Modra <amodra@gmail.com>
Date:   Sat Aug 17 18:46:05 2013 +0930

    PowerPC LE strchr
    http://sourceware.org/ml/libc-alpha/2013-08/msg00101.html
    
    Adds little-endian support to optimised strchr assembly.  I've also
    tweaked the big-endian code a little.  In power7/strchr.S there's a
    check in the tail of the function that we didn't match 0 before
    finding a c match, done by comparing leading zero counts.  It's just
    as valid, and quicker, to compare the raw output from cmpb.
    
    Another little tweak is to use rldimi/insrdi in place of rlwimi for
    the power7 strchr functions.  Since rlwimi is cracked, it is a few
    cycles slower.  rldimi can be used on the 32-bit power7 functions
    too.
    
    	* sysdeps/powerpc/powerpc64/power7/strchr.S (strchr): Add little-endian
    	support.  Correct typos, formatting.  Optimize tail.  Use insrdi
    	rather than rlwimi.
    	* sysdeps/powerpc/powerpc32/power7/strchr.S: Likewise.
    	* sysdeps/powerpc/powerpc64/power7/strchrnul.S (__strchrnul): Add
    	little-endian support.  Correct typos.
    	* sysdeps/powerpc/powerpc32/power7/strchrnul.S: Likewise.  Use insrdi
    	rather than rlwimi.
    	* sysdeps/powerpc/powerpc64/strchr.S (rTMP4, rTMP5): Define.  Use
    	in loop and entry code to keep "and." results.
    	(strchr): Add little-endian support.  Comment.  Move cntlzd
    	earlier in tail.
    	* sysdeps/powerpc/powerpc32/strchr.S: Likewise.

diff --git a/ChangeLog b/ChangeLog
index 9ca77fe..37a85c2 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,21 @@
 2013-10-04  Alan Modra  <amodra@gmail.com>
 
+	* sysdeps/powerpc/powerpc64/power7/strchr.S (strchr): Add little-endian
+	support.  Correct typos, formatting.  Optimize tail.  Use insrdi
+	rather than rlwimi.
+	* sysdeps/powerpc/powerpc32/power7/strchr.S: Likewise.
+	* sysdeps/powerpc/powerpc64/power7/strchrnul.S (__strchrnul): Add
+	little-endian support.  Correct typos.
+	* sysdeps/powerpc/powerpc32/power7/strchrnul.S: Likewise.  Use insrdi
+	rather than rlwimi.
+	* sysdeps/powerpc/powerpc64/strchr.S (rTMP4, rTMP5): Define.  Use
+	in loop and entry code to keep "and." results.
+	(strchr): Add little-endian support.  Comment.  Move cntlzd
+	earlier in tail.
+	* sysdeps/powerpc/powerpc32/strchr.S: Likewise.
+
+2013-10-04  Alan Modra  <amodra@gmail.com>
+
 	* sysdeps/powerpc/powerpc64/strcpy.S: Add little-endian support:
 	* sysdeps/powerpc/powerpc32/strcpy.S: Likewise.
 	* sysdeps/powerpc/powerpc64/stpcpy.S: Likewise.
diff --git a/sysdeps/powerpc/powerpc32/power7/strchr.S b/sysdeps/powerpc/powerpc32/power7/strchr.S
index 0ecadb2..b662659 100644
--- a/sysdeps/powerpc/powerpc32/power7/strchr.S
+++ b/sysdeps/powerpc/powerpc32/power7/strchr.S
@@ -35,8 +35,8 @@ ENTRY (strchr)
 	beq	cr7,L(null_match)
 
 	/* Replicate byte to word.  */
-	rlwimi	r4,r4,8,16,23
-	rlwimi	r4,r4,16,0,15
+	insrdi	r4,r4,8,48
+	insrdi	r4,r4,16,32
 
 	/* Now r4 has a word of c bytes and r0 has
 	   a word of null bytes.  */
@@ -46,11 +46,17 @@ ENTRY (strchr)
 
 	/* Move the words left and right to discard the bits that are
 	   not part of the string and to bring them back as zeros.  */
-
+#ifdef __LITTLE_ENDIAN__
+	srw	r10,r10,r6
+	srw	r11,r11,r6
+	slw	r10,r10,r6
+	slw	r11,r11,r6
+#else
 	slw	r10,r10,r6
 	slw	r11,r11,r6
 	srw	r10,r10,r6
 	srw	r11,r11,r6
+#endif
 	or	r5,r10,r11    /* OR the results to speed things up.  */
 	cmpwi	cr7,r5,0      /* If r5 == 0, no c or null bytes
 				 have been found.  */
@@ -65,7 +71,7 @@ ENTRY (strchr)
 
 	/* Handle WORD2 of pair.  */
 	lwzu	r12,4(r8)
-	cmpb    r10,r12,r4
+	cmpb	r10,r12,r4
 	cmpb	r11,r12,r0
 	or	r5,r10,r11
 	cmpwi	cr7,r5,0
@@ -100,22 +106,31 @@ L(loop):
 	bne	cr6,L(done)
 
 	/* The c/null byte must be in the second word.  Adjust the address
-	   again and move the result of cmpb to r10 so we can calculate the
-	   pointer.  */
+	   again and move the result of cmpb to r10/r11 so we can calculate
+	   the pointer.  */
 
 	mr	r10,r6
 	mr	r11,r7
 	addi	r8,r8,4
 
-	/* r5 has the output of the cmpb instruction, that is, it contains
+	/* r10/r11 have the output of the cmpb instructions, that is,
 	   0xff in the same position as the c/null byte in the original
 	   word from the string.  Use that to calculate the pointer.  */
 L(done):
-	cntlzw	r4,r10	      /* Count leading zeroes before c matches.  */
-	cntlzw	r0,r11	      /* Count leading zeroes before null matches.  */
-	cmplw	cr7,r4,r0
+#ifdef __LITTLE_ENDIAN__
+	addi    r3,r10,-1
+	andc    r3,r3,r10
+	popcntw	r0,r3
+	addi    r4,r11,-1
+	andc    r4,r4,r11
+	cmplw	cr7,r3,r4
+	bgt	cr7,L(no_match)
+#else
+	cntlzw	r0,r10	      /* Count leading zeros before c matches.  */
+	cmplw	cr7,r11,r10
 	bgt	cr7,L(no_match)
-	srwi	r0,r4,3	      /* Convert leading zeroes to bytes.  */
+#endif
+	srwi	r0,r0,3	      /* Convert leading zeros to bytes.  */
 	add	r3,r8,r0      /* Return address of the matching c byte
 				 or null in case c was not found.  */
 	blr
@@ -133,10 +148,14 @@ L(null_match):
 	cmpb	r5,r12,r0     /* Compare each byte against null bytes.  */
 
 	/* Move the words left and right to discard the bits that are
-	   not part of the string and to bring them back as zeros.  */
-
+	   not part of the string and bring them back as zeros.  */
+#ifdef __LITTLE_ENDIAN__
+	srw	r5,r5,r6
+	slw	r5,r5,r6
+#else
 	slw	r5,r5,r6
 	srw	r5,r5,r6
+#endif
 	cmpwi	cr7,r5,0      /* If r10 == 0, no c or null bytes
 				 have been found.  */
 	bne	cr7,L(done_null)
@@ -191,7 +210,13 @@ L(loop_null):
 	   0xff in the same position as the null byte in the original
 	   word from the string.  Use that to calculate the pointer.  */
 L(done_null):
+#ifdef __LITTLE_ENDIAN__
+	addi    r0,r5,-1
+	andc    r0,r0,r5
+	popcntw	r0,r0
+#else
 	cntlzw	r0,r5	      /* Count leading zeros before the match.  */
+#endif
 	srwi	r0,r0,3	      /* Convert leading zeros to bytes.  */
 	add	r3,r8,r0      /* Return address of the matching null byte.  */
 	blr
diff --git a/sysdeps/powerpc/powerpc32/power7/strchrnul.S b/sysdeps/powerpc/powerpc32/power7/strchrnul.S
index d4cacab..f5d24d4 100644
--- a/sysdeps/powerpc/powerpc32/power7/strchrnul.S
+++ b/sysdeps/powerpc/powerpc32/power7/strchrnul.S
@@ -27,8 +27,8 @@ ENTRY (__strchrnul)
 	clrrwi	r8,r3,2	      /* Align the address to word boundary.  */
 
 	/* Replicate byte to word.  */
-	rlwimi	r4,r4,8,16,23
-	rlwimi	r4,r4,16,0,15
+	insrdi	r4,r4,8,48
+	insrdi	r4,r4,16,32
 
 	rlwinm	r6,r3,3,27,28 /* Calculate padding.  */
 	lwz	r12,0(r8)     /* Load word from memory.  */
@@ -43,10 +43,17 @@ ENTRY (__strchrnul)
 
 	/* Move the words left and right to discard the bits that are
 	   not part of the string and bring them back as zeros.  */
+#ifdef __LITTLE_ENDIAN__
+	srw	r10,r10,r6
+	srw	r9,r9,r6
+	slw	r10,r10,r6
+	slw	r9,r9,r6
+#else
 	slw	r10,r10,r6
 	slw	r9,r9,r6
 	srw	r10,r10,r6
 	srw	r9,r9,r6
+#endif
 	or	r5,r9,r10     /* OR the results to speed things up.  */
 	cmpwi	cr7,r5,0      /* If r5 == 0, no c or null bytes
 				 have been found.  */
@@ -54,7 +61,7 @@ ENTRY (__strchrnul)
 
 	mtcrf   0x01,r8
 
-	/* Are we now aligned to a quadword boundary?  If so, skip to
+	/* Are we now aligned to a doubleword boundary?  If so, skip to
 	   the main loop.  Otherwise, go through the alignment code.  */
 
 	bt	29,L(loop)
@@ -76,7 +83,7 @@ L(loop):
 	   single register for speed.  This is an attempt
 	   to speed up the null-checking process for bigger strings.  */
 	lwz	r12,4(r8)
-	lwzu     r11,8(r8)
+	lwzu	r11,8(r8)
 	cmpb	r10,r12,r0
 	cmpb	r9,r12,r4
 	cmpb	r6,r11,r0
@@ -95,9 +102,9 @@ L(loop):
 	addi	r8,r8,-4
 	bne	cr6,L(done)
 
-	/* The c/null byte must be in the second word.  Adjust the
-	   address again and move the result of cmpb to r10 so we can calculate
-	   the pointer.  */
+	/* The c/null byte must be in the second word.  Adjust the address
+	   again and move the result of cmpb to r5 so we can calculate the
+	   pointer.  */
 	mr	r5,r10
 	addi	r8,r8,4
 
@@ -105,7 +112,13 @@ L(loop):
 	   0xff in the same position as the c/null byte in the original
 	   word from the string.  Use that to calculate the pointer.  */
 L(done):
+#ifdef __LITTLE_ENDIAN__
+	addi    r0,r5,-1
+	andc    r0,r0,r5
+	popcntw	r0,r0
+#else
 	cntlzw	r0,r5	      /* Count leading zeros before the match.  */
+#endif
 	srwi	r0,r0,3	      /* Convert leading zeros to bytes.  */
 	add	r3,r8,r0      /* Return address of matching c/null byte.  */
 	blr
diff --git a/sysdeps/powerpc/powerpc32/strchr.S b/sysdeps/powerpc/powerpc32/strchr.S
index c9952ee..6050565 100644
--- a/sysdeps/powerpc/powerpc32/strchr.S
+++ b/sysdeps/powerpc/powerpc32/strchr.S
@@ -36,6 +36,8 @@ ENTRY (strchr)
 #define rIGN	r10	/* number of bits we should ignore in the first word */
 #define rMASK	r11	/* mask with the bits to ignore set to 0 */
 #define rTMP3	r12
+#define rTMP4	rIGN
+#define rTMP5	rMASK
 
 
 	rlwimi	rCHR, rCHR, 8, 16, 23
@@ -49,64 +51,93 @@ ENTRY (strchr)
 	addi	r7F7F, r7F7F, 0x7f7f
 /* Test the first (partial?) word.  */
 	lwz	rWORD, 0(rSTR)
+#ifdef __LITTLE_ENDIAN__
+	slw	rMASK, rMASK, rIGN
+#else
 	srw	rMASK, rMASK, rIGN
+#endif
 	orc	rWORD, rWORD, rMASK
 	add	rTMP1, rFEFE, rWORD
 	nor	rTMP2, r7F7F, rWORD
-	and.	rTMP1, rTMP1, rTMP2
+	and.	rTMP4, rTMP1, rTMP2
 	xor	rTMP3, rCHR, rWORD
 	orc	rTMP3, rTMP3, rMASK
 	b	L(loopentry)
 
 /* The loop.  */
 
-L(loop):lwzu rWORD, 4(rSTR)
-	and.	rTMP1, rTMP1, rTMP2
+L(loop):
+	lwzu	rWORD, 4(rSTR)
+	and.	rTMP5, rTMP1, rTMP2
 /* Test for 0.	*/
-	add	rTMP1, rFEFE, rWORD
-	nor	rTMP2, r7F7F, rWORD
+	add	rTMP1, rFEFE, rWORD /* x - 0x01010101.  */
+	nor	rTMP2, r7F7F, rWORD /* ~(x | 0x7f7f7f7f) == ~x & 0x80808080.  */
 	bne	L(foundit)
-	and.	rTMP1, rTMP1, rTMP2
+	and.	rTMP4, rTMP1, rTMP2 /* (x - 0x01010101) & ~x & 0x80808080.  */
 /* Start test for the bytes we're looking for.  */
 	xor	rTMP3, rCHR, rWORD
 L(loopentry):
 	add	rTMP1, rFEFE, rTMP3
 	nor	rTMP2, r7F7F, rTMP3
 	beq	L(loop)
+
 /* There is a zero byte in the word, but may also be a matching byte (either
    before or after the zero byte).  In fact, we may be looking for a
-   zero byte, in which case we return a match.  We guess that this hasn't
-   happened, though.  */
-L(missed):
-	and.	rTMP1, rTMP1, rTMP2
+   zero byte, in which case we return a match.  */
+	and.	rTMP5, rTMP1, rTMP2
 	li	rRTN, 0
 	beqlr
-/* It did happen. Decide which one was first...
-   I'm not sure if this is actually faster than a sequence of
-   rotates, compares, and branches (we use it anyway because it's shorter).  */
+/* At this point:
+   rTMP5 bytes are 0x80 for each match of c, 0 otherwise.
+   rTMP4 bytes are 0x80 for each match of 0, 0 otherwise.
+   But there may be false matches in the next most significant byte from
+   a true match due to carries.  This means we need to recalculate the
+   matches using a longer method for big-endian.  */
+#ifdef __LITTLE_ENDIAN__
+	addi	rTMP1, rTMP5, -1
+	andc	rTMP1, rTMP1, rTMP5
+	cntlzw	rCLZB, rTMP1
+	addi	rTMP2, rTMP4, -1
+	andc	rTMP2, rTMP2, rTMP4
+	cmplw	rTMP1, rTMP2
+	bgtlr
+	subfic	rCLZB, rCLZB, 32-7
+#else
+/* I think we could reduce this by two instructions by keeping the "nor"
+   results from the loop for reuse here.  See strlen.S tail.  Similarly
+   one instruction could be pruned from L(foundit).  */
 	and	rFEFE, r7F7F, rWORD
-	or	rMASK, r7F7F, rWORD
+	or	rTMP5, r7F7F, rWORD
 	and	rTMP1, r7F7F, rTMP3
-	or	rIGN, r7F7F, rTMP3
+	or	rTMP4, r7F7F, rTMP3
 	add	rFEFE, rFEFE, r7F7F
 	add	rTMP1, rTMP1, r7F7F
-	nor	rWORD, rMASK, rFEFE
-	nor	rTMP2, rIGN, rTMP1
+	nor	rWORD, rTMP5, rFEFE
+	nor	rTMP2, rTMP4, rTMP1
+	cntlzw	rCLZB, rTMP2
 	cmplw	rWORD, rTMP2
 	bgtlr
-	cntlzw	rCLZB, rTMP2
+#endif
 	srwi	rCLZB, rCLZB, 3
 	add	rRTN, rSTR, rCLZB
 	blr
 
 L(foundit):
+#ifdef __LITTLE_ENDIAN__
+	addi	rTMP1, rTMP5, -1
+	andc	rTMP1, rTMP1, rTMP5
+	cntlzw	rCLZB, rTMP1
+	subfic	rCLZB, rCLZB, 32-7-32
+	srawi	rCLZB, rCLZB, 3
+#else
 	and	rTMP1, r7F7F, rTMP3
-	or	rIGN, r7F7F, rTMP3
+	or	rTMP4, r7F7F, rTMP3
 	add	rTMP1, rTMP1, r7F7F
-	nor	rTMP2, rIGN, rTMP1
+	nor	rTMP2, rTMP4, rTMP1
 	cntlzw	rCLZB, rTMP2
 	subi	rSTR, rSTR, 4
 	srwi	rCLZB, rCLZB, 3
+#endif
 	add	rRTN, rSTR, rCLZB
 	blr
 END (strchr)
diff --git a/sysdeps/powerpc/powerpc64/power7/strchr.S b/sysdeps/powerpc/powerpc64/power7/strchr.S
index 3ffe7a1..4679a15 100644
--- a/sysdeps/powerpc/powerpc64/power7/strchr.S
+++ b/sysdeps/powerpc/powerpc64/power7/strchr.S
@@ -35,8 +35,8 @@ ENTRY (strchr)
 	beq	cr7,L(null_match)
 
 	/* Replicate byte to doubleword.  */
-	rlwimi	r4,r4,8,16,23
-	rlwimi	r4,r4,16,0,15
+	insrdi	r4,r4,8,48
+	insrdi	r4,r4,16,32
 	insrdi  r4,r4,32,0
 
 	/* Now r4 has a doubleword of c bytes and r0 has
@@ -47,11 +47,17 @@ ENTRY (strchr)
 
 	/* Move the doublewords left and right to discard the bits that are
 	   not part of the string and bring them back as zeros.  */
-
+#ifdef __LITTLE_ENDIAN__
+	srd	r10,r10,r6
+	srd	r11,r11,r6
+	sld	r10,r10,r6
+	sld	r11,r11,r6
+#else
 	sld	r10,r10,r6
 	sld	r11,r11,r6
 	srd	r10,r10,r6
 	srd	r11,r11,r6
+#endif
 	or	r5,r10,r11    /* OR the results to speed things up.  */
 	cmpdi	cr7,r5,0      /* If r5 == 0, no c or null bytes
 				 have been found.  */
@@ -108,15 +114,24 @@ L(loop):
 	mr	r11,r7
 	addi	r8,r8,8
 
-	/* r5 has the output of the cmpb instruction, that is, it contains
+	/* r10/r11 have the output of the cmpb instructions, that is,
 	   0xff in the same position as the c/null byte in the original
 	   doubleword from the string.  Use that to calculate the pointer.  */
 L(done):
-	cntlzd	r4,r10	      /* Count leading zeroes before c matches.  */
-	cntlzd	r0,r11	      /* Count leading zeroes before null matches.  */
-	cmpld	cr7,r4,r0
+#ifdef __LITTLE_ENDIAN__
+	addi    r3,r10,-1
+	andc    r3,r3,r10
+	popcntd	r0,r3
+	addi    r4,r11,-1
+	andc    r4,r4,r11
+	cmpld	cr7,r3,r4
 	bgt	cr7,L(no_match)
-	srdi	r0,r4,3	      /* Convert leading zeroes to bytes.  */
+#else
+	cntlzd	r0,r10	      /* Count leading zeros before c matches.  */
+	cmpld	cr7,r11,r10
+	bgt	cr7,L(no_match)
+#endif
+	srdi	r0,r0,3	      /* Convert leading zeros to bytes.  */
 	add	r3,r8,r0      /* Return address of the matching c byte
 				 or null in case c was not found.  */
 	blr
@@ -135,9 +150,13 @@ L(null_match):
 
 	/* Move the doublewords left and right to discard the bits that are
 	   not part of the string and bring them back as zeros.  */
-
+#ifdef __LITTLE_ENDIAN__
+	srd	r5,r5,r6
+	sld	r5,r5,r6
+#else
 	sld	r5,r5,r6
 	srd	r5,r5,r6
+#endif
 	cmpdi	cr7,r5,0      /* If r10 == 0, no c or null bytes
 				 have been found.  */
 	bne	cr7,L(done_null)
@@ -192,7 +211,13 @@ L(loop_null):
 	   0xff in the same position as the null byte in the original
 	   doubleword from the string.  Use that to calculate the pointer.  */
 L(done_null):
+#ifdef __LITTLE_ENDIAN__
+	addi    r0,r5,-1
+	andc    r0,r0,r5
+	popcntd	r0,r0
+#else
 	cntlzd	r0,r5	      /* Count leading zeros before the match.  */
+#endif
 	srdi	r0,r0,3	      /* Convert leading zeros to bytes.  */
 	add	r3,r8,r0      /* Return address of the matching null byte.  */
 	blr
diff --git a/sysdeps/powerpc/powerpc64/power7/strchrnul.S b/sysdeps/powerpc/powerpc64/power7/strchrnul.S
index 9dbc51b..df45752 100644
--- a/sysdeps/powerpc/powerpc64/power7/strchrnul.S
+++ b/sysdeps/powerpc/powerpc64/power7/strchrnul.S
@@ -27,8 +27,8 @@ ENTRY (__strchrnul)
 	clrrdi	r8,r3,3	      /* Align the address to doubleword boundary.  */
 
 	/* Replicate byte to doubleword.  */
-	rlwimi	r4,r4,8,16,23
-	rlwimi	r4,r4,16,0,15
+	insrdi	r4,r4,8,48
+	insrdi	r4,r4,16,32
 	insrdi	r4,r4,32,0
 
 	rlwinm	r6,r3,3,26,28 /* Calculate padding.  */
@@ -44,10 +44,17 @@ ENTRY (__strchrnul)
 
 	/* Move the doublewords left and right to discard the bits that are
 	   not part of the string and to bring them back as zeros.  */
+#ifdef __LITTLE_ENDIAN__
+	srd	r10,r10,r6
+	srd	r9,r9,r6
+	sld	r10,r10,r6
+	sld	r9,r9,r6
+#else
 	sld	r10,r10,r6
 	sld	r9,r9,r6
 	srd	r10,r10,r6
 	srd	r9,r9,r6
+#endif
 	or	r5,r9,r10     /* OR the results to speed things up.  */
 	cmpdi	cr7,r5,0      /* If r5 == 0, no c or null bytes
 				 have been found.  */
@@ -97,7 +104,7 @@ L(loop):
 	bne	cr6,L(done)
 
 	/* The c/null byte must be in the second doubleword.  Adjust the
-	   address again and move the result of cmpb to r10 so we can calculate
+	   address again and move the result of cmpb to r5 so we can calculate
 	   the pointer.  */
 	mr	r5,r10
 	addi	r8,r8,8
@@ -106,7 +113,13 @@ L(loop):
 	   0xff in the same position as the c/null byte in the original
 	   doubleword from the string.  Use that to calculate the pointer.  */
 L(done):
+#ifdef __LITTLE_ENDIAN__
+	addi    r0,r5,-1
+	andc    r0,r0,r5
+	popcntd	r0,r0
+#else
 	cntlzd	r0,r5	      /* Count leading zeros before the match.  */
+#endif
 	srdi	r0,r0,3	      /* Convert leading zeros to bytes.  */
 	add	r3,r8,r0      /* Return address of matching c/null byte.  */
 	blr
diff --git a/sysdeps/powerpc/powerpc64/strchr.S b/sysdeps/powerpc/powerpc64/strchr.S
index d2d8cd3..da707ae 100644
--- a/sysdeps/powerpc/powerpc64/strchr.S
+++ b/sysdeps/powerpc/powerpc64/strchr.S
@@ -37,11 +37,13 @@ ENTRY (strchr)
 #define rIGN	r10	/* number of bits we should ignore in the first word */
 #define rMASK	r11	/* mask with the bits to ignore set to 0 */
 #define rTMP3	r12
+#define rTMP4	rIGN
+#define rTMP5	rMASK
 
 	dcbt	0,rRTN
-	rlwimi	rCHR, rCHR, 8, 16, 23
+	insrdi	rCHR, rCHR, 8, 48
 	li	rMASK, -1
-	rlwimi	rCHR, rCHR, 16, 0, 15
+	insrdi	rCHR, rCHR, 16, 32
 	rlwinm	rIGN, rRTN, 3, 26, 28
 	insrdi	rCHR, rCHR, 32, 0
 	lis	rFEFE, -0x101
@@ -54,64 +56,93 @@ ENTRY (strchr)
 	add	rFEFE, rFEFE, rTMP1
 /* Test the first (partial?) word.  */
 	ld	rWORD, 0(rSTR)
+#ifdef __LITTLE_ENDIAN__
+	sld	rMASK, rMASK, rIGN
+#else
 	srd	rMASK, rMASK, rIGN
+#endif
 	orc	rWORD, rWORD, rMASK
 	add	rTMP1, rFEFE, rWORD
 	nor	rTMP2, r7F7F, rWORD
-	and.	rTMP1, rTMP1, rTMP2
+	and.	rTMP4, rTMP1, rTMP2
 	xor	rTMP3, rCHR, rWORD
 	orc	rTMP3, rTMP3, rMASK
 	b	L(loopentry)
 
 /* The loop.  */
 
-L(loop):ldu rWORD, 8(rSTR)
-	and.	rTMP1, rTMP1, rTMP2
+L(loop):
+	ldu	rWORD, 8(rSTR)
+	and.	rTMP5, rTMP1, rTMP2
 /* Test for 0.	*/
-	add	rTMP1, rFEFE, rWORD
-	nor	rTMP2, r7F7F, rWORD
+	add	rTMP1, rFEFE, rWORD /* x - 0x01010101.  */
+	nor	rTMP2, r7F7F, rWORD /* ~(x | 0x7f7f7f7f) == ~x & 0x80808080.  */
 	bne	L(foundit)
-	and.	rTMP1, rTMP1, rTMP2
+	and.	rTMP4, rTMP1, rTMP2 /* (x - 0x01010101) & ~x & 0x80808080.  */
 /* Start test for the bytes we're looking for.  */
 	xor	rTMP3, rCHR, rWORD
 L(loopentry):
 	add	rTMP1, rFEFE, rTMP3
 	nor	rTMP2, r7F7F, rTMP3
 	beq	L(loop)
+
 /* There is a zero byte in the word, but may also be a matching byte (either
    before or after the zero byte).  In fact, we may be looking for a
-   zero byte, in which case we return a match.  We guess that this hasn't
-   happened, though.  */
-L(missed):
-	and.	rTMP1, rTMP1, rTMP2
+   zero byte, in which case we return a match.  */
+	and.	rTMP5, rTMP1, rTMP2
 	li	rRTN, 0
 	beqlr
-/* It did happen. Decide which one was first...
-   I'm not sure if this is actually faster than a sequence of
-   rotates, compares, and branches (we use it anyway because it's shorter).  */
+/* At this point:
+   rTMP5 bytes are 0x80 for each match of c, 0 otherwise.
+   rTMP4 bytes are 0x80 for each match of 0, 0 otherwise.
+   But there may be false matches in the next most significant byte from
+   a true match due to carries.  This means we need to recalculate the
+   matches using a longer method for big-endian.  */
+#ifdef __LITTLE_ENDIAN__
+	addi	rTMP1, rTMP5, -1
+	andc	rTMP1, rTMP1, rTMP5
+	cntlzd	rCLZB, rTMP1
+	addi	rTMP2, rTMP4, -1
+	andc	rTMP2, rTMP2, rTMP4
+	cmpld	rTMP1, rTMP2
+	bgtlr
+	subfic	rCLZB, rCLZB, 64-7
+#else
+/* I think we could reduce this by two instructions by keeping the "nor"
+   results from the loop for reuse here.  See strlen.S tail.  Similarly
+   one instruction could be pruned from L(foundit).  */
 	and	rFEFE, r7F7F, rWORD
-	or	rMASK, r7F7F, rWORD
+	or	rTMP5, r7F7F, rWORD
 	and	rTMP1, r7F7F, rTMP3
-	or	rIGN, r7F7F, rTMP3
+	or	rTMP4, r7F7F, rTMP3
 	add	rFEFE, rFEFE, r7F7F
 	add	rTMP1, rTMP1, r7F7F
-	nor	rWORD, rMASK, rFEFE
-	nor	rTMP2, rIGN, rTMP1
+	nor	rWORD, rTMP5, rFEFE
+	nor	rTMP2, rTMP4, rTMP1
+	cntlzd	rCLZB, rTMP2
 	cmpld	rWORD, rTMP2
 	bgtlr
-	cntlzd	rCLZB, rTMP2
+#endif
 	srdi	rCLZB, rCLZB, 3
 	add	rRTN, rSTR, rCLZB
 	blr
 
 L(foundit):
+#ifdef __LITTLE_ENDIAN__
+	addi	rTMP1, rTMP5, -1
+	andc	rTMP1, rTMP1, rTMP5
+	cntlzd	rCLZB, rTMP1
+	subfic	rCLZB, rCLZB, 64-7-64
+	sradi	rCLZB, rCLZB, 3
+#else
 	and	rTMP1, r7F7F, rTMP3
-	or	rIGN, r7F7F, rTMP3
+	or	rTMP4, r7F7F, rTMP3
 	add	rTMP1, rTMP1, r7F7F
-	nor	rTMP2, rIGN, rTMP1
+	nor	rTMP2, rTMP4, rTMP1
 	cntlzd	rCLZB, rTMP2
 	subi	rSTR, rSTR, 8
 	srdi	rCLZB, rCLZB, 3
+#endif
 	add	rRTN, rSTR, rCLZB
 	blr
 END (strchr)

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=f7721c628c1d9d3c92cb4a9f7695be07a92c9293

commit f7721c628c1d9d3c92cb4a9f7695be07a92c9293
Author: Alan Modra <amodra@gmail.com>
Date:   Sat Aug 17 18:45:31 2013 +0930

    PowerPC LE strcpy
    http://sourceware.org/ml/libc-alpha/2013-08/msg00100.html
    
    The strcpy changes for little-endian are quite straight-forward, just
    a matter of rotating the last word differently.
    
    I'll note that the powerpc64 version of stpcpy is just begging to be
    converted to use 64-bit loads and stores..
    
    	* sysdeps/powerpc/powerpc64/strcpy.S: Add little-endian support:
    	* sysdeps/powerpc/powerpc32/strcpy.S: Likewise.
    	* sysdeps/powerpc/powerpc64/stpcpy.S: Likewise.
    	* sysdeps/powerpc/powerpc32/stpcpy.S: Likewise.

diff --git a/ChangeLog b/ChangeLog
index 0315ee0..9ca77fe 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,12 @@
 2013-10-04  Alan Modra  <amodra@gmail.com>
 
+	* sysdeps/powerpc/powerpc64/strcpy.S: Add little-endian support:
+	* sysdeps/powerpc/powerpc32/strcpy.S: Likewise.
+	* sysdeps/powerpc/powerpc64/stpcpy.S: Likewise.
+	* sysdeps/powerpc/powerpc32/stpcpy.S: Likewise.
+
+2013-10-04  Alan Modra  <amodra@gmail.com>
+
 	* sysdeps/powerpc/powerpc64/strcmp.S (rTMP2): Define as r0.
 	(rTMP): Define as r11.
 	(strcmp): Add little-endian support.  Optimise tail.
diff --git a/sysdeps/powerpc/powerpc32/stpcpy.S b/sysdeps/powerpc/powerpc32/stpcpy.S
index 03c6ddd..7e106e0 100644
--- a/sysdeps/powerpc/powerpc32/stpcpy.S
+++ b/sysdeps/powerpc/powerpc32/stpcpy.S
@@ -62,7 +62,22 @@ L(g2):	add	rTMP, rFEFE, rWORD
 
 	mr	rALT, rWORD
 /* We've hit the end of the string.  Do the rest byte-by-byte.  */
-L(g1):	rlwinm.	rTMP, rALT, 8, 24, 31
+L(g1):
+#ifdef __LITTLE_ENDIAN__
+	rlwinm.	rTMP, rALT, 0, 24, 31
+	stbu	rALT, 4(rDEST)
+	beqlr-
+	rlwinm.	rTMP, rALT, 24, 24, 31
+	stbu	rTMP, 1(rDEST)
+	beqlr-
+	rlwinm.	rTMP, rALT, 16, 24, 31
+	stbu	rTMP, 1(rDEST)
+	beqlr-
+	rlwinm	rTMP, rALT, 8, 24, 31
+	stbu	rTMP, 1(rDEST)
+	blr
+#else
+	rlwinm.	rTMP, rALT, 8, 24, 31
 	stbu	rTMP, 4(rDEST)
 	beqlr-
 	rlwinm.	rTMP, rALT, 16, 24, 31
@@ -73,6 +88,7 @@ L(g1):	rlwinm.	rTMP, rALT, 8, 24, 31
 	beqlr-
 	stbu	rALT, 1(rDEST)
 	blr
+#endif
 
 /* Oh well.  In this case, we just do a byte-by-byte copy.  */
 	.align 4
diff --git a/sysdeps/powerpc/powerpc32/strcpy.S b/sysdeps/powerpc/powerpc32/strcpy.S
index 4ae577d..e938cc4 100644
--- a/sysdeps/powerpc/powerpc32/strcpy.S
+++ b/sysdeps/powerpc/powerpc32/strcpy.S
@@ -62,7 +62,22 @@ L(g2):	add	rTMP, rFEFE, rWORD
 
 	mr	rALT, rWORD
 /* We've hit the end of the string.  Do the rest byte-by-byte.  */
-L(g1):	rlwinm.	rTMP, rALT, 8, 24, 31
+L(g1):
+#ifdef __LITTLE_ENDIAN__
+	rlwinm.	rTMP, rALT, 0, 24, 31
+	stb	rALT, 4(rDEST)
+	beqlr-
+	rlwinm.	rTMP, rALT, 24, 24, 31
+	stb	rTMP, 5(rDEST)
+	beqlr-
+	rlwinm.	rTMP, rALT, 16, 24, 31
+	stb	rTMP, 6(rDEST)
+	beqlr-
+	rlwinm	rTMP, rALT, 8, 24, 31
+	stb	rTMP, 7(rDEST)
+	blr
+#else
+	rlwinm.	rTMP, rALT, 8, 24, 31
 	stb	rTMP, 4(rDEST)
 	beqlr-
 	rlwinm.	rTMP, rALT, 16, 24, 31
@@ -73,6 +88,7 @@ L(g1):	rlwinm.	rTMP, rALT, 8, 24, 31
 	beqlr-
 	stb	rALT, 7(rDEST)
 	blr
+#endif
 
 /* Oh well.  In this case, we just do a byte-by-byte copy.  */
 	.align 4
diff --git a/sysdeps/powerpc/powerpc64/stpcpy.S b/sysdeps/powerpc/powerpc64/stpcpy.S
index 070cd46..c0b3972 100644
--- a/sysdeps/powerpc/powerpc64/stpcpy.S
+++ b/sysdeps/powerpc/powerpc64/stpcpy.S
@@ -62,7 +62,22 @@ L(g2):	add	rTMP, rFEFE, rWORD
 
 	mr	rALT, rWORD
 /* We've hit the end of the string.  Do the rest byte-by-byte.  */
-L(g1):	rlwinm.	rTMP, rALT, 8, 24, 31
+L(g1):
+#ifdef __LITTLE_ENDIAN__
+	rlwinm.	rTMP, rALT, 0, 24, 31
+	stbu	rALT, 4(rDEST)
+	beqlr-
+	rlwinm.	rTMP, rALT, 24, 24, 31
+	stbu	rTMP, 1(rDEST)
+	beqlr-
+	rlwinm.	rTMP, rALT, 16, 24, 31
+	stbu	rTMP, 1(rDEST)
+	beqlr-
+	rlwinm	rTMP, rALT, 8, 24, 31
+	stbu	rTMP, 1(rDEST)
+	blr
+#else
+	rlwinm.	rTMP, rALT, 8, 24, 31
 	stbu	rTMP, 4(rDEST)
 	beqlr-
 	rlwinm.	rTMP, rALT, 16, 24, 31
@@ -73,6 +88,7 @@ L(g1):	rlwinm.	rTMP, rALT, 8, 24, 31
 	beqlr-
 	stbu	rALT, 1(rDEST)
 	blr
+#endif
 
 /* Oh well.  In this case, we just do a byte-by-byte copy.  */
 	.align 4
diff --git a/sysdeps/powerpc/powerpc64/strcpy.S b/sysdeps/powerpc/powerpc64/strcpy.S
index 4c6fd3f..a7fd85b 100644
--- a/sysdeps/powerpc/powerpc64/strcpy.S
+++ b/sysdeps/powerpc/powerpc64/strcpy.S
@@ -68,6 +68,32 @@ L(g2):	add	rTMP, rFEFE, rWORD
 	mr	rALT, rWORD
 /* We've hit the end of the string.  Do the rest byte-by-byte.  */
 L(g1):
+#ifdef __LITTLE_ENDIAN__
+	extrdi.	rTMP, rALT, 8, 56
+	stb	rALT, 8(rDEST)
+	beqlr-
+	extrdi.	rTMP, rALT, 8, 48
+	stb	rTMP, 9(rDEST)
+	beqlr-
+	extrdi.	rTMP, rALT, 8, 40
+	stb	rTMP, 10(rDEST)
+	beqlr-
+	extrdi.	rTMP, rALT, 8, 32
+	stb	rTMP, 11(rDEST)
+	beqlr-
+	extrdi.	rTMP, rALT, 8, 24
+	stb	rTMP, 12(rDEST)
+	beqlr-
+	extrdi.	rTMP, rALT, 8, 16
+	stb	rTMP, 13(rDEST)
+	beqlr-
+	extrdi.	rTMP, rALT, 8, 8
+	stb	rTMP, 14(rDEST)
+	beqlr-
+	extrdi	rTMP, rALT, 8, 0
+	stb	rTMP, 15(rDEST)
+	blr
+#else
 	extrdi.	rTMP, rALT, 8, 0
 	stb	rTMP, 8(rDEST)
 	beqlr-
@@ -91,6 +117,7 @@ L(g1):
 	beqlr-
 	stb	rALT, 15(rDEST)
 	blr
+#endif
 
 /* Oh well.  In this case, we just do a byte-by-byte copy.  */
 	.align 4

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=84f850520baed35f83fdce3ac9ca00929ba40e0d

commit 84f850520baed35f83fdce3ac9ca00929ba40e0d
Author: Alan Modra <amodra@gmail.com>
Date:   Sat Aug 17 18:41:17 2013 +0930

    PowerPC LE strcmp and strncmp
    http://sourceware.org/ml/libc-alpha/2013-08/msg00099.html
    
    More little-endian support.  I leave the main strcmp loops unchanged,
    (well, except for renumbering rTMP to something other than r0 since
    it's needed in an addi insn) and modify the tail for little-endian.
    
    I noticed some of the big-endian tail code was a little untidy so have
    cleaned that up too.
    
    	* sysdeps/powerpc/powerpc64/strcmp.S (rTMP2): Define as r0.
    	(rTMP): Define as r11.
    	(strcmp): Add little-endian support.  Optimise tail.
    	* sysdeps/powerpc/powerpc32/strcmp.S: Similarly.
    	* sysdeps/powerpc/powerpc64/strncmp.S: Likewise.
    	* sysdeps/powerpc/powerpc32/strncmp.S: Likewise.
    	* sysdeps/powerpc/powerpc64/power4/strncmp.S: Likewise.
    	* sysdeps/powerpc/powerpc32/power4/strncmp.S: Likewise.
    	* sysdeps/powerpc/powerpc64/power7/strncmp.S: Likewise.
    	* sysdeps/powerpc/powerpc32/power7/strncmp.S: Likewise.

diff --git a/ChangeLog b/ChangeLog
index 811e852..0315ee0 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,18 @@
 2013-10-04  Alan Modra  <amodra@gmail.com>
 
+	* sysdeps/powerpc/powerpc64/strcmp.S (rTMP2): Define as r0.
+	(rTMP): Define as r11.
+	(strcmp): Add little-endian support.  Optimise tail.
+	* sysdeps/powerpc/powerpc32/strcmp.S: Similarly.
+	* sysdeps/powerpc/powerpc64/strncmp.S: Likewise.
+	* sysdeps/powerpc/powerpc32/strncmp.S: Likewise.
+	* sysdeps/powerpc/powerpc64/power4/strncmp.S: Likewise.
+	* sysdeps/powerpc/powerpc32/power4/strncmp.S: Likewise.
+	* sysdeps/powerpc/powerpc64/power7/strncmp.S: Likewise.
+	* sysdeps/powerpc/powerpc32/power7/strncmp.S: Likewise.
+
+2013-10-04  Alan Modra  <amodra@gmail.com>
+
 	* sysdeps/powerpc/powerpc64/power7/strnlen.S (strnlen): Add
 	little-endian support.  Remove unnecessary "are we done" tests.
 	Handle "s" wrapping around zero and extremely large "size".
diff --git a/sysdeps/powerpc/powerpc32/power4/strncmp.S b/sysdeps/powerpc/powerpc32/power4/strncmp.S
index 724d908..89b961e 100644
--- a/sysdeps/powerpc/powerpc32/power4/strncmp.S
+++ b/sysdeps/powerpc/powerpc32/power4/strncmp.S
@@ -24,7 +24,7 @@
 
 EALIGN (strncmp, 4, 0)
 
-#define rTMP	r0
+#define rTMP2	r0
 #define rRTN	r3
 #define rSTR1	r3	/* first string arg */
 #define rSTR2	r4	/* second string arg */
@@ -37,6 +37,7 @@ EALIGN (strncmp, 4, 0)
 #define r7F7F	r9	/* constant 0x7f7f7f7f */
 #define rNEG	r10	/* ~(word in s1 | 0x7f7f7f7f) */
 #define rBITDIF	r11	/* bits that differ in s1 & s2 words */
+#define rTMP	r12
 
 	dcbt	0,rSTR1
 	or	rTMP, rSTR2, rSTR1
@@ -75,12 +76,45 @@ L(g1):	add	rTMP, rFEFE, rWORD1
    we don't compare two strings as different because of gunk beyond
    the end of the strings...  */
 
+#ifdef __LITTLE_ENDIAN__
+L(endstring):
+	slwi	rTMP, rTMP, 1
+	addi    rTMP2, rTMP, -1
+	andc    rTMP2, rTMP2, rTMP
+	and	rWORD2, rWORD2, rTMP2		/* Mask off gunk.  */
+	and	rWORD1, rWORD1, rTMP2
+	rlwinm	rTMP2, rWORD2, 8, 0xffffffff	/* Byte reverse word.  */
+	rlwinm	rTMP, rWORD1, 8, 0xffffffff
+	rldimi	rTMP2, rWORD2, 24, 32
+	rldimi	rTMP, rWORD1, 24, 32
+	rlwimi	rTMP2, rWORD2, 24, 16, 23
+	rlwimi	rTMP, rWORD1, 24, 16, 23
+	xor.	rBITDIF, rTMP, rTMP2
+	sub	rRTN, rTMP, rTMP2
+	bgelr+
+	ori	rRTN, rTMP2, 1
+	blr
+
+L(different):
+	lwz	rWORD1, -4(rSTR1)
+	rlwinm	rTMP2, rWORD2, 8, 0xffffffff	/* Byte reverse word.  */
+	rlwinm	rTMP, rWORD1, 8, 0xffffffff
+	rldimi	rTMP2, rWORD2, 24, 32
+	rldimi	rTMP, rWORD1, 24, 32
+	rlwimi	rTMP2, rWORD2, 24, 16, 23
+	rlwimi	rTMP, rWORD1, 24, 16, 23
+	xor.	rBITDIF, rTMP, rTMP2
+	sub	rRTN, rTMP, rTMP2
+	bgelr+
+	ori	rRTN, rTMP2, 1
+	blr
+
+#else
 L(endstring):
 	and	rTMP, r7F7F, rWORD1
 	beq	cr1, L(equal)
 	add	rTMP, rTMP, r7F7F
 	xor.	rBITDIF, rWORD1, rWORD2
-
 	andc	rNEG, rNEG, rTMP
 	blt-	L(highbit)
 	cntlzw	rBITDIF, rBITDIF
@@ -88,28 +122,20 @@ L(endstring):
 	addi	rNEG, rNEG, 7
 	cmpw	cr1, rNEG, rBITDIF
 	sub	rRTN, rWORD1, rWORD2
-	blt-	cr1, L(equal)
-	srawi	rRTN, rRTN, 31
-	ori	rRTN, rRTN, 1
-	blr
+	bgelr+	cr1
 L(equal):
 	li	rRTN, 0
 	blr
 
 L(different):
-	lwzu	rWORD1, -4(rSTR1)
+	lwz	rWORD1, -4(rSTR1)
 	xor.	rBITDIF, rWORD1, rWORD2
 	sub	rRTN, rWORD1, rWORD2
-	blt-	L(highbit)
-	srawi	rRTN, rRTN, 31
-	ori	rRTN, rRTN, 1
-	blr
+	bgelr+
 L(highbit):
-	srwi	rWORD2, rWORD2, 24
-	srwi	rWORD1, rWORD1, 24
-	sub	rRTN, rWORD1, rWORD2
+	ori	rRTN, rWORD2, 1
 	blr
-
+#endif
 
 /* Oh well.  In this case, we just do a byte-by-byte comparison.  */
 	.align 4
diff --git a/sysdeps/powerpc/powerpc32/power7/strncmp.S b/sysdeps/powerpc/powerpc32/power7/strncmp.S
index fdae44d..10c9d25 100644
--- a/sysdeps/powerpc/powerpc32/power7/strncmp.S
+++ b/sysdeps/powerpc/powerpc32/power7/strncmp.S
@@ -26,7 +26,7 @@
 
 EALIGN (strncmp,5,0)
 
-#define rTMP	r0
+#define rTMP2	r0
 #define rRTN	r3
 #define rSTR1	r3	/* first string arg */
 #define rSTR2	r4	/* second string arg */
@@ -39,6 +39,7 @@ EALIGN (strncmp,5,0)
 #define r7F7F	r9	/* constant 0x7f7f7f7f */
 #define rNEG	r10	/* ~(word in s1 | 0x7f7f7f7f) */
 #define rBITDIF	r11	/* bits that differ in s1 & s2 words */
+#define rTMP	r12
 
 	dcbt	0,rSTR1
 	nop
@@ -78,13 +79,45 @@ L(g1):	add	rTMP,rFEFE,rWORD1
 /* OK. We've hit the end of the string. We need to be careful that
    we don't compare two strings as different because of gunk beyond
    the end of the strings...  */
+#ifdef __LITTLE_ENDIAN__
+L(endstring):
+	slwi	rTMP, rTMP, 1
+	addi    rTMP2, rTMP, -1
+	andc    rTMP2, rTMP2, rTMP
+	and	rWORD2, rWORD2, rTMP2		/* Mask off gunk.  */
+	and	rWORD1, rWORD1, rTMP2
+	rlwinm	rTMP2, rWORD2, 8, 0xffffffff	/* Byte reverse word.  */
+	rlwinm	rTMP, rWORD1, 8, 0xffffffff
+	rldimi	rTMP2, rWORD2, 24, 32
+	rldimi	rTMP, rWORD1, 24, 32
+	rlwimi	rTMP2, rWORD2, 24, 16, 23
+	rlwimi	rTMP, rWORD1, 24, 16, 23
+	xor.	rBITDIF, rTMP, rTMP2
+	sub	rRTN, rTMP, rTMP2
+	bgelr
+	ori	rRTN, rTMP2, 1
+	blr
+
+L(different):
+	lwz	rWORD1, -4(rSTR1)
+	rlwinm	rTMP2, rWORD2, 8, 0xffffffff	/* Byte reverse word.  */
+	rlwinm	rTMP, rWORD1, 8, 0xffffffff
+	rldimi	rTMP2, rWORD2, 24, 32
+	rldimi	rTMP, rWORD1, 24, 32
+	rlwimi	rTMP2, rWORD2, 24, 16, 23
+	rlwimi	rTMP, rWORD1, 24, 16, 23
+	xor.	rBITDIF, rTMP, rTMP2
+	sub	rRTN, rTMP, rTMP2
+	bgelr
+	ori	rRTN, rTMP2, 1
+	blr
 
+#else
 L(endstring):
 	and	rTMP,r7F7F,rWORD1
 	beq	cr1,L(equal)
 	add	rTMP,rTMP,r7F7F
 	xor.	rBITDIF,rWORD1,rWORD2
-
 	andc	rNEG,rNEG,rTMP
 	blt	L(highbit)
 	cntlzw	rBITDIF,rBITDIF
@@ -92,28 +125,20 @@ L(endstring):
 	addi	rNEG,rNEG,7
 	cmpw	cr1,rNEG,rBITDIF
 	sub	rRTN,rWORD1,rWORD2
-	blt	cr1,L(equal)
-	srawi	rRTN,rRTN,31
-	ori	rRTN,rRTN,1
-	blr
+	bgelr	cr1
 L(equal):
 	li	rRTN,0
 	blr
 
 L(different):
-	lwzu	rWORD1,-4(rSTR1)
+	lwz	rWORD1,-4(rSTR1)
 	xor.	rBITDIF,rWORD1,rWORD2
 	sub	rRTN,rWORD1,rWORD2
-	blt	L(highbit)
-	srawi	rRTN,rRTN,31
-	ori	rRTN,rRTN,1
-	blr
+	bgelr
 L(highbit):
-	srwi	rWORD2,rWORD2,24
-	srwi	rWORD1,rWORD1,24
-	sub	rRTN,rWORD1,rWORD2
+	ori	rRTN, rWORD2, 1
 	blr
-
+#endif
 
 /* Oh well. In this case, we just do a byte-by-byte comparison.  */
 	.align	4
diff --git a/sysdeps/powerpc/powerpc32/strcmp.S b/sysdeps/powerpc/powerpc32/strcmp.S
index 297ca3c..91d60c9 100644
--- a/sysdeps/powerpc/powerpc32/strcmp.S
+++ b/sysdeps/powerpc/powerpc32/strcmp.S
@@ -24,7 +24,7 @@
 
 EALIGN (strcmp, 4, 0)
 
-#define rTMP	r0
+#define rTMP2	r0
 #define rRTN	r3
 #define rSTR1	r3	/* first string arg */
 #define rSTR2	r4	/* second string arg */
@@ -34,6 +34,7 @@ EALIGN (strcmp, 4, 0)
 #define r7F7F	r8	/* constant 0x7f7f7f7f */
 #define rNEG	r9	/* ~(word in s1 | 0x7f7f7f7f) */
 #define rBITDIF	r10	/* bits that differ in s1 & s2 words */
+#define rTMP	r11
 
 
 	or	rTMP, rSTR2, rSTR1
@@ -56,10 +57,45 @@ L(g1):	add	rTMP, rFEFE, rWORD1
 	and.	rTMP, rTMP, rNEG
 	cmpw	cr1, rWORD1, rWORD2
 	beq+	L(g0)
-L(endstring):
+
 /* OK. We've hit the end of the string. We need to be careful that
    we don't compare two strings as different because of gunk beyond
    the end of the strings...  */
+#ifdef __LITTLE_ENDIAN__
+L(endstring):
+	addi    rTMP2, rTMP, -1
+	andc    rTMP2, rTMP2, rTMP
+	rlwimi	rTMP2, rTMP2, 1, 0, 30
+	and	rWORD2, rWORD2, rTMP2		/* Mask off gunk.  */
+	and	rWORD1, rWORD1, rTMP2
+	rlwinm	rTMP2, rWORD2, 8, 0xffffffff	/* Byte reverse word.  */
+	rlwinm	rTMP, rWORD1, 8, 0xffffffff
+	rlwimi	rTMP2, rWORD2, 24, 0, 7
+	rlwimi	rTMP, rWORD1, 24, 0, 7
+	rlwimi	rTMP2, rWORD2, 24, 16, 23
+	rlwimi	rTMP, rWORD1, 24, 16, 23
+	xor.	rBITDIF, rTMP, rTMP2
+	sub	rRTN, rTMP, rTMP2
+	bgelr+
+	ori	rRTN, rTMP2, 1
+	blr
+
+L(different):
+	lwz	rWORD1, -4(rSTR1)
+	rlwinm	rTMP2, rWORD2, 8, 0xffffffff	/* Byte reverse word.  */
+	rlwinm	rTMP, rWORD1, 8, 0xffffffff
+	rlwimi	rTMP2, rWORD2, 24, 0, 7
+	rlwimi	rTMP, rWORD1, 24, 0, 7
+	rlwimi	rTMP2, rWORD2, 24, 16, 23
+	rlwimi	rTMP, rWORD1, 24, 16, 23
+	xor.	rBITDIF, rTMP, rTMP2
+	sub	rRTN, rTMP, rTMP2
+	bgelr+
+	ori	rRTN, rTMP2, 1
+	blr
+
+#else
+L(endstring):
 	and	rTMP, r7F7F, rWORD1
 	beq	cr1, L(equal)
 	add	rTMP, rTMP, r7F7F
@@ -84,7 +120,7 @@ L(different):
 L(highbit):
 	ori	rRTN, rWORD2, 1
 	blr
-
+#endif
 
 /* Oh well.  In this case, we just do a byte-by-byte comparison.  */
 	.align 4
diff --git a/sysdeps/powerpc/powerpc32/strncmp.S b/sysdeps/powerpc/powerpc32/strncmp.S
index fa345d2..e36a160 100644
--- a/sysdeps/powerpc/powerpc32/strncmp.S
+++ b/sysdeps/powerpc/powerpc32/strncmp.S
@@ -24,7 +24,7 @@
 
 EALIGN (strncmp, 4, 0)
 
-#define rTMP	r0
+#define rTMP2	r0
 #define rRTN	r3
 #define rSTR1	r3	/* first string arg */
 #define rSTR2	r4	/* second string arg */
@@ -35,6 +35,7 @@ EALIGN (strncmp, 4, 0)
 #define r7F7F	r9	/* constant 0x7f7f7f7f */
 #define rNEG	r10	/* ~(word in s1 | 0x7f7f7f7f) */
 #define rBITDIF	r11	/* bits that differ in s1 & s2 words */
+#define rTMP	r12
 
 	dcbt	0,rSTR1
 	or	rTMP, rSTR2, rSTR1
@@ -73,12 +74,45 @@ L(g1):	add	rTMP, rFEFE, rWORD1
    we don't compare two strings as different because of gunk beyond
    the end of the strings...  */
 
+#ifdef __LITTLE_ENDIAN__
+L(endstring):
+	slwi	rTMP, rTMP, 1
+	addi    rTMP2, rTMP, -1
+	andc    rTMP2, rTMP2, rTMP
+	and	rWORD2, rWORD2, rTMP2		/* Mask off gunk.  */
+	and	rWORD1, rWORD1, rTMP2
+	rlwinm	rTMP2, rWORD2, 8, 0xffffffff	/* Byte reverse word.  */
+	rlwinm	rTMP, rWORD1, 8, 0xffffffff
+	rlwimi	rTMP2, rWORD2, 24, 0, 7
+	rlwimi	rTMP, rWORD1, 24, 0, 7
+	rlwimi	rTMP2, rWORD2, 24, 16, 23
+	rlwimi	rTMP, rWORD1, 24, 16, 23
+	xor.	rBITDIF, rTMP, rTMP2
+	sub	rRTN, rTMP, rTMP2
+	bgelr+
+	ori	rRTN, rTMP2, 1
+	blr
+
+L(different):
+	lwz	rWORD1, -4(rSTR1)
+	rlwinm	rTMP2, rWORD2, 8, 0xffffffff	/* Byte reverse word.  */
+	rlwinm	rTMP, rWORD1, 8, 0xffffffff
+	rlwimi	rTMP2, rWORD2, 24, 0, 7
+	rlwimi	rTMP, rWORD1, 24, 0, 7
+	rlwimi	rTMP2, rWORD2, 24, 16, 23
+	rlwimi	rTMP, rWORD1, 24, 16, 23
+	xor.	rBITDIF, rTMP, rTMP2
+	sub	rRTN, rTMP, rTMP2
+	bgelr+
+	ori	rRTN, rTMP2, 1
+	blr
+
+#else
 L(endstring):
 	and	rTMP, r7F7F, rWORD1
 	beq	cr1, L(equal)
 	add	rTMP, rTMP, r7F7F
 	xor.	rBITDIF, rWORD1, rWORD2
-
 	andc	rNEG, rNEG, rTMP
 	blt-	L(highbit)
 	cntlzw	rBITDIF, rBITDIF
@@ -86,28 +120,20 @@ L(endstring):
 	addi	rNEG, rNEG, 7
 	cmpw	cr1, rNEG, rBITDIF
 	sub	rRTN, rWORD1, rWORD2
-	blt-	cr1, L(equal)
-	srawi	rRTN, rRTN, 31
-	ori	rRTN, rRTN, 1
-	blr
+	bgelr+	cr1
 L(equal):
 	li	rRTN, 0
 	blr
 
 L(different):
-	lwzu	rWORD1, -4(rSTR1)
+	lwz	rWORD1, -4(rSTR1)
 	xor.	rBITDIF, rWORD1, rWORD2
 	sub	rRTN, rWORD1, rWORD2
-	blt-	L(highbit)
-	srawi	rRTN, rRTN, 31
-	ori	rRTN, rRTN, 1
-	blr
+	bgelr+
 L(highbit):
-	srwi	rWORD2, rWORD2, 24
-	srwi	rWORD1, rWORD1, 24
-	sub	rRTN, rWORD1, rWORD2
+	ori	rRTN, rWORD2, 1
 	blr
-
+#endif
 
 /* Oh well.  In this case, we just do a byte-by-byte comparison.  */
 	.align 4
diff --git a/sysdeps/powerpc/powerpc64/power4/strncmp.S b/sysdeps/powerpc/powerpc64/power4/strncmp.S
index 1276e16..5d136cf 100644
--- a/sysdeps/powerpc/powerpc64/power4/strncmp.S
+++ b/sysdeps/powerpc/powerpc64/power4/strncmp.S
@@ -25,7 +25,7 @@
 EALIGN (strncmp, 4, 0)
 	CALL_MCOUNT 3
 
-#define rTMP	r0
+#define rTMP2	r0
 #define rRTN	r3
 #define rSTR1	r3	/* first string arg */
 #define rSTR2	r4	/* second string arg */
@@ -38,6 +38,7 @@ EALIGN (strncmp, 4, 0)
 #define r7F7F	r9	/* constant 0x7f7f7f7f7f7f7f7f */
 #define rNEG	r10	/* ~(word in s1 | 0x7f7f7f7f7f7f7f7f) */
 #define rBITDIF	r11	/* bits that differ in s1 & s2 words */
+#define rTMP	r12
 
 	dcbt	0,rSTR1
 	or	rTMP, rSTR2, rSTR1
@@ -79,12 +80,59 @@ L(g1):	add	rTMP, rFEFE, rWORD1
    we don't compare two strings as different because of gunk beyond
    the end of the strings...  */
 
+#ifdef __LITTLE_ENDIAN__
+L(endstring):
+	addi    rTMP2, rTMP, -1
+	beq	cr1, L(equal)
+	andc    rTMP2, rTMP2, rTMP
+	rldimi	rTMP2, rTMP2, 1, 0
+	and	rWORD2, rWORD2, rTMP2	/* Mask off gunk.  */
+	and	rWORD1, rWORD1, rTMP2
+	cmpd	cr1, rWORD1, rWORD2
+	beq	cr1, L(equal)
+	xor	rBITDIF, rWORD1, rWORD2	/* rBITDIF has bits that differ.  */
+	neg	rNEG, rBITDIF
+	and	rNEG, rNEG, rBITDIF	/* rNEG has LS bit that differs.  */
+	cntlzd	rNEG, rNEG		/* bitcount of the bit.  */
+	andi.	rNEG, rNEG, 56		/* bitcount to LS byte that differs. */
+	sld	rWORD1, rWORD1, rNEG	/* shift left to clear MS bytes.  */
+	sld	rWORD2, rWORD2, rNEG
+	xor.	rBITDIF, rWORD1, rWORD2
+	sub	rRTN, rWORD1, rWORD2
+	blt-	L(highbit)
+	sradi	rRTN, rRTN, 63		/* must return an int.  */
+	ori	rRTN, rRTN, 1
+	blr
+L(equal):
+	li	rRTN, 0
+	blr
+
+L(different):
+	ld	rWORD1, -8(rSTR1)
+	xor	rBITDIF, rWORD1, rWORD2	/* rBITDIF has bits that differ.  */
+	neg	rNEG, rBITDIF
+	and	rNEG, rNEG, rBITDIF	/* rNEG has LS bit that differs.  */
+	cntlzd	rNEG, rNEG		/* bitcount of the bit.  */
+	andi.	rNEG, rNEG, 56		/* bitcount to LS byte that differs. */
+	sld	rWORD1, rWORD1, rNEG	/* shift left to clear MS bytes.  */
+	sld	rWORD2, rWORD2, rNEG
+	xor.	rBITDIF, rWORD1, rWORD2
+	sub	rRTN, rWORD1, rWORD2
+	blt-	L(highbit)
+	sradi	rRTN, rRTN, 63
+	ori	rRTN, rRTN, 1
+	blr
+L(highbit):
+	sradi	rRTN, rWORD2, 63
+	ori	rRTN, rRTN, 1
+	blr
+
+#else
 L(endstring):
 	and	rTMP, r7F7F, rWORD1
 	beq	cr1, L(equal)
 	add	rTMP, rTMP, r7F7F
 	xor.	rBITDIF, rWORD1, rWORD2
-
 	andc	rNEG, rNEG, rTMP
 	blt-	L(highbit)
 	cntlzd	rBITDIF, rBITDIF
@@ -93,7 +141,7 @@ L(endstring):
 	cmpd	cr1, rNEG, rBITDIF
 	sub	rRTN, rWORD1, rWORD2
 	blt-	cr1, L(equal)
-	sradi	rRTN, rRTN, 63
+	sradi	rRTN, rRTN, 63		/* must return an int.  */
 	ori	rRTN, rRTN, 1
 	blr
 L(equal):
@@ -101,7 +149,7 @@ L(equal):
 	blr
 
 L(different):
-	ldu	rWORD1, -8(rSTR1)
+	ld	rWORD1, -8(rSTR1)
 	xor.	rBITDIF, rWORD1, rWORD2
 	sub	rRTN, rWORD1, rWORD2
 	blt-	L(highbit)
@@ -109,11 +157,10 @@ L(different):
 	ori	rRTN, rRTN, 1
 	blr
 L(highbit):
-	srdi	rWORD2, rWORD2, 56
-	srdi	rWORD1, rWORD1, 56
-	sub	rRTN, rWORD1, rWORD2
+	sradi	rRTN, rWORD2, 63
+	ori	rRTN, rRTN, 1
 	blr
-
+#endif
 
 /* Oh well.  In this case, we just do a byte-by-byte comparison.  */
 	.align 4
diff --git a/sysdeps/powerpc/powerpc64/power7/strncmp.S b/sysdeps/powerpc/powerpc64/power7/strncmp.S
index 77ecad5..e618b01 100644
--- a/sysdeps/powerpc/powerpc64/power7/strncmp.S
+++ b/sysdeps/powerpc/powerpc64/power7/strncmp.S
@@ -27,7 +27,7 @@
 EALIGN (strncmp,5,0)
 	CALL_MCOUNT 3
 
-#define rTMP	r0
+#define rTMP2	r0
 #define rRTN	r3
 #define rSTR1	r3	/* first string arg */
 #define rSTR2	r4	/* second string arg */
@@ -40,6 +40,7 @@ EALIGN (strncmp,5,0)
 #define r7F7F	r9	/* constant 0x7f7f7f7f7f7f7f7f */
 #define rNEG	r10	/* ~(word in s1 | 0x7f7f7f7f7f7f7f7f) */
 #define rBITDIF	r11	/* bits that differ in s1 & s2 words */
+#define rTMP	r12
 
 	dcbt	0,rSTR1
 	nop
@@ -83,12 +84,57 @@ L(g1):	add	rTMP,rFEFE,rWORD1
    we don't compare two strings as different because of gunk beyond
    the end of the strings...  */
 
+#ifdef __LITTLE_ENDIAN__
+L(endstring):
+	addi    rTMP2, rTMP, -1
+	beq	cr1, L(equal)
+	andc    rTMP2, rTMP2, rTMP
+	rldimi	rTMP2, rTMP2, 1, 0
+	and	rWORD2, rWORD2, rTMP2	/* Mask off gunk.  */
+	and	rWORD1, rWORD1, rTMP2
+	cmpd	cr1, rWORD1, rWORD2
+	beq	cr1, L(equal)
+	cmpb	rBITDIF, rWORD1, rWORD2	/* 0xff on equal bytes.  */
+	addi	rNEG, rBITDIF, 1
+	orc	rNEG, rNEG, rBITDIF	/* 0's below LS differing byte.  */
+	sldi	rNEG, rNEG, 8		/* 1's above LS differing byte.  */
+	andc	rWORD1, rWORD1, rNEG	/* mask off MS bytes.  */
+	andc	rWORD2, rWORD2, rNEG
+	xor.	rBITDIF, rWORD1, rWORD2
+	sub	rRTN, rWORD1, rWORD2
+	blt	L(highbit)
+	sradi	rRTN, rRTN, 63		/* must return an int.  */
+	ori	rRTN, rRTN, 1
+	blr
+L(equal):
+	li	rRTN, 0
+	blr
+
+L(different):
+	ld	rWORD1, -8(rSTR1)
+	cmpb	rBITDIF, rWORD1, rWORD2	/* 0xff on equal bytes.  */
+	addi	rNEG, rBITDIF, 1
+	orc	rNEG, rNEG, rBITDIF	/* 0's below LS differing byte.  */
+	sldi	rNEG, rNEG, 8		/* 1's above LS differing byte.  */
+	andc	rWORD1, rWORD1, rNEG	/* mask off MS bytes.  */
+	andc	rWORD2, rWORD2, rNEG
+	xor.	rBITDIF, rWORD1, rWORD2
+	sub	rRTN, rWORD1, rWORD2
+	blt	L(highbit)
+	sradi	rRTN, rRTN, 63
+	ori	rRTN, rRTN, 1
+	blr
+L(highbit):
+	sradi	rRTN, rWORD2, 63
+	ori	rRTN, rRTN, 1
+	blr
+
+#else
 L(endstring):
 	and	rTMP,r7F7F,rWORD1
 	beq	cr1,L(equal)
 	add	rTMP,rTMP,r7F7F
 	xor.	rBITDIF,rWORD1,rWORD2
-
 	andc	rNEG,rNEG,rTMP
 	blt	L(highbit)
 	cntlzd	rBITDIF,rBITDIF
@@ -97,7 +143,7 @@ L(endstring):
 	cmpd	cr1,rNEG,rBITDIF
 	sub	rRTN,rWORD1,rWORD2
 	blt	cr1,L(equal)
-	sradi	rRTN,rRTN,63
+	sradi	rRTN,rRTN,63		/* must return an int.  */
 	ori	rRTN,rRTN,1
 	blr
 L(equal):
@@ -105,7 +151,7 @@ L(equal):
 	blr
 
 L(different):
-	ldu	rWORD1,-8(rSTR1)
+	ld	rWORD1,-8(rSTR1)
 	xor.	rBITDIF,rWORD1,rWORD2
 	sub	rRTN,rWORD1,rWORD2
 	blt	L(highbit)
@@ -113,11 +159,10 @@ L(different):
 	ori	rRTN,rRTN,1
 	blr
 L(highbit):
-	srdi	rWORD2,rWORD2,56
-	srdi	rWORD1,rWORD1,56
-	sub	rRTN,rWORD1,rWORD2
+	sradi	rRTN,rWORD2,63
+	ori	rRTN,rRTN,1
 	blr
-
+#endif
 
 /* Oh well.  In this case, we just do a byte-by-byte comparison.  */
 	.align	4
diff --git a/sysdeps/powerpc/powerpc64/strcmp.S b/sysdeps/powerpc/powerpc64/strcmp.S
index c9d6dac..7085468 100644
--- a/sysdeps/powerpc/powerpc64/strcmp.S
+++ b/sysdeps/powerpc/powerpc64/strcmp.S
@@ -25,7 +25,7 @@
 EALIGN (strcmp, 4, 0)
 	CALL_MCOUNT 2
 
-#define rTMP	r0
+#define rTMP2	r0
 #define rRTN	r3
 #define rSTR1	r3	/* first string arg */
 #define rSTR2	r4	/* second string arg */
@@ -35,6 +35,7 @@ EALIGN (strcmp, 4, 0)
 #define r7F7F	r8	/* constant 0x7f7f7f7f7f7f7f7f */
 #define rNEG	r9	/* ~(word in s1 | 0x7f7f7f7f7f7f7f7f) */
 #define rBITDIF	r10	/* bits that differ in s1 & s2 words */
+#define rTMP	r11
 
 	dcbt	0,rSTR1
 	or	rTMP, rSTR2, rSTR1
@@ -58,19 +59,66 @@ L(g0):	ldu	rWORD1, 8(rSTR1)
 	ldu	rWORD2, 8(rSTR2)
 L(g1):	add	rTMP, rFEFE, rWORD1
 	nor	rNEG, r7F7F, rWORD1
-
 	and.	rTMP, rTMP, rNEG
 	cmpd	cr1, rWORD1, rWORD2
 	beq+	L(g0)
-L(endstring):
+
 /* OK. We've hit the end of the string. We need to be careful that
    we don't compare two strings as different because of gunk beyond
    the end of the strings...  */
+#ifdef __LITTLE_ENDIAN__
+L(endstring):
+	addi    rTMP2, rTMP, -1
+	beq	cr1, L(equal)
+	andc    rTMP2, rTMP2, rTMP
+	rldimi	rTMP2, rTMP2, 1, 0
+	and	rWORD2, rWORD2, rTMP2	/* Mask off gunk.  */
+	and	rWORD1, rWORD1, rTMP2
+	cmpd	cr1, rWORD1, rWORD2
+	beq	cr1, L(equal)
+	xor	rBITDIF, rWORD1, rWORD2	/* rBITDIF has bits that differ.  */
+	neg	rNEG, rBITDIF
+	and	rNEG, rNEG, rBITDIF	/* rNEG has LS bit that differs.  */
+	cntlzd	rNEG, rNEG		/* bitcount of the bit.  */
+	andi.	rNEG, rNEG, 56		/* bitcount to LS byte that differs. */
+	sld	rWORD1, rWORD1, rNEG	/* shift left to clear MS bytes.  */
+	sld	rWORD2, rWORD2, rNEG
+	xor.	rBITDIF, rWORD1, rWORD2
+	sub	rRTN, rWORD1, rWORD2
+	blt-	L(highbit)
+	sradi	rRTN, rRTN, 63		/* must return an int.  */
+	ori	rRTN, rRTN, 1
+	blr
+L(equal):
+	li	rRTN, 0
+	blr
+
+L(different):
+	ld	rWORD1, -8(rSTR1)
+	xor	rBITDIF, rWORD1, rWORD2	/* rBITDIF has bits that differ.  */
+	neg	rNEG, rBITDIF
+	and	rNEG, rNEG, rBITDIF	/* rNEG has LS bit that differs.  */
+	cntlzd	rNEG, rNEG		/* bitcount of the bit.  */
+	andi.	rNEG, rNEG, 56		/* bitcount to LS byte that differs. */
+	sld	rWORD1, rWORD1, rNEG	/* shift left to clear MS bytes.  */
+	sld	rWORD2, rWORD2, rNEG
+	xor.	rBITDIF, rWORD1, rWORD2
+	sub	rRTN, rWORD1, rWORD2
+	blt-	L(highbit)
+	sradi	rRTN, rRTN, 63
+	ori	rRTN, rRTN, 1
+	blr
+L(highbit):
+	sradi	rRTN, rWORD2, 63
+	ori	rRTN, rRTN, 1
+	blr
+
+#else
+L(endstring):
 	and	rTMP, r7F7F, rWORD1
 	beq	cr1, L(equal)
 	add	rTMP, rTMP, r7F7F
 	xor.	rBITDIF, rWORD1, rWORD2
-
 	andc	rNEG, rNEG, rTMP
 	blt-	L(highbit)
 	cntlzd	rBITDIF, rBITDIF
@@ -79,7 +127,7 @@ L(endstring):
 	cmpd	cr1, rNEG, rBITDIF
 	sub	rRTN, rWORD1, rWORD2
 	blt-	cr1, L(equal)
-	sradi	rRTN, rRTN, 63
+	sradi	rRTN, rRTN, 63		/* must return an int.  */
 	ori	rRTN, rRTN, 1
 	blr
 L(equal):
@@ -95,11 +143,10 @@ L(different):
 	ori	rRTN, rRTN, 1
 	blr
 L(highbit):
-	srdi	rWORD2, rWORD2, 56
-	srdi	rWORD1, rWORD1, 56
-	sub	rRTN, rWORD1, rWORD2
+	sradi	rRTN, rWORD2, 63
+	ori	rRTN, rRTN, 1
 	blr
-
+#endif
 
 /* Oh well.  In this case, we just do a byte-by-byte comparison.  */
 	.align 4
diff --git a/sysdeps/powerpc/powerpc64/strncmp.S b/sysdeps/powerpc/powerpc64/strncmp.S
index 779d9f7..8f842c4 100644
--- a/sysdeps/powerpc/powerpc64/strncmp.S
+++ b/sysdeps/powerpc/powerpc64/strncmp.S
@@ -25,7 +25,7 @@
 EALIGN (strncmp, 4, 0)
 	CALL_MCOUNT 3
 
-#define rTMP	r0
+#define rTMP2	r0
 #define rRTN	r3
 #define rSTR1	r3	/* first string arg */
 #define rSTR2	r4	/* second string arg */
@@ -36,6 +36,7 @@ EALIGN (strncmp, 4, 0)
 #define r7F7F	r9	/* constant 0x7f7f7f7f7f7f7f7f */
 #define rNEG	r10	/* ~(word in s1 | 0x7f7f7f7f7f7f7f7f) */
 #define rBITDIF	r11	/* bits that differ in s1 & s2 words */
+#define rTMP	r12
 
 	dcbt	0,rSTR1
 	or	rTMP, rSTR2, rSTR1
@@ -77,12 +78,59 @@ L(g1):	add	rTMP, rFEFE, rWORD1
    we don't compare two strings as different because of gunk beyond
    the end of the strings...  */
 
+#ifdef __LITTLE_ENDIAN__
+L(endstring):
+	addi    rTMP2, rTMP, -1
+	beq	cr1, L(equal)
+	andc    rTMP2, rTMP2, rTMP
+	rldimi	rTMP2, rTMP2, 1, 0
+	and	rWORD2, rWORD2, rTMP2	/* Mask off gunk.  */
+	and	rWORD1, rWORD1, rTMP2
+	cmpd	cr1, rWORD1, rWORD2
+	beq	cr1, L(equal)
+	xor	rBITDIF, rWORD1, rWORD2	/* rBITDIF has bits that differ.  */
+	neg	rNEG, rBITDIF
+	and	rNEG, rNEG, rBITDIF	/* rNEG has LS bit that differs.  */
+	cntlzd	rNEG, rNEG		/* bitcount of the bit.  */
+	andi.	rNEG, rNEG, 56		/* bitcount to LS byte that differs. */
+	sld	rWORD1, rWORD1, rNEG	/* shift left to clear MS bytes.  */
+	sld	rWORD2, rWORD2, rNEG
+	xor.	rBITDIF, rWORD1, rWORD2
+	sub	rRTN, rWORD1, rWORD2
+	blt-	L(highbit)
+	sradi	rRTN, rRTN, 63		/* must return an int.  */
+	ori	rRTN, rRTN, 1
+	blr
+L(equal):
+	li	rRTN, 0
+	blr
+
+L(different):
+	ld	rWORD1, -8(rSTR1)
+	xor	rBITDIF, rWORD1, rWORD2	/* rBITDIF has bits that differ.  */
+	neg	rNEG, rBITDIF
+	and	rNEG, rNEG, rBITDIF	/* rNEG has LS bit that differs.  */
+	cntlzd	rNEG, rNEG		/* bitcount of the bit.  */
+	andi.	rNEG, rNEG, 56		/* bitcount to LS byte that differs. */
+	sld	rWORD1, rWORD1, rNEG	/* shift left to clear MS bytes.  */
+	sld	rWORD2, rWORD2, rNEG
+	xor.	rBITDIF, rWORD1, rWORD2
+	sub	rRTN, rWORD1, rWORD2
+	blt-	L(highbit)
+	sradi	rRTN, rRTN, 63
+	ori	rRTN, rRTN, 1
+	blr
+L(highbit):
+	sradi	rRTN, rWORD2, 63
+	ori	rRTN, rRTN, 1
+	blr
+
+#else
 L(endstring):
 	and	rTMP, r7F7F, rWORD1
 	beq	cr1, L(equal)
 	add	rTMP, rTMP, r7F7F
 	xor.	rBITDIF, rWORD1, rWORD2
-
 	andc	rNEG, rNEG, rTMP
 	blt-	L(highbit)
 	cntlzd	rBITDIF, rBITDIF
@@ -91,7 +139,7 @@ L(endstring):
 	cmpd	cr1, rNEG, rBITDIF
 	sub	rRTN, rWORD1, rWORD2
 	blt-	cr1, L(equal)
-	sradi	rRTN, rRTN, 63
+	sradi	rRTN, rRTN, 63		/* must return an int.  */
 	ori	rRTN, rRTN, 1
 	blr
 L(equal):
@@ -99,7 +147,7 @@ L(equal):
 	blr
 
 L(different):
-	ldu	rWORD1, -8(rSTR1)
+	ld	rWORD1, -8(rSTR1)
 	xor.	rBITDIF, rWORD1, rWORD2
 	sub	rRTN, rWORD1, rWORD2
 	blt-	L(highbit)
@@ -107,11 +155,10 @@ L(different):
 	ori	rRTN, rRTN, 1
 	blr
 L(highbit):
-	srdi	rWORD2, rWORD2, 56
-	srdi	rWORD1, rWORD1, 56
-	sub	rRTN, rWORD1, rWORD2
+	sradi	rRTN, rWORD2, 63
+	ori	rRTN, rRTN, 1
 	blr
-
+#endif
 
 /* Oh well.  In this case, we just do a byte-by-byte comparison.  */
 	.align 4

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=65d975581da8f616f0a8dfca1b961f3a006186de

commit 65d975581da8f616f0a8dfca1b961f3a006186de
Author: Alan Modra <amodra@gmail.com>
Date:   Sat Aug 17 18:40:48 2013 +0930

    PowerPC LE strnlen
    http://sourceware.org/ml/libc-alpha/2013-08/msg00098.html
    
    The existing strnlen code has a number of defects, so this patch is more
    than just adding little-endian support.  The changes here are similar to
    those for memchr.
    
    	* sysdeps/powerpc/powerpc64/power7/strnlen.S (strnlen): Add
    	little-endian support.  Remove unnecessary "are we done" tests.
    	Handle "s" wrapping around zero and extremely large "size".
    	Correct main loop count.  Handle single left-over word from main
    	loop inline rather than by using small_loop.  Correct comments.
    	Delete "zero" tail, use "end_max" instead.
    	* sysdeps/powerpc/powerpc32/power7/strnlen.S: Likewise.

diff --git a/ChangeLog b/ChangeLog
index 690d370..811e852 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,15 @@
 2013-10-04  Alan Modra  <amodra@gmail.com>
 
+	* sysdeps/powerpc/powerpc64/power7/strnlen.S (strnlen): Add
+	little-endian support.  Remove unnecessary "are we done" tests.
+	Handle "s" wrapping around zero and extremely large "size".
+	Correct main loop count.  Handle single left-over word from main
+	loop inline rather than by using small_loop.  Correct comments.
+	Delete "zero" tail, use "end_max" instead.
+	* sysdeps/powerpc/powerpc32/power7/strnlen.S: Likewise.
+
+2013-10-04  Alan Modra  <amodra@gmail.com>
+
 	* sysdeps/powerpc/powerpc64/power7/strlen.S (strlen): Add little-endian
 	support.  Don't branch over align.
 	* sysdeps/powerpc/powerpc32/power7/strlen.S: Likewise.
diff --git a/sysdeps/powerpc/powerpc32/power7/strnlen.S b/sysdeps/powerpc/powerpc32/power7/strnlen.S
index ed08836..eb52afd 100644
--- a/sysdeps/powerpc/powerpc32/power7/strnlen.S
+++ b/sysdeps/powerpc/powerpc32/power7/strnlen.S
@@ -28,51 +28,47 @@ ENTRY (__strnlen)
 	add	r7,r3,r4      /* Calculate the last acceptable address.  */
 	cmplwi	r4,16
 	li	r0,0	      /* Word with null chars.  */
+	addi	r7,r7,-1
 	ble	L(small_range)
 
-	cmplw	cr7,r3,r7     /* Is the address equal or less than r3?  If
-				 it's equal or less, it means size is either 0
-				 or a negative number.  */
-	ble	cr7,L(proceed)
-
-	li	r7,-1	      /* Make r11 the biggest if r4 <= 0.  */
-L(proceed):
 	rlwinm	r6,r3,3,27,28 /* Calculate padding.  */
 	lwz	r12,0(r8)     /* Load word from memory.  */
 	cmpb	r10,r12,r0    /* Check for null bytes in DWORD1.  */
+#ifdef __LITTLE_ENDIAN__
+	srw	r10,r10,r6
+	slw	r10,r10,r6
+#else
 	slw	r10,r10,r6
 	srw	r10,r10,r6
+#endif
 	cmplwi	cr7,r10,0     /* If r10 == 0, no null's have been found.  */
 	bne	cr7,L(done)
 
-	/* Are we done already?  */
-	addi	r9,r8,4
-	cmplw	cr6,r9,r7
-	bge	cr6,L(end_max)
-
+	clrrwi	r7,r7,2       /* Address of last word.  */
 	mtcrf   0x01,r8
 	/* Are we now aligned to a doubleword boundary?  If so, skip to
 	   the main loop.  Otherwise, go through the alignment code.  */
 
 	bt	29,L(loop_setup)
 
-	/* Handle DWORD2 of pair.  */
+	/* Handle WORD2 of pair.  */
 	lwzu	r12,4(r8)
 	cmpb	r10,r12,r0
 	cmplwi	cr7,r10,0
 	bne	cr7,L(done)
 
-	/* Are we done already?  */
-	addi	r9,r8,4
-	cmplw	cr6,r9,r7
-	bge	cr6,L(end_max)
-
 L(loop_setup):
-	sub	r5,r7,r9
+	/* The last word we want to read in the loop below is the one
+	   containing the last byte of the string, ie. the word at
+	   (s + size - 1) & ~3, or r7.  The first word read is at
+	   r8 + 4, we read 2 * cnt words, so the last word read will
+	   be at r8 + 4 + 8 * cnt - 4.  Solving for cnt gives
+	   cnt = (r7 - r8) / 8  */
+	sub	r5,r7,r8
 	srwi	r6,r5,3	      /* Number of loop iterations.  */
 	mtctr	r6	      /* Setup the counter.  */
-	b	L(loop)
-	/* Main loop to look for the null byte backwards in the string.  Since
+
+	/* Main loop to look for the null byte in the string.  Since
 	   it's a small loop (< 8 instructions), align it to 32-bytes.  */
 	.p2align  5
 L(loop):
@@ -88,15 +84,18 @@ L(loop):
 	cmplwi	cr7,r5,0
 	bne	cr7,L(found)
 	bdnz	L(loop)
-	/* We're here because the counter reached 0, and that means we
-	   didn't have any matches for null in the whole range.  Just return
-	   the original size.  */
-	addi	r9,r8,4
-	cmplw	cr6,r9,r7
-	blt	cr6,L(loop_small)
+
+	/* We may have one more word to read.  */
+	cmplw	cr6,r8,r7
+	beq	cr6,L(end_max)
+
+	lwzu	r12,4(r8)
+	cmpb	r10,r12,r0
+	cmplwi	cr6,r10,0
+	bne	cr6,L(done)
 
 L(end_max):
-	sub	r3,r7,r3
+	mr	r3,r4
 	blr
 
 	/* OK, one (or both) of the words contains a null byte.  Check
@@ -121,49 +120,56 @@ L(found):
 	   We need to make sure the null char is *before* the end of the
 	   range.  */
 L(done):
-	cntlzw	r0,r10	      /* Count leading zeroes before the match.  */
-	srwi	r0,r0,3	      /* Convert leading zeroes to bytes.  */
-	add	r9,r8,r0
-	sub	r6,r9,r3      /* Length until the match.  */
-	cmplw	r9,r7
-	bgt	L(end_max)
-	mr	r3,r6
-	blr
-
-	.align	4
-L(zero):
-	li	r3,0
+#ifdef __LITTLE_ENDIAN__
+	addi	r0,r10,-1
+	andc	r0,r0,r10
+	popcntw	r0,r0
+#else
+	cntlzw	r0,r10	      /* Count leading zeros before the match.  */
+#endif
+	sub	r3,r8,r3
+	srwi	r0,r0,3	      /* Convert leading/trailing zeros to bytes.  */
+	add	r3,r3,r0      /* Length until the match.  */
+	cmplw	r3,r4
+	blelr
+	mr	r3,r4
 	blr
 
-/* Deals with size <= 32.  */
+/* Deals with size <= 16.  */
 	.align	4
 L(small_range):
 	cmplwi	r4,0
-	beq	L(zero)
+	beq	L(end_max)
+
+	clrrwi	r7,r7,2       /* Address of last word.  */
 
 	rlwinm	r6,r3,3,27,28 /* Calculate padding.  */
 	lwz	r12,0(r8)     /* Load word from memory.  */
 	cmpb	r10,r12,r0    /* Check for null bytes in WORD1.  */
+#ifdef __LITTLE_ENDIAN__
+	srw	r10,r10,r6
+	slw	r10,r10,r6
+#else
 	slw	r10,r10,r6
 	srw	r10,r10,r6
+#endif
 	cmplwi	cr7,r10,0
 	bne	cr7,L(done)
 
-	addi    r9,r8,4
-	cmplw	r9,r7
-	bge	L(end_max)
-	b	L(loop_small)
+	cmplw	r8,r7
+	beq	L(end_max)
 
 	.p2align  5
 L(loop_small):
 	lwzu	r12,4(r8)
 	cmpb	r10,r12,r0
-	addi	r9,r8,4
 	cmplwi	cr6,r10,0
 	bne	cr6,L(done)
-	cmplw	r9,r7
-	bge	L(end_max)
-	b	L(loop_small)
+	cmplw	r8,r7
+	bne	L(loop_small)
+	mr	r3,r4
+	blr
+
 END (__strnlen)
 weak_alias (__strnlen, strnlen)
 libc_hidden_builtin_def (strnlen)
diff --git a/sysdeps/powerpc/powerpc64/power7/strnlen.S b/sysdeps/powerpc/powerpc64/power7/strnlen.S
index 37c7dbf..5159106 100644
--- a/sysdeps/powerpc/powerpc64/power7/strnlen.S
+++ b/sysdeps/powerpc/powerpc64/power7/strnlen.S
@@ -24,33 +24,29 @@
 ENTRY (__strnlen)
 	CALL_MCOUNT 2
 	dcbt	0,r3
-	clrrdi  r8,r3,3
+	clrrdi	r8,r3,3
 	add	r7,r3,r4      /* Calculate the last acceptable address.  */
 	cmpldi	r4,32
 	li	r0,0	      /* Doubleword with null chars.  */
+	addi	r7,r7,-1
+
 	/* If we have less than 33 bytes to search, skip to a faster code.  */
 	ble	L(small_range)
 
-	cmpld	cr7,r3,r7    /* Is the address equal or less than r3?  If
-				it's equal or less, it means size is either 0
-				or a negative number.  */
-	ble	cr7,L(proceed)
-
-	li	r7,-1	      /* Make r11 the biggest if r4 <= 0.  */
-L(proceed):
 	rlwinm	r6,r3,3,26,28 /* Calculate padding.  */
 	ld	r12,0(r8)     /* Load doubleword from memory.  */
 	cmpb	r10,r12,r0    /* Check for null bytes in DWORD1.  */
+#ifdef __LITTLE_ENDIAN__
+	srd	r10,r10,r6
+	sld	r10,r10,r6
+#else
 	sld	r10,r10,r6
 	srd	r10,r10,r6
+#endif
 	cmpldi	cr7,r10,0     /* If r10 == 0, no null's have been found.  */
 	bne	cr7,L(done)
 
-	/* Are we done already?  */
-	addi	r9,r8,8
-	cmpld	cr6,r9,r7
-	bge	cr6,L(end_max)
-
+	clrrdi	r7,r7,3       /* Address of last doubleword.  */
 	mtcrf   0x01,r8
 	/* Are we now aligned to a quadword boundary?  If so, skip to
 	   the main loop.  Otherwise, go through the alignment code.  */
@@ -63,17 +59,18 @@ L(proceed):
 	cmpldi	cr7,r10,0
 	bne	cr7,L(done)
 
-	/* Are we done already?  */
-	addi	r9,r8,8
-	cmpld	cr6,r9,r7
-	bge	cr6,L(end_max)
-
 L(loop_setup):
-	sub	r5,r7,r9
+	/* The last dword we want to read in the loop below is the one
+	   containing the last byte of the string, ie. the dword at
+	   (s + size - 1) & ~7, or r7.  The first dword read is at
+	   r8 + 8, we read 2 * cnt dwords, so the last dword read will
+	   be at r8 + 8 + 16 * cnt - 8.  Solving for cnt gives
+	   cnt = (r7 - r8) / 16  */
+	sub	r5,r7,r8
 	srdi	r6,r5,4	      /* Number of loop iterations.  */
 	mtctr	r6	      /* Setup the counter.  */
-	b	L(loop)
-	/* Main loop to look for the null byte backwards in the string.  Since
+
+	/* Main loop to look for the null byte in the string.  Since
 	   it's a small loop (< 8 instructions), align it to 32-bytes.  */
 	.p2align  5
 L(loop):
@@ -89,15 +86,18 @@ L(loop):
 	cmpldi	cr7,r5,0
 	bne	cr7,L(found)
 	bdnz	L(loop)
-	/* We're here because the counter reached 0, and that means we
-	   didn't have any matches for null in the whole range.  Just return
-	   the original size.  */
-	addi	r9,r8,8
-	cmpld	cr6,r9,r7
-	blt	cr6,L(loop_small)
+
+	/* We may have one more dword to read.  */
+	cmpld	cr6,r8,r7
+	beq	cr6,L(end_max)
+
+	ldu	r12,8(r8)
+	cmpb	r10,r12,r0
+	cmpldi	cr6,r10,0
+	bne	cr6,L(done)
 
 L(end_max):
-	sub	r3,r7,r3
+	mr	r3,r4
 	blr
 
 	/* OK, one (or both) of the doublewords contains a null byte.  Check
@@ -119,52 +119,59 @@ L(found):
 	/* r10 has the output of the cmpb instruction, that is, it contains
 	   0xff in the same position as the null byte in the original
 	   doubleword from the string.  Use that to calculate the length.
-	   We need to make sure the null char is *before* the start of the
-	   range (since we're going backwards).  */
+	   We need to make sure the null char is *before* the end of the
+	   range.  */
 L(done):
-	cntlzd	r0,r10	      /* Count leading zeroes before the match.  */
-	srdi	r0,r0,3	      /* Convert leading zeroes to bytes.  */
-	add	r9,r8,r0
-	sub	r6,r9,r3      /* Length until the match.  */
-	cmpld	r9,r7
-	bgt	L(end_max)
-	mr	r3,r6
-	blr
-
-	.align	4
-L(zero):
-	li	r3,0
+#ifdef __LITTLE_ENDIAN__
+	addi	r0,r10,-1
+	andc	r0,r0,r10
+	popcntd	r0,r0
+#else
+	cntlzd	r0,r10	      /* Count leading zeros before the match.  */
+#endif
+	sub	r3,r8,r3
+	srdi	r0,r0,3	      /* Convert leading/trailing zeros to bytes.  */
+	add	r3,r3,r0      /* Length until the match.  */
+	cmpld	r3,r4
+	blelr
+	mr	r3,r4
 	blr
 
 /* Deals with size <= 32.  */
 	.align	4
 L(small_range):
 	cmpldi	r4,0
-	beq	L(zero)
+	beq	L(end_max)
+
+	clrrdi	r7,r7,3       /* Address of last doubleword.  */
 
 	rlwinm	r6,r3,3,26,28 /* Calculate padding.  */
-	ld	r12,0(r8)     /* Load word from memory.  */
+	ld	r12,0(r8)     /* Load doubleword from memory.  */
 	cmpb	r10,r12,r0    /* Check for null bytes in DWORD1.  */
+#ifdef __LITTLE_ENDIAN__
+	srd	r10,r10,r6
+	sld	r10,r10,r6
+#else
 	sld	r10,r10,r6
 	srd	r10,r10,r6
+#endif
 	cmpldi	cr7,r10,0
 	bne	cr7,L(done)
 
-	addi    r9,r8,8
-	cmpld	r9,r7
-	bge	L(end_max)
-	b	L(loop_small)
+	cmpld	r8,r7
+	beq	L(end_max)
 
 	.p2align  5
 L(loop_small):
 	ldu	r12,8(r8)
 	cmpb	r10,r12,r0
-	addi	r9,r8,8
 	cmpldi	cr6,r10,0
 	bne	cr6,L(done)
-	cmpld	r9,r7
-	bge	L(end_max)
-	b	L(loop_small)
+	cmpld	r8,r7
+	bne	L(loop_small)
+	mr	r3,r4
+	blr
+
 END (__strnlen)
 weak_alias (__strnlen, strnlen)
 libc_hidden_builtin_def (strnlen)

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=23fcb887a028aa322b8c4d0da881fc13ffe2ac0a

commit 23fcb887a028aa322b8c4d0da881fc13ffe2ac0a
Author: Alan Modra <amodra@gmail.com>
Date:   Sat Aug 17 18:40:11 2013 +0930

    PowerPC LE strlen
    http://sourceware.org/ml/libc-alpha/2013-08/msg00097.html
    
    This is the first of nine patches adding little-endian support to the
    existing optimised string and memory functions.  I did spend some
    time with a power7 simulator looking at cycle by cycle behaviour for
    memchr, but most of these patches have not been run on cpu simulators
    to check that we are going as fast as possible.  I'm sure PowerPC can
    do better.  However, the little-endian support mostly leaves main
    loops unchanged, so I'm banking on previous authors having done a
    good job on big-endian..  As with most code you stare at long enough,
    I found some improvements for big-endian too.
    
    Little-endian support for strlen.  Like most of the string functions,
    I leave the main word or multiple-word loops substantially unchanged,
    just needing to modify the tail.
    
    Removing the branch in the power7 functions is just a tidy.  .align
    produces a branch anyway.  Modifying regs in the non-power7 functions
    is to suit the new little-endian tail.
    
    	* sysdeps/powerpc/powerpc64/power7/strlen.S (strlen): Add little-endian
    	support.  Don't branch over align.
    	* sysdeps/powerpc/powerpc32/power7/strlen.S: Likewise.
    	* sysdeps/powerpc/powerpc64/strlen.S (strlen): Add little-endian support.
    	Rearrange tmp reg use to suit.  Comment.
    	* sysdeps/powerpc/powerpc32/strlen.S: Likewise.

diff --git a/ChangeLog b/ChangeLog
index 99fdeb1..690d370 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,14 @@
 2013-10-04  Alan Modra  <amodra@gmail.com>
 
+	* sysdeps/powerpc/powerpc64/power7/strlen.S (strlen): Add little-endian
+	support.  Don't branch over align.
+	* sysdeps/powerpc/powerpc32/power7/strlen.S: Likewise.
+	* sysdeps/powerpc/powerpc64/strlen.S (strlen): Add little-endian
+	support.  Rearrange tmp reg use to suit.  Comment.
+	* sysdeps/powerpc/powerpc32/strlen.S: Likewise.
+
+2013-10-04  Alan Modra  <amodra@gmail.com>
+
 	* sysdeps/unix/sysv/linux/powerpc/bits/sigstack.h: New file.
 
 2013-10-04  Alan Modra  <amodra@gmail.com>
diff --git a/sysdeps/powerpc/powerpc32/power7/strlen.S b/sysdeps/powerpc/powerpc32/power7/strlen.S
index b71a10f..b08d6c0 100644
--- a/sysdeps/powerpc/powerpc32/power7/strlen.S
+++ b/sysdeps/powerpc/powerpc32/power7/strlen.S
@@ -29,7 +29,11 @@ ENTRY (strlen)
 	li	r0,0	      /* Word with null chars to use with cmpb.  */
 	li	r5,-1	      /* MASK = 0xffffffffffffffff.  */
 	lwz	r12,0(r4)     /* Load word from memory.  */
+#ifdef __LITTLE_ENDIAN__
+	slw	r5,r5,r6
+#else
 	srw	r5,r5,r6      /* MASK = MASK >> padding.  */
+#endif
 	orc	r9,r12,r5     /* Mask bits that are not part of the string.  */
 	cmpb	r10,r9,r0     /* Check for null bytes in WORD1.  */
 	cmpwi	cr7,r10,0     /* If r10 == 0, no null's have been found.  */
@@ -47,9 +51,6 @@ ENTRY (strlen)
 	cmpb	r10,r12,r0
 	cmpwi	cr7,r10,0
 	bne	cr7,L(done)
-	b	L(loop)	      /* We branch here (rather than falling through)
-				 to skip the nops due to heavy alignment
-				 of the loop below.  */
 
 	/* Main loop to look for the end of the string.  Since it's a
 	   small loop (< 8 instructions), align it to 32-bytes.  */
@@ -86,9 +87,15 @@ L(loop):
 	   0xff in the same position as the null byte in the original
 	   word from the string.  Use that to calculate the length.  */
 L(done):
-	cntlzw	r0,r10	      /* Count leading zeroes before the match.  */
+#ifdef __LITTLE_ENDIAN__
+	addi	r9, r10, -1   /* Form a mask from trailing zeros.  */
+	andc	r9, r9, r10
+	popcntw r0, r9	      /* Count the bits in the mask.  */
+#else
+	cntlzw	r0,r10	      /* Count leading zeros before the match.  */
+#endif
 	subf	r5,r3,r4
-	srwi	r0,r0,3	      /* Convert leading zeroes to bytes.  */
+	srwi	r0,r0,3	      /* Convert leading zeros to bytes.  */
 	add	r3,r5,r0      /* Compute final length.  */
 	blr
 END (strlen)
diff --git a/sysdeps/powerpc/powerpc32/strlen.S b/sysdeps/powerpc/powerpc32/strlen.S
index 9a6eafc..a7153ed 100644
--- a/sysdeps/powerpc/powerpc32/strlen.S
+++ b/sysdeps/powerpc/powerpc32/strlen.S
@@ -29,7 +29,12 @@
       1 is subtracted you get a value in the range 0x00-0x7f, none of which
       have their high bit set. The expression here is
       (x + 0xfefefeff) & ~(x | 0x7f7f7f7f), which gives 0x00000000 when
-      there were no 0x00 bytes in the word.
+      there were no 0x00 bytes in the word.  You get 0x80 in bytes that
+      match, but possibly false 0x80 matches in the next more significant
+      byte to a true match due to carries.  For little-endian this is
+      of no consequence since the least significant match is the one
+      we're interested in, but big-endian needs method 2 to find which
+      byte matches.
 
    2) Given a word 'x', we can test to see _which_ byte was zero by
       calculating ~(((x & 0x7f7f7f7f) + 0x7f7f7f7f) | x | 0x7f7f7f7f).
@@ -72,7 +77,7 @@
 
 ENTRY (strlen)
 
-#define rTMP1	r0
+#define rTMP4	r0
 #define rRTN	r3	/* incoming STR arg, outgoing result */
 #define rSTR	r4	/* current string position */
 #define rPADN	r5	/* number of padding bits we prepend to the
@@ -82,9 +87,9 @@ ENTRY (strlen)
 #define rWORD1	r8	/* current string word */
 #define rWORD2	r9	/* next string word */
 #define rMASK	r9	/* mask for first string word */
-#define rTMP2	r10
-#define rTMP3	r11
-#define rTMP4	r12
+#define rTMP1	r10
+#define rTMP2	r11
+#define rTMP3	r12
 
 
 	clrrwi	rSTR, rRTN, 2
@@ -93,15 +98,20 @@ ENTRY (strlen)
 	lwz	rWORD1, 0(rSTR)
 	li	rMASK, -1
 	addi	r7F7F, r7F7F, 0x7f7f
-/* That's the setup done, now do the first pair of words.
-   We make an exception and use method (2) on the first two words, to reduce
-   overhead.  */
+/* We use method (2) on the first two words, because rFEFE isn't
+   required which reduces setup overhead.  Also gives a faster return
+   for small strings on big-endian due to needing to recalculate with
+   method (2) anyway.  */
+#ifdef __LITTLE_ENDIAN__
+	slw	rMASK, rMASK, rPADN
+#else
 	srw	rMASK, rMASK, rPADN
+#endif
 	and	rTMP1, r7F7F, rWORD1
 	or	rTMP2, r7F7F, rWORD1
 	add	rTMP1, rTMP1, r7F7F
-	nor	rTMP1, rTMP2, rTMP1
-	and.	rWORD1, rTMP1, rMASK
+	nor	rTMP3, rTMP2, rTMP1
+	and.	rTMP3, rTMP3, rMASK
 	mtcrf	0x01, rRTN
 	bne	L(done0)
 	lis	rFEFE, -0x101
@@ -110,11 +120,12 @@ ENTRY (strlen)
 	bt	29, L(loop)
 
 /* Handle second word of pair.  */
+/* Perhaps use method (1) here for little-endian, saving one instruction?  */
 	lwzu	rWORD1, 4(rSTR)
 	and	rTMP1, r7F7F, rWORD1
 	or	rTMP2, r7F7F, rWORD1
 	add	rTMP1, rTMP1, r7F7F
-	nor.	rWORD1, rTMP2, rTMP1
+	nor.	rTMP3, rTMP2, rTMP1
 	bne	L(done0)
 
 /* The loop.  */
@@ -128,28 +139,52 @@ L(loop):
 	add	rTMP3, rFEFE, rWORD2
 	nor	rTMP4, r7F7F, rWORD2
 	bne	L(done1)
-	and.	rTMP1, rTMP3, rTMP4
+	and.	rTMP3, rTMP3, rTMP4
 	beq	L(loop)
 
+#ifndef __LITTLE_ENDIAN__
 	and	rTMP1, r7F7F, rWORD2
 	add	rTMP1, rTMP1, r7F7F
-	andc	rWORD1, rTMP4, rTMP1
+	andc	rTMP3, rTMP4, rTMP1
 	b	L(done0)
 
 L(done1):
 	and	rTMP1, r7F7F, rWORD1
 	subi	rSTR, rSTR, 4
 	add	rTMP1, rTMP1, r7F7F
-	andc	rWORD1, rTMP2, rTMP1
+	andc	rTMP3, rTMP2, rTMP1
 
 /* When we get to here, rSTR points to the first word in the string that
-   contains a zero byte, and the most significant set bit in rWORD1 is in that
-   byte.  */
+   contains a zero byte, and rTMP3 has 0x80 for bytes that are zero,
+   and 0x00 otherwise.  */
 L(done0):
-	cntlzw	rTMP3, rWORD1
+	cntlzw	rTMP3, rTMP3
 	subf	rTMP1, rRTN, rSTR
 	srwi	rTMP3, rTMP3, 3
 	add	rRTN, rTMP1, rTMP3
 	blr
+#else
+
+L(done0):
+	addi	rTMP1, rTMP3, -1	/* Form a mask from trailing zeros.  */
+	andc	rTMP1, rTMP1, rTMP3
+	cntlzw	rTMP1, rTMP1		/* Count bits not in the mask.  */
+	subf	rTMP3, rRTN, rSTR
+	subfic	rTMP1, rTMP1, 32-7
+	srwi	rTMP1, rTMP1, 3
+	add	rRTN, rTMP1, rTMP3
+	blr
+
+L(done1):
+	addi	rTMP3, rTMP1, -1
+	andc	rTMP3, rTMP3, rTMP1
+	cntlzw	rTMP3, rTMP3
+	subf	rTMP1, rRTN, rSTR
+	subfic	rTMP3, rTMP3, 32-7-32
+	srawi	rTMP3, rTMP3, 3
+	add	rRTN, rTMP1, rTMP3
+	blr
+#endif
+
 END (strlen)
 libc_hidden_builtin_def (strlen)
diff --git a/sysdeps/powerpc/powerpc64/power7/strlen.S b/sysdeps/powerpc/powerpc64/power7/strlen.S
index 3432169..807ef10 100644
--- a/sysdeps/powerpc/powerpc64/power7/strlen.S
+++ b/sysdeps/powerpc/powerpc64/power7/strlen.S
@@ -30,7 +30,11 @@ ENTRY (strlen)
 				 with cmpb.  */
 	li	r5,-1	      /* MASK = 0xffffffffffffffff.  */
 	ld	r12,0(r4)     /* Load doubleword from memory.  */
+#ifdef __LITTLE_ENDIAN__
+	sld	r5,r5,r6
+#else
 	srd	r5,r5,r6      /* MASK = MASK >> padding.  */
+#endif
 	orc	r9,r12,r5     /* Mask bits that are not part of the string.  */
 	cmpb	r10,r9,r0     /* Check for null bytes in DWORD1.  */
 	cmpdi	cr7,r10,0     /* If r10 == 0, no null's have been found.  */
@@ -48,9 +52,6 @@ ENTRY (strlen)
 	cmpb	r10,r12,r0
 	cmpdi	cr7,r10,0
 	bne	cr7,L(done)
-	b	L(loop)	      /* We branch here (rather than falling through)
-				 to skip the nops due to heavy alignment
-				 of the loop below.  */
 
 	/* Main loop to look for the end of the string.  Since it's a
 	   small loop (< 8 instructions), align it to 32-bytes.  */
@@ -87,9 +88,15 @@ L(loop):
 	   0xff in the same position as the null byte in the original
 	   doubleword from the string.  Use that to calculate the length.  */
 L(done):
-	cntlzd	r0,r10	      /* Count leading zeroes before the match.  */
+#ifdef __LITTLE_ENDIAN__
+	addi	r9, r10, -1   /* Form a mask from trailing zeros.  */
+	andc	r9, r9, r10
+	popcntd r0, r9	      /* Count the bits in the mask.  */
+#else
+	cntlzd	r0,r10	      /* Count leading zeros before the match.  */
+#endif
 	subf	r5,r3,r4
-	srdi	r0,r0,3	      /* Convert leading zeroes to bytes.  */
+	srdi	r0,r0,3	      /* Convert leading/trailing zeros to bytes.  */
 	add	r3,r5,r0      /* Compute final length.  */
 	blr
 END (strlen)
diff --git a/sysdeps/powerpc/powerpc64/strlen.S b/sysdeps/powerpc/powerpc64/strlen.S
index 0f9b5ee..4ed1ba3 100644
--- a/sysdeps/powerpc/powerpc64/strlen.S
+++ b/sysdeps/powerpc/powerpc64/strlen.S
@@ -29,7 +29,12 @@
       1 is subtracted you get a value in the range 0x00-0x7f, none of which
       have their high bit set. The expression here is
       (x + 0xfefefeff) & ~(x | 0x7f7f7f7f), which gives 0x00000000 when
-      there were no 0x00 bytes in the word.
+      there were no 0x00 bytes in the word.  You get 0x80 in bytes that
+      match, but possibly false 0x80 matches in the next more significant
+      byte to a true match due to carries.  For little-endian this is
+      of no consequence since the least significant match is the one
+      we're interested in, but big-endian needs method 2 to find which
+      byte matches.
 
    2) Given a word 'x', we can test to see _which_ byte was zero by
       calculating ~(((x & 0x7f7f7f7f) + 0x7f7f7f7f) | x | 0x7f7f7f7f).
@@ -62,7 +67,7 @@
    Answer:
    1) Added a Data Cache Block Touch early to prefetch the first 128
    byte cache line. Adding dcbt instructions to the loop would not be
-   effective since most strings will be shorter than the cache line.*/
+   effective since most strings will be shorter than the cache line.  */
 
 /* Some notes on register usage: Under the SVR4 ABI, we can use registers
    0 and 3 through 12 (so long as we don't call any procedures) without
@@ -78,7 +83,7 @@
 ENTRY (strlen)
 	CALL_MCOUNT 1
 
-#define rTMP1	r0
+#define rTMP4	r0
 #define rRTN	r3	/* incoming STR arg, outgoing result */
 #define rSTR	r4	/* current string position */
 #define rPADN	r5	/* number of padding bits we prepend to the
@@ -88,9 +93,9 @@ ENTRY (strlen)
 #define rWORD1	r8	/* current string doubleword */
 #define rWORD2	r9	/* next string doubleword */
 #define rMASK	r9	/* mask for first string doubleword */
-#define rTMP2	r10
-#define rTMP3	r11
-#define rTMP4	r12
+#define rTMP1	r10
+#define rTMP2	r11
+#define rTMP3	r12
 
 	dcbt	0,rRTN
 	clrrdi	rSTR, rRTN, 3
@@ -100,30 +105,36 @@ ENTRY (strlen)
 	addi	r7F7F, r7F7F, 0x7f7f
 	li	rMASK, -1
 	insrdi	r7F7F, r7F7F, 32, 0
-/* That's the setup done, now do the first pair of doublewords.
-   We make an exception and use method (2) on the first two doublewords,
-   to reduce overhead.  */
+/* We use method (2) on the first two doublewords, because rFEFE isn't
+   required which reduces setup overhead.  Also gives a faster return
+   for small strings on big-endian due to needing to recalculate with
+   method (2) anyway.  */
+#ifdef __LITTLE_ENDIAN__
+	sld	rMASK, rMASK, rPADN
+#else
 	srd	rMASK, rMASK, rPADN
+#endif
 	and	rTMP1, r7F7F, rWORD1
 	or	rTMP2, r7F7F, rWORD1
 	lis	rFEFE, -0x101
 	add	rTMP1, rTMP1, r7F7F
 	addi	rFEFE, rFEFE, -0x101
-	nor	rTMP1, rTMP2, rTMP1
-	and.	rWORD1, rTMP1, rMASK
+	nor	rTMP3, rTMP2, rTMP1
+	and.	rTMP3, rTMP3, rMASK
 	mtcrf	0x01, rRTN
 	bne	L(done0)
-	sldi  rTMP1, rFEFE, 32
-	add  rFEFE, rFEFE, rTMP1
+	sldi	rTMP1, rFEFE, 32
+	add	rFEFE, rFEFE, rTMP1
 /* Are we now aligned to a doubleword boundary?  */
 	bt	28, L(loop)
 
 /* Handle second doubleword of pair.  */
+/* Perhaps use method (1) here for little-endian, saving one instruction?  */
 	ldu	rWORD1, 8(rSTR)
 	and	rTMP1, r7F7F, rWORD1
 	or	rTMP2, r7F7F, rWORD1
 	add	rTMP1, rTMP1, r7F7F
-	nor.	rWORD1, rTMP2, rTMP1
+	nor.	rTMP3, rTMP2, rTMP1
 	bne	L(done0)
 
 /* The loop.  */
@@ -137,28 +148,52 @@ L(loop):
 	add	rTMP3, rFEFE, rWORD2
 	nor	rTMP4, r7F7F, rWORD2
 	bne	L(done1)
-	and.	rTMP1, rTMP3, rTMP4
+	and.	rTMP3, rTMP3, rTMP4
 	beq	L(loop)
 
+#ifndef __LITTLE_ENDIAN__
 	and	rTMP1, r7F7F, rWORD2
 	add	rTMP1, rTMP1, r7F7F
-	andc	rWORD1, rTMP4, rTMP1
+	andc	rTMP3, rTMP4, rTMP1
 	b	L(done0)
 
 L(done1):
 	and	rTMP1, r7F7F, rWORD1
 	subi	rSTR, rSTR, 8
 	add	rTMP1, rTMP1, r7F7F
-	andc	rWORD1, rTMP2, rTMP1
+	andc	rTMP3, rTMP2, rTMP1
 
 /* When we get to here, rSTR points to the first doubleword in the string that
-   contains a zero byte, and the most significant set bit in rWORD1 is in that
-   byte.  */
+   contains a zero byte, and rTMP3 has 0x80 for bytes that are zero, and 0x00
+   otherwise.  */
 L(done0):
-	cntlzd	rTMP3, rWORD1
+	cntlzd	rTMP3, rTMP3
 	subf	rTMP1, rRTN, rSTR
 	srdi	rTMP3, rTMP3, 3
 	add	rRTN, rTMP1, rTMP3
 	blr
+#else
+
+L(done0):
+	addi	rTMP1, rTMP3, -1	/* Form a mask from trailing zeros.  */
+	andc	rTMP1, rTMP1, rTMP3
+	cntlzd	rTMP1, rTMP1		/* Count bits not in the mask.  */
+	subf	rTMP3, rRTN, rSTR
+	subfic	rTMP1, rTMP1, 64-7
+	srdi	rTMP1, rTMP1, 3
+	add	rRTN, rTMP1, rTMP3
+	blr
+
+L(done1):
+	addi	rTMP3, rTMP1, -1
+	andc	rTMP3, rTMP3, rTMP1
+	cntlzd	rTMP3, rTMP3
+	subf	rTMP1, rRTN, rSTR
+	subfic	rTMP3, rTMP3, 64-7-64
+	sradi	rTMP3, rTMP3, 3
+	add	rRTN, rTMP1, rTMP3
+	blr
+#endif
+
 END (strlen)
 libc_hidden_builtin_def (strlen)

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=319cb16b517026f42a338f30a8d8d503f9530e67

commit 319cb16b517026f42a338f30a8d8d503f9530e67
Author: Alan Modra <amodra@gmail.com>
Date:   Sat Aug 17 18:37:18 2013 +0930

    PowerPC SIGSTKSZ
    http://sourceware.org/ml/libc-alpha/2013-08/msg00093.html
    
    This copies the sparc version of sigstack.h, which gives powerpc
     #define MINSIGSTKSZ     4096
     #define SIGSTKSZ        16384
    
    Before the VSX changes, struct rt_sigframe size was 1920 plus 128 for
    __SIGNAL_FRAMESIZE giving ppc64 exactly the default MINSIGSTKSZ of
    2048.
    
    After VSX, ucontext increased by 256 bytes.  Oops, we're over
    MINSIGSTKSZ, so powerpc has been using the wrong value for quite a
    while.  Add another ucontext for TM and rt_sigframe is now at 3872,
    giving actual MINSIGSTKSZ of 4000.
    
    The glibc testcase that I was looking at was tst-cancel21, which
    allocates 2*SIGSTKSZ (not because the test is trying to be
    conservative, but because the test actually has nested signal stack
    frames).  We blew the allocation by 48 bytes when using current
    mainline gcc to compile glibc (le ppc64).
    
    The required stack depth in _dl_lookup_symbol_x from the top of the
    next signal frame was 10944 bytes.  I guess you'd want to add 288 to
    that, implying an actual SIGSTKSZ of 11232.
    
    	* sysdeps/unix/sysv/linux/powerpc/bits/sigstack.h: New file.

diff --git a/ChangeLog b/ChangeLog
index 696a340..99fdeb1 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,9 @@
 2013-10-04  Alan Modra  <amodra@gmail.com>
 
+	* sysdeps/unix/sysv/linux/powerpc/bits/sigstack.h: New file.
+
+2013-10-04  Alan Modra  <amodra@gmail.com>
+
 	* sysdeps/unix/sysv/linux/powerpc/powerpc32/makecontext.S: Use
 	conditional form of branch and link when obtaining pc.
 	* sysdeps/unix/sysv/linux/powerpc/powerpc64/makecontext.S: Likewise.
diff --git a/sysdeps/unix/sysv/linux/powerpc/bits/sigstack.h b/sysdeps/unix/sysv/linux/powerpc/bits/sigstack.h
new file mode 100644
index 0000000..33be9e8
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/powerpc/bits/sigstack.h
@@ -0,0 +1,54 @@
+/* sigstack, sigaltstack definitions.
+   Copyright (C) 1998-2013 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 _SIGNAL_H
+# error "Never include this file directly.  Use <signal.h> instead"
+#endif
+
+
+/* Structure describing a signal stack (obsolete).  */
+struct sigstack
+  {
+    void *ss_sp;		/* Signal stack pointer.  */
+    int ss_onstack;		/* Nonzero if executing on this stack.  */
+  };
+
+
+/* Possible values for `ss_flags.'.  */
+enum
+{
+  SS_ONSTACK = 1,
+#define SS_ONSTACK	SS_ONSTACK
+  SS_DISABLE
+#define SS_DISABLE	SS_DISABLE
+};
+
+/* Minimum stack size for a signal handler.  */
+#define MINSIGSTKSZ	4096
+
+/* System default stack size.  */
+#define SIGSTKSZ	16384
+
+
+/* Alternate, preferred interface.  */
+typedef struct sigaltstack
+  {
+    void *ss_sp;
+    int ss_flags;
+    size_t ss_size;
+  } stack_t;

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=fb2a1205a251c0fd1458fdfffc6641c382e83717

commit fb2a1205a251c0fd1458fdfffc6641c382e83717
Author: Alan Modra <amodra@gmail.com>
Date:   Sat Aug 17 18:36:45 2013 +0930

    PowerPC makecontext
    http://sourceware.org/ml/libc-alpha/2013-08/msg00092.html
    
    Use conditional form of branch and link to avoid destroying the cpu
    link stack used to predict blr return addresses.
    
    	* sysdeps/unix/sysv/linux/powerpc/powerpc32/makecontext.S: Use
    	conditional form of branch and link when obtaining pc.
    	* sysdeps/unix/sysv/linux/powerpc/powerpc64/makecontext.S: Likewise.

diff --git a/ChangeLog b/ChangeLog
index 2e6eb84..696a340 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,11 @@
 2013-10-04  Alan Modra  <amodra@gmail.com>
 
+	* sysdeps/unix/sysv/linux/powerpc/powerpc32/makecontext.S: Use
+	conditional form of branch and link when obtaining pc.
+	* sysdeps/unix/sysv/linux/powerpc/powerpc64/makecontext.S: Likewise.
+
+2013-10-04  Alan Modra  <amodra@gmail.com>
+
 	* sysdeps/unix/sysv/linux/powerpc/powerpc32/getcontext-common.S: Use
 	HIWORD/LOWORD.
 	* sysdeps/unix/sysv/linux/powerpc/powerpc32/setcontext-common.S: Ditto.
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/makecontext.S b/sysdeps/unix/sysv/linux/powerpc/powerpc32/makecontext.S
index 95902b1..70e3c97 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/makecontext.S
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/makecontext.S
@@ -47,7 +47,9 @@ ENTRY(__makecontext)
 #ifdef PIC
 	mflr	r0
 	cfi_register(lr,r0)
-	bl	1f
+	/* Use this conditional form of branch and link to avoid destroying
+	   the cpu link stack used to predict blr return addresses.  */
+	bcl	20,31,1f
 1:	mflr	r6
 	addi	r6,r6,L(exitcode)-1b
 	mtlr	r0
@@ -136,7 +138,9 @@ ENTRY(__novec_makecontext)
 #ifdef PIC
 	mflr	r0
 	cfi_register(lr,r0)
-	bl	1f
+	/* Use this conditional form of branch and link to avoid destroying
+	   the cpu link stack used to predict blr return addresses.  */
+	bcl	20,31,1f
 1:	mflr	r6
 	addi	r6,r6,L(novec_exitcode)-1b
 	mtlr	r0
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/makecontext.S b/sysdeps/unix/sysv/linux/powerpc/powerpc64/makecontext.S
index 4a16669..32fc47c 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/makecontext.S
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/makecontext.S
@@ -124,8 +124,10 @@ L(noparms):
 
   /* If the target function returns we need to do some cleanup.  We use a
      code trick to get the address of our cleanup function into the link
-     register.  Do not add any code between here and L(exitcode).  */
-  bl  L(gotexitcodeaddr);
+     register.  Do not add any code between here and L(exitcode).
+     Use this conditional form of branch and link to avoid destroying
+     the cpu link stack used to predict blr return addresses.  */
+  bcl	20,31,L(gotexitcodeaddr);
 
 	/* This is the helper code which gets called if a function which
 	   is registered with 'makecontext' returns.  In this case we

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=f50a734f453d9993dabbbd91e5e276f83c3b38e5

commit f50a734f453d9993dabbbd91e5e276f83c3b38e5
Author: Alan Modra <amodra@gmail.com>
Date:   Sat Aug 17 18:36:11 2013 +0930

    PowerPC LE _dl_hwcap access
    http://sourceware.org/ml/libc-alpha/2013-08/msg00091.html
    
    More LE support, correcting word accesses to _dl_hwcap.
    
    	* sysdeps/unix/sysv/linux/powerpc/powerpc32/getcontext-common.S: Use
    	HIWORD/LOWORD.
    	* sysdeps/unix/sysv/linux/powerpc/powerpc32/setcontext-common.S: Ditto.
    	* sysdeps/unix/sysv/linux/powerpc/powerpc32/swapcontext-common.S: Ditto.

diff --git a/ChangeLog b/ChangeLog
index f37cd7b..2e6eb84 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,12 @@
 2013-10-04  Alan Modra  <amodra@gmail.com>
 
+	* sysdeps/unix/sysv/linux/powerpc/powerpc32/getcontext-common.S: Use
+	HIWORD/LOWORD.
+	* sysdeps/unix/sysv/linux/powerpc/powerpc32/setcontext-common.S: Ditto.
+	* sysdeps/unix/sysv/linux/powerpc/powerpc32/swapcontext-common.S: Ditto.
+
+2013-10-04  Alan Modra  <amodra@gmail.com>
+
 	* sysdeps/powerpc/longjmp.c: Use proper symbol versioning macros.
 	* sysdeps/powerpc/novmx-longjmp.c: Likewise.
 	* sysdeps/powerpc/powerpc32/bsd-_setjmp.S: Likewise.
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/getcontext-common.S b/sysdeps/unix/sysv/linux/powerpc/powerpc32/getcontext-common.S
index 989899e..7e108f9 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/getcontext-common.S
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/getcontext-common.S
@@ -151,15 +151,15 @@ ENTRY(__CONTEXT_FUNC_NAME)
 #   ifdef SHARED
 	lwz     r7,_rtld_global_ro@got(r7)
 	mtlr    r8
-	lwz     r7,RTLD_GLOBAL_RO_DL_HWCAP_OFFSET+4(r7)
+	lwz     r7,RTLD_GLOBAL_RO_DL_HWCAP_OFFSET+LOWORD(r7)
 #   else
 	lwz     r7,_dl_hwcap@got(r7)
 	mtlr    r8
-	lwz     r7,4(r7)
+	lwz     r7,LOWORD(r7)
 #   endif
 #  else
-	lis	r7,(_dl_hwcap+4)@ha
-	lwz     r7,(_dl_hwcap+4)@l(r7)
+	lis	r7,(_dl_hwcap+LOWORD)@ha
+	lwz     r7,(_dl_hwcap+LOWORD)@l(r7)
 #  endif
 	andis.	r7,r7,(PPC_FEATURE_HAS_ALTIVEC >> 16)
 
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/setcontext-common.S b/sysdeps/unix/sysv/linux/powerpc/powerpc32/setcontext-common.S
index 900ce04..3121995 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/setcontext-common.S
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/setcontext-common.S
@@ -79,15 +79,15 @@ ENTRY(__CONTEXT_FUNC_NAME)
 # ifdef SHARED
 	lwz     r7,_rtld_global_ro@got(r7)
 	mtlr    r8
-	lwz     r7,RTLD_GLOBAL_RO_DL_HWCAP_OFFSET+4(r7)
+	lwz     r7,RTLD_GLOBAL_RO_DL_HWCAP_OFFSET+LOWORD(r7)
 # else
 	lwz     r7,_dl_hwcap@got(r7)
 	mtlr    r8
-	lwz     r7,4(r7)
+	lwz     r7,LOWORD(r7)
 # endif
 #else
-	lis	r7,(_dl_hwcap+4)@ha
-	lwz     r7,(_dl_hwcap+4)@l(r7)
+	lis	r7,(_dl_hwcap+LOWORD)@ha
+	lwz     r7,(_dl_hwcap+LOWORD)@l(r7)
 #endif
 
 #ifdef __CONTEXT_ENABLE_FPRS
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/swapcontext-common.S b/sysdeps/unix/sysv/linux/powerpc/powerpc32/swapcontext-common.S
index 77e47a7..0e942d3 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/swapcontext-common.S
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/swapcontext-common.S
@@ -152,15 +152,15 @@ ENTRY(__CONTEXT_FUNC_NAME)
 #  ifdef SHARED
 	lwz     r7,_rtld_global_ro@got(r7)
 	mtlr    r8
-	lwz     r7,RTLD_GLOBAL_RO_DL_HWCAP_OFFSET+4(r7)
+	lwz     r7,RTLD_GLOBAL_RO_DL_HWCAP_OFFSET+LOWORD(r7)
 #  else
 	lwz     r7,_dl_hwcap@got(r7)
 	mtlr    r8
-	lwz     r7,4(r7)
+	lwz     r7,LOWORD(r7)
 #  endif
 # else
-	lis	r7,(_dl_hwcap+4)@ha
-	lwz     r7,(_dl_hwcap+4)@l(r7)
+	lis	r7,(_dl_hwcap+LOWORD)@ha
+	lwz     r7,(_dl_hwcap+LOWORD)@l(r7)
 # endif
 
 # ifdef __CONTEXT_ENABLE_VRS
@@ -308,14 +308,14 @@ ENTRY(__CONTEXT_FUNC_NAME)
 	mtlr    r8
 #   ifdef SHARED
 	lwz     r7,_rtld_global_ro@got(r7)
-	lwz     r7,RTLD_GLOBAL_RO_DL_HWCAP_OFFSET+4(r7)
+	lwz     r7,RTLD_GLOBAL_RO_DL_HWCAP_OFFSET+LOWORD(r7)
 #   else
 	lwz     r7,_dl_hwcap@got(r7)
-	lwz     r7,4(r7)
+	lwz     r7,LOWORD(r7)
 #   endif
 #  else
-	lis	r7,(_dl_hwcap+4)@ha
-	lwz     r7,(_dl_hwcap+4)@l(r7)
+	lis	r7,(_dl_hwcap+LOWORD)@ha
+	lwz     r7,(_dl_hwcap+LOWORD)@l(r7)
 #  endif
 	andis.	r7,r7,(PPC_FEATURE_HAS_ALTIVEC >> 16)
 	la	r10,(_UC_VREGS)(r31)

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=e9c9326efdd0e7ad3ee06d60d6fb3b9a9370cd4b

commit e9c9326efdd0e7ad3ee06d60d6fb3b9a9370cd4b
Author: Alan Modra <amodra@gmail.com>
Date:   Sat Aug 17 18:35:40 2013 +0930

    PowerPC ugly symbol versioning
    http://sourceware.org/ml/libc-alpha/2013-08/msg00090.html
    
    This patch fixes symbol versioning in setjmp/longjmp.  The existing
    code uses raw versions, which results in wrong symbol versioning when
    you want to build glibc with a base version of 2.19 for LE.
    
    Note that the merging the 64-bit and 32-bit versions in novmx-lonjmp.c
    and pt-longjmp.c doesn't result in GLIBC_2.0 versions for 64-bit, due
    to the base in shlib_versions.
    
    	* sysdeps/powerpc/longjmp.c: Use proper symbol versioning macros.
    	* sysdeps/powerpc/novmx-longjmp.c: Likewise.
    	* sysdeps/powerpc/powerpc32/bsd-_setjmp.S: Likewise.
    	* sysdeps/powerpc/powerpc32/bsd-setjmp.S: Likewise.
    	* sysdeps/powerpc/powerpc32/fpu/__longjmp.S: Likewise.
    	* sysdeps/powerpc/powerpc32/fpu/setjmp.S: Likewise.
    	* sysdeps/powerpc/powerpc32/mcount.c: Likewise.
    	* sysdeps/powerpc/powerpc32/setjmp.S: Likewise.
    	* sysdeps/powerpc/powerpc64/setjmp.S: Likewise.
    	* nptl/sysdeps/unix/sysv/linux/powerpc/pt-longjmp.c: Likewise.

diff --git a/ChangeLog b/ChangeLog
index 56e77be..f37cd7b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,16 @@
+2013-10-04  Alan Modra  <amodra@gmail.com>
+
+	* sysdeps/powerpc/longjmp.c: Use proper symbol versioning macros.
+	* sysdeps/powerpc/novmx-longjmp.c: Likewise.
+	* sysdeps/powerpc/powerpc32/bsd-_setjmp.S: Likewise.
+	* sysdeps/powerpc/powerpc32/bsd-setjmp.S: Likewise.
+	* sysdeps/powerpc/powerpc32/fpu/__longjmp.S: Likewise.
+	* sysdeps/powerpc/powerpc32/fpu/setjmp.S: Likewise.
+	* sysdeps/powerpc/powerpc32/mcount.c: Likewise.
+	* sysdeps/powerpc/powerpc32/setjmp.S: Likewise.
+	* sysdeps/powerpc/powerpc64/setjmp.S: Likewise.
+	* nptl/sysdeps/unix/sysv/linux/powerpc/pt-longjmp.c: Likewise.
+
 2013-10-04  Anton Blanchard <anton@au1.ibm.com>
 	    Alistair Popple <alistair@ozlabs.au.ibm.com>
 	    Alan Modra <amodra@gmail.com>
diff --git a/nptl/sysdeps/unix/sysv/linux/powerpc/pt-longjmp.c b/nptl/sysdeps/unix/sysv/linux/powerpc/pt-longjmp.c
index ace858f..4ac913c 100644
--- a/nptl/sysdeps/unix/sysv/linux/powerpc/pt-longjmp.c
+++ b/nptl/sysdeps/unix/sysv/linux/powerpc/pt-longjmp.c
@@ -41,13 +41,8 @@ void __novmx_longjmp (jmp_buf env, int val)
   __novmx__libc_longjmp (env, val);
 }
 
-# if __WORDSIZE == 64
-symbol_version (__novmx_longjmp,longjmp,GLIBC_2.3);
-symbol_version (__novmx_siglongjmp,siglongjmp,GLIBC_2.3);
-# else
-symbol_version (__novmx_longjmp,longjmp,GLIBC_2.0);
-symbol_version (__novmx_siglongjmp,siglongjmp,GLIBC_2.0);
-# endif
+compat_symbol (libpthread, __novmx_longjmp, longjmp, GLIBC_2_0);
+compat_symbol (libpthread, __novmx_siglongjmp, siglongjmp, GLIBC_2_0);
 #endif /* defined SHARED && SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_3_4))  */
 
 void
@@ -62,5 +57,5 @@ __vmx_siglongjmp (jmp_buf env, int val)
   __libc_siglongjmp (env, val);
 }
 
-versioned_symbol (libc, __vmx_longjmp, longjmp, GLIBC_2_3_4);
-versioned_symbol (libc, __vmx_siglongjmp, siglongjmp, GLIBC_2_3_4);
+versioned_symbol (libpthread, __vmx_longjmp, longjmp, GLIBC_2_3_4);
+versioned_symbol (libpthread, __vmx_siglongjmp, siglongjmp, GLIBC_2_3_4);
diff --git a/sysdeps/powerpc/longjmp.c b/sysdeps/powerpc/longjmp.c
index 198c894..189fc03 100644
--- a/sysdeps/powerpc/longjmp.c
+++ b/sysdeps/powerpc/longjmp.c
@@ -55,6 +55,6 @@ weak_alias (__vmx__libc_siglongjmp, __vmxsiglongjmp)
 
 default_symbol_version (__vmx__libc_longjmp, __libc_longjmp, GLIBC_PRIVATE);
 default_symbol_version (__vmx__libc_siglongjmp, __libc_siglongjmp, GLIBC_PRIVATE);
-default_symbol_version (__vmx_longjmp, _longjmp, GLIBC_2.3.4);
-default_symbol_version (__vmxlongjmp, longjmp, GLIBC_2.3.4);
-default_symbol_version (__vmxsiglongjmp, siglongjmp, GLIBC_2.3.4);
+versioned_symbol (libc, __vmx_longjmp, _longjmp, GLIBC_2_3_4);
+versioned_symbol (libc, __vmxlongjmp, longjmp, GLIBC_2_3_4);
+versioned_symbol (libc, __vmxsiglongjmp, siglongjmp, GLIBC_2_3_4);
diff --git a/sysdeps/powerpc/novmx-longjmp.c b/sysdeps/powerpc/novmx-longjmp.c
index 8f6ea35..b2c0e4c 100644
--- a/sysdeps/powerpc/novmx-longjmp.c
+++ b/sysdeps/powerpc/novmx-longjmp.c
@@ -50,13 +50,7 @@ weak_alias (__novmx__libc_siglongjmp, __novmx_longjmp)
 weak_alias (__novmx__libc_siglongjmp, __novmxlongjmp)
 weak_alias (__novmx__libc_siglongjmp, __novmxsiglongjmp)
 
-# if __WORDSIZE == 64
-symbol_version (__novmx_longjmp,_longjmp,GLIBC_2.3);
-symbol_version (__novmxlongjmp,longjmp,GLIBC_2.3);
-symbol_version (__novmxsiglongjmp,siglongjmp,GLIBC_2.3);
-# else
-symbol_version (__novmx_longjmp,_longjmp,GLIBC_2.0);
-symbol_version (__novmxlongjmp,longjmp,GLIBC_2.0);
-symbol_version (__novmxsiglongjmp,siglongjmp,GLIBC_2.0);
-# endif
+compat_symbol (libc, __novmx_longjmp, _longjmp, GLIBC_2_0);
+compat_symbol (libc, __novmxlongjmp, longjmp, GLIBC_2_0);
+compat_symbol (libc, __novmxsiglongjmp, siglongjmp, GLIBC_2_0);
 #endif /* defined SHARED && SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_3_4))  */
diff --git a/sysdeps/powerpc/powerpc32/bsd-_setjmp.S b/sysdeps/powerpc/powerpc32/bsd-_setjmp.S
index 95e8a5a..ad2b5ff 100644
--- a/sysdeps/powerpc/powerpc32/bsd-_setjmp.S
+++ b/sysdeps/powerpc/powerpc32/bsd-_setjmp.S
@@ -30,7 +30,7 @@ libc_hidden_def (_setjmp)
 /* Build a versioned object for libc.  */
 
 # if defined SHARED && SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_3_4)
-symbol_version (__novmx_setjmp,_setjmp,GLIBC_2.0);
+compat_symbol (libc, __novmx_setjmp, _setjmp, GLIBC_2_0);
 
 ENTRY (__novmx_setjmp)
 	li r4,0			/* Set second argument to 0.  */
@@ -39,7 +39,7 @@ END (__novmx_setjmp)
 libc_hidden_def (__novmx_setjmp)
 # endif /* defined SHARED  && SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_3_4) */
 
-default_symbol_version (__vmx_setjmp,_setjmp,GLIBC_2.3.4)
+versioned_symbol (libc, __vmx_setjmp, _setjmp, GLIBC_2_3_4)
 /* __GI__setjmp prototype is needed for ntpl i.e. _setjmp is defined
    as a libc_hidden_proto & is used in sysdeps/generic/libc-start.c
    if HAVE_CLEANUP_JMP_BUF is defined */
diff --git a/sysdeps/powerpc/powerpc32/bsd-setjmp.S b/sysdeps/powerpc/powerpc32/bsd-setjmp.S
index 1113ea5..5e1e860 100644
--- a/sysdeps/powerpc/powerpc32/bsd-setjmp.S
+++ b/sysdeps/powerpc/powerpc32/bsd-setjmp.S
@@ -26,7 +26,7 @@ ENTRY (__novmxsetjmp)
 	b __novmx__sigsetjmp@local
 END (__novmxsetjmp)
 strong_alias (__novmxsetjmp, __novmx__setjmp)
-symbol_version (__novmxsetjmp, setjmp, GLIBC_2.0)
+compat_symbol (libc, __novmxsetjmp, setjmp, GLIBC_2_0)
 
 #endif  /* defined SHARED && SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_3_4) ) */
 
@@ -36,4 +36,4 @@ ENTRY (__vmxsetjmp)
 END (__vmxsetjmp)
 strong_alias (__vmxsetjmp, __vmx__setjmp)
 strong_alias (__vmx__setjmp, __setjmp)
-default_symbol_version (__vmxsetjmp,setjmp,GLIBC_2.3.4)
+versioned_symbol (libc, __vmxsetjmp, setjmp, GLIBC_2_3_4)
diff --git a/sysdeps/powerpc/powerpc32/fpu/__longjmp.S b/sysdeps/powerpc/powerpc32/fpu/__longjmp.S
index 96e50de..27166c4 100644
--- a/sysdeps/powerpc/powerpc32/fpu/__longjmp.S
+++ b/sysdeps/powerpc/powerpc32/fpu/__longjmp.S
@@ -26,14 +26,14 @@
 
 #else /* !NOT_IN_libc */
 /* Build a versioned object for libc.  */
-default_symbol_version (__vmx__longjmp,__longjmp,GLIBC_2.3.4);
+versioned_symbol (libc, __vmx__longjmp, __longjmp, GLIBC_2_3_4);
 # define __longjmp  __vmx__longjmp
 # include "__longjmp-common.S"
 
 # if defined SHARED && SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_3_4)
 #  define __NO_VMX__
 #  undef JB_SIZE
-symbol_version (__novmx__longjmp,__longjmp,GLIBC_2.0);
+compat_symbol (libc, __novmx__longjmp, __longjmp, GLIBC_2_0);
 #  undef __longjmp
 #  define __longjmp  __novmx__longjmp
 #  include "__longjmp-common.S"
diff --git a/sysdeps/powerpc/powerpc32/fpu/setjmp.S b/sysdeps/powerpc/powerpc32/fpu/setjmp.S
index dc93db3..671032d 100644
--- a/sysdeps/powerpc/powerpc32/fpu/setjmp.S
+++ b/sysdeps/powerpc/powerpc32/fpu/setjmp.S
@@ -26,7 +26,7 @@
 
 #else /* !NOT_IN_libc */
 /* Build a versioned object for libc.  */
-default_symbol_version (__vmx__sigsetjmp,__sigsetjmp,GLIBC_2.3.4)
+versioned_symbol (libc, __vmx__sigsetjmp, __sigsetjmp, GLIBC_2_3_4)
 # define __sigsetjmp __vmx__sigsetjmp
 # define __sigjmp_save __vmx__sigjmp_save
 # include "setjmp-common.S"
@@ -36,7 +36,7 @@ default_symbol_version (__vmx__sigsetjmp,__sigsetjmp,GLIBC_2.3.4)
 #  undef __sigsetjmp
 #  undef __sigjmp_save
 #  undef JB_SIZE
-symbol_version (__novmx__sigsetjmp,__sigsetjmp,GLIBC_2.0)
+compat_symbol (libc, __novmx__sigsetjmp, __sigsetjmp, GLIBC_2_0)
 #  define __sigsetjmp __novmx__sigsetjmp
 #  define __sigjmp_save __novmx__sigjmp_save
 #  include "setjmp-common.S"
diff --git a/sysdeps/powerpc/powerpc32/mcount.c b/sysdeps/powerpc/powerpc32/mcount.c
index 0476bf6..d8c0632 100644
--- a/sysdeps/powerpc/powerpc32/mcount.c
+++ b/sysdeps/powerpc/powerpc32/mcount.c
@@ -9,7 +9,7 @@
 /* __mcount_internal was added in glibc 2.15 with version GLIBC_PRIVATE,
    but it should have been put in version GLIBC_2.15.  Mark the
    GLIBC_PRIVATE version obsolete and add it to GLIBC_2.16 instead.  */
-default_symbol_version (___mcount_internal, __mcount_internal, GLIBC_2.16);
+versioned_symbol (libc, ___mcount_internal, __mcount_internal, GLIBC_2_16);
 
 #if SHLIB_COMPAT (libc, GLIBC_2_15, GLIBC_2_16)
 strong_alias (___mcount_internal, ___mcount_internal_private);
diff --git a/sysdeps/powerpc/powerpc32/setjmp.S b/sysdeps/powerpc/powerpc32/setjmp.S
index 851a5b9..f0c1507 100644
--- a/sysdeps/powerpc/powerpc32/setjmp.S
+++ b/sysdeps/powerpc/powerpc32/setjmp.S
@@ -25,7 +25,7 @@
 
 #else /* !NOT_IN_libc */
 /* Build a versioned object for libc.  */
-default_symbol_version (__vmx__sigsetjmp,__sigsetjmp,GLIBC_2.3.4)
+versioned_symbol (libc, __vmx__sigsetjmp, __sigsetjmp, GLIBC_2_3_4)
 # define __sigsetjmp __vmx__sigsetjmp
 # define __sigjmp_save __vmx__sigjmp_save
 # include "setjmp-common.S"
@@ -35,7 +35,7 @@ default_symbol_version (__vmx__sigsetjmp,__sigsetjmp,GLIBC_2.3.4)
 #  undef __sigsetjmp
 #  undef __sigjmp_save
 #  undef JB_SIZE
-symbol_version (__novmx__sigsetjmp,__sigsetjmp,GLIBC_2.0)
+compat_symbol (libc, __novmx__sigsetjmp, __sigsetjmp, GLIBC_2_0)
 #  define __sigsetjmp __novmx__sigsetjmp
 #  define __sigjmp_save __novmx__sigjmp_save
 #  include "setjmp-common.S"
diff --git a/sysdeps/powerpc/powerpc64/setjmp.S b/sysdeps/powerpc/powerpc64/setjmp.S
index 667b9d1..0a3b2fc 100644
--- a/sysdeps/powerpc/powerpc64/setjmp.S
+++ b/sysdeps/powerpc/powerpc64/setjmp.S
@@ -26,9 +26,9 @@
 
 #else /* !NOT_IN_libc */
 /* Build a versioned object for libc.  */
-default_symbol_version (__vmxsetjmp, setjmp, GLIBC_2.3.4)
-default_symbol_version (__vmx_setjmp,_setjmp,GLIBC_2.3.4)
-default_symbol_version (__vmx__sigsetjmp,__sigsetjmp,GLIBC_2.3.4)
+versioned_symbol (libc, __vmxsetjmp, setjmp, GLIBC_2_3_4)
+versioned_symbol (libc, __vmx_setjmp, _setjmp, GLIBC_2_3_4)
+versioned_symbol (libc, __vmx__sigsetjmp, __sigsetjmp, GLIBC_2_3_4)
 # define setjmp __vmxsetjmp
 # define _setjmp __vmx_setjmp
 # define __sigsetjmp __vmx__sigsetjmp
@@ -44,9 +44,9 @@ strong_alias (__vmx__sigsetjmp, __setjmp)
 #  undef __sigjmp_save
 #  undef JB_SIZE
 #  define __NO_VMX__
-symbol_version (__novmxsetjmp, setjmp, GLIBC_2.3)
-symbol_version (__novmx_setjmp,_setjmp,GLIBC_2.3);
-symbol_version (__novmx__sigsetjmp,__sigsetjmp,GLIBC_2.3)
+compat_symbol (libc, __novmxsetjmp, setjmp, GLIBC_2_3)
+compat_symbol (libc, __novmx_setjmp,_setjmp, GLIBC_2_3);
+compat_symbol (libc, __novmx__sigsetjmp,__sigsetjmp, GLIBC_2_3)
 #  define setjmp __novmxsetjmp
 #  define _setjmp __novmx_setjmp
 #  define __sigsetjmp __novmx__sigsetjmp

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=9ed6497ec694382feabd02f16a0c7c1eda97b1c5

commit 9ed6497ec694382feabd02f16a0c7c1eda97b1c5
Author: Anton Blanchard <anton@au1.ibm.com>
Date:   Sat Aug 17 18:34:40 2013 +0930

    PowerPC LE setjmp/longjmp
    http://sourceware.org/ml/libc-alpha/2013-08/msg00089.html
    
    Little-endian fixes for setjmp/longjmp.  When writing these I noticed
    the setjmp code corrupts the non volatile VMX registers when using an
    unaligned buffer.  Anton fixed this, and also simplified it quite a
    bit.
    
    The current code uses boilerplate for the case where we want to store
    16 bytes to an unaligned address.  For that we have to do a
    read/modify/write of two aligned 16 byte quantities.  In our case we
    are storing a bunch of back to back data (consective VMX registers),
    and only the start and end of the region need the read/modify/write.
    
    	[BZ #15723]
    	* sysdeps/powerpc/jmpbuf-offsets.h: Comment fix.
    	* sysdeps/powerpc/powerpc32/fpu/__longjmp-common.S: Correct
    	_dl_hwcap access for little-endian.
    	* sysdeps/powerpc/powerpc32/fpu/setjmp-common.S: Likewise.  Don't
    	destroy vmx regs when saving unaligned.
    	* sysdeps/powerpc/powerpc64/__longjmp-common.S: Correct CR load.
    	* sysdeps/powerpc/powerpc64/setjmp-common.S: Likewise CR save.  Don't
    	destroy vmx regs when saving unaligned.

diff --git a/ChangeLog b/ChangeLog
index 1e3a6c7..56e77be 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,17 @@
+2013-10-04  Anton Blanchard <anton@au1.ibm.com>
+	    Alistair Popple <alistair@ozlabs.au.ibm.com>
+	    Alan Modra <amodra@gmail.com>
+
+	[BZ #15723]
+	* sysdeps/powerpc/jmpbuf-offsets.h: Comment fix.
+	* sysdeps/powerpc/powerpc32/fpu/__longjmp-common.S: Correct
+	_dl_hwcap access for little-endian.
+	* sysdeps/powerpc/powerpc32/fpu/setjmp-common.S: Likewise.  Don't
+	destroy vmx regs when saving unaligned.
+	* sysdeps/powerpc/powerpc64/__longjmp-common.S: Correct CR load.
+	* sysdeps/powerpc/powerpc64/setjmp-common.S: Likewise CR save.  Don't
+	destroy vmx regs when saving unaligned.
+
 2013-10-04  Alan Modra  <amodra@gmail.com>
 
 	* sysdeps/powerpc/powerpc32/power4/hp-timing.h (HP_TIMING_NOW):
diff --git a/sysdeps/powerpc/jmpbuf-offsets.h b/sysdeps/powerpc/jmpbuf-offsets.h
index 64c658a..f2116bd 100644
--- a/sysdeps/powerpc/jmpbuf-offsets.h
+++ b/sysdeps/powerpc/jmpbuf-offsets.h
@@ -21,12 +21,10 @@
 #define JB_LR     2  /* The address we will return to */
 #if __WORDSIZE == 64
 # define JB_GPRS   3  /* GPRs 14 through 31 are saved, 18*2 words total.  */
-# define JB_CR     21 /* Condition code registers with the VRSAVE at */
-                       /* offset 172 (low half of the double word.  */
+# define JB_CR     21 /* Shared dword with VRSAVE.  CR word at offset 172.  */
 # define JB_FPRS   22 /* FPRs 14 through 31 are saved, 18*2 words total.  */
 # define JB_SIZE   (64 * 8) /* As per PPC64-VMX ABI.  */
-# define JB_VRSAVE 21 /* VRSAVE shares a double word with the CR at offset */
-                       /* 168 (high half of the double word).  */
+# define JB_VRSAVE 21 /* Shared dword with CR.  VRSAVE word at offset 168.  */
 # define JB_VRS    40 /* VRs 20 through 31 are saved, 12*4 words total.  */
 #else
 # define JB_GPRS   3  /* GPRs 14 through 31 are saved, 18 in total.  */
diff --git a/sysdeps/powerpc/powerpc32/fpu/__longjmp-common.S b/sysdeps/powerpc/powerpc32/fpu/__longjmp-common.S
index 9d34cd9..d02aa57 100644
--- a/sysdeps/powerpc/powerpc32/fpu/__longjmp-common.S
+++ b/sysdeps/powerpc/powerpc32/fpu/__longjmp-common.S
@@ -43,16 +43,16 @@ ENTRY (__longjmp)
 #   endif
 	mtlr    r6
 	cfi_same_value (lr)
-	lwz     r5,RTLD_GLOBAL_RO_DL_HWCAP_OFFSET+4(r5)
+	lwz     r5,RTLD_GLOBAL_RO_DL_HWCAP_OFFSET+LOWORD(r5)
 #  else
 	lwz     r5,_dl_hwcap@got(r5)
 	mtlr    r6
 	cfi_same_value (lr)
-	lwz     r5,4(r5)
+	lwz     r5,LOWORD(r5)
 #  endif
 # else
-	lis	r5,(_dl_hwcap+4)@ha
-	lwz     r5,(_dl_hwcap+4)@l(r5)
+	lis	r5,(_dl_hwcap+LOWORD)@ha
+	lwz     r5,(_dl_hwcap+LOWORD)@l(r5)
 # endif
 	andis.	r5,r5,(PPC_FEATURE_HAS_ALTIVEC >> 16)
 	beq	L(no_vmx)
diff --git a/sysdeps/powerpc/powerpc32/fpu/setjmp-common.S b/sysdeps/powerpc/powerpc32/fpu/setjmp-common.S
index 46ea2b0..f324406 100644
--- a/sysdeps/powerpc/powerpc32/fpu/setjmp-common.S
+++ b/sysdeps/powerpc/powerpc32/fpu/setjmp-common.S
@@ -94,14 +94,14 @@ ENTRY (__sigsetjmp)
 #   else
 	lwz     r5,_rtld_global_ro@got(r5)
 #   endif
-	lwz     r5,RTLD_GLOBAL_RO_DL_HWCAP_OFFSET+4(r5)
+	lwz     r5,RTLD_GLOBAL_RO_DL_HWCAP_OFFSET+LOWORD(r5)
 #  else
 	lwz     r5,_dl_hwcap@got(r5)
-	lwz     r5,4(r5)
+	lwz     r5,LOWORD(r5)
 #  endif
 # else
-	lis	r6,(_dl_hwcap+4)@ha
-	lwz     r5,(_dl_hwcap+4)@l(r6)
+	lis	r6,(_dl_hwcap+LOWORD)@ha
+	lwz     r5,(_dl_hwcap+LOWORD)@l(r6)
 # endif
 	andis.	r5,r5,(PPC_FEATURE_HAS_ALTIVEC >> 16)
 	beq	L(no_vmx)
@@ -111,44 +111,43 @@ ENTRY (__sigsetjmp)
 	stw	r0,((JB_VRSAVE)*4)(3)
 	addi	r6,r5,16
 	beq+	L(aligned_save_vmx)
-	lvsr	v0,0,r5
-	vspltisb v1,-1         /* set v1 to all 1's */
-	vspltisb v2,0          /* set v2 to all 0's */
-	vperm   v3,v2,v1,v0   /* v3 contains shift mask with num all 1 bytes on left = misalignment  */
 
+	lvsr	v0,0,r5
+	lvsl	v1,0,r5
+	addi	r6,r5,-16
 
-	/* Special case for v20 we need to preserve what is in save area below v20 before obliterating it */
-	lvx     v5,0,r5
-	vperm   v20,v20,v20,v0
-	vsel    v5,v5,v20,v3
-	vsel    v20,v20,v2,v3
-	stvx    v5,0,r5
+# define save_misaligned_vmx(savevr,prevvr,shiftvr,tmpvr,savegpr,addgpr) \
+	addi	addgpr,addgpr,32;					 \
+	vperm	tmpvr,prevvr,savevr,shiftvr;				 \
+	stvx	tmpvr,0,savegpr
 
-#define save_2vmx_partial(savevr,prev_savevr,hivr,shiftvr,maskvr,savegpr,addgpr) \
-	addi    addgpr,addgpr,32; \
-	vperm   savevr,savevr,savevr,shiftvr; \
-	vsel    hivr,prev_savevr,savevr,maskvr; \
-	stvx    hivr,0,savegpr;
+	/*
+	 * We have to be careful not to corrupt the data below v20 and
+	 * above v31. To keep things simple we just rotate both ends in
+	 * the opposite direction to our main permute so we can use
+	 * the common macro.
+	 */
 
-	save_2vmx_partial(v21,v20,v5,v0,v3,r6,r5)
-	save_2vmx_partial(v22,v21,v5,v0,v3,r5,r6)
-	save_2vmx_partial(v23,v22,v5,v0,v3,r6,r5)
-	save_2vmx_partial(v24,v23,v5,v0,v3,r5,r6)
-	save_2vmx_partial(v25,v24,v5,v0,v3,r6,r5)
-	save_2vmx_partial(v26,v25,v5,v0,v3,r5,r6)
-	save_2vmx_partial(v27,v26,v5,v0,v3,r6,r5)
-	save_2vmx_partial(v28,v27,v5,v0,v3,r5,r6)
-	save_2vmx_partial(v29,v28,v5,v0,v3,r6,r5)
-	save_2vmx_partial(v30,v29,v5,v0,v3,r5,r6)
+	/* load and rotate data below v20 */
+	lvx	v2,0,r5
+	vperm	v2,v2,v2,v1
+	save_misaligned_vmx(v20,v2,v0,v3,r5,r6)
+	save_misaligned_vmx(v21,v20,v0,v3,r6,r5)
+	save_misaligned_vmx(v22,v21,v0,v3,r5,r6)
+	save_misaligned_vmx(v23,v22,v0,v3,r6,r5)
+	save_misaligned_vmx(v24,v23,v0,v3,r5,r6)
+	save_misaligned_vmx(v25,v24,v0,v3,r6,r5)
+	save_misaligned_vmx(v26,v25,v0,v3,r5,r6)
+	save_misaligned_vmx(v27,v26,v0,v3,r6,r5)
+	save_misaligned_vmx(v28,v27,v0,v3,r5,r6)
+	save_misaligned_vmx(v29,v28,v0,v3,r6,r5)
+	save_misaligned_vmx(v30,v29,v0,v3,r5,r6)
+	save_misaligned_vmx(v31,v30,v0,v3,r6,r5)
+	/* load and rotate data above v31 */
+	lvx	v2,0,r6
+	vperm	v2,v2,v2,v1
+	save_misaligned_vmx(v2,v31,v0,v3,r5,r6)
 
-	/* Special case for r31 we need to preserve what is in save area above v31 before obliterating it */
-	addi    r5,r5,32
-	vperm   v31,v31,v31,v0
-	lvx     v4,0,r5
-	vsel    v5,v30,v31,v3
-	stvx    v5,0,r6
-	vsel    v4,v31,v4,v3
-	stvx    v4,0,r5
 	b	L(no_vmx)
 
 L(aligned_save_vmx):
diff --git a/sysdeps/powerpc/powerpc64/__longjmp-common.S b/sysdeps/powerpc/powerpc64/__longjmp-common.S
index 70c3704..4f1e3c8 100644
--- a/sysdeps/powerpc/powerpc64/__longjmp-common.S
+++ b/sysdeps/powerpc/powerpc64/__longjmp-common.S
@@ -57,7 +57,7 @@ ENTRY (__longjmp)
 	beq	L(no_vmx)
 	la	r5,((JB_VRS)*8)(3)
 	andi.	r6,r5,0xf
-	lwz	r0,((JB_VRSAVE)*8)(3)
+	lwz	r0,((JB_VRSAVE)*8)(3)	/* 32-bit VRSAVE.  */
 	mtspr	VRSAVE,r0
 	beq+	L(aligned_restore_vmx)
 	addi    r6,r5,16
@@ -153,7 +153,7 @@ L(no_vmx):
 	lfd fp21,((JB_FPRS+7)*8)(r3)
 	ld r22,((JB_GPRS+8)*8)(r3)
 	lfd fp22,((JB_FPRS+8)*8)(r3)
-	ld r0,(JB_CR*8)(r3)
+	lwz r0,((JB_CR*8)+4)(r3)	/* 32-bit CR.  */
 	ld r23,((JB_GPRS+9)*8)(r3)
 	lfd fp23,((JB_FPRS+9)*8)(r3)
 	ld r24,((JB_GPRS+10)*8)(r3)
diff --git a/sysdeps/powerpc/powerpc64/setjmp-common.S b/sysdeps/powerpc/powerpc64/setjmp-common.S
index 58ec610..1829b9a 100644
--- a/sysdeps/powerpc/powerpc64/setjmp-common.S
+++ b/sysdeps/powerpc/powerpc64/setjmp-common.S
@@ -95,7 +95,7 @@ JUMPTARGET(GLUE(__sigsetjmp,_ent)):
 	mfcr r0
 	std  r16,((JB_GPRS+2)*8)(3)
 	stfd fp16,((JB_FPRS+2)*8)(3)
-	std  r0,(JB_CR*8)(3)
+	stw  r0,((JB_CR*8)+4)(3)	/* 32-bit CR.  */
 	std  r17,((JB_GPRS+3)*8)(3)
 	stfd fp17,((JB_FPRS+3)*8)(3)
 	std  r18,((JB_GPRS+4)*8)(3)
@@ -139,50 +139,46 @@ JUMPTARGET(GLUE(__sigsetjmp,_ent)):
 	la	r5,((JB_VRS)*8)(3)
 	andi.	r6,r5,0xf
 	mfspr	r0,VRSAVE
-	stw	r0,((JB_VRSAVE)*8)(3)
+	stw	r0,((JB_VRSAVE)*8)(3)	/* 32-bit VRSAVE.  */
 	addi	r6,r5,16
 	beq+	L(aligned_save_vmx)
-	lvsr	v0,0,r5
-	vspltisb v1,-1         /* set v1 to all 1's */
-	vspltisb v2,0          /* set v2 to all 0's */
-	vperm   v3,v2,v1,v0   /* v3 contains shift mask with num all 1 bytes
-				 on left = misalignment  */
 
+	lvsr	v0,0,r5
+	lvsl	v1,0,r5
+	addi	r6,r5,-16
 
-	/* Special case for v20 we need to preserve what is in save area
-	   below v20 before obliterating it */
-	lvx     v5,0,r5
-	vperm   v20,v20,v20,v0
-	vsel    v5,v5,v20,v3
-	vsel    v20,v20,v2,v3
-	stvx    v5,0,r5
+# define save_misaligned_vmx(savevr,prevvr,shiftvr,tmpvr,savegpr,addgpr) \
+	addi	addgpr,addgpr,32;					 \
+	vperm	tmpvr,prevvr,savevr,shiftvr;				 \
+	stvx	tmpvr,0,savegpr
 
-# define save_2vmx_partial(savevr,prev_savevr,hivr,shiftvr,maskvr,savegpr,addgpr) \
-	addi    addgpr,addgpr,32; \
-	vperm   savevr,savevr,savevr,shiftvr; \
-	vsel    hivr,prev_savevr,savevr,maskvr; \
-	stvx    hivr,0,savegpr;
+	/*
+	 * We have to be careful not to corrupt the data below v20 and
+	 * above v31. To keep things simple we just rotate both ends in
+	 * the opposite direction to our main permute so we can use
+	 * the common macro.
+	 */
 
-	save_2vmx_partial(v21,v20,v5,v0,v3,r6,r5)
-	save_2vmx_partial(v22,v21,v5,v0,v3,r5,r6)
-	save_2vmx_partial(v23,v22,v5,v0,v3,r6,r5)
-	save_2vmx_partial(v24,v23,v5,v0,v3,r5,r6)
-	save_2vmx_partial(v25,v24,v5,v0,v3,r6,r5)
-	save_2vmx_partial(v26,v25,v5,v0,v3,r5,r6)
-	save_2vmx_partial(v27,v26,v5,v0,v3,r6,r5)
-	save_2vmx_partial(v28,v27,v5,v0,v3,r5,r6)
-	save_2vmx_partial(v29,v28,v5,v0,v3,r6,r5)
-	save_2vmx_partial(v30,v29,v5,v0,v3,r5,r6)
+	/* load and rotate data below v20 */
+	lvx	v2,0,r5
+	vperm	v2,v2,v2,v1
+	save_misaligned_vmx(v20,v2,v0,v3,r5,r6)
+	save_misaligned_vmx(v21,v20,v0,v3,r6,r5)
+	save_misaligned_vmx(v22,v21,v0,v3,r5,r6)
+	save_misaligned_vmx(v23,v22,v0,v3,r6,r5)
+	save_misaligned_vmx(v24,v23,v0,v3,r5,r6)
+	save_misaligned_vmx(v25,v24,v0,v3,r6,r5)
+	save_misaligned_vmx(v26,v25,v0,v3,r5,r6)
+	save_misaligned_vmx(v27,v26,v0,v3,r6,r5)
+	save_misaligned_vmx(v28,v27,v0,v3,r5,r6)
+	save_misaligned_vmx(v29,v28,v0,v3,r6,r5)
+	save_misaligned_vmx(v30,v29,v0,v3,r5,r6)
+	save_misaligned_vmx(v31,v30,v0,v3,r6,r5)
+	/* load and rotate data above v31 */
+	lvx	v2,0,r6
+	vperm	v2,v2,v2,v1
+	save_misaligned_vmx(v2,v31,v0,v3,r5,r6)
 
-	/* Special case for r31 we need to preserve what is in save area
-	   above v31 before obliterating it */
-	addi    r5,r5,32
-	vperm   v31,v31,v31,v0
-	lvx     v4,0,r5
-	vsel    v5,v30,v31,v3
-	stvx    v5,0,r6
-	vsel    v4,v31,v4,v3
-	stvx    v4,0,r5
 	b	L(no_vmx)
 
 L(aligned_save_vmx):

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=4ec9dde3cc121c1167824b5c5a6fe4a4a683c4e5

commit 4ec9dde3cc121c1167824b5c5a6fe4a4a683c4e5
Author: Alan Modra <amodra@gmail.com>
Date:   Sat Aug 17 18:33:45 2013 +0930

    PowerPC floating point little-endian [15 of 15]
    http://sourceware.org/ml/libc-alpha/2013-07/msg00206.html
    
    The union loses when little-endian.
    
    	* sysdeps/powerpc/powerpc32/power4/hp-timing.h (HP_TIMING_NOW):
    	Don't use a union to pack hi/low value.

diff --git a/ChangeLog b/ChangeLog
index 81dc345..1e3a6c7 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2013-10-04  Alan Modra  <amodra@gmail.com>
+
+	* sysdeps/powerpc/powerpc32/power4/hp-timing.h (HP_TIMING_NOW):
+	Don't use a union to pack hi/low value.
+
 2013-10-04  Anton Blanchard <anton@au1.ibm.com>
 
 	* sysdeps/powerpc/powerpc64/fpu/s_ceilf.S: Correct float constants
diff --git a/sysdeps/powerpc/powerpc32/power4/hp-timing.h b/sysdeps/powerpc/powerpc32/power4/hp-timing.h
index 7d6c96e..4e42374 100644
--- a/sysdeps/powerpc/powerpc32/power4/hp-timing.h
+++ b/sysdeps/powerpc/powerpc32/power4/hp-timing.h
@@ -87,18 +87,15 @@ typedef unsigned long long int hp_timing_t;
 
 #define HP_TIMING_NOW(Var)						\
   do {									\
-        union { long long ll; long ii[2]; } _var;			\
-	long tmp;							\
-        __asm__ __volatile__ (						\
-		"1:	mfspr	%0,269;"				\
-		"	mfspr	%1,268;"				\
-		"	mfspr	%2,269;"				\
-		"	cmpw	%0,%2;"					\
-		"	bne	1b;"					\
-		: "=r" (_var.ii[0]), "=r" (_var.ii[1]) , "=r" (tmp)	\
-		: : "cr0"						\
-		);							\
-	Var = _var.ll;							\
+    unsigned int hi, lo, tmp;						\
+    __asm__ __volatile__ ("1:	mfspr	%0,269;"			\
+			  "	mfspr	%1,268;"			\
+			  "	mfspr	%2,269;"			\
+			  "	cmpw	%0,%2;"				\
+			  "	bne	1b;"				\
+			  : "=&r" (hi), "=&r" (lo), "=&r" (tmp)		\
+			  : : "cr0");					\
+    Var = ((hp_timing_t) hi << 32) | lo;				\
   } while (0)
 
 

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=91f32e9adb55272f231009028b4d0f9d12400f25

commit 91f32e9adb55272f231009028b4d0f9d12400f25
Author: Anton Blanchard <anton@au1.ibm.com>
Date:   Sat Aug 17 18:33:02 2013 +0930

    PowerPC floating point little-endian [14 of 15]
    http://sourceware.org/ml/libc-alpha/2013-07/msg00205.html
    
    These all wrongly specified float constants in a 64-bit word.
    
    	* sysdeps/powerpc/powerpc64/fpu/s_ceilf.S: Correct float constants
    	for little-endian.
    	* sysdeps/powerpc/powerpc64/fpu/s_floorf.S: Likewise.
    	* sysdeps/powerpc/powerpc64/fpu/s_nearbyintf.S: Likewise.
    	* sysdeps/powerpc/powerpc64/fpu/s_rintf.S: Likewise.
    	* sysdeps/powerpc/powerpc64/fpu/s_roundf.S: Likewise.
    	* sysdeps/powerpc/powerpc64/fpu/s_truncf.S: Likewise.

diff --git a/ChangeLog b/ChangeLog
index 8ed3d80..81dc345 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+2013-10-04  Anton Blanchard <anton@au1.ibm.com>
+
+	* sysdeps/powerpc/powerpc64/fpu/s_ceilf.S: Correct float constants
+	for little-endian.
+	* sysdeps/powerpc/powerpc64/fpu/s_floorf.S: Likewise.
+	* sysdeps/powerpc/powerpc64/fpu/s_nearbyintf.S: Likewise.
+	* sysdeps/powerpc/powerpc64/fpu/s_rintf.S: Likewise.
+	* sysdeps/powerpc/powerpc64/fpu/s_roundf.S: Likewise.
+	* sysdeps/powerpc/powerpc64/fpu/s_truncf.S: Likewise.
+
 2013-10-04  Alan Modra  <amodra@gmail.com>
 
 	* sysdeps/powerpc/powerpc32/fpu/s_roundf.S: Increase alignment of
diff --git a/sysdeps/powerpc/powerpc64/fpu/s_ceilf.S b/sysdeps/powerpc/powerpc64/fpu/s_ceilf.S
index 801af5d..45f71d7 100644
--- a/sysdeps/powerpc/powerpc64/fpu/s_ceilf.S
+++ b/sysdeps/powerpc/powerpc64/fpu/s_ceilf.S
@@ -19,8 +19,10 @@
 #include <sysdep.h>
 
 	.section	".toc","aw"
+	.p2align 3
 .LC0:	/* 2**23 */
-	.tc FD_4b000000_0[TC],0x4b00000000000000
+	.long 0x4b000000
+	.long 0x0
 	.section	".text"
 
 EALIGN (__ceilf, 4, 0)
diff --git a/sysdeps/powerpc/powerpc64/fpu/s_floorf.S b/sysdeps/powerpc/powerpc64/fpu/s_floorf.S
index a0a22e7..e85b820 100644
--- a/sysdeps/powerpc/powerpc64/fpu/s_floorf.S
+++ b/sysdeps/powerpc/powerpc64/fpu/s_floorf.S
@@ -19,8 +19,10 @@
 #include <sysdep.h>
 
 	.section	".toc","aw"
+	.p2align 3
 .LC0:	/* 2**23 */
-	.tc FD_4b000000_0[TC],0x4b00000000000000
+	.long 0x4b000000
+	.long 0x0
 	.section	".text"
 
 EALIGN (__floorf, 4, 0)
diff --git a/sysdeps/powerpc/powerpc64/fpu/s_nearbyintf.S b/sysdeps/powerpc/powerpc64/fpu/s_nearbyintf.S
index 876707c..b1a2b8c 100644
--- a/sysdeps/powerpc/powerpc64/fpu/s_nearbyintf.S
+++ b/sysdeps/powerpc/powerpc64/fpu/s_nearbyintf.S
@@ -26,8 +26,10 @@
 /* float [fp1] nearbyintf(float [fp1]) */
 
 	.section	".toc","aw"
+	.p2align 3
 .LC0:	/* 2**23 */
-	.tc FD_4b000000_0[TC],0x4b00000000000000
+	.long 0x4b000000
+	.long 0x0
 	.section	".text"
 
 EALIGN (__nearbyintf, 4, 0)
diff --git a/sysdeps/powerpc/powerpc64/fpu/s_rintf.S b/sysdeps/powerpc/powerpc64/fpu/s_rintf.S
index cb28ec7..1887717 100644
--- a/sysdeps/powerpc/powerpc64/fpu/s_rintf.S
+++ b/sysdeps/powerpc/powerpc64/fpu/s_rintf.S
@@ -19,8 +19,10 @@
 #include <sysdep.h>
 
 	.section	".toc","aw"
+	.p2align 3
 .LC0:	/* 2**23 */
-	.tc FD_4b000000_0[TC],0x4b00000000000000
+	.long 0x4b000000
+	.long 0x0
 	.section	".text"
 
 EALIGN (__rintf, 4, 0)
diff --git a/sysdeps/powerpc/powerpc64/fpu/s_roundf.S b/sysdeps/powerpc/powerpc64/fpu/s_roundf.S
index 980a77b..4f2c851 100644
--- a/sysdeps/powerpc/powerpc64/fpu/s_roundf.S
+++ b/sysdeps/powerpc/powerpc64/fpu/s_roundf.S
@@ -19,10 +19,12 @@
 #include <sysdep.h>
 
 	.section	".toc","aw"
+	.p2align 3
 .LC0:	/* 2**23 */
-	.tc FD_4b000000_0[TC],0x4b00000000000000
+	.long 0x4b000000
 .LC1:	/* 0.5 */
-	.tc FD_3f000000_0[TC],0x3f00000000000000
+	.long 0x3f000000
+
 	.section	".text"
 
 /* float [fp1] roundf  (float x [fp1])
diff --git a/sysdeps/powerpc/powerpc64/fpu/s_truncf.S b/sysdeps/powerpc/powerpc64/fpu/s_truncf.S
index 5ea5f3d..b8fd050 100644
--- a/sysdeps/powerpc/powerpc64/fpu/s_truncf.S
+++ b/sysdeps/powerpc/powerpc64/fpu/s_truncf.S
@@ -19,8 +19,10 @@
 #include <sysdep.h>
 
 	.section	".toc","aw"
+	.p2align 3
 .LC0:	/* 2**23 */
-	.tc FD_4b000000_0[TC],0x4b00000000000000
+	.long 0x4b000000
+	.long 0x0
 	.section	".text"
 
 /* float [fp1] truncf (float x [fp1])

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=e3c82825a789573337cf4d712cf21b3ba3d1fa65

commit e3c82825a789573337cf4d712cf21b3ba3d1fa65
Author: Alan Modra <amodra@gmail.com>
Date:   Sat Aug 17 18:32:18 2013 +0930

    PowerPC floating point little-endian [13 of 15]
    http://sourceware.org/ml/libc-alpha/2013-08/msg00088.html
    
    	* sysdeps/powerpc/powerpc32/fpu/s_roundf.S: Increase alignment of
    	constants to usual value for .cst8 section, and remove redundant
    	high address load.
    	* sysdeps/powerpc/powerpc32/power4/fpu/s_llround.S: Use float
    	constant for 0x1p52.  Load little-endian words of double from
    	correct stack offsets.

diff --git a/ChangeLog b/ChangeLog
index e8e9cd9..8ed3d80 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,14 @@
 2013-10-04  Alan Modra  <amodra@gmail.com>
 
+	* sysdeps/powerpc/powerpc32/fpu/s_roundf.S: Increase alignment of
+	constants to usual value for .cst8 section, and remove redundant
+	high address load.
+	* sysdeps/powerpc/powerpc32/power4/fpu/s_llround.S: Use float
+	constant for 0x1p52.  Load little-endian words of double from
+	correct stack offsets.
+
+2013-10-04  Alan Modra  <amodra@gmail.com>
+
 	* sysdeps/powerpc/sysdep.h (LOWORD, HIWORD, HISHORT): Define.
 	* sysdeps/powerpc/powerpc32/fpu/s_copysign.S: Load little-endian
 	words of double from correct stack offsets.
diff --git a/sysdeps/powerpc/powerpc32/fpu/s_roundf.S b/sysdeps/powerpc/powerpc32/fpu/s_roundf.S
index 2ed9ca7..8cff156 100644
--- a/sysdeps/powerpc/powerpc32/fpu/s_roundf.S
+++ b/sysdeps/powerpc/powerpc32/fpu/s_roundf.S
@@ -19,7 +19,7 @@
 #include <sysdep.h>
 
 	.section	.rodata.cst8,"aM",@progbits,8
-	.align	2
+	.align	3
 .LC0:	/* 2**23 */
 	.long 0x4b000000
 .LC1:	/* 0.5 */
@@ -60,7 +60,6 @@ ENTRY (__roundf )
 #ifdef SHARED
 	lfs	fp10,.LC1-.LC0(r9)
 #else
-	lis	r9,.LC1@ha
 	lfs	fp10,.LC1@l(r9)
 #endif
 	ble-	cr6,.L4
diff --git a/sysdeps/powerpc/powerpc32/power4/fpu/s_llround.S b/sysdeps/powerpc/powerpc32/power4/fpu/s_llround.S
index 631180f..7246ca4 100644
--- a/sysdeps/powerpc/powerpc32/power4/fpu/s_llround.S
+++ b/sysdeps/powerpc/powerpc32/power4/fpu/s_llround.S
@@ -19,12 +19,10 @@
 #include <sysdep.h>
 #include <math_ldbl_opt.h>
 
- .section .rodata.cst12,"aM",@progbits,12
+ .section .rodata.cst8,"aM",@progbits,8
  .align 3
- .LC0:   /* 0x1.0000000000000p+52 == 2^52 */
-	.long 0x43300000
-	.long 0x00000000
-	.long 0x3f000000 /* Use this for 0.5  */
+ .LC0:	.long (52+127)<<23 /* 0x1p+52  */
+	.long (-1+127)<<23 /* 0.5  */
 
 	.section	".text"
 
@@ -57,12 +55,12 @@ ENTRY (__llround)
 	addi	r9,r9,.LC0-got_label@l
 	mtlr	r11
 	cfi_same_value (lr)
-	lfd	fp9,0(r9)
-	lfs	fp10,8(r9)
+	lfs	fp9,0(r9)
+	lfs	fp10,4(r9)
 #else
 	lis r9,.LC0@ha
-	lfd fp9,.LC0@l(r9)	/* Load 2^52 into fpr9.  */
-	lfs fp10,.LC0@l+8(r9)	/* Load 0.5 into fpr10.  */
+	lfs fp9,.LC0@l(r9)	/* Load 2^52 into fpr9.  */
+	lfs fp10,.LC0@l+4(r9)	/* Load 0.5 into fpr10.  */
 #endif
 	fabs	fp2,fp1		/* Get the absolute value of x.  */
 	fsub	fp12,fp10,fp10	/* Compute 0.0 into fpr12.  */
@@ -80,8 +78,8 @@ ENTRY (__llround)
 	nop
 	nop
 	nop
-	lwz	r4,12(r1)	/* Load return as integer.  */
-	lwz	r3,8(r1)
+	lwz	r3,8+HIWORD(r1)	/* Load return as integer.  */
+	lwz	r4,8+LOWORD(r1)
 .Lout:
 	addi	r1,r1,16
 	blr

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=f1a45ccc7e37f63b76d996ffff86dfbc6f7f0676

commit f1a45ccc7e37f63b76d996ffff86dfbc6f7f0676
Author: Alan Modra <amodra@gmail.com>
Date:   Sat Aug 17 18:31:45 2013 +0930

    PowerPC floating point little-endian [12 of 15]
    http://sourceware.org/ml/libc-alpha/2013-08/msg00087.html
    
    Fixes for little-endian in 32-bit assembly.
    
    	* sysdeps/powerpc/sysdep.h (LOWORD, HIWORD, HISHORT): Define.
    	* sysdeps/powerpc/powerpc32/fpu/s_copysign.S: Load little-endian
    	words of double from correct stack offsets.
    	* sysdeps/powerpc/powerpc32/fpu/s_copysignl.S: Likewise.
    	* sysdeps/powerpc/powerpc32/fpu/s_lrint.S: Likewise.
    	* sysdeps/powerpc/powerpc32/fpu/s_lround.S: Likewise.
    	* sysdeps/powerpc/powerpc32/power4/fpu/s_llrint.S: Likewise.
    	* sysdeps/powerpc/powerpc32/power4/fpu/s_llrintf.S: Likewise.
    	* sysdeps/powerpc/powerpc32/power5+/fpu/s_llround.S: Likewise.
    	* sysdeps/powerpc/powerpc32/power5+/fpu/s_lround.S: Likewise.
    	* sysdeps/powerpc/powerpc32/power5/fpu/s_isnan.S: Likewise.
    	* sysdeps/powerpc/powerpc32/power6/fpu/s_isnan.S: Likewise.
    	* sysdeps/powerpc/powerpc32/power6/fpu/s_llrint.S: Likewise.
    	* sysdeps/powerpc/powerpc32/power6/fpu/s_llrintf.S: Likewise.
    	* sysdeps/powerpc/powerpc32/power6/fpu/s_llround.S: Likewise.
    	* sysdeps/powerpc/powerpc32/power7/fpu/s_finite.S: Likewise.
    	* sysdeps/powerpc/powerpc32/power7/fpu/s_isinf.S: Likewise.
    	* sysdeps/powerpc/powerpc32/power7/fpu/s_isnan.S: Likewise.
    	* sysdeps/powerpc/powerpc64/power7/fpu/s_finite.S: Use HISHORT.
    	* sysdeps/powerpc/powerpc64/power7/fpu/s_isinf.S: Likewise.

diff --git a/ChangeLog b/ChangeLog
index 5327d98..e8e9cd9 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,28 @@
 2013-10-04  Alan Modra  <amodra@gmail.com>
 
+	* sysdeps/powerpc/sysdep.h (LOWORD, HIWORD, HISHORT): Define.
+	* sysdeps/powerpc/powerpc32/fpu/s_copysign.S: Load little-endian
+	words of double from correct stack offsets.
+	* sysdeps/powerpc/powerpc32/fpu/s_copysignl.S: Likewise.
+	* sysdeps/powerpc/powerpc32/fpu/s_lrint.S: Likewise.
+	* sysdeps/powerpc/powerpc32/fpu/s_lround.S: Likewise.
+	* sysdeps/powerpc/powerpc32/power4/fpu/s_llrint.S: Likewise.
+	* sysdeps/powerpc/powerpc32/power4/fpu/s_llrintf.S: Likewise.
+	* sysdeps/powerpc/powerpc32/power5+/fpu/s_llround.S: Likewise.
+	* sysdeps/powerpc/powerpc32/power5+/fpu/s_lround.S: Likewise.
+	* sysdeps/powerpc/powerpc32/power5/fpu/s_isnan.S: Likewise.
+	* sysdeps/powerpc/powerpc32/power6/fpu/s_isnan.S: Likewise.
+	* sysdeps/powerpc/powerpc32/power6/fpu/s_llrint.S: Likewise.
+	* sysdeps/powerpc/powerpc32/power6/fpu/s_llrintf.S: Likewise.
+	* sysdeps/powerpc/powerpc32/power6/fpu/s_llround.S: Likewise.
+	* sysdeps/powerpc/powerpc32/power7/fpu/s_finite.S: Likewise.
+	* sysdeps/powerpc/powerpc32/power7/fpu/s_isinf.S: Likewise.
+	* sysdeps/powerpc/powerpc32/power7/fpu/s_isnan.S: Likewise.
+	* sysdeps/powerpc/powerpc64/power7/fpu/s_finite.S: Use HISHORT.
+	* sysdeps/powerpc/powerpc64/power7/fpu/s_isinf.S: Likewise.
+
+2013-10-04  Alan Modra  <amodra@gmail.com>
+
 	* sysdeps/powerpc/fpu_control.h (_FPU_GETCW): Rewrite using
 	64-bit int/double union.
 	(_FPU_SETCW): Likewise.
diff --git a/sysdeps/powerpc/powerpc32/fpu/s_copysign.S b/sysdeps/powerpc/powerpc32/fpu/s_copysign.S
index 840891f..1da24f4 100644
--- a/sysdeps/powerpc/powerpc32/fpu/s_copysign.S
+++ b/sysdeps/powerpc/powerpc32/fpu/s_copysign.S
@@ -29,7 +29,7 @@ ENTRY(__copysign)
 	stwu	r1,-16(r1)
 	cfi_adjust_cfa_offset (16)
 	stfd	fp2,8(r1)
-	lwz	r3,8(r1)
+	lwz	r3,8+HIWORD(r1)
 	cmpwi   r3,0
 	addi    r1,r1,16
 	cfi_adjust_cfa_offset (-16)
diff --git a/sysdeps/powerpc/powerpc32/fpu/s_copysignl.S b/sysdeps/powerpc/powerpc32/fpu/s_copysignl.S
index 4ec8389..2ad6de2 100644
--- a/sysdeps/powerpc/powerpc32/fpu/s_copysignl.S
+++ b/sysdeps/powerpc/powerpc32/fpu/s_copysignl.S
@@ -30,7 +30,7 @@ ENTRY(__copysignl)
 	fmr	fp0,fp1
 	fabs	fp1,fp1
 	fcmpu	cr7,fp0,fp1
-	lwz	r3,8(r1)
+	lwz	r3,8+HIWORD(r1)
 	cmpwi	cr6,r3,0
 	addi	r1,r1,16
 	cfi_adjust_cfa_offset (-16)
diff --git a/sysdeps/powerpc/powerpc32/fpu/s_lrint.S b/sysdeps/powerpc/powerpc32/fpu/s_lrint.S
index 27881f8..249fda5 100644
--- a/sysdeps/powerpc/powerpc32/fpu/s_lrint.S
+++ b/sysdeps/powerpc/powerpc32/fpu/s_lrint.S
@@ -24,10 +24,10 @@ ENTRY (__lrint)
 	stwu	r1,-16(r1)
 	fctiw	fp13,fp1
 	stfd	fp13,8(r1)
-	nop	/* Insure the following load is in a different dispatch group */
+	nop	/* Ensure the following load is in a different dispatch group */
 	nop	/* to avoid pipe stall on POWER4&5.  */
 	nop
-	lwz	r3,12(r1)
+	lwz	r3,8+LOWORD(r1)
 	addi	r1,r1,16
 	blr
 	END (__lrint)
diff --git a/sysdeps/powerpc/powerpc32/fpu/s_lround.S b/sysdeps/powerpc/powerpc32/fpu/s_lround.S
index 92dc378..6309f86 100644
--- a/sysdeps/powerpc/powerpc32/fpu/s_lround.S
+++ b/sysdeps/powerpc/powerpc32/fpu/s_lround.S
@@ -67,7 +67,7 @@ ENTRY (__lround)
 	nop	/* Ensure the following load is in a different dispatch  */
 	nop	/* group to avoid pipe stall on POWER4&5.  */
 	nop
-	lwz	r3,12(r1)	/* Load return as integer.  */
+	lwz	r3,8+LOWORD(r1)	/* Load return as integer.  */
 .Lout:
 	addi	r1,r1,16
 	blr
diff --git a/sysdeps/powerpc/powerpc32/power4/fpu/s_llrint.S b/sysdeps/powerpc/powerpc32/power4/fpu/s_llrint.S
index 55b2850..e7a88fe 100644
--- a/sysdeps/powerpc/powerpc32/power4/fpu/s_llrint.S
+++ b/sysdeps/powerpc/powerpc32/power4/fpu/s_llrint.S
@@ -29,8 +29,8 @@ ENTRY (__llrint)
 	nop	/* Insure the following load is in a different dispatch group */
 	nop	/* to avoid pipe stall on POWER4&5.  */
 	nop
-	lwz	r3,8(r1)
-	lwz	r4,12(r1)
+	lwz	r3,8+HIWORD(r1)
+	lwz	r4,8+LOWORD(r1)
 	addi	r1,r1,16
 	blr
 	END (__llrint)
diff --git a/sysdeps/powerpc/powerpc32/power4/fpu/s_llrintf.S b/sysdeps/powerpc/powerpc32/power4/fpu/s_llrintf.S
index cc80fcb..da24ad3 100644
--- a/sysdeps/powerpc/powerpc32/power4/fpu/s_llrintf.S
+++ b/sysdeps/powerpc/powerpc32/power4/fpu/s_llrintf.S
@@ -28,8 +28,8 @@ ENTRY (__llrintf)
 	nop	/* Insure the following load is in a different dispatch group */
 	nop	/* to avoid pipe stall on POWER4&5.  */
 	nop
-	lwz	r3,8(r1)
-	lwz	r4,12(r1)
+	lwz	r3,8+HIWORD(r1)
+	lwz	r4,8+LOWORD(r1)
 	addi	r1,r1,16
 	blr
 	END (__llrintf)
diff --git a/sysdeps/powerpc/powerpc32/power5+/fpu/s_llround.S b/sysdeps/powerpc/powerpc32/power5+/fpu/s_llround.S
index ecd37c3..49c8a08 100644
--- a/sysdeps/powerpc/powerpc32/power5+/fpu/s_llround.S
+++ b/sysdeps/powerpc/powerpc32/power5+/fpu/s_llround.S
@@ -39,8 +39,8 @@ ENTRY (__llround)
 	nop	/* Ensure the following load is in a different dispatch  */
 	nop	/* group to avoid pipe stall on POWER4&5.  */
 	nop
-	lwz	r4,12(r1)
-	lwz	r3,8(r1)
+	lwz	r3,8+HIWORD(r1)
+	lwz	r4,8+LOWORD(r1)
 	addi	r1,r1,16
 	blr
 	END (__llround)
diff --git a/sysdeps/powerpc/powerpc32/power5+/fpu/s_lround.S b/sysdeps/powerpc/powerpc32/power5+/fpu/s_lround.S
index d4da625..780dd9c 100644
--- a/sysdeps/powerpc/powerpc32/power5+/fpu/s_lround.S
+++ b/sysdeps/powerpc/powerpc32/power5+/fpu/s_lround.S
@@ -38,7 +38,7 @@ ENTRY (__lround)
 	nop	/* Ensure the following load is in a different dispatch  */
 	nop	/* group to avoid pipe stall on POWER4&5.  */
 	nop
-	lwz	r3,12(r1)
+	lwz	r3,8+LOWORD(r1)
 	addi	r1,r1,16
 	blr
 	END (__lround)
diff --git a/sysdeps/powerpc/powerpc32/power5/fpu/s_isnan.S b/sysdeps/powerpc/powerpc32/power5/fpu/s_isnan.S
index f2417fd..5f7ba43 100644
--- a/sysdeps/powerpc/powerpc32/power5/fpu/s_isnan.S
+++ b/sysdeps/powerpc/powerpc32/power5/fpu/s_isnan.S
@@ -27,8 +27,8 @@ EALIGN (__isnan, 4, 0)
 	ori	r1,r1,0
 	stfd	fp1,24(r1)	/* copy FPR to GPR */
 	ori	r1,r1,0
-	lwz	r4,24(r1)
-	lwz	r5,28(r1)
+	lwz	r4,24+HIWORD(r1)
+	lwz	r5,24+LOWORD(r1)
 	lis	r0,0x7ff0	/* const long r0 0x7ff00000 00000000 */
 	clrlwi	r4,r4,1		/* x = fabs(x) */
 	cmpw	cr7,r4,r0	/* if (fabs(x) =< inf) */
diff --git a/sysdeps/powerpc/powerpc32/power6/fpu/s_isnan.S b/sysdeps/powerpc/powerpc32/power6/fpu/s_isnan.S
index 2c095db..3ea1858 100644
--- a/sysdeps/powerpc/powerpc32/power6/fpu/s_isnan.S
+++ b/sysdeps/powerpc/powerpc32/power6/fpu/s_isnan.S
@@ -27,8 +27,8 @@ EALIGN (__isnan, 4, 0)
 	ori	r1,r1,0
 	stfd	fp1,24(r1)	/* copy FPR to GPR */
 	ori	r1,r1,0
-	lwz	r4,24(r1)
-	lwz	r5,28(r1)
+	lwz	r4,24+HIWORD(r1)
+	lwz	r5,24+LOWORD(r1)
 	lis	r0,0x7ff0	/* const long r0 0x7ff00000 00000000 */
 	clrlwi	r4,r4,1		/* x = fabs(x) */
 	cmpw	cr7,r4,r0	/* if (fabs(x) =< inf) */
diff --git a/sysdeps/powerpc/powerpc32/power6/fpu/s_llrint.S b/sysdeps/powerpc/powerpc32/power6/fpu/s_llrint.S
index 3344b31..c0660cf 100644
--- a/sysdeps/powerpc/powerpc32/power6/fpu/s_llrint.S
+++ b/sysdeps/powerpc/powerpc32/power6/fpu/s_llrint.S
@@ -29,8 +29,8 @@ ENTRY (__llrint)
 /* Insure the following load is in a different dispatch group by
    inserting "group ending nop".  */
 	ori	r1,r1,0
-	lwz	r3,8(r1)
-	lwz	r4,12(r1)
+	lwz	r3,8+HIWORD(r1)
+	lwz	r4,8+LOWORD(r1)
 	addi	r1,r1,16
 	blr
 	END (__llrint)
diff --git a/sysdeps/powerpc/powerpc32/power6/fpu/s_llrintf.S b/sysdeps/powerpc/powerpc32/power6/fpu/s_llrintf.S
index 7f64f8d..ce29890 100644
--- a/sysdeps/powerpc/powerpc32/power6/fpu/s_llrintf.S
+++ b/sysdeps/powerpc/powerpc32/power6/fpu/s_llrintf.S
@@ -28,8 +28,8 @@ ENTRY (__llrintf)
 /* Insure the following load is in a different dispatch group by
    inserting "group ending nop".  */
 	ori	r1,r1,0
-	lwz	r3,8(r1)
-	lwz	r4,12(r1)
+	lwz	r3,8+HIWORD(r1)
+	lwz	r4,8+LOWORD(r1)
 	addi	r1,r1,16
 	blr
 	END (__llrintf)
diff --git a/sysdeps/powerpc/powerpc32/power6/fpu/s_llround.S b/sysdeps/powerpc/powerpc32/power6/fpu/s_llround.S
index 0ff04cb..abb0840 100644
--- a/sysdeps/powerpc/powerpc32/power6/fpu/s_llround.S
+++ b/sysdeps/powerpc/powerpc32/power6/fpu/s_llround.S
@@ -39,8 +39,8 @@ ENTRY (__llround)
 /* Insure the following load is in a different dispatch group by
    inserting "group ending nop".  */
 	ori	r1,r1,0
-	lwz	r4,12(r1)
-	lwz	r3,8(r1)
+	lwz	r3,8+HIWORD(r1)
+	lwz	r4,8+LOWORD(r1)
 	addi	r1,r1,16
 	blr
 	END (__llround)
diff --git a/sysdeps/powerpc/powerpc32/power7/fpu/s_finite.S b/sysdeps/powerpc/powerpc32/power7/fpu/s_finite.S
index b2ab5bf..095c155 100644
--- a/sysdeps/powerpc/powerpc32/power7/fpu/s_finite.S
+++ b/sysdeps/powerpc/powerpc32/power7/fpu/s_finite.S
@@ -54,9 +54,8 @@ ENTRY (__finite)
 	stfd    fp1,8(r1)     /* Transfer FP to GPR's.  */
 
 	ori	2,2,0	      /* Force a new dispatch group.  */
-	lhz     r0,8(r1)      /* Fetch the upper portion of the high word of
-			      the FP value (where the exponent and sign bits
-			      are).  */
+	lhz	r0,8+HISHORT(r1) /* Fetch the upper 16 bits of the FP value
+				    (biased exponent and sign bit).  */
 	clrlwi	r0,r0,17      /* r0 = abs(r0).  */
 	addi	r1,r1,16      /* Reset the stack pointer.  */
 	cmpwi	cr7,r0,0x7ff0 /* r4 == 0x7ff0?.  */
diff --git a/sysdeps/powerpc/powerpc32/power7/fpu/s_isinf.S b/sysdeps/powerpc/powerpc32/power7/fpu/s_isinf.S
index 3f8af60..0101c8f 100644
--- a/sysdeps/powerpc/powerpc32/power7/fpu/s_isinf.S
+++ b/sysdeps/powerpc/powerpc32/power7/fpu/s_isinf.S
@@ -48,14 +48,13 @@ ENTRY (__isinf)
 	li	r3,0
 	bflr    29	      /* If not INF, return.  */
 
-	/* Either we have -INF/+INF or a denormal.  */
+	/* Either we have +INF or -INF.  */
 
 	stwu    r1,-16(r1)    /* Allocate stack space.  */
 	stfd    fp1,8(r1)     /* Transfer FP to GPR's.  */
 	ori	2,2,0	      /* Force a new dispatch group.  */
-	lhz	r4,8(r1)      /* Fetch the upper portion of the high word of
-			      the FP value (where the exponent and sign bits
-			      are).  */
+	lhz	r4,8+HISHORT(r1) /* Fetch the upper 16 bits of the FP value
+				    (biased exponent and sign bit).  */
 	addi	r1,r1,16      /* Reset the stack pointer.  */
 	cmpwi	cr7,r4,0x7ff0 /* r4 == 0x7ff0?  */
 	li	r3,1
diff --git a/sysdeps/powerpc/powerpc32/power7/fpu/s_isnan.S b/sysdeps/powerpc/powerpc32/power7/fpu/s_isnan.S
index 99ff126..0ad1dcf 100644
--- a/sysdeps/powerpc/powerpc32/power7/fpu/s_isnan.S
+++ b/sysdeps/powerpc/powerpc32/power7/fpu/s_isnan.S
@@ -53,8 +53,8 @@ ENTRY (__isnan)
 	stwu	r1,-16(r1)    /* Allocate stack space.  */
 	stfd	fp1,8(r1)     /* Transfer FP to GPR's.  */
 	ori	2,2,0	      /* Force a new dispatch group.  */
-	lwz     r4,8(r1)      /* Load the upper half of the FP value.  */
-	lwz     r5,12(r1)     /* Load the lower half of the FP value.  */
+	lwz     r4,8+HIWORD(r1) /* Load the upper half of the FP value.  */
+	lwz     r5,8+LOWORD(r1) /* Load the lower half of the FP value.  */
 	addi	r1,r1,16      /* Reset the stack pointer.  */
 	lis     r0,0x7ff0     /* Load the upper portion for an INF/NaN.  */
 	clrlwi  r4,r4,1	      /* r4 = abs(r4).  */
diff --git a/sysdeps/powerpc/powerpc64/power7/fpu/s_finite.S b/sysdeps/powerpc/powerpc64/power7/fpu/s_finite.S
index d0071c7..ebec0e0 100644
--- a/sysdeps/powerpc/powerpc64/power7/fpu/s_finite.S
+++ b/sysdeps/powerpc/powerpc64/power7/fpu/s_finite.S
@@ -39,10 +39,8 @@ EALIGN (__finite, 4, 0)
 
 	stfd    fp1,-16(r1)   /* Transfer FP to GPR's.  */
 	ori	2,2,0	      /* Force a new dispatch group.  */
-
-	lhz     r4,-16(r1)    /* Fetch the upper portion of the high word of
-			      the FP value (where the exponent and sign bits
-			      are).  */
+	lhz     r4,-16+HISHORT(r1)  /* Fetch the upper 16 bits of the FP value
+				    (biased exponent and sign bit).  */
 	clrlwi  r4,r4,17      /* r4 = abs(r4).  */
 	cmpwi   cr7,r4,0x7ff0 /* r4 == 0x7ff0?  */
 	bltlr   cr7	      /* LT means finite, other non-finite.  */
diff --git a/sysdeps/powerpc/powerpc64/power7/fpu/s_isinf.S b/sysdeps/powerpc/powerpc64/power7/fpu/s_isinf.S
index 1aea123..8d088db 100644
--- a/sysdeps/powerpc/powerpc64/power7/fpu/s_isinf.S
+++ b/sysdeps/powerpc/powerpc64/power7/fpu/s_isinf.S
@@ -38,9 +38,8 @@ EALIGN (__isinf, 4, 0)
 
 	stfd    fp1,-16(r1)   /* Transfer FP to GPR's.  */
 	ori	2,2,0	      /* Force a new dispatch group.  */
-	lhz	r4,-16(r1)    /* Fetch the upper portion of the high word of
-			      the FP value (where the exponent and sign bits
-			      are).  */
+	lhz	r4,-16+HISHORT(r1)  /* Fetch the upper 16 bits of the FP value
+				    (biased exponent and sign bit).  */
 	cmpwi	cr7,r4,0x7ff0 /* r4 == 0x7ff0?  */
 	li	r3,1
 	beqlr   cr7	      /* EQ means INF, otherwise -INF.  */
diff --git a/sysdeps/powerpc/sysdep.h b/sysdeps/powerpc/sysdep.h
index 1b5334a..bc2cb66 100644
--- a/sysdeps/powerpc/sysdep.h
+++ b/sysdeps/powerpc/sysdep.h
@@ -144,6 +144,21 @@
 
 #define VRSAVE	256
 
+/* The 32-bit words of a 64-bit dword are at these offsets in memory.  */
+#if defined __LITTLE_ENDIAN__ || defined _LITTLE_ENDIAN
+# define LOWORD 0
+# define HIWORD 4
+#else
+# define LOWORD 4
+# define HIWORD 0
+#endif
+
+/* The high 16-bit word of a 64-bit dword is at this offset in memory.  */
+#if defined __LITTLE_ENDIAN__ || defined _LITTLE_ENDIAN
+# define HISHORT 6
+#else
+# define HISHORT 0
+#endif
 
 /* This seems to always be the case on PPC.  */
 #define ALIGNARG(log2) log2

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=5febc7ff25ecdbab6b445286887a4cf3b1083273

commit 5febc7ff25ecdbab6b445286887a4cf3b1083273
Author: Alan Modra <amodra@gmail.com>
Date:   Sat Aug 17 18:31:05 2013 +0930

    PowerPC floating point little-endian [11 of 15]
    http://sourceware.org/ml/libc-alpha/2013-07/msg00202.html
    
    Another little-endian fix.
    
    	* sysdeps/powerpc/fpu_control.h (_FPU_GETCW): Rewrite using
    	64-bit int/double union.
    	(_FPU_SETCW): Likewise.
    	* sysdeps/powerpc/fpu/tst-setcontext-fpscr.c (_GET_DI_FPSCR): Likewise.
    	(_SET_DI_FPSCR, _GET_SI_FPSCR, _SET_SI_FPSCR): Likewise.

diff --git a/ChangeLog b/ChangeLog
index 34cc9c1..5327d98 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,13 @@
 2013-10-04  Alan Modra  <amodra@gmail.com>
 
+	* sysdeps/powerpc/fpu_control.h (_FPU_GETCW): Rewrite using
+	64-bit int/double union.
+	(_FPU_SETCW): Likewise.
+	* sysdeps/powerpc/fpu/tst-setcontext-fpscr.c (_GET_DI_FPSCR): Likewise.
+	(_SET_DI_FPSCR, _GET_SI_FPSCR, _SET_SI_FPSCR): Likewise.
+
+2013-10-04  Alan Modra  <amodra@gmail.com>
+
 	* sysdeps/powerpc/fpu/s_llround.c (__llround): Rewrite.
 	* sysdeps/powerpc/fpu/s_llroundf.c (__llroundf): Rewrite.
 
diff --git a/sysdeps/powerpc/fpu/tst-setcontext-fpscr.c b/sysdeps/powerpc/fpu/tst-setcontext-fpscr.c
index feffa6b..cc9b320 100644
--- a/sysdeps/powerpc/fpu/tst-setcontext-fpscr.c
+++ b/sysdeps/powerpc/fpu/tst-setcontext-fpscr.c
@@ -83,7 +83,7 @@ ElfW(Addr) query_auxv(int type)
   return 0;
 }
 
-typedef unsigned long long di_fpscr_t __attribute__ ((__mode__ (__DI__)));
+typedef unsigned int di_fpscr_t __attribute__ ((__mode__ (__DI__)));
 typedef unsigned int si_fpscr_t __attribute__ ((__mode__ (__SI__)));
 
 #define _FPSCR_RESERVED 0xfffffff8ffffff04ULL
@@ -95,50 +95,51 @@ typedef unsigned int si_fpscr_t __attribute__ ((__mode__ (__SI__)));
 #define _FPSCR_TEST1_RN  0x0000000000000002ULL
 
 /* Macros for accessing the hardware control word on Power6[x].  */
-# define _GET_DI_FPSCR(__fpscr) ({					     \
-   union { double d;							     \
-           di_fpscr_t fpscr; }						     \
-     tmp __attribute__ ((__aligned__(8)));				     \
-   __asm__ ("mffs 0; stfd%U0 0,%0" : "=m" (tmp.d) : : "fr0");		     \
-   (__fpscr)=tmp.fpscr;							     \
-   tmp.fpscr; })
-
-/* We make sure to zero fp0 after we use it in order to prevent stale data
+#define _GET_DI_FPSCR(__fpscr)						\
+  ({union { double d; di_fpscr_t fpscr; } u;				\
+    register double fr;							\
+    __asm__ ("mffs %0" : "=f" (fr));					\
+    u.d = fr;								\
+    (__fpscr) = u.fpscr;						\
+    u.fpscr;								\
+  })
+
+/* We make sure to zero fp after we use it in order to prevent stale data
    in an fp register from making a test-case pass erroneously.  */
-# define _SET_DI_FPSCR(__fpscr) {					     \
-  union { double d; di_fpscr_t fpscr; }					     \
-    tmp __attribute__ ((__aligned__(8)));				     \
-  tmp.fpscr = __fpscr;							     \
-  /* Set the entire 64-bit FPSCR.  */					     \
-  __asm__ ("lfd%U0 0,%0; "						     \
-	   ".machine push; "						     \
-	   ".machine \"power6\"; "					     \
-	   "mtfsf 255,0,1,0; "						     \
-	   ".machine pop" : : "m" (tmp.d) : "fr0");			     \
-  tmp.d = 0;								     \
-  __asm__("lfd%U0 0,%0" : : "m" (tmp.d) : "fr0");			     \
-}
-
-# define _GET_SI_FPSCR(__fpscr) ({					     \
-   union { double d;							     \
-           si_fpscr_t cw[2]; }						     \
-     tmp __attribute__ ((__aligned__(8)));				     \
-   __asm__ ("mffs 0; stfd%U0 0,%0" : "=m" (tmp.d) : : "fr0");		     \
-   (__fpscr)=tmp.cw[1];							     \
-   tmp.cw[0]; })
-
-/* We make sure to zero fp0 after we use it in order to prevent stale data
+# define _SET_DI_FPSCR(__fpscr)						\
+  { union { double d; di_fpscr_t fpscr; } u;				\
+    register double fr;							\
+    u.fpscr = __fpscr;							\
+    fr = u.d;								\
+    /* Set the entire 64-bit FPSCR.  */					\
+    __asm__ (".machine push; "						\
+	     ".machine \"power6\"; "					\
+	     "mtfsf 255,%0,1,0; "					\
+	     ".machine pop" : : "f" (fr));				\
+    fr = 0.0;								\
+  }
+
+# define _GET_SI_FPSCR(__fpscr)						\
+  ({union { double d; di_fpscr_t fpscr; } u;				\
+    register double fr;							\
+    __asm__ ("mffs %0" : "=f" (fr));					\
+    u.d = fr;								\
+    (__fpscr) = (si_fpscr_t) u.fpscr;					\
+    (si_fpscr_t) u.fpscr;						\
+  })
+
+/* We make sure to zero fp after we use it in order to prevent stale data
    in an fp register from making a test-case pass erroneously.  */
-# define _SET_SI_FPSCR(__fpscr) {					     \
-  union { double d; si_fpscr_t fpscr[2]; }				     \
-    tmp __attribute__ ((__aligned__(8)));				     \
-  /* More-or-less arbitrary; this is a QNaN. */				     \
-  tmp.fpscr[0] = 0xFFF80000;						     \
-  tmp.fpscr[1] = __fpscr;						     \
-  __asm__ ("lfd%U0 0,%0; mtfsf 255,0" : : "m" (tmp.d) : "fr0");		     \
-  tmp.d = 0;								     \
-  __asm__("lfd%U0 0,%0" : : "m" (tmp.d) : "fr0");			     \
-}
+# define _SET_SI_FPSCR(__fpscr)						\
+  { union { double d; di_fpscr_t fpscr; } u;				\
+    register double fr;							\
+    /* More-or-less arbitrary; this is a QNaN. */			\
+    u.fpscr = 0xfff80000ULL << 32;					\
+    u.fpscr |= __fpscr & 0xffffffffULL;					\
+    fr = u.d;								\
+    __asm__ ("mtfsf 255,%0" : : "f" (fr));				\
+    fr = 0.0;								\
+  }
 
 void prime_special_regs(int which)
 {
diff --git a/sysdeps/powerpc/fpu_control.h b/sysdeps/powerpc/fpu_control.h
index 159543b..c6c4cb9 100644
--- a/sysdeps/powerpc/fpu_control.h
+++ b/sysdeps/powerpc/fpu_control.h
@@ -56,22 +56,26 @@ extern fpu_control_t __fpu_control;
 # define _FPU_IEEE     0x000000f0
 
 /* Type of the control word.  */
-typedef unsigned int fpu_control_t __attribute__ ((__mode__ (__SI__)));
+typedef unsigned int fpu_control_t;
 
 /* Macros for accessing the hardware control word.  */
-# define _FPU_GETCW(__cw) ( { \
-  union { double d; fpu_control_t cw[2]; } \
-    tmp __attribute__ ((__aligned__(8))); \
-  __asm__ ("mffs 0; stfd%U0 0,%0" : "=m" (tmp.d) : : "fr0"); \
-  (__cw)=tmp.cw[1]; \
-  tmp.cw[1]; } )
-# define _FPU_SETCW(__cw) { \
-  union { double d; fpu_control_t cw[2]; } \
-    tmp __attribute__ ((__aligned__(8))); \
-  tmp.cw[0] = 0xFFF80000; /* More-or-less arbitrary; this is a QNaN. */ \
-  tmp.cw[1] = __cw; \
-  __asm__ ("lfd%U0 0,%0; mtfsf 255,0" : : "m" (tmp.d) : "fr0"); \
-}
+# define _FPU_GETCW(cw)						\
+  ({union { double __d; unsigned long long __ll; } __u;		\
+    register double __fr;					\
+    __asm__ ("mffs %0" : "=f" (__fr));				\
+    __u.__d = __fr;						\
+    (cw) = (fpu_control_t) __u.__ll;				\
+    (fpu_control_t) __u.__ll;					\
+  })
+
+# define _FPU_SETCW(cw)						\
+  { union { double __d; unsigned long long __ll; } __u;		\
+    register double __fr;					\
+    __u.__ll = 0xfff80000LL << 32; /* This is a QNaN.  */	\
+    __u.__ll |= (cw) & 0xffffffffLL;				\
+    __fr = __u.__d;						\
+    __asm__ ("mtfsf 255,%0" : : "f" (__fr));			\
+  }
 
 /* Default control word set at startup.  */
 extern fpu_control_t __fpu_control;

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=c88484088a11983552f59cafcccbcd7a16b5ab09

commit c88484088a11983552f59cafcccbcd7a16b5ab09
Author: Alan Modra <amodra@gmail.com>
Date:   Sat Aug 17 18:30:23 2013 +0930

    PowerPC floating point little-endian [10 of 15]
    http://sourceware.org/ml/libc-alpha/2013-07/msg00201.html
    
    These two functions oddly test x+1>0 when a double x is >= 0.0, and
    similarly when x is negative.  I don't see the point of that since the
    test should always be true.  I also don't see any need to convert x+1
    to integer rather than simply using xr+1.  Note that the standard
    allows these functions to return any value when the input is outside
    the range of long long, but it's not too hard to prevent xr+1
    overflowing so that's what I've done.
    
    (With rounding mode FE_UPWARD, x+1 can be a lot more than what you
    might naively expect, but perhaps that situation was covered by the
    x - xrf < 1.0 test.)
    
    	* sysdeps/powerpc/fpu/s_llround.c (__llround): Rewrite.
    	* sysdeps/powerpc/fpu/s_llroundf.c (__llroundf): Rewrite.

diff --git a/ChangeLog b/ChangeLog
index 62923b5..34cc9c1 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,10 @@
 2013-10-04  Alan Modra  <amodra@gmail.com>
 
+	* sysdeps/powerpc/fpu/s_llround.c (__llround): Rewrite.
+	* sysdeps/powerpc/fpu/s_llroundf.c (__llroundf): Rewrite.
+
+2013-10-04  Alan Modra  <amodra@gmail.com>
+
 	* sysdeps/powerpc/fpu/s_float_bitwise.h (__float_and_test28): Don't
 	use vector int constants.
 	(__float_and_test24, __float_and8, __float_get_exp): Likewise.
diff --git a/sysdeps/powerpc/fpu/s_llround.c b/sysdeps/powerpc/fpu/s_llround.c
index 9a01826..995d0a7 100644
--- a/sysdeps/powerpc/fpu/s_llround.c
+++ b/sysdeps/powerpc/fpu/s_llround.c
@@ -19,29 +19,28 @@
 #include <math.h>
 #include <math_ldbl_opt.h>
 
-/* I think that what this routine is supposed to do is round a value
-   to the nearest integer, with values exactly on the boundary rounded
-   away from zero.  */
-/* This routine relies on (long long)x, when x is out of range of a long long,
-   clipping to MAX_LLONG or MIN_LLONG.  */
+/* Round to the nearest integer, with values exactly on a 0.5 boundary
+   rounded away from zero, regardless of the current rounding mode.
+   If (long long)x, when x is out of range of a long long, clips at
+   LLONG_MAX or LLONG_MIN, then this implementation also clips.  */
 
 long long int
 __llround (double x)
 {
-  double xrf;
-  long long int xr;
-  xr = (long long int) x;
-  xrf = (double) xr;
+  long long xr = (long long) x;
+  double xrf = (double) xr;
+
   if (x >= 0.0)
-    if (x - xrf >= 0.5 && x - xrf < 1.0 && x+1 > 0)
-      return x+1;
-    else
-      return x;
+    {
+      if (x - xrf >= 0.5)
+	xr += (long long) ((unsigned long long) xr + 1) > 0;
+    }
   else
-    if (xrf - x >= 0.5 && xrf - x < 1.0 && x-1 < 0)
-      return x-1;
-    else
-      return x;
+    {
+      if (xrf - x >= 0.5)
+	xr -= (long long) ((unsigned long long) xr - 1) < 0;
+    }
+  return xr;
 }
 weak_alias (__llround, llround)
 #ifdef NO_LONG_DOUBLE
diff --git a/sysdeps/powerpc/fpu/s_llroundf.c b/sysdeps/powerpc/fpu/s_llroundf.c
index 07d12ad..0935de6 100644
--- a/sysdeps/powerpc/fpu/s_llroundf.c
+++ b/sysdeps/powerpc/fpu/s_llroundf.c
@@ -18,28 +18,27 @@
 
 #include <math.h>
 
-/* I think that what this routine is supposed to do is round a value
-   to the nearest integer, with values exactly on the boundary rounded
-   away from zero.  */
-/* This routine relies on (long long)x, when x is out of range of a long long,
-   clipping to MAX_LLONG or MIN_LLONG.  */
+/* Round to the nearest integer, with values exactly on a 0.5 boundary
+   rounded away from zero, regardless of the current rounding mode.
+   If (long long)x, when x is out of range of a long long, clips at
+   LLONG_MAX or LLONG_MIN, then this implementation also clips.  */
 
 long long int
 __llroundf (float x)
 {
-  float xrf;
-  long long int xr;
-  xr = (long long int) x;
-  xrf = (float) xr;
+  long long xr = (long long) x;
+  float xrf = (float) xr;
+
   if (x >= 0.0)
-    if (x - xrf >= 0.5 && x - xrf < 1.0 && x+1 > 0)
-      return x+1;
-    else
-      return x;
+    {
+      if (x - xrf >= 0.5)
+	xr += (long long) ((unsigned long long) xr + 1) > 0;
+    }
   else
-    if (xrf - x >= 0.5 && xrf - x < 1.0 && x-1 < 0)
-      return x-1;
-    else
-      return x;
+    {
+      if (xrf - x >= 0.5)
+	xr -= (long long) ((unsigned long long) xr - 1) < 0;
+    }
+  return xr;
 }
 weak_alias (__llroundf, llroundf)

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=cbeb3f0edee7afc90bb02bb973863a43ab5b076d

commit cbeb3f0edee7afc90bb02bb973863a43ab5b076d
Author: Alan Modra <amodra@gmail.com>
Date:   Sat Aug 17 18:29:43 2013 +0930

    PowerPC floating point little-endian [9 of 15]
    http://sourceware.org/ml/libc-alpha/2013-07/msg00200.html
    
    This works around the fact that vsx is disabled in current
    little-endian gcc.  Also, float constants take 4 bytes in memory
    vs. 16 bytes for vector constants, and we don't need to write one lot
    of masks for double (register format) and another for float (mem
    format).
    
    	* sysdeps/powerpc/fpu/s_float_bitwise.h (__float_and_test28): Don't
    	use vector int constants.
    	(__float_and_test24, __float_and8, __float_get_exp): Likewise.

diff --git a/ChangeLog b/ChangeLog
index e9ed5d8..62923b5 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2013-10-04  Alan Modra  <amodra@gmail.com>
+
+	* sysdeps/powerpc/fpu/s_float_bitwise.h (__float_and_test28): Don't
+	use vector int constants.
+	(__float_and_test24, __float_and8, __float_get_exp): Likewise.
+
 2013-10-04  Anton Blanchard <anton@au1.ibm.com>
 
 	* sysdeps/powerpc/fpu/fenv_libc.h (fenv_union_t): Replace int
diff --git a/sysdeps/powerpc/fpu/s_float_bitwise.h b/sysdeps/powerpc/fpu/s_float_bitwise.h
index 8e4adca..c0a4e56 100644
--- a/sysdeps/powerpc/fpu/s_float_bitwise.h
+++ b/sysdeps/powerpc/fpu/s_float_bitwise.h
@@ -23,18 +23,19 @@
 #include <math_private.h>
 
 /* Returns (int)(num & 0x7FFFFFF0 == value) */
-static inline
-int __float_and_test28 (float num, float value)
+static inline int
+__float_and_test28 (float num, float value)
 {
   float ret;
 #ifdef _ARCH_PWR7
-  vector int mask = (vector int) {
-    0x7ffffffe, 0x00000000, 0x00000000, 0x0000000
-  };
+  union {
+    int i;
+    float f;
+  } mask = { .i = 0x7ffffff0 };
   __asm__ (
-  /* the 'f' constrain is use on mask because we just need
+  /* the 'f' constraint is used on mask because we just need
    * to compare floats, not full vector */
-    "xxland %x0,%x1,%x2" : "=f" (ret) : "f" (num), "f" (mask)
+    "xxland %x0,%x1,%x2" : "=f" (ret) : "f" (num), "f" (mask.f)
   );
 #else
   int32_t inum;
@@ -46,16 +47,17 @@ int __float_and_test28 (float num, float value)
 }
 
 /* Returns (int)(num & 0x7FFFFF00 == value) */
-static inline
-int __float_and_test24 (float num, float value)
+static inline int
+__float_and_test24 (float num, float value)
 {
   float ret;
 #ifdef _ARCH_PWR7
-  vector int mask = (vector int) {
-    0x7fffffe0, 0x00000000, 0x00000000, 0x0000000
-  };
+  union {
+    int i;
+    float f;
+  } mask = { .i = 0x7fffff00 };
   __asm__ (
-    "xxland %x0,%x1,%x2" : "=f" (ret) : "f" (num), "f" (mask)
+    "xxland %x0,%x1,%x2" : "=f" (ret) : "f" (num), "f" (mask.f)
   );
 #else
   int32_t inum;
@@ -67,16 +69,17 @@ int __float_and_test24 (float num, float value)
 }
 
 /* Returns (float)(num & 0x7F800000) */
-static inline
-float __float_and8 (float num)
+static inline float
+__float_and8 (float num)
 {
   float ret;
 #ifdef _ARCH_PWR7
-  vector int mask = (vector int) {
-    0x7ff00000, 0x00000000, 0x00000000, 0x00000000
-  };
+  union {
+    int i;
+    float f;
+  } mask = { .i = 0x7f800000 };
   __asm__ (
-    "xxland %x0,%x1,%x2" : "=f" (ret) : "f" (num), "f" (mask)
+    "xxland %x0,%x1,%x2" : "=f" (ret) : "f" (num), "f" (mask.f)
   );
 #else
   int32_t inum;
@@ -88,17 +91,18 @@ float __float_and8 (float num)
 }
 
 /* Returns ((int32_t)(num & 0x7F800000) >> 23) */
-static inline
-int32_t __float_get_exp (float num)
+static inline int32_t
+__float_get_exp (float num)
 {
   int32_t inum;
 #ifdef _ARCH_PWR7
   float ret;
-  vector int mask = (vector int) {
-    0x7ff00000, 0x00000000, 0x00000000, 0x00000000
-  };
+  union {
+    int i;
+    float f;
+  } mask = { .i = 0x7f800000 };
   __asm__ (
-    "xxland %x0,%x1,%x2" : "=f" (ret) : "f" (num), "f" (mask)
+    "xxland %x0,%x1,%x2" : "=f" (ret) : "f" (num), "f" (mask.f)
   );
   GET_FLOAT_WORD(inum, ret);
 #else

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=977432e4f3061cde059ec9afbf8dd38d64dcf8e9

commit 977432e4f3061cde059ec9afbf8dd38d64dcf8e9
Author: Anton Blanchard <anton@au1.ibm.com>
Date:   Sat Aug 17 18:28:55 2013 +0930

    PowerPC floating point little-endian [8 of 15]
    http://sourceware.org/ml/libc-alpha/2013-07/msg00199.html
    
    Corrects floating-point environment code for little-endian.
    
    	* sysdeps/powerpc/fpu/fenv_libc.h (fenv_union_t): Replace int
    	array with long long.
    	* sysdeps/powerpc/fpu/e_sqrt.c (__slow_ieee754_sqrt): Adjust.
    	* sysdeps/powerpc/fpu/e_sqrtf.c (__slow_ieee754_sqrtf): Adjust.
    	* sysdeps/powerpc/fpu/fclrexcpt.c (__feclearexcept): Adjust.
    	* sysdeps/powerpc/fpu/fedisblxcpt.c (fedisableexcept): Adjust.
    	* sysdeps/powerpc/fpu/feenablxcpt.c (feenableexcept): Adjust.
    	* sysdeps/powerpc/fpu/fegetexcept.c (__fegetexcept): Adjust.
    	* sysdeps/powerpc/fpu/feholdexcpt.c (feholdexcept): Adjust.
    	* sysdeps/powerpc/fpu/fesetenv.c (__fesetenv): Adjust.
    	* sysdeps/powerpc/fpu/feupdateenv.c (__feupdateenv): Adjust.
    	* sysdeps/powerpc/fpu/fgetexcptflg.c (__fegetexceptflag): Adjust.
    	* sysdeps/powerpc/fpu/fraiseexcpt.c (__feraiseexcept): Adjust.
    	* sysdeps/powerpc/fpu/fsetexcptflg.c (__fesetexceptflag): Adjust.
    	* sysdeps/powerpc/fpu/ftestexcept.c (fetestexcept): Adjust.

diff --git a/ChangeLog b/ChangeLog
index 5c0f524..e9ed5d8 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,23 @@
 2013-10-04  Anton Blanchard <anton@au1.ibm.com>
 
+	* sysdeps/powerpc/fpu/fenv_libc.h (fenv_union_t): Replace int
+	array with long long.
+	* sysdeps/powerpc/fpu/e_sqrt.c (__slow_ieee754_sqrt): Adjust.
+	* sysdeps/powerpc/fpu/e_sqrtf.c (__slow_ieee754_sqrtf): Adjust.
+	* sysdeps/powerpc/fpu/fclrexcpt.c (__feclearexcept): Adjust.
+	* sysdeps/powerpc/fpu/fedisblxcpt.c (fedisableexcept): Adjust.
+	* sysdeps/powerpc/fpu/feenablxcpt.c (feenableexcept): Adjust.
+	* sysdeps/powerpc/fpu/fegetexcept.c (__fegetexcept): Adjust.
+	* sysdeps/powerpc/fpu/feholdexcpt.c (feholdexcept): Adjust.
+	* sysdeps/powerpc/fpu/fesetenv.c (__fesetenv): Adjust.
+	* sysdeps/powerpc/fpu/feupdateenv.c (__feupdateenv): Adjust.
+	* sysdeps/powerpc/fpu/fgetexcptflg.c (__fegetexceptflag): Adjust.
+	* sysdeps/powerpc/fpu/fraiseexcpt.c (__feraiseexcept): Adjust.
+	* sysdeps/powerpc/fpu/fsetexcptflg.c (__fesetexceptflag): Adjust.
+	* sysdeps/powerpc/fpu/ftestexcept.c (fetestexcept): Adjust.
+
+2013-10-04  Anton Blanchard <anton@au1.ibm.com>
+
 	* sysdeps/powerpc/bits/mathinline.h (__signbitf): Use builtin.
 	(__signbit): Likewise.  Correct for little-endian.
 	(__signbitl): Call __signbit.
diff --git a/sysdeps/powerpc/fpu/e_sqrt.c b/sysdeps/powerpc/fpu/e_sqrt.c
index 3efe277..2d50fb5 100644
--- a/sysdeps/powerpc/fpu/e_sqrt.c
+++ b/sysdeps/powerpc/fpu/e_sqrt.c
@@ -145,7 +145,7 @@ __slow_ieee754_sqrt (double x)
       feraiseexcept (FE_INVALID_SQRT);
 
       fenv_union_t u = { .fenv = fegetenv_register () };
-      if ((u.l[1] & FE_INVALID) == 0)
+      if ((u.l & FE_INVALID) == 0)
 #endif
 	feraiseexcept (FE_INVALID);
       x = a_nan.value;
diff --git a/sysdeps/powerpc/fpu/e_sqrtf.c b/sysdeps/powerpc/fpu/e_sqrtf.c
index 6e50a3c..91d2d37 100644
--- a/sysdeps/powerpc/fpu/e_sqrtf.c
+++ b/sysdeps/powerpc/fpu/e_sqrtf.c
@@ -121,7 +121,7 @@ __slow_ieee754_sqrtf (float x)
       feraiseexcept (FE_INVALID_SQRT);
 
       fenv_union_t u = { .fenv = fegetenv_register () };
-      if ((u.l[1] & FE_INVALID) == 0)
+      if ((u.l & FE_INVALID) == 0)
 #endif
 	feraiseexcept (FE_INVALID);
       x = a_nan.value;
diff --git a/sysdeps/powerpc/fpu/fclrexcpt.c b/sysdeps/powerpc/fpu/fclrexcpt.c
index 86575db..7f66e21 100644
--- a/sysdeps/powerpc/fpu/fclrexcpt.c
+++ b/sysdeps/powerpc/fpu/fclrexcpt.c
@@ -28,8 +28,8 @@ __feclearexcept (int excepts)
   u.fenv = fegetenv_register ();
 
   /* Clear the relevant bits.  */
-  u.l[1] = u.l[1] & ~((-(excepts >> (31 - FPSCR_VX) & 1) & FE_ALL_INVALID)
-		      | (excepts & FPSCR_STICKY_BITS));
+  u.l = u.l & ~((-(excepts >> (31 - FPSCR_VX) & 1) & FE_ALL_INVALID)
+		| (excepts & FPSCR_STICKY_BITS));
 
   /* Put the new state in effect.  */
   fesetenv_register (u.fenv);
diff --git a/sysdeps/powerpc/fpu/fedisblxcpt.c b/sysdeps/powerpc/fpu/fedisblxcpt.c
index 659566b..f2c45a6 100644
--- a/sysdeps/powerpc/fpu/fedisblxcpt.c
+++ b/sysdeps/powerpc/fpu/fedisblxcpt.c
@@ -32,15 +32,15 @@ fedisableexcept (int excepts)
 
   fe.fenv = fegetenv_register ();
   if (excepts & FE_INEXACT)
-    fe.l[1] &= ~(1 << (31 - FPSCR_XE));
+    fe.l &= ~(1 << (31 - FPSCR_XE));
   if (excepts & FE_DIVBYZERO)
-    fe.l[1] &= ~(1 << (31 - FPSCR_ZE));
+    fe.l &= ~(1 << (31 - FPSCR_ZE));
   if (excepts & FE_UNDERFLOW)
-    fe.l[1] &= ~(1 << (31 - FPSCR_UE));
+    fe.l &= ~(1 << (31 - FPSCR_UE));
   if (excepts & FE_OVERFLOW)
-    fe.l[1] &= ~(1 << (31 - FPSCR_OE));
+    fe.l &= ~(1 << (31 - FPSCR_OE));
   if (excepts & FE_INVALID)
-    fe.l[1] &= ~(1 << (31 - FPSCR_VE));
+    fe.l &= ~(1 << (31 - FPSCR_VE));
   fesetenv_register (fe.fenv);
 
   new = __fegetexcept ();
diff --git a/sysdeps/powerpc/fpu/feenablxcpt.c b/sysdeps/powerpc/fpu/feenablxcpt.c
index fc4bfff..472796d 100644
--- a/sysdeps/powerpc/fpu/feenablxcpt.c
+++ b/sysdeps/powerpc/fpu/feenablxcpt.c
@@ -32,15 +32,15 @@ feenableexcept (int excepts)
 
   fe.fenv = fegetenv_register ();
   if (excepts & FE_INEXACT)
-    fe.l[1] |= (1 << (31 - FPSCR_XE));
+    fe.l |= (1 << (31 - FPSCR_XE));
   if (excepts & FE_DIVBYZERO)
-    fe.l[1] |= (1 << (31 - FPSCR_ZE));
+    fe.l |= (1 << (31 - FPSCR_ZE));
   if (excepts & FE_UNDERFLOW)
-    fe.l[1] |= (1 << (31 - FPSCR_UE));
+    fe.l |= (1 << (31 - FPSCR_UE));
   if (excepts & FE_OVERFLOW)
-    fe.l[1] |= (1 << (31 - FPSCR_OE));
+    fe.l |= (1 << (31 - FPSCR_OE));
   if (excepts & FE_INVALID)
-    fe.l[1] |= (1 << (31 - FPSCR_VE));
+    fe.l |= (1 << (31 - FPSCR_VE));
   fesetenv_register (fe.fenv);
 
   new = __fegetexcept ();
diff --git a/sysdeps/powerpc/fpu/fegetexcept.c b/sysdeps/powerpc/fpu/fegetexcept.c
index f3d5724..23d47a2 100644
--- a/sysdeps/powerpc/fpu/fegetexcept.c
+++ b/sysdeps/powerpc/fpu/fegetexcept.c
@@ -27,15 +27,15 @@ __fegetexcept (void)
 
   fe.fenv = fegetenv_register ();
 
-  if (fe.l[1] & (1 << (31 - FPSCR_XE)))
+  if (fe.l & (1 << (31 - FPSCR_XE)))
       result |= FE_INEXACT;
-  if (fe.l[1] & (1 << (31 - FPSCR_ZE)))
+  if (fe.l & (1 << (31 - FPSCR_ZE)))
       result |= FE_DIVBYZERO;
-  if (fe.l[1] & (1 << (31 - FPSCR_UE)))
+  if (fe.l & (1 << (31 - FPSCR_UE)))
       result |= FE_UNDERFLOW;
-  if (fe.l[1] & (1 << (31 - FPSCR_OE)))
+  if (fe.l & (1 << (31 - FPSCR_OE)))
       result |= FE_OVERFLOW;
-  if (fe.l[1] & (1 << (31 - FPSCR_VE)))
+  if (fe.l & (1 << (31 - FPSCR_VE)))
       result |= FE_INVALID;
 
   return result;
diff --git a/sysdeps/powerpc/fpu/feholdexcpt.c b/sysdeps/powerpc/fpu/feholdexcpt.c
index 013d2bf..0ecf0f7 100644
--- a/sysdeps/powerpc/fpu/feholdexcpt.c
+++ b/sysdeps/powerpc/fpu/feholdexcpt.c
@@ -30,13 +30,12 @@ feholdexcept (fenv_t *envp)
 
   /* Clear everything except for the rounding modes and non-IEEE arithmetic
      flag.  */
-  new.l[1] = old.l[1] & 7;
-  new.l[0] = old.l[0];
+  new.l = old.l & 0xffffffff00000007LL;
 
   /* If the old env had any enabled exceptions, then mask SIGFPE in the
      MSR FE0/FE1 bits.  This may allow the FPU to run faster because it
      always takes the default action and can not generate SIGFPE. */
-  if ((old.l[1] & _FPU_MASK_ALL) != 0)
+  if ((old.l & _FPU_MASK_ALL) != 0)
     (void)__fe_mask_env ();
 
   /* Put the new state in effect.  */
diff --git a/sysdeps/powerpc/fpu/fenv_libc.h b/sysdeps/powerpc/fpu/fenv_libc.h
index 1910951..baa2a7d 100644
--- a/sysdeps/powerpc/fpu/fenv_libc.h
+++ b/sysdeps/powerpc/fpu/fenv_libc.h
@@ -69,7 +69,7 @@ libm_hidden_proto (__fe_nomask_env)
 typedef union
 {
   fenv_t fenv;
-  unsigned int l[2];
+  unsigned long long l;
 } fenv_union_t;
 
 
diff --git a/sysdeps/powerpc/fpu/fesetenv.c b/sysdeps/powerpc/fpu/fesetenv.c
index e92adb4..6c00b26 100644
--- a/sysdeps/powerpc/fpu/fesetenv.c
+++ b/sysdeps/powerpc/fpu/fesetenv.c
@@ -34,14 +34,14 @@ __fesetenv (const fenv_t *envp)
      exceptions, then unmask SIGFPE in the MSR FE0/FE1 bits.  This will put the
      hardware into "precise mode" and may cause the FPU to run slower on some
      hardware.  */
-  if ((old.l[1] & _FPU_MASK_ALL) == 0 && (new.l[1] & _FPU_MASK_ALL) != 0)
+  if ((old.l & _FPU_MASK_ALL) == 0 && (new.l & _FPU_MASK_ALL) != 0)
     (void)__fe_nomask_env ();
 
   /* If the old env had any enabled exceptions and the new env has no enabled
      exceptions, then mask SIGFPE in the MSR FE0/FE1 bits.  This may allow the
      FPU to run faster because it always takes the default action and can not
      generate SIGFPE. */
-  if ((old.l[1] & _FPU_MASK_ALL) != 0 && (new.l[1] & _FPU_MASK_ALL) == 0)
+  if ((old.l & _FPU_MASK_ALL) != 0 && (new.l & _FPU_MASK_ALL) == 0)
     (void)__fe_mask_env ();
 
   fesetenv_register (*envp);
diff --git a/sysdeps/powerpc/fpu/feupdateenv.c b/sysdeps/powerpc/fpu/feupdateenv.c
index 6500ea1..6775044 100644
--- a/sysdeps/powerpc/fpu/feupdateenv.c
+++ b/sysdeps/powerpc/fpu/feupdateenv.c
@@ -34,20 +34,20 @@ __feupdateenv (const fenv_t *envp)
   /* Restore rounding mode and exception enable from *envp and merge
      exceptions.  Leave fraction rounded/inexact and FP result/CC bits
      unchanged.  */
-  new.l[1] = (old.l[1] & 0x1FFFFF00) | (new.l[1] & 0x1FF80FFF);
+  new.l = (old.l & 0xffffffff1fffff00LL) | (new.l & 0x1ff80fff);
 
   /* If the old env has no enabled exceptions and the new env has any enabled
      exceptions, then unmask SIGFPE in the MSR FE0/FE1 bits.  This will put
      the hardware into "precise mode" and may cause the FPU to run slower on
      some hardware.  */
-  if ((old.l[1] & _FPU_MASK_ALL) == 0 && (new.l[1] & _FPU_MASK_ALL) != 0)
+  if ((old.l & _FPU_MASK_ALL) == 0 && (new.l & _FPU_MASK_ALL) != 0)
     (void)__fe_nomask_env ();
 
   /* If the old env had any enabled exceptions and the new env has no enabled
      exceptions, then mask SIGFPE in the MSR FE0/FE1 bits.  This may allow the
      FPU to run faster because it always takes the default action and can not
      generate SIGFPE. */
-  if ((old.l[1] & _FPU_MASK_ALL) != 0 && (new.l[1] & _FPU_MASK_ALL) == 0)
+  if ((old.l & _FPU_MASK_ALL) != 0 && (new.l & _FPU_MASK_ALL) == 0)
     (void)__fe_mask_env ();
 
   /* Atomically enable and raise (if appropriate) exceptions set in `new'. */
diff --git a/sysdeps/powerpc/fpu/fgetexcptflg.c b/sysdeps/powerpc/fpu/fgetexcptflg.c
index f6327ce..1395bed 100644
--- a/sysdeps/powerpc/fpu/fgetexcptflg.c
+++ b/sysdeps/powerpc/fpu/fgetexcptflg.c
@@ -27,7 +27,7 @@ __fegetexceptflag (fexcept_t *flagp, int excepts)
   u.fenv = fegetenv_register ();
 
   /* Return (all of) it.  */
-  *flagp = u.l[1] & excepts & FE_ALL_EXCEPT;
+  *flagp = u.l & excepts & FE_ALL_EXCEPT;
 
   /* Success.  */
   return 0;
diff --git a/sysdeps/powerpc/fpu/fraiseexcpt.c b/sysdeps/powerpc/fpu/fraiseexcpt.c
index 9118c19..6193071 100644
--- a/sysdeps/powerpc/fpu/fraiseexcpt.c
+++ b/sysdeps/powerpc/fpu/fraiseexcpt.c
@@ -33,11 +33,11 @@ __feraiseexcept (int excepts)
   u.fenv = fegetenv_register ();
 
   /* Add the exceptions */
-  u.l[1] = (u.l[1]
-	    | (excepts & FPSCR_STICKY_BITS)
-	    /* Turn FE_INVALID into FE_INVALID_SOFTWARE.  */
-	    | (excepts >> ((31 - FPSCR_VX) - (31 - FPSCR_VXSOFT))
-	       & FE_INVALID_SOFTWARE));
+  u.l = (u.l
+	 | (excepts & FPSCR_STICKY_BITS)
+	 /* Turn FE_INVALID into FE_INVALID_SOFTWARE.  */
+	 | (excepts >> ((31 - FPSCR_VX) - (31 - FPSCR_VXSOFT))
+	    & FE_INVALID_SOFTWARE));
 
   /* Store the new status word (along with the rest of the environment),
      triggering any appropriate exceptions.  */
@@ -49,7 +49,7 @@ __feraiseexcept (int excepts)
 	 don't have FE_INVALID_SOFTWARE implemented.  Detect this
 	 case and raise FE_INVALID_SNAN instead.  */
       u.fenv = fegetenv_register ();
-      if ((u.l[1] & FE_INVALID) == 0)
+      if ((u.l & FE_INVALID) == 0)
 	set_fpscr_bit (FPSCR_VXSNAN);
     }
 
diff --git a/sysdeps/powerpc/fpu/fsetexcptflg.c b/sysdeps/powerpc/fpu/fsetexcptflg.c
index c050d40..0d309c8 100644
--- a/sysdeps/powerpc/fpu/fsetexcptflg.c
+++ b/sysdeps/powerpc/fpu/fsetexcptflg.c
@@ -31,10 +31,10 @@ __fesetexceptflag (const fexcept_t *flagp, int excepts)
   flag = *flagp & excepts;
 
   /* Replace the exception status */
-  u.l[1] = ((u.l[1] & ~(FPSCR_STICKY_BITS & excepts))
-	    | (flag & FPSCR_STICKY_BITS)
-	    | (flag >> ((31 - FPSCR_VX) - (31 - FPSCR_VXSOFT))
-	       & FE_INVALID_SOFTWARE));
+  u.l = ((u.l & ~(FPSCR_STICKY_BITS & excepts))
+	 | (flag & FPSCR_STICKY_BITS)
+	 | (flag >> ((31 - FPSCR_VX) - (31 - FPSCR_VXSOFT))
+	    & FE_INVALID_SOFTWARE));
 
   /* Store the new status word (along with the rest of the environment).
      This may cause floating-point exceptions if the restored state
diff --git a/sysdeps/powerpc/fpu/ftestexcept.c b/sysdeps/powerpc/fpu/ftestexcept.c
index 0dbc3be..86eea0f 100644
--- a/sysdeps/powerpc/fpu/ftestexcept.c
+++ b/sysdeps/powerpc/fpu/ftestexcept.c
@@ -28,6 +28,6 @@ fetestexcept (int excepts)
 
   /* The FE_INVALID bit is dealt with correctly by the hardware, so we can
      just:  */
-  return u.l[1] & excepts;
+  return u.l & excepts;
 }
 libm_hidden_def (fetestexcept)

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=d6bbeb3f4ee99cdfcf7935780d710dfc2d2b3cbc

commit d6bbeb3f4ee99cdfcf7935780d710dfc2d2b3cbc
Author: Anton Blanchard <anton@au1.ibm.com>
Date:   Sat Aug 17 18:28:06 2013 +0930

    PowerPC floating point little-endian [7 of 15]
    http://sourceware.org/ml/libc-alpha/2013-08/msg00086.html
    
    	* sysdeps/powerpc/bits/mathinline.h (__signbitf): Use builtin.
    	(__signbit): Likewise.  Correct for little-endian.
    	(__signbitl): Call __signbit.
    	(lrint): Correct for little-endian.
    	(lrintf): Call lrint.

diff --git a/ChangeLog b/ChangeLog
index b090c79..5c0f524 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+2013-10-04  Anton Blanchard <anton@au1.ibm.com>
+
+	* sysdeps/powerpc/bits/mathinline.h (__signbitf): Use builtin.
+	(__signbit): Likewise.  Correct for little-endian.
+	(__signbitl): Call __signbit.
+	(lrint): Correct for little-endian.
+	(lrintf): Call lrint.
+
 2013-10-04  Alan Modra  <amodra@gmail.com>
 
 	* sysdeps/ieee754/ldbl-128ibm/e_sqrtl.c (mynumber): Replace
diff --git a/sysdeps/powerpc/bits/mathinline.h b/sysdeps/powerpc/bits/mathinline.h
index 140fff0..cef5b29 100644
--- a/sysdeps/powerpc/bits/mathinline.h
+++ b/sysdeps/powerpc/bits/mathinline.h
@@ -61,21 +61,28 @@
 __MATH_INLINE int
 __NTH (__signbitf (float __x))
 {
+#if __GNUC_PREREQ (4, 0)
+  return __builtin_signbitf (__x);
+#else
   __extension__ union { float __f; int __i; } __u = { __f: __x };
   return __u.__i < 0;
+#endif
 }
 __MATH_INLINE int
 __NTH (__signbit (double __x))
 {
-  __extension__ union { double __d; int __i[2]; } __u = { __d: __x };
-  return __u.__i[0] < 0;
+#if __GNUC_PREREQ (4, 0)
+  return __builtin_signbit (__x);
+#else
+  __extension__ union { double __d; long long __i; } __u = { __d: __x };
+  return __u.__i < 0;
+#endif
 }
 #  ifdef __LONG_DOUBLE_128__
 __MATH_INLINE int
 __NTH (__signbitl (long double __x))
 {
-  __extension__ union { long double __d; int __i[4]; } __u = { __d: __x };
-  return __u.__i[0] < 0;
+  return __signbit ((double) __x);
 }
 #  endif
 # endif
@@ -92,22 +99,17 @@ __NTH (lrint (double __x))
 {
   union {
     double __d;
-    int __ll[2];
+    long long __ll;
   } __u;
   __asm__ ("fctiw %0,%1" : "=f"(__u.__d) : "f"(__x));
-  return __u.__ll[1];
+  return __u.__ll;
 }
 
 __MATH_INLINE long int lrintf (float __x) __THROW;
 __MATH_INLINE long int
 __NTH (lrintf (float __x))
 {
-  union {
-    double __d;
-    int __ll[2];
-  } __u;
-  __asm__ ("fctiw %0,%1" : "=f"(__u.__d) : "f"(__x));
-  return __u.__ll[1];
+  return lrint ((double) __x);
 }
 # endif
 

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=e1120ce9e80828f3619c7dc0d619be2d75aecc46

commit e1120ce9e80828f3619c7dc0d619be2d75aecc46
Author: Alan Modra <amodra@gmail.com>
Date:   Sat Aug 17 18:27:19 2013 +0930

    PowerPC floating point little-endian [6 of 15]
    http://sourceware.org/ml/libc-alpha/2013-07/msg00197.html
    
    A rewrite to make this code correct for little-endian.
    
    	* sysdeps/ieee754/ldbl-128ibm/e_sqrtl.c (mynumber): Replace
    	union 32-bit int array member with 64-bit int array.
    	(t515, tm256): Double rather than long double.
    	(__ieee754_sqrtl): Rewrite using 64-bit arithmetic.

diff --git a/ChangeLog b/ChangeLog
index 13b7ea3..b090c79 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,12 @@
 2013-10-04  Alan Modra  <amodra@gmail.com>
 
+	* sysdeps/ieee754/ldbl-128ibm/e_sqrtl.c (mynumber): Replace
+	union 32-bit int array member with 64-bit int array.
+	(t515, tm256): Double rather than long double.
+	(__ieee754_sqrtl): Rewrite using 64-bit arithmetic.
+
+2013-10-04  Alan Modra  <amodra@gmail.com>
+
 	* sysdeps/ieee754/ldbl-128ibm/ieee754.h (union ieee854_long_double):
 	Delete.
 	(IEEE854_LONG_DOUBLE_BIAS): Delete.
diff --git a/sysdeps/ieee754/ldbl-128ibm/e_sqrtl.c b/sysdeps/ieee754/ldbl-128ibm/e_sqrtl.c
index 2b0f7c6..61feb36 100644
--- a/sysdeps/ieee754/ldbl-128ibm/e_sqrtl.c
+++ b/sysdeps/ieee754/ldbl-128ibm/e_sqrtl.c
@@ -34,15 +34,13 @@
 
 #include <math_private.h>
 
-typedef unsigned int int4;
-typedef union {int4 i[4]; long double x; double d[2]; } mynumber;
+typedef union {int64_t i[2]; long double x; double d[2]; } mynumber;
 
-static const  mynumber
-  t512 = {{0x5ff00000, 0x00000000, 0x00000000, 0x00000000 }},  /* 2^512  */
-  tm256 = {{0x2ff00000, 0x00000000, 0x00000000, 0x00000000 }};  /* 2^-256 */
 static const double
-two54 = 1.80143985094819840000e+16, /* 0x4350000000000000 */
-twom54 = 5.55111512312578270212e-17; /* 0x3C90000000000000 */
+  t512 = 0x1p512,
+  tm256 = 0x1p-256,
+  two54 = 0x1p54,	/* 0x4350000000000000 */
+  twom54 = 0x1p-54;	/* 0x3C90000000000000 */
 
 /*********************************************************************/
 /* An ultimate sqrt routine. Given an IEEE double machine number x   */
@@ -54,56 +52,53 @@ long double __ieee754_sqrtl(long double x)
   static const long double big = 134217728.0, big1 = 134217729.0;
   long double t,s,i;
   mynumber a,c;
-  int4 k, l, m;
-  int n;
+  uint64_t k, l;
+  int64_t m, n;
   double d;
 
   a.x=x;
-  k=a.i[0] & 0x7fffffff;
+  k=a.i[0] & INT64_C(0x7fffffffffffffff);
   /*----------------- 2^-1022  <= | x |< 2^1024  -----------------*/
-  if (k>0x000fffff && k<0x7ff00000) {
+  if (k>INT64_C(0x000fffff00000000) && k<INT64_C(0x7ff0000000000000)) {
     if (x < 0) return (big1-big1)/(big-big);
-    l = (k&0x001fffff)|0x3fe00000;
-    if (((a.i[2] & 0x7fffffff) | a.i[3]) != 0) {
-      n = (int) ((l - k) * 2) >> 21;
-      m = (a.i[2] >> 20) & 0x7ff;
+    l = (k&INT64_C(0x001fffffffffffff))|INT64_C(0x3fe0000000000000);
+    if ((a.i[1] & INT64_C(0x7fffffffffffffff)) != 0) {
+      n = (int64_t) ((l - k) * 2) >> 53;
+      m = (a.i[1] >> 52) & 0x7ff;
       if (m == 0) {
 	a.d[1] *= two54;
-	m = ((a.i[2] >> 20) & 0x7ff) - 54;
+	m = ((a.i[1] >> 52) & 0x7ff) - 54;
       }
       m += n;
-      if ((int) m > 0)
-	a.i[2] = (a.i[2] & 0x800fffff) | (m << 20);
-      else if ((int) m <= -54) {
-	a.i[2] &= 0x80000000;
-	a.i[3] = 0;
+      if (m > 0)
+	a.i[1] = (a.i[1] & INT64_C(0x800fffffffffffff)) | (m << 52);
+      else if (m <= -54) {
+	a.i[1] &= INT64_C(0x8000000000000000);
       } else {
 	m += 54;
-	a.i[2] = (a.i[2] & 0x800fffff) | (m << 20);
+	a.i[1] = (a.i[1] & INT64_C(0x800fffffffffffff)) | (m << 52);
 	a.d[1] *= twom54;
       }
     }
     a.i[0] = l;
     s = a.x;
     d = __ieee754_sqrt (a.d[0]);
-    c.i[0] = 0x20000000+((k&0x7fe00000)>>1);
+    c.i[0] = INT64_C(0x2000000000000000)+((k&INT64_C(0x7fe0000000000000))>>1);
     c.i[1] = 0;
-    c.i[2] = 0;
-    c.i[3] = 0;
     i = d;
     t = 0.5L * (i + s / i);
     i = 0.5L * (t + s / t);
     return c.x * i;
   }
   else {
-    if (k>=0x7ff00000) {
-      if (a.i[0] == 0xfff00000 && a.i[1] == 0)
+    if (k>=INT64_C(0x7ff0000000000000)) {
+      if (a.i[0] == INT64_C(0xfff0000000000000))
 	return (big1-big1)/(big-big); /* sqrt (-Inf) = NaN.  */
       return x; /* sqrt (NaN) = NaN, sqrt (+Inf) = +Inf.  */
     }
     if (x == 0) return x;
     if (x < 0) return (big1-big1)/(big-big);
-    return tm256.x*__ieee754_sqrtl(x*t512.x);
+    return tm256*__ieee754_sqrtl(x*t512);
   }
 }
 strong_alias (__ieee754_sqrtl, __sqrtl_finite)

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=09b803a2824424a31cf92093b29105920d1f7ad5

commit 09b803a2824424a31cf92093b29105920d1f7ad5
Author: Alan Modra <amodra@gmail.com>
Date:   Sat Aug 17 18:26:39 2013 +0930

    PowerPC floating point little-endian [5 of 15]
    http://sourceware.org/ml/libc-alpha/2013-08/msg00085.html
    
    Rid ourselves of ieee854.
    
    	* sysdeps/ieee754/ldbl-128ibm/ieee754.h (union ieee854_long_double):
    	Delete.
    	(IEEE854_LONG_DOUBLE_BIAS): Delete.
    	* sysdeps/ieee754/ldbl-128ibm/math_ldbl.h: Don't include ieee854
    	version of math_ldbl.h.

diff --git a/ChangeLog b/ChangeLog
index 993f6bf..13b7ea3 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,13 @@
 2013-10-04  Alan Modra  <amodra@gmail.com>
 
+	* sysdeps/ieee754/ldbl-128ibm/ieee754.h (union ieee854_long_double):
+	Delete.
+	(IEEE854_LONG_DOUBLE_BIAS): Delete.
+	* sysdeps/ieee754/ldbl-128ibm/math_ldbl.h: Don't include ieee854
+	version of math_ldbl.h.
+
+2013-10-04  Alan Modra  <amodra@gmail.com>
+
 	[BZ #15734], [BZ #15735]
 	* sysdeps/ieee754/ldbl-128ibm/e_fmodl.c (__ieee754_fmodl): Rewrite
 	all uses of ieee875 long double macros and unions.  Simplify test
diff --git a/sysdeps/ieee754/ldbl-128ibm/ieee754.h b/sysdeps/ieee754/ldbl-128ibm/ieee754.h
index 0778b1f..0c97a99 100644
--- a/sysdeps/ieee754/ldbl-128ibm/ieee754.h
+++ b/sysdeps/ieee754/ldbl-128ibm/ieee754.h
@@ -111,61 +111,6 @@ union ieee754_double
 #define IEEE754_DOUBLE_BIAS	0x3ff /* Added to exponent.  */
 
 
-union ieee854_long_double
-  {
-    long double d;
-
-    /* This is the IEEE 854 quad-precision format.  */
-    struct
-      {
-#if	__BYTE_ORDER == __BIG_ENDIAN
-	unsigned int negative:1;
-	unsigned int exponent:15;
-	/* Together these comprise the mantissa.  */
-	unsigned int mantissa0:16;
-	unsigned int mantissa1:32;
-	unsigned int mantissa2:32;
-	unsigned int mantissa3:32;
-#endif				/* Big endian.  */
-#if	__BYTE_ORDER == __LITTLE_ENDIAN
-	/* Together these comprise the mantissa.  */
-	unsigned int mantissa3:32;
-	unsigned int mantissa2:32;
-	unsigned int mantissa1:32;
-	unsigned int mantissa0:16;
-	unsigned int exponent:15;
-	unsigned int negative:1;
-#endif				/* Little endian.  */
-      } ieee;
-
-    /* This format makes it easier to see if a NaN is a signalling NaN.  */
-    struct
-      {
-#if	__BYTE_ORDER == __BIG_ENDIAN
-	unsigned int negative:1;
-	unsigned int exponent:15;
-	unsigned int quiet_nan:1;
-	/* Together these comprise the mantissa.  */
-	unsigned int mantissa0:15;
-	unsigned int mantissa1:32;
-	unsigned int mantissa2:32;
-	unsigned int mantissa3:32;
-#else
-	/* Together these comprise the mantissa.  */
-	unsigned int mantissa3:32;
-	unsigned int mantissa2:32;
-	unsigned int mantissa1:32;
-	unsigned int mantissa0:15;
-	unsigned int quiet_nan:1;
-	unsigned int exponent:15;
-	unsigned int negative:1;
-#endif
-      } ieee_nan;
-  };
-
-#define IEEE854_LONG_DOUBLE_BIAS 0x3fff /* Added to exponent.  */
-
-
 /* IBM extended format for long double.
 
    Each long double is made up of two IEEE doubles.  The value of the
diff --git a/sysdeps/ieee754/ldbl-128ibm/math_ldbl.h b/sysdeps/ieee754/ldbl-128ibm/math_ldbl.h
index 8adb081..1b6e27a 100644
--- a/sysdeps/ieee754/ldbl-128ibm/math_ldbl.h
+++ b/sysdeps/ieee754/ldbl-128ibm/math_ldbl.h
@@ -2,7 +2,6 @@
 #error "Never use <math_ldbl.h> directly; include <math_private.h> instead."
 #endif
 
-#include <sysdeps/ieee754/ldbl-128/math_ldbl.h>
 #include <ieee754.h>
 #include <stdint.h>
 

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=2d025af1cbc32649e30a84253689b84ec9ae5a6f

commit 2d025af1cbc32649e30a84253689b84ec9ae5a6f
Author: Alan Modra <amodra@gmail.com>
Date:   Sat Aug 17 18:25:51 2013 +0930

    PowerPC floating point little-endian [4 of 15]
    http://sourceware.org/ml/libc-alpha/2013-08/msg00084.html
    
    Another batch of ieee854 macros and union replacement.  These four
    files also have bugs fixed with this patch.  The fact that the two
    doubles in an IBM long double may have different signs means that
    negation and absolute value operations can't just twiddle one sign bit
    as you can with ieee864 style extended double.  fmodl, remainderl,
    erfl and erfcl all had errors of this type.  erfl also returned +1 for
    large magnitude negative input where it should return -1.  The hypotl
    error is innocuous since the value adjusted twice is only used as a
    flag.  The e_hypotl.c tests for large "a" and small "b" are mutually
    exclusive because we've already exited when x/y > 2**120.  That allows
    some further small simplifications.
    
    	[BZ #15734], [BZ #15735]
    	* sysdeps/ieee754/ldbl-128ibm/e_fmodl.c (__ieee754_fmodl): Rewrite
    	all uses of ieee875 long double macros and unions.  Simplify test
    	for 0.0L.  Correct |x|<|y| and |x|=|y| test.  Use
    	ldbl_extract_mantissa value for ix,iy exponents.  Properly
    	normalize after ldbl_extract_mantissa, and don't add hidden bit
    	already handled.  Don't treat low word of ieee854 mantissa like
    	low word of IBM long double and mask off bit when testing for
    	zero.
    	* sysdeps/ieee754/ldbl-128ibm/e_hypotl.c (__ieee754_hypotl): Rewrite
    	all uses of ieee875 long double macros and unions.  Simplify tests
    	for 0.0L and inf.  Correct double adjustment of k.  Delete dead code
    	adjusting ha,hb.  Simplify code setting kld.  Delete two600 and
    	two1022, instead use their values.  Recognise that tests for large
    	"a" and small "b" are mutually exclusive.  Rename vars.  Comment.
    	* sysdeps/ieee754/ldbl-128ibm/e_remainderl.c (__ieee754_remainderl):
    	Rewrite all uses of ieee875 long double macros and unions.  Simplify
    	test for 0.0L and nan.  Correct negation.
    	* sysdeps/ieee754/ldbl-128ibm/s_erfl.c (__erfl): Rewrite all uses of
    	ieee875 long double macros and unions.  Correct output for large
    	magnitude x.  Correct absolute value calculation.
    	(__erfcl): Likewise.
    	* math/libm-test.inc: Add tests for errors discovered in IBM long
    	double versions of fmodl, remainderl, erfl and erfcl.

diff --git a/ChangeLog b/ChangeLog
index aeb2f2c..993f6bf 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,32 @@
 2013-10-04  Alan Modra  <amodra@gmail.com>
 
+	[BZ #15734], [BZ #15735]
+	* sysdeps/ieee754/ldbl-128ibm/e_fmodl.c (__ieee754_fmodl): Rewrite
+	all uses of ieee875 long double macros and unions.  Simplify test
+	for 0.0L.  Correct |x|<|y| and |x|=|y| test.  Use
+	ldbl_extract_mantissa value for ix,iy exponents.  Properly
+	normalize after ldbl_extract_mantissa, and don't add hidden bit
+	already handled.  Don't treat low word of ieee854 mantissa like
+	low word of IBM long double and mask off bit when testing for
+	zero.
+	* sysdeps/ieee754/ldbl-128ibm/e_hypotl.c (__ieee754_hypotl): Rewrite
+	all uses of ieee875 long double macros and unions.  Simplify tests
+	for 0.0L and inf.  Correct double adjustment of k.  Delete dead code
+	adjusting ha,hb.  Simplify code setting kld.  Delete two600 and
+	two1022, instead use their values.  Recognise that tests for large
+	"a" and small "b" are mutually exclusive.  Rename vars.  Comment.
+	* sysdeps/ieee754/ldbl-128ibm/e_remainderl.c (__ieee754_remainderl):
+	Rewrite all uses of ieee875 long double macros and unions.  Simplify
+	test for 0.0L and nan.  Correct negation.
+	* sysdeps/ieee754/ldbl-128ibm/s_erfl.c (__erfl): Rewrite all uses of
+	ieee875 long double macros and unions.  Correct output for large
+	magnitude x.  Correct absolute value calculation.
+	(__erfcl): Likewise.
+	* math/libm-test.inc: Add tests for errors discovered in IBM long
+	double versions of fmodl, remainderl, erfl and erfcl.
+
+2013-10-04  Alan Modra  <amodra@gmail.com>
+
 	* sysdeps/ieee754/ldbl-128ibm/e_atan2l.c (__ieee754_atan2l): Rewrite
 	all uses of ieee854 long double macros and unions.  Simplify tests
 	for long doubles that are fully specified by the high double.
diff --git a/math/libm-test.inc b/math/libm-test.inc
index 7a11c90..a84cf24 100644
--- a/math/libm-test.inc
+++ b/math/libm-test.inc
@@ -7816,6 +7816,11 @@ static const struct test_f_f_data erf_test_data[] =
     TEST_f_f (erf, 2.0L, 0.995322265018952734162069256367252929L),
     TEST_f_f (erf, 4.125L, 0.999999994576599200434933994687765914L),
     TEST_f_f (erf, 27.0L, 1.0L),
+    TEST_f_f (erf, -27.0L, -1.0L),
+#if defined TEST_LDOUBLE && LDBL_MANT_DIG >= 54
+    /* The input is not exactly representable as a double.  */
+    TEST_f_f (erf, -0x1.fffffffffffff8p-2L, -0.5204998778130465132916303345518417673509L),
+#endif
   };
 
 static void
@@ -7844,6 +7849,10 @@ static const struct test_f_f_data erfc_test_data[] =
     TEST_f_f (erfc, 0x1.ffa002p+2L, 1.233585992097580296336099501489175967033e-29L),
     TEST_f_f (erfc, 0x1.ffffc8p+2L, 1.122671365033056305522366683719541099329e-29L),
 #ifdef TEST_LDOUBLE
+# if LDBL_MANT_DIG >= 54
+    /* The input is not exactly representable as a double.  */
+    TEST_f_f (erfc, -0x1.fffffffffffff8p-2L, 1.52049987781304651329163033455184176735L),
+# endif
     /* The result can only be represented in long double.  */
 # if LDBL_MIN_10_EXP < -319
     TEST_f_f (erfc, 27.0L, 0.523704892378925568501606768284954709e-318L),
@@ -9342,6 +9351,13 @@ static const struct test_ff_f_data fmod_test_data[] =
 #if defined TEST_LDOUBLE && LDBL_MIN_EXP <= -16381
     TEST_ff_f (fmod, 0x0.fffffffffffffffep-16382L, 0x1p-16445L, plus_zero, NO_INEXACT_EXCEPTION),
 #endif
+#if defined TEST_LDOUBLE && LDBL_MANT_DIG >= 56
+    TEST_ff_f (fmod, -0x1.00000000000004p+0L, 0x1.fffffffffffff8p-1L, -0x1p-53L, NO_INEXACT_EXCEPTION),
+    TEST_ff_f (fmod, 0x1.fffffffffffffap-1L, 0x1.fffffffffffff8p-1L, 0x1p-56L, NO_INEXACT_EXCEPTION),
+    TEST_ff_f (fmod, -0x1.fffffffffffffap-1L, 0x1.fffffffffffff8p-1L, -0x1p-56L, NO_INEXACT_EXCEPTION),
+    TEST_ff_f (fmod, 0x1.fffffffffffffap-1L, -0x1.fffffffffffff8p-1L, 0x1p-56L, NO_INEXACT_EXCEPTION),
+    TEST_ff_f (fmod, -0x1.fffffffffffffap-1L, -0x1.fffffffffffff8p-1L, -0x1p-56L, NO_INEXACT_EXCEPTION),
+#endif
   };
 
 static void
@@ -12303,6 +12319,9 @@ static const struct test_ff_f_data remainder_test_data[] =
     TEST_ff_f (remainder, -1.625, -1.0, 0.375, NO_INEXACT_EXCEPTION),
     TEST_ff_f (remainder, 5.0, 2.0, 1.0, NO_INEXACT_EXCEPTION),
     TEST_ff_f (remainder, 3.0, 2.0, -1.0, NO_INEXACT_EXCEPTION),
+#if defined TEST_LDOUBLE && LDBL_MANT_DIG >= 56
+    TEST_ff_f (remainder, -0x1.80000000000002p1L, 2.0, 0x1.fffffffffffff8p-1L, NO_INEXACT_EXCEPTION),
+#endif
   };
 
 static void
diff --git a/sysdeps/ieee754/ldbl-128ibm/e_fmodl.c b/sysdeps/ieee754/ldbl-128ibm/e_fmodl.c
index a60963c..a140fb3 100644
--- a/sysdeps/ieee754/ldbl-128ibm/e_fmodl.c
+++ b/sysdeps/ieee754/ldbl-128ibm/e_fmodl.c
@@ -27,76 +27,83 @@ static const long double one = 1.0, Zero[] = {0.0, -0.0,};
 long double
 __ieee754_fmodl (long double x, long double y)
 {
-	int64_t n,hx,hy,hz,ix,iy,sx, i;
-	u_int64_t lx,ly,lz;
-	int temp;
+	int64_t hx, hy, hz, sx, sy;
+	uint64_t lx, ly, lz;
+	int n, ix, iy;
+	double xhi, xlo, yhi, ylo;
 
-	GET_LDOUBLE_WORDS64(hx,lx,x);
-	GET_LDOUBLE_WORDS64(hy,ly,y);
+	ldbl_unpack (x, &xhi, &xlo);
+	EXTRACT_WORDS64 (hx, xhi);
+	EXTRACT_WORDS64 (lx, xlo);
+	ldbl_unpack (y, &yhi, &ylo);
+	EXTRACT_WORDS64 (hy, yhi);
+	EXTRACT_WORDS64 (ly, ylo);
 	sx = hx&0x8000000000000000ULL;		/* sign of x */
-	hx ^=sx;				/* |x| */
-	hy &= 0x7fffffffffffffffLL;		/* |y| */
+	hx ^= sx;				/* |x| */
+	sy = hy&0x8000000000000000ULL;		/* sign of y */
+	hy ^= sy;				/* |y| */
 
     /* purge off exception values */
-	if(__builtin_expect((hy|(ly&0x7fffffffffffffff))==0 ||
+	if(__builtin_expect(hy==0 ||
 			    (hx>=0x7ff0000000000000LL)|| /* y=0,or x not finite */
 			    (hy>0x7ff0000000000000LL),0))	/* or y is NaN */
 	    return (x*y)/(x*y);
-	if(__builtin_expect(hx<=hy,0)) {
-	    if((hx<hy)||(lx<ly)) return x;	/* |x|<|y| return x */
-	    if(lx==ly)
-		return Zero[(u_int64_t)sx>>63];	/* |x|=|y| return x*0*/
+	if (__builtin_expect (hx <= hy, 0))
+	  {
+	    /* If |x| < |y| return x.  */
+	    if (hx < hy)
+	      return x;
+	    /* At this point the absolute value of the high doubles of
+	       x and y must be equal.  */
+	    /* If the low double of y is the same sign as the high
+	       double of y (ie. the low double increases |y|)...  */
+	    if (((ly ^ sy) & 0x8000000000000000LL) == 0
+		/* ... then a different sign low double to high double
+		   for x or same sign but lower magnitude...  */
+		&& (int64_t) (lx ^ sx) < (int64_t) (ly ^ sy))
+	      /* ... means |x| < |y|.  */
+	      return x;
+	    /* If the low double of x differs in sign to the high
+	       double of x (ie. the low double decreases |x|)...  */
+	    if (((lx ^ sx) & 0x8000000000000000LL) != 0
+		/* ... then a different sign low double to high double
+		   for y with lower magnitude (we've already caught
+		   the same sign for y case above)...  */
+		&& (int64_t) (lx ^ sx) > (int64_t) (ly ^ sy))
+	      /* ... means |x| < |y|.  */
+	      return x;
+	    /* If |x| == |y| return x*0.  */
+	    if ((lx ^ sx) == (ly ^ sy))
+	      return Zero[(uint64_t) sx >> 63];
 	}
 
-    /* determine ix = ilogb(x) */
-	if(__builtin_expect(hx<0x0010000000000000LL,0)) {	/* subnormal x */
-	    if(hx==0) {
-		for (ix = -1043, i=lx; i>0; i<<=1) ix -=1;
-	    } else {
-		for (ix = -1022, i=(hx<<11); i>0; i<<=1) ix -=1;
-	    }
-	} else ix = (hx>>52)-0x3ff;
-
-    /* determine iy = ilogb(y) */
-	if(__builtin_expect(hy<0x0010000000000000LL,0)) {	/* subnormal y */
-	    if(hy==0) {
-		for (iy = -1043, i=ly; i>0; i<<=1) iy -=1;
-	    } else {
-		for (iy = -1022, i=(hy<<11); i>0; i<<=1) iy -=1;
-	    }
-	} else iy = (hy>>52)-0x3ff;
-
     /* Make the IBM extended format 105 bit mantissa look like the ieee854 112
        bit mantissa so the following operations will give the correct
        result.  */
-	ldbl_extract_mantissa(&hx, &lx, &temp, x);
-	ldbl_extract_mantissa(&hy, &ly, &temp, y);
+	ldbl_extract_mantissa(&hx, &lx, &ix, x);
+	ldbl_extract_mantissa(&hy, &ly, &iy, y);
 
-    /* set up {hx,lx}, {hy,ly} and align y to x */
-	if(__builtin_expect(ix >= -1022, 1))
-	    hx = 0x0001000000000000LL|(0x0000ffffffffffffLL&hx);
-	else {		/* subnormal x, shift x to normal */
-	    n = -1022-ix;
-	    if(n<=63) {
-		hx = (hx<<n)|(lx>>(64-n));
-		lx <<= n;
-	    } else {
-		hx = lx<<(n-64);
-		lx = 0;
-	    }
-	}
-	if(__builtin_expect(iy >= -1022, 1))
-	    hy = 0x0001000000000000LL|(0x0000ffffffffffffLL&hy);
-	else {		/* subnormal y, shift y to normal */
-	    n = -1022-iy;
-	    if(n<=63) {
-		hy = (hy<<n)|(ly>>(64-n));
-		ly <<= n;
-	    } else {
-		hy = ly<<(n-64);
-		ly = 0;
-	    }
-	}
+	if (__builtin_expect (ix == -IEEE754_DOUBLE_BIAS, 0))
+	  {
+	    /* subnormal x, shift x to normal.  */
+	    while ((hx & (1LL << 48)) == 0)
+	      {
+		hx = (hx << 1) | (lx >> 63);
+		lx = lx << 1;
+		ix -= 1;
+	      }
+	  }
+
+	if (__builtin_expect (iy == -IEEE754_DOUBLE_BIAS, 0))
+	  {
+	    /* subnormal y, shift y to normal.  */
+	    while ((hy & (1LL << 48)) == 0)
+	      {
+		hy = (hy << 1) | (ly >> 63);
+		ly = ly << 1;
+		iy -= 1;
+	      }
+	  }
 
     /* fix point fmod */
 	n = ix - iy;
@@ -104,7 +111,7 @@ __ieee754_fmodl (long double x, long double y)
 	    hz=hx-hy;lz=lx-ly; if(lx<ly) hz -= 1;
 	    if(hz<0){hx = hx+hx+(lx>>63); lx = lx+lx;}
 	    else {
-		if((hz|(lz&0x7fffffffffffffff))==0)		/* return sign(x)*0 */
+		if((hz|lz)==0)		/* return sign(x)*0 */
 		    return Zero[(u_int64_t)sx>>63];
 		hx = hz+hz+(lz>>63); lx = lz+lz;
 	    }
@@ -113,7 +120,7 @@ __ieee754_fmodl (long double x, long double y)
 	if(hz>=0) {hx=hz;lx=lz;}
 
     /* convert back to floating value and restore the sign */
-	if((hx|(lx&0x7fffffffffffffff))==0)			/* return sign(x)*0 */
+	if((hx|lx)==0)			/* return sign(x)*0 */
 	    return Zero[(u_int64_t)sx>>63];
 	while(hx<0x0001000000000000LL) {	/* normalize x */
 	    hx = hx+hx+(lx>>63); lx = lx+lx;
diff --git a/sysdeps/ieee754/ldbl-128ibm/e_hypotl.c b/sysdeps/ieee754/ldbl-128ibm/e_hypotl.c
index 768bd3b..3b07a47 100644
--- a/sysdeps/ieee754/ldbl-128ibm/e_hypotl.c
+++ b/sysdeps/ieee754/ldbl-128ibm/e_hypotl.c
@@ -45,76 +45,84 @@
 #include <math.h>
 #include <math_private.h>
 
-static const long double two600 = 0x1.0p+600L;
-static const long double two1022 = 0x1.0p+1022L;
-
 long double
 __ieee754_hypotl(long double x, long double y)
 {
-	long double a,b,t1,t2,y1,y2,w,kld;
+	long double a,b,a1,a2,b1,b2,w,kld;
 	int64_t j,k,ha,hb;
+	double xhi, yhi, hi, lo;
 
-	GET_LDOUBLE_MSW64(ha,x);
+	xhi = ldbl_high (x);
+	EXTRACT_WORDS64 (ha, xhi);
+	yhi = ldbl_high (y);
+	EXTRACT_WORDS64 (hb, yhi);
 	ha &= 0x7fffffffffffffffLL;
-	GET_LDOUBLE_MSW64(hb,y);
 	hb &= 0x7fffffffffffffffLL;
 	if(hb > ha) {a=y;b=x;j=ha; ha=hb;hb=j;} else {a=x;b=y;}
 	a = fabsl(a);	/* a <- |a| */
 	b = fabsl(b);	/* b <- |b| */
-	if((ha-hb)>0x780000000000000LL) {return a+b;} /* x/y > 2**120 */
+	if((ha-hb)>0x0780000000000000LL) {return a+b;} /* x/y > 2**120 */
 	k=0;
 	kld = 1.0L;
 	if(ha > 0x5f30000000000000LL) {	/* a>2**500 */
 	   if(ha >= 0x7ff0000000000000LL) {	/* Inf or NaN */
-	       u_int64_t low;
 	       w = a+b;			/* for sNaN */
-	       GET_LDOUBLE_LSW64(low,a);
-	       if(((ha&0xfffffffffffffLL)|(low&0x7fffffffffffffffLL))==0)
+	       if(ha == 0x7ff0000000000000LL)
 		 w = a;
-	       GET_LDOUBLE_LSW64(low,b);
-	       if(((hb^0x7ff0000000000000LL)|(low&0x7fffffffffffffffLL))==0)
+	       if(hb == 0x7ff0000000000000LL)
 		 w = b;
 	       return w;
 	   }
 	   /* scale a and b by 2**-600 */
-	   ha -= 0x2580000000000000LL; hb -= 0x2580000000000000LL; k += 600;
-	   a /= two600;
-	   b /= two600;
-	   k += 600;
-	   kld = two600;
+	   a *= 0x1p-600L;
+	   b *= 0x1p-600L;
+	   k = 600;
+	   kld = 0x1p+600L;
 	}
-	if(hb < 0x23d0000000000000LL) {	/* b < 2**-450 */
+	else if(hb < 0x23d0000000000000LL) {	/* b < 2**-450 */
 	    if(hb <= 0x000fffffffffffffLL) {	/* subnormal b or 0 */
-		u_int64_t low;
-		GET_LDOUBLE_LSW64(low,b);
-		if((hb|(low&0x7fffffffffffffffLL))==0) return a;
-		t1=two1022;	/* t1=2^1022 */
-		b *= t1;
-		a *= t1;
-		k -= 1022;
-		kld = kld / two1022;
+		if(hb==0) return a;
+		a *= 0x1p+1022L;
+		b *= 0x1p+1022L;
+		k = -1022;
+		kld = 0x1p-1022L;
 	    } else {		/* scale a and b by 2^600 */
-		ha += 0x2580000000000000LL;	/* a *= 2^600 */
-		hb += 0x2580000000000000LL;	/* b *= 2^600 */
-		k -= 600;
-		a *= two600;
-		b *= two600;
-		kld = kld / two600;
+		a *= 0x1p+600L;
+		b *= 0x1p+600L;
+		k = -600;
+		kld = 0x1p-600L;
 	    }
 	}
     /* medium size a and b */
 	w = a-b;
 	if (w>b) {
-	    SET_LDOUBLE_WORDS64(t1,ha,0);
-	    t2 = a-t1;
-	    w  = __ieee754_sqrtl(t1*t1-(b*(-b)-t2*(a+t1)));
+	    ldbl_unpack (a, &hi, &lo);
+	    a1 = hi;
+	    a2 = lo;
+	    /* a*a + b*b
+	       = (a1+a2)*a + b*b
+	       = a1*a + a2*a + b*b
+	       = a1*(a1+a2) + a2*a + b*b
+	       = a1*a1 + a1*a2 + a2*a + b*b
+	       = a1*a1 + a2*(a+a1) + b*b  */
+	    w  = __ieee754_sqrtl(a1*a1-(b*(-b)-a2*(a+a1)));
 	} else {
 	    a  = a+a;
-	    SET_LDOUBLE_WORDS64(y1,hb,0);
-	    y2 = b - y1;
-	    SET_LDOUBLE_WORDS64(t1,ha+0x0010000000000000LL,0);
-	    t2 = a - t1;
-	    w  = __ieee754_sqrtl(t1*y1-(w*(-w)-(t1*y2+t2*b)));
+	    ldbl_unpack (b, &hi, &lo);
+	    b1 = hi;
+	    b2 = lo;
+	    ldbl_unpack (a, &hi, &lo);
+	    a1 = hi;
+	    a2 = lo;
+	    /* a*a + b*b
+	       = a*a + (a-b)*(a-b) - (a-b)*(a-b) + b*b
+	       = a*a + w*w  - (a*a - 2*a*b + b*b) + b*b
+	       = w*w + 2*a*b
+	       = w*w + (a1+a2)*b
+	       = w*w + a1*b + a2*b
+	       = w*w + a1*(b1+b2) + a2*b
+	       = w*w + a1*b1 + a1*b2 + a2*b  */
+	    w  = __ieee754_sqrtl(a1*b1-(w*(-w)-(a1*b2+a2*b)));
 	}
 	if(k!=0)
 	    return w*kld;
diff --git a/sysdeps/ieee754/ldbl-128ibm/e_remainderl.c b/sysdeps/ieee754/ldbl-128ibm/e_remainderl.c
index 67d7db7..800416f 100644
--- a/sysdeps/ieee754/ldbl-128ibm/e_remainderl.c
+++ b/sysdeps/ieee754/ldbl-128ibm/e_remainderl.c
@@ -33,18 +33,22 @@ __ieee754_remainderl(long double x, long double p)
 	int64_t hx,hp;
 	u_int64_t sx,lx,lp;
 	long double p_half;
+	double xhi, xlo, phi, plo;
 
-	GET_LDOUBLE_WORDS64(hx,lx,x);
-	GET_LDOUBLE_WORDS64(hp,lp,p);
+	ldbl_unpack (x, &xhi, &xlo);
+	EXTRACT_WORDS64 (hx, xhi);
+	EXTRACT_WORDS64 (lx, xlo);
+	ldbl_unpack (p, &phi, &plo);
+	EXTRACT_WORDS64 (hp, phi);
+	EXTRACT_WORDS64 (lp, plo);
 	sx = hx&0x8000000000000000ULL;
 	hp &= 0x7fffffffffffffffLL;
 	hx &= 0x7fffffffffffffffLL;
 
     /* purge off exception values */
-	if((hp|(lp&0x7fffffffffffffff))==0) return (x*p)/(x*p);	/* p = 0 */
+	if(hp==0) return (x*p)/(x*p);	/* p = 0 */
 	if((hx>=0x7ff0000000000000LL)||			/* x not finite */
-	  ((hp>=0x7ff0000000000000LL)&&			/* p is NaN */
-	  (((hp-0x7ff0000000000000LL)|lp)!=0)))
+	   (hp>0x7ff0000000000000LL))			/* p is NaN */
 	    return (x*p)/(x*p);
 
 
@@ -64,8 +68,8 @@ __ieee754_remainderl(long double x, long double p)
 		if(x>=p_half) x -= p;
 	    }
 	}
-	GET_LDOUBLE_MSW64(hx,x);
-	SET_LDOUBLE_MSW64(x,hx^sx);
+	if (sx)
+	  x = -x;
 	return x;
 }
 strong_alias (__ieee754_remainderl, __remainderl_finite)
diff --git a/sysdeps/ieee754/ldbl-128ibm/s_erfl.c b/sysdeps/ieee754/ldbl-128ibm/s_erfl.c
index 6a4475e..c861c65 100644
--- a/sysdeps/ieee754/ldbl-128ibm/s_erfl.c
+++ b/sysdeps/ieee754/ldbl-128ibm/s_erfl.c
@@ -760,16 +760,16 @@ long double
 __erfl (long double x)
 {
   long double a, y, z;
-  int32_t i, ix, sign;
-  ieee854_long_double_shape_type u;
+  int32_t i, ix, hx;
+  double xhi;
 
-  u.value = x;
-  sign = u.parts32.w0;
-  ix = sign & 0x7fffffff;
+  xhi = ldbl_high (x);
+  GET_HIGH_WORD (hx, xhi);
+  ix = hx & 0x7fffffff;
 
   if (ix >= 0x7ff00000)
     {				/* erf(nan)=nan */
-      i = ((sign & 0xfff00000) >> 31) << 1;
+      i = ((uint32_t) hx >> 31) << 1;
       return (long double) (1 - i) + one / x;	/* erf(+-inf)=+-1 */
     }
 
@@ -778,7 +778,7 @@ __erfl (long double x)
       if (ix >= 0x4039A0DE)
 	{
 	/* __erfcl (x) underflows if x > 25.6283 */
-	  if (sign)
+	  if ((hx & 0x80000000) == 0)
 	    return one-tiny;
 	  else
 	    return tiny-one;
@@ -789,8 +789,9 @@ __erfl (long double x)
 	  return (one - y);
 	}
     }
-  u.parts32.w0 = ix;
-  a = u.value;
+  a = x;
+  if ((hx & 0x80000000) != 0)
+    a = -a;
   z = x * x;
   if (ix < 0x3fec0000)  /* a < 0.875 */
     {
@@ -814,7 +815,7 @@ __erfl (long double x)
       y = erf_const + neval (a, TN2, NTN2) / deval (a, TD2, NTD2);
     }
 
-  if (sign & 0x80000000) /* x < 0 */
+  if (hx & 0x80000000) /* x < 0 */
     y = -y;
   return( y );
 }
@@ -824,18 +825,18 @@ long double
 __erfcl (long double x)
 {
   long double y, z, p, r;
-  int32_t i, ix, sign;
-  ieee854_long_double_shape_type u;
+  int32_t i, ix;
+  uint32_t hx;
+  double xhi;
 
-  u.value = x;
-  sign = u.parts32.w0;
-  ix = sign & 0x7fffffff;
-  u.parts32.w0 = ix;
+  xhi = ldbl_high (x);
+  GET_HIGH_WORD (hx, xhi);
+  ix = hx & 0x7fffffff;
 
   if (ix >= 0x7ff00000)
     {				/* erfc(nan)=nan */
       /* erfc(+-inf)=0,2 */
-      return (long double) (((u_int32_t) sign >> 31) << 1) + one / x;
+      return (long double) ((hx >> 31) << 1) + one / x;
     }
 
   if (ix < 0x3fd00000) /* |x| <1/4 */
@@ -846,7 +847,8 @@ __erfcl (long double x)
     }
   if (ix < 0x3ff40000) /* 1.25 */
     {
-      x = u.value;
+      if ((hx & 0x80000000) != 0)
+	x = -x;
       i = 8.0 * x;
       switch (i)
 	{
@@ -891,7 +893,7 @@ __erfcl (long double x)
 	  y += C20a;
 	  break;
 	}
-      if (sign & 0x80000000)
+      if (hx & 0x80000000)
 	y = 2.0L - y;
       return y;
     }
@@ -899,10 +901,11 @@ __erfcl (long double x)
   if (ix < 0x405ac000)
     {
       /* x < -9 */
-      if ((ix >= 0x40220000) && (sign & 0x80000000))
+      if (hx >= 0xc0220000)
 	return two - tiny;
 
-      x = fabsl (x);
+      if ((hx & 0x80000000) != 0)
+	x = -x;
       z = one / (x * x);
       i = 8.0 / x;
       switch (i)
@@ -933,21 +936,17 @@ __erfcl (long double x)
 	  p = neval (z, RNr8, NRNr8) / deval (z, RDr8, NRDr8);
 	  break;
 	}
-      u.value = x;
-      u.parts32.w3 = 0;
-      u.parts32.w2 = 0;
-      u.parts32.w1 &= 0xf8000000;
-      z = u.value;
+      z = (float) x;
       r = __ieee754_expl (-z * z - 0.5625) *
 	__ieee754_expl ((z - x) * (z + x) + p);
-      if ((sign & 0x80000000) == 0)
+      if ((hx & 0x80000000) == 0)
 	return r / x;
       else
 	return two - r / x;
     }
   else
     {
-      if ((sign & 0x80000000) == 0)
+      if ((hx & 0x80000000) == 0)
 	return tiny * tiny;
       else
 	return two - tiny;

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=1ce1b171c86c73ea6b52d4784c43942a2060664c

commit 1ce1b171c86c73ea6b52d4784c43942a2060664c
Author: Alan Modra <amodra@gmail.com>
Date:   Sat Aug 17 18:24:58 2013 +0930

    PowerPC floating point little-endian [3 of 15]
    http://sourceware.org/ml/libc-alpha/2013-08/msg00083.html
    
    Further replacement of ieee854 macros and unions.  These files also
    have some optimisations for comparison against 0.0L, infinity and nan.
    Since the ABI specifies that the high double of an IBM long double
    pair is the value rounded to double, a high double of 0.0 means the
    low double must also be 0.0.  The ABI also says that infinity and
    nan are encoded in the high double, with the low double unspecified.
    This means that tests for 0.0L, +/-Infinity and +/-NaN need only check
    the high double.
    
    	* sysdeps/ieee754/ldbl-128ibm/e_atan2l.c (__ieee754_atan2l): Rewrite
    	all uses of ieee854 long double macros and unions.  Simplify tests
    	for long doubles that are fully specified by the high double.
    	* sysdeps/ieee754/ldbl-128ibm/e_gammal_r.c (__ieee754_gammal_r):
    	Likewise.
    	* sysdeps/ieee754/ldbl-128ibm/e_ilogbl.c (__ieee754_ilogbl): Likewise.
    	Remove dead code too.
    	* sysdeps/ieee754/ldbl-128ibm/e_jnl.c (__ieee754_jnl): Likewise.
    	(__ieee754_ynl): Likewise.
    	* sysdeps/ieee754/ldbl-128ibm/e_log10l.c (__ieee754_log10l): Likewise.
    	* sysdeps/ieee754/ldbl-128ibm/e_logl.c (__ieee754_logl): Likewise.
    	* sysdeps/ieee754/ldbl-128ibm/e_powl.c (__ieee754_powl): Likewise.
    	Remove dead code too.
    	* sysdeps/ieee754/ldbl-128ibm/k_tanl.c (__kernel_tanl): Likewise.
    	* sysdeps/ieee754/ldbl-128ibm/s_expm1l.c (__expm1l): Likewise.
    	* sysdeps/ieee754/ldbl-128ibm/s_frexpl.c (__frexpl): Likewise.
    	* sysdeps/ieee754/ldbl-128ibm/s_isinf_nsl.c (__isinf_nsl): Likewise.
    	Simplify.
    	* sysdeps/ieee754/ldbl-128ibm/s_isinfl.c (___isinfl): Likewise.
    	Simplify.
    	* sysdeps/ieee754/ldbl-128ibm/s_log1pl.c (__log1pl): Likewise.
    	* sysdeps/ieee754/ldbl-128ibm/s_modfl.c (__modfl): Likewise.
    	* sysdeps/ieee754/ldbl-128ibm/s_nextafterl.c (__nextafterl): Likewise.
    	Comment on variable precision.
    	* sysdeps/ieee754/ldbl-128ibm/s_nexttoward.c (__nexttoward): Likewise.
    	* sysdeps/ieee754/ldbl-128ibm/s_nexttowardf.c (__nexttowardf):
    	Likewise.
    	* sysdeps/ieee754/ldbl-128ibm/s_remquol.c (__remquol): Likewise.
    	* sysdeps/ieee754/ldbl-128ibm/s_scalblnl.c (__scalblnl): Likewise.
    	* sysdeps/ieee754/ldbl-128ibm/s_scalbnl.c (__scalbnl): Likewise.
    	* sysdeps/ieee754/ldbl-128ibm/s_tanhl.c (__tanhl): Likewise.
    	* sysdeps/powerpc/fpu/libm-test-ulps: Adjust tan_towardzero ulps.

diff --git a/ChangeLog b/ChangeLog
index 38a8b7d..aeb2f2c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,40 @@
 2013-10-04  Alan Modra  <amodra@gmail.com>
 
+	* sysdeps/ieee754/ldbl-128ibm/e_atan2l.c (__ieee754_atan2l): Rewrite
+	all uses of ieee854 long double macros and unions.  Simplify tests
+	for long doubles that are fully specified by the high double.
+	* sysdeps/ieee754/ldbl-128ibm/e_gammal_r.c (__ieee754_gammal_r):
+	Likewise.
+	* sysdeps/ieee754/ldbl-128ibm/e_ilogbl.c (__ieee754_ilogbl): Likewise.
+	Remove dead code too.
+	* sysdeps/ieee754/ldbl-128ibm/e_jnl.c (__ieee754_jnl): Likewise.
+	(__ieee754_ynl): Likewise.
+	* sysdeps/ieee754/ldbl-128ibm/e_log10l.c (__ieee754_log10l): Likewise.
+	* sysdeps/ieee754/ldbl-128ibm/e_logl.c (__ieee754_logl): Likewise.
+	* sysdeps/ieee754/ldbl-128ibm/e_powl.c (__ieee754_powl): Likewise.
+	Remove dead code too.
+	* sysdeps/ieee754/ldbl-128ibm/k_tanl.c (__kernel_tanl): Likewise.
+	* sysdeps/ieee754/ldbl-128ibm/s_expm1l.c (__expm1l): Likewise.
+	* sysdeps/ieee754/ldbl-128ibm/s_frexpl.c (__frexpl): Likewise.
+	* sysdeps/ieee754/ldbl-128ibm/s_isinf_nsl.c (__isinf_nsl): Likewise.
+	Simplify.
+	* sysdeps/ieee754/ldbl-128ibm/s_isinfl.c (___isinfl): Likewise.
+	Simplify.
+	* sysdeps/ieee754/ldbl-128ibm/s_log1pl.c (__log1pl): Likewise.
+	* sysdeps/ieee754/ldbl-128ibm/s_modfl.c (__modfl): Likewise.
+	* sysdeps/ieee754/ldbl-128ibm/s_nextafterl.c (__nextafterl): Likewise.
+	Comment on variable precision.
+	* sysdeps/ieee754/ldbl-128ibm/s_nexttoward.c (__nexttoward): Likewise.
+	* sysdeps/ieee754/ldbl-128ibm/s_nexttowardf.c (__nexttowardf):
+	Likewise.
+	* sysdeps/ieee754/ldbl-128ibm/s_remquol.c (__remquol): Likewise.
+	* sysdeps/ieee754/ldbl-128ibm/s_scalblnl.c (__scalblnl): Likewise.
+	* sysdeps/ieee754/ldbl-128ibm/s_scalbnl.c (__scalbnl): Likewise.
+	* sysdeps/ieee754/ldbl-128ibm/s_tanhl.c (__tanhl): Likewise.
+	* sysdeps/powerpc/fpu/libm-test-ulps: Adjust tan_towardzero ulps.
+
+2013-10-04  Alan Modra  <amodra@gmail.com>
+
 	* sysdeps/ieee754/ldbl-128ibm/math_ldbl.h (ldbl_high): Define.
 	* sysdeps/ieee754/ldbl-128ibm/e_acoshl.c (__ieee754_acoshl): Rewrite
 	all uses of ieee854 long double macros and unions.
diff --git a/sysdeps/ieee754/ldbl-128ibm/e_atan2l.c b/sysdeps/ieee754/ldbl-128ibm/e_atan2l.c
index 3e05355..b625323 100644
--- a/sysdeps/ieee754/ldbl-128ibm/e_atan2l.c
+++ b/sysdeps/ieee754/ldbl-128ibm/e_atan2l.c
@@ -56,11 +56,15 @@ __ieee754_atan2l(long double y, long double x)
 {
 	long double z;
 	int64_t k,m,hx,hy,ix,iy;
-	u_int64_t lx,ly;
+	uint64_t lx;
+	double xhi, xlo, yhi;
 
-	GET_LDOUBLE_WORDS64(hx,lx,x);
+	ldbl_unpack (x, &xhi, &xlo);
+	EXTRACT_WORDS64 (hx, xhi);
+	EXTRACT_WORDS64 (lx, xlo);
 	ix = hx&0x7fffffffffffffffLL;
-	GET_LDOUBLE_WORDS64(hy,ly,y);
+	yhi = ldbl_high (y);
+	EXTRACT_WORDS64 (hy, yhi);
 	iy = hy&0x7fffffffffffffffLL;
 	if(((ix)>0x7ff0000000000000LL)||
 	   ((iy)>0x7ff0000000000000LL))	/* x or y is NaN */
@@ -70,7 +74,7 @@ __ieee754_atan2l(long double y, long double x)
 	m = ((hy>>63)&1)|((hx>>62)&2);	/* 2*sign(x)+sign(y) */
 
     /* when y = 0 */
-	if((iy|(ly&0x7fffffffffffffffLL))==0) {
+	if(iy==0) {
 	    switch(m) {
 		case 0:
 		case 1: return y;	/* atan(+-0,+anything)=+-0 */
@@ -79,7 +83,7 @@ __ieee754_atan2l(long double y, long double x)
 	    }
 	}
     /* when x = 0 */
-	if((ix|(lx&0x7fffffffffffffff))==0) return (hy<0)?  -pi_o_2-tiny: pi_o_2+tiny;
+	if(ix==0) return (hy<0)?  -pi_o_2-tiny: pi_o_2+tiny;
 
     /* when x is INF */
 	if(ix==0x7ff0000000000000LL) {
diff --git a/sysdeps/ieee754/ldbl-128ibm/e_gammal_r.c b/sysdeps/ieee754/ldbl-128ibm/e_gammal_r.c
index 90d8e3f..84c13de 100644
--- a/sysdeps/ieee754/ldbl-128ibm/e_gammal_r.c
+++ b/sysdeps/ieee754/ldbl-128ibm/e_gammal_r.c
@@ -122,11 +122,12 @@ long double
 __ieee754_gammal_r (long double x, int *signgamp)
 {
   int64_t hx;
-  u_int64_t lx;
+  double xhi;
 
-  GET_LDOUBLE_WORDS64 (hx, lx, x);
+  xhi = ldbl_high (x);
+  EXTRACT_WORDS64 (hx, xhi);
 
-  if (((hx | lx) & 0x7fffffffffffffffLL) == 0)
+  if ((hx & 0x7fffffffffffffffLL) == 0)
     {
       /* Return value for x == 0 is Inf with divide by zero exception.  */
       *signgamp = 0;
diff --git a/sysdeps/ieee754/ldbl-128ibm/e_ilogbl.c b/sysdeps/ieee754/ldbl-128ibm/e_ilogbl.c
index 55f87ed..aeace7c 100644
--- a/sysdeps/ieee754/ldbl-128ibm/e_ilogbl.c
+++ b/sysdeps/ieee754/ldbl-128ibm/e_ilogbl.c
@@ -31,26 +31,24 @@ static char rcsid[] = "$NetBSD: $";
 
 int __ieee754_ilogbl(long double x)
 {
-	int64_t hx,lx;
+	int64_t hx;
 	int ix;
+	double xhi;
 
-	GET_LDOUBLE_WORDS64(hx,lx,x);
+	xhi = ldbl_high (x);
+	EXTRACT_WORDS64 (hx, xhi);
 	hx &= 0x7fffffffffffffffLL;
 	if(hx <= 0x0010000000000000LL) {
-	    if((hx|(lx&0x7fffffffffffffffLL))==0)
+	    if(hx==0)
 		return FP_ILOGB0;	/* ilogbl(0) = FP_ILOGB0 */
 	    else			/* subnormal x */
-		if(hx==0) {
-		    for (ix = -1043; lx>0; lx<<=1) ix -=1;
-		} else {
-		    for (ix = -1022, hx<<=11; hx>0; hx<<=1) ix -=1;
-		}
+		for (ix = -1022, hx<<=11; hx>0; hx<<=1) ix -=1;
 	    return ix;
 	}
 	else if (hx<0x7ff0000000000000LL) return (hx>>52)-0x3ff;
 	else if (FP_ILOGBNAN != INT_MAX) {
 	    /* ISO C99 requires ilogbl(+-Inf) == INT_MAX.  */
-	    if (((hx^0x7ff0000000000000LL)|lx) == 0)
+	    if (hx==0x7ff0000000000000LL)
 		return INT_MAX;
 	}
 	return FP_ILOGBNAN;
diff --git a/sysdeps/ieee754/ldbl-128ibm/e_jnl.c b/sysdeps/ieee754/ldbl-128ibm/e_jnl.c
index 40012e4..817977d 100644
--- a/sysdeps/ieee754/ldbl-128ibm/e_jnl.c
+++ b/sysdeps/ieee754/ldbl-128ibm/e_jnl.c
@@ -70,26 +70,25 @@ static const long double
 long double
 __ieee754_jnl (int n, long double x)
 {
-  u_int32_t se;
+  uint32_t se, lx;
   int32_t i, ix, sgn;
   long double a, b, temp, di;
   long double z, w;
-  ieee854_long_double_shape_type u;
+  double xhi;
 
 
   /* J(-n,x) = (-1)^n * J(n, x), J(n, -x) = (-1)^n * J(n, x)
    * Thus, J(-n,x) = J(n,-x)
    */
 
-  u.value = x;
-  se = u.parts32.w0;
+  xhi = ldbl_high (x);
+  EXTRACT_WORDS (se, lx, xhi);
   ix = se & 0x7fffffff;
 
   /* if J(n,NaN) is NaN */
   if (ix >= 0x7ff00000)
     {
-      if ((u.parts32.w0 & 0xfffff) | u.parts32.w1
-	  | (u.parts32.w2 & 0x7fffffff) | u.parts32.w3)
+      if (((ix - 0x7ff00000) | lx) != 0)
 	return x + x;
     }
 
@@ -298,21 +297,20 @@ strong_alias (__ieee754_jnl, __jnl_finite)
 long double
 __ieee754_ynl (int n, long double x)
 {
-  u_int32_t se;
+  uint32_t se, lx;
   int32_t i, ix;
   int32_t sign;
   long double a, b, temp;
-  ieee854_long_double_shape_type u;
+  double xhi;
 
-  u.value = x;
-  se = u.parts32.w0;
+  xhi = ldbl_high (x);
+  EXTRACT_WORDS (se, lx, xhi);
   ix = se & 0x7fffffff;
 
   /* if Y(n,NaN) is NaN */
   if (ix >= 0x7ff00000)
     {
-      if ((u.parts32.w0 & 0xfffff) | u.parts32.w1
-	  | (u.parts32.w2 & 0x7fffffff) | u.parts32.w3)
+      if (((ix - 0x7ff00000) | lx) != 0)
 	return x + x;
     }
   if (x <= 0.0L)
@@ -377,14 +375,16 @@ __ieee754_ynl (int n, long double x)
       a = __ieee754_y0l (x);
       b = __ieee754_y1l (x);
       /* quit if b is -inf */
-      u.value = b;
-      se = u.parts32.w0 & 0xfff00000;
+      xhi = ldbl_high (b);
+      GET_HIGH_WORD (se, xhi);
+      se &= 0xfff00000;
       for (i = 1; i < n && se != 0xfff00000; i++)
 	{
 	  temp = b;
 	  b = ((long double) (i + i) / x) * b - a;
-	  u.value = b;
-	  se = u.parts32.w0 & 0xfff00000;
+	  xhi = ldbl_high (b);
+	  GET_HIGH_WORD (se, xhi);
+	  se &= 0xfff00000;
 	  a = temp;
 	}
     }
diff --git a/sysdeps/ieee754/ldbl-128ibm/e_log10l.c b/sysdeps/ieee754/ldbl-128ibm/e_log10l.c
index fae774c..1a6a4a0 100644
--- a/sysdeps/ieee754/ldbl-128ibm/e_log10l.c
+++ b/sysdeps/ieee754/ldbl-128ibm/e_log10l.c
@@ -182,11 +182,13 @@ __ieee754_log10l (long double x)
   long double z;
   long double y;
   int e;
-  int64_t hx, lx;
+  int64_t hx;
+  double xhi;
 
 /* Test for domain */
-  GET_LDOUBLE_WORDS64 (hx, lx, x);
-  if (((hx & 0x7fffffffffffffffLL) | (lx & 0x7fffffffffffffffLL)) == 0)
+  xhi = ldbl_high (x);
+  EXTRACT_WORDS64 (hx, xhi);
+  if ((hx & 0x7fffffffffffffffLL) == 0)
     return (-1.0L / (x - x));
   if (hx < 0)
     return (x - x) / (x - x);
diff --git a/sysdeps/ieee754/ldbl-128ibm/e_logl.c b/sysdeps/ieee754/ldbl-128ibm/e_logl.c
index 15b5edf..b7db2b9 100644
--- a/sysdeps/ieee754/ldbl-128ibm/e_logl.c
+++ b/sysdeps/ieee754/ldbl-128ibm/e_logl.c
@@ -188,18 +188,20 @@ static const long double
 long double
 __ieee754_logl(long double x)
 {
-  long double z, y, w;
-  ieee854_long_double_shape_type u, t;
+  long double z, y, w, t;
   unsigned int m;
   int k, e;
+  double xhi;
+  uint32_t hx, lx;
 
-  u.value = x;
-  m = u.parts32.w0;
+  xhi = ldbl_high (x);
+  EXTRACT_WORDS (hx, lx, xhi);
+  m = hx;
 
   /* Check for IEEE special cases.  */
   k = m & 0x7fffffff;
   /* log(0) = -infinity. */
-  if ((k | u.parts32.w1 | (u.parts32.w2 & 0x7fffffff) | u.parts32.w3) == 0)
+  if ((k | lx) == 0)
     {
       return -0.5L / ZERO;
     }
@@ -219,7 +221,7 @@ __ieee754_logl(long double x)
     {
       z = x - 1.0L;
       k = 64;
-      t.value  = 1.0L;
+      t = 1.0L;
       e = 0;
     }
   else
@@ -236,10 +238,8 @@ __ieee754_logl(long double x)
 	  k = (m - 0xff000) >> 13;
 	  /* t is the argument 0.5 + (k+26)/128
 	     of the nearest item to u in the lookup table.  */
-	  t.parts32.w0 = 0x3ff00000 + (k << 13);
-	  t.parts32.w1 = 0;
-	  t.parts32.w2 = 0;
-	  t.parts32.w3 = 0;
+	  INSERT_WORDS (xhi, 0x3ff00000 + (k << 13), 0);
+	  t = xhi;
 	  w0 += 0x100000;
 	  e -= 1;
 	  k += 64;
@@ -247,17 +247,15 @@ __ieee754_logl(long double x)
       else
 	{
 	  k = (m - 0xfe000) >> 14;
-	  t.parts32.w0 = 0x3fe00000 + (k << 14);
-	  t.parts32.w1 = 0;
-	  t.parts32.w2 = 0;
-	  t.parts32.w3 = 0;
+	  INSERT_WORDS (xhi, 0x3fe00000 + (k << 14), 0);
+	  t = xhi;
 	}
-      u.value = __scalbnl (u.value, ((int) ((w0 - u.parts32.w0) * 2)) >> 21);
+      x = __scalbnl (x, ((int) ((w0 - hx) * 2)) >> 21);
       /* log(u) = log( t u/t ) = log(t) + log(u/t)
 	 log(t) is tabulated in the lookup table.
 	 Express log(u/t) = log(1+z),  where z = u/t - 1 = (u-t)/t.
 	 cf. Cody & Waite. */
-      z = (u.value - t.value) / t.value;
+      z = (x - t) / t;
     }
   /* Series expansion of log(1+z).  */
   w = z * z;
@@ -284,7 +282,7 @@ __ieee754_logl(long double x)
   y += e * ln2b;  /* Base 2 exponent offset times ln(2).  */
   y += z;
   y += logtbl[k-26]; /* log(t) - (t-1) */
-  y += (t.value - 1.0L);
+  y += (t - 1.0L);
   y += e * ln2a;
   return y;
 }
diff --git a/sysdeps/ieee754/ldbl-128ibm/e_powl.c b/sysdeps/ieee754/ldbl-128ibm/e_powl.c
index 8bd35d0..c942f2f 100644
--- a/sysdeps/ieee754/ldbl-128ibm/e_powl.c
+++ b/sysdeps/ieee754/ldbl-128ibm/e_powl.c
@@ -151,37 +151,32 @@ __ieee754_powl (long double x, long double y)
   long double y1, t1, t2, r, s, t, u, v, w;
   long double s2, s_h, s_l, t_h, t_l, ay;
   int32_t i, j, k, yisint, n;
-  u_int32_t ix, iy;
-  int32_t hx, hy;
-  ieee854_long_double_shape_type o, p, q;
+  uint32_t ix, iy;
+  int32_t hx, hy, hax;
+  double ohi, xhi, xlo, yhi, ylo;
+  uint32_t lx, ly, lj;
 
-  p.value = x;
-  hx = p.parts32.w0;
+  ldbl_unpack (x, &xhi, &xlo);
+  EXTRACT_WORDS (hx, lx, xhi);
   ix = hx & 0x7fffffff;
 
-  q.value = y;
-  hy = q.parts32.w0;
+  ldbl_unpack (y, &yhi, &ylo);
+  EXTRACT_WORDS (hy, ly, yhi);
   iy = hy & 0x7fffffff;
 
-
   /* y==zero: x**0 = 1 */
-  if ((iy | q.parts32.w1 | (q.parts32.w2 & 0x7fffffff) | q.parts32.w3) == 0)
+  if ((iy | ly) == 0)
     return one;
 
   /* 1.0**y = 1; -1.0**+-Inf = 1 */
   if (x == one)
     return one;
-  if (x == -1.0L && iy == 0x7ff00000
-      && (q.parts32.w1 | (q.parts32.w2 & 0x7fffffff) | q.parts32.w3) == 0)
+  if (x == -1.0L && ((iy - 0x7ff00000) | ly) == 0)
     return one;
 
   /* +-NaN return x+y */
-  if ((ix > 0x7ff00000)
-      || ((ix == 0x7ff00000)
-	  && ((p.parts32.w1 | (p.parts32.w2 & 0x7fffffff) | p.parts32.w3) != 0))
-      || (iy > 0x7ff00000)
-      || ((iy == 0x7ff00000)
-	  && ((q.parts32.w1 | (q.parts32.w2 & 0x7fffffff) | q.parts32.w3) != 0)))
+  if ((ix >= 0x7ff00000 && ((ix - 0x7ff00000) | lx) != 0)
+      || (iy >= 0x7ff00000 && ((iy - 0x7ff00000) | ly) != 0))
     return x + y;
 
   /* determine if y is an odd int when x < 0
@@ -192,7 +187,10 @@ __ieee754_powl (long double x, long double y)
   yisint = 0;
   if (hx < 0)
     {
-      if ((q.parts32.w2 & 0x7fffffff) >= 0x43400000)	/* Low part >= 2^53 */
+      uint32_t low_ye;
+
+      GET_HIGH_WORD (low_ye, ylo);
+      if ((low_ye & 0x7fffffff) >= 0x43400000)	/* Low part >= 2^53 */
 	yisint = 2;		/* even integer y */
       else if (iy >= 0x3ff00000)	/* 1.0 */
 	{
@@ -207,42 +205,43 @@ __ieee754_powl (long double x, long double y)
 	}
     }
 
+  ax = fabsl (x);
+
   /* special value of y */
-  if ((q.parts32.w1 | (q.parts32.w2 & 0x7fffffff) | q.parts32.w3) == 0)
+  if (ly == 0)
     {
-      if (iy == 0x7ff00000 && q.parts32.w1 == 0)	/* y is +-inf */
+      if (iy == 0x7ff00000)	/* y is +-inf */
 	{
-	  if (((ix - 0x3ff00000) | p.parts32.w1
-	       | (p.parts32.w2 & 0x7fffffff) | p.parts32.w3) == 0)
-	    return y - y;	/* inf**+-1 is NaN */
-	  else if (ix > 0x3ff00000 || fabsl (x) > 1.0L)
+	  if (ax > one)
 	    /* (|x|>1)**+-inf = inf,0 */
 	    return (hy >= 0) ? y : zero;
 	  else
 	    /* (|x|<1)**-,+inf = inf,0 */
 	    return (hy < 0) ? -y : zero;
 	}
-      if (iy == 0x3ff00000)
-	{			/* y is  +-1 */
-	  if (hy < 0)
-	    return one / x;
-	  else
-	    return x;
-	}
-      if (hy == 0x40000000)
-	return x * x;		/* y is  2 */
-      if (hy == 0x3fe00000)
-	{			/* y is  0.5 */
-	  if (hx >= 0)		/* x >= +0 */
-	    return __ieee754_sqrtl (x);
+      if (ylo == 0.0)
+	{
+	  if (iy == 0x3ff00000)
+	    {			/* y is  +-1 */
+	      if (hy < 0)
+		return one / x;
+	      else
+		return x;
+	    }
+	  if (hy == 0x40000000)
+	    return x * x;		/* y is  2 */
+	  if (hy == 0x3fe00000)
+	    {			/* y is  0.5 */
+	      if (hx >= 0)		/* x >= +0 */
+		return __ieee754_sqrtl (x);
+	    }
 	}
     }
 
-  ax = fabsl (x);
   /* special value of x */
-  if ((p.parts32.w1 | (p.parts32.w2 & 0x7fffffff) | p.parts32.w3) == 0)
+  if (lx == 0)
     {
-      if (ix == 0x7ff00000 || ix == 0 || ix == 0x3ff00000)
+      if (ix == 0x7ff00000 || ix == 0 || (ix == 0x3ff00000 && xlo == 0.0))
 	{
 	  z = ax;		/*x is +-0,+-inf,+-1 */
 	  if (hy < 0)
@@ -294,8 +293,8 @@ __ieee754_powl (long double x, long double y)
     {
       ax *= two113;
       n -= 113;
-      o.value = ax;
-      ix = o.parts32.w0;
+      ohi = ldbl_high (ax);
+      GET_HIGH_WORD (ix, ohi);
     }
   n += ((ix) >> 20) - 0x3ff;
   j = ix & 0x000fffff;
@@ -312,26 +311,19 @@ __ieee754_powl (long double x, long double y)
       ix -= 0x00100000;
     }
 
-  o.value = ax;
-  o.value = __scalbnl (o.value, ((int) ((ix - o.parts32.w0) * 2)) >> 21);
-  ax = o.value;
+  ohi = ldbl_high (ax);
+  GET_HIGH_WORD (hax, ohi);
+  ax = __scalbnl (ax, ((int) ((ix - hax) * 2)) >> 21);
 
   /* compute s = s_h+s_l = (x-1)/(x+1) or (x-1.5)/(x+1.5) */
   u = ax - bp[k];		/* bp[0]=1.0, bp[1]=1.5 */
   v = one / (ax + bp[k]);
   s = u * v;
-  s_h = s;
+  s_h = ldbl_high (s);
 
-  o.value = s_h;
-  o.parts32.w3 = 0;
-  o.parts32.w2 = 0;
-  s_h = o.value;
   /* t_h=ax+bp[k] High */
   t_h = ax + bp[k];
-  o.value = t_h;
-  o.parts32.w3 = 0;
-  o.parts32.w2 = 0;
-  t_h = o.value;
+  t_h = ldbl_high (t_h);
   t_l = ax - (t_h - bp[k]);
   s_l = v * ((u - s_h * t_h) - s_h * t_l);
   /* compute log(ax) */
@@ -342,30 +334,21 @@ __ieee754_powl (long double x, long double y)
   r += s_l * (s_h + s);
   s2 = s_h * s_h;
   t_h = 3.0 + s2 + r;
-  o.value = t_h;
-  o.parts32.w3 = 0;
-  o.parts32.w2 = 0;
-  t_h = o.value;
+  t_h = ldbl_high (t_h);
   t_l = r - ((t_h - 3.0) - s2);
   /* u+v = s*(1+...) */
   u = s_h * t_h;
   v = s_l * t_h + t_l * s;
   /* 2/(3log2)*(s+...) */
   p_h = u + v;
-  o.value = p_h;
-  o.parts32.w3 = 0;
-  o.parts32.w2 = 0;
-  p_h = o.value;
+  p_h = ldbl_high (p_h);
   p_l = v - (p_h - u);
   z_h = cp_h * p_h;		/* cp_h+cp_l = 2/(3*log2) */
   z_l = cp_l * p_h + p_l * cp + dp_l[k];
   /* log2(ax) = (s+..)*2/(3*log2) = n + dp_h + z_h + z_l */
   t = (long double) n;
   t1 = (((z_h + z_l) + dp_h[k]) + t);
-  o.value = t1;
-  o.parts32.w3 = 0;
-  o.parts32.w2 = 0;
-  t1 = o.value;
+  t1 = ldbl_high (t1);
   t2 = z_l - (((t1 - t) - dp_h[k]) - z_h);
 
   /* s (sign of result -ve**odd) = -1 else = 1 */
@@ -374,21 +357,16 @@ __ieee754_powl (long double x, long double y)
     s = -one;			/* (-ve)**(odd int) */
 
   /* split up y into y1+y2 and compute (y1+y2)*(t1+t2) */
-  y1 = y;
-  o.value = y1;
-  o.parts32.w3 = 0;
-  o.parts32.w2 = 0;
-  y1 = o.value;
+  y1 = ldbl_high (y);
   p_l = (y - y1) * t1 + y * t2;
   p_h = y1 * t1;
   z = p_l + p_h;
-  o.value = z;
-  j = o.parts32.w0;
+  ohi = ldbl_high (z);
+  EXTRACT_WORDS (j, lj, ohi);
   if (j >= 0x40d00000) /* z >= 16384 */
     {
       /* if z > 16384 */
-      if (((j - 0x40d00000) | o.parts32.w1
-	| (o.parts32.w2 & 0x7fffffff) | o.parts32.w3) != 0)
+      if (((j - 0x40d00000) | lj) != 0)
 	return s * huge * huge;	/* overflow */
       else
 	{
@@ -399,8 +377,7 @@ __ieee754_powl (long double x, long double y)
   else if ((j & 0x7fffffff) >= 0x40d01b90)	/* z <= -16495 */
     {
       /* z < -16495 */
-      if (((j - 0xc0d01bc0) | o.parts32.w1
-	 | (o.parts32.w2 & 0x7fffffff) | o.parts32.w3) != 0)
+      if (((j - 0xc0d01bc0) | lj) != 0)
 	return s * tiny * tiny;	/* underflow */
       else
 	{
@@ -419,10 +396,7 @@ __ieee754_powl (long double x, long double y)
       p_h -= t;
     }
   t = p_l + p_h;
-  o.value = t;
-  o.parts32.w3 = 0;
-  o.parts32.w2 = 0;
-  t = o.value;
+  t = ldbl_high (t);
   u = t * lg2_h;
   v = (p_l - (t - p_h)) * lg2 + t * lg2_l;
   z = u + v;
diff --git a/sysdeps/ieee754/ldbl-128ibm/k_tanl.c b/sysdeps/ieee754/ldbl-128ibm/k_tanl.c
index 1f6bad2..bcf8b5e 100644
--- a/sysdeps/ieee754/ldbl-128ibm/k_tanl.c
+++ b/sysdeps/ieee754/ldbl-128ibm/k_tanl.c
@@ -85,17 +85,17 @@ long double
 __kernel_tanl (long double x, long double y, int iy)
 {
   long double z, r, v, w, s;
-  int32_t ix, sign;
-  ieee854_long_double_shape_type u, u1;
+  int32_t ix, sign, hx, lx;
+  double xhi;
 
-  u.value = x;
-  ix = u.parts32.w0 & 0x7fffffff;
+  xhi = ldbl_high (x);
+  EXTRACT_WORDS (hx, lx, xhi);
+  ix = hx & 0x7fffffff;
   if (ix < 0x3c600000)		/* x < 2**-57 */
     {
-      if ((int) x == 0)
-	{			/* generate inexact */
-	  if ((ix | u.parts32.w1 | (u.parts32.w2 & 0x7fffffff) | u.parts32.w3
-	       | (iy + 1)) == 0)
+      if ((int) x == 0)		/* generate inexact */
+	{
+	  if ((ix | lx | (iy + 1)) == 0)
 	    return one / fabs (x);
 	  else
 	    return (iy == 1) ? x : -one / x;
@@ -103,7 +103,7 @@ __kernel_tanl (long double x, long double y, int iy)
     }
   if (ix >= 0x3fe59420) /* |x| >= 0.6743316650390625 */
     {
-      if ((u.parts32.w0 & 0x80000000) != 0)
+      if ((hx & 0x80000000) != 0)
 	{
 	  x = -x;
 	  y = -y;
@@ -139,15 +139,13 @@ __kernel_tanl (long double x, long double y, int iy)
     {				/* if allow error up to 2 ulp,
 				   simply return -1.0/(x+r) here */
       /*  compute -1.0/(x+r) accurately */
-      u1.value = w;
-      u1.parts32.w2 = 0;
-      u1.parts32.w3 = 0;
-      v = r - (u1.value - x);		/* u1+v = r+x */
+      long double u1, z1;
+
+      u1 = ldbl_high (w);
+      v = r - (u1 - x);		/* u1+v = r+x */
       z = -1.0 / w;
-      u.value = z;
-      u.parts32.w2 = 0;
-      u.parts32.w3 = 0;
-      s = 1.0 + u.value * u1.value;
-      return u.value + z * (s + u.value * v);
+      z1 = ldbl_high (z);
+      s = 1.0 + z1 * u1;
+      return z1 + z * (s + z1 * v);
     }
 }
diff --git a/sysdeps/ieee754/ldbl-128ibm/s_expm1l.c b/sysdeps/ieee754/ldbl-128ibm/s_expm1l.c
index 8808dcd..007e785 100644
--- a/sysdeps/ieee754/ldbl-128ibm/s_expm1l.c
+++ b/sysdeps/ieee754/ldbl-128ibm/s_expm1l.c
@@ -92,19 +92,19 @@ long double
 __expm1l (long double x)
 {
   long double px, qx, xx;
-  int32_t ix, sign;
-  ieee854_long_double_shape_type u;
+  int32_t ix, lx, sign;
   int k;
+  double xhi;
 
   /* Detect infinity and NaN.  */
-  u.value = x;
-  ix = u.parts32.w0;
+  xhi = ldbl_high (x);
+  EXTRACT_WORDS (ix, lx, xhi);
   sign = ix & 0x80000000;
   ix &= 0x7fffffff;
   if (ix >= 0x7ff00000)
     {
       /* Infinity. */
-      if (((ix & 0xfffff) | u.parts32.w1 | (u.parts32.w2&0x7fffffff) | u.parts32.w3) == 0)
+      if (((ix - 0x7ff00000) | lx) == 0)
 	{
 	  if (sign)
 	    return -1.0L;
@@ -116,7 +116,7 @@ __expm1l (long double x)
     }
 
   /* expm1(+- 0) = +- 0.  */
-  if ((ix == 0) && (u.parts32.w1 | (u.parts32.w2&0x7fffffff) | u.parts32.w3) == 0)
+  if ((ix | lx) == 0)
     return x;
 
   /* Overflow.  */
diff --git a/sysdeps/ieee754/ldbl-128ibm/s_frexpl.c b/sysdeps/ieee754/ldbl-128ibm/s_frexpl.c
index 3ac5374..7e40663 100644
--- a/sysdeps/ieee754/ldbl-128ibm/s_frexpl.c
+++ b/sysdeps/ieee754/ldbl-128ibm/s_frexpl.c
@@ -36,16 +36,21 @@ two107 = 162259276829213363391578010288128.0; /* 0x4670000000000000, 0 */
 
 long double __frexpl(long double x, int *eptr)
 {
-	u_int64_t hx, lx, ix, ixl;
+	uint64_t hx, lx, ix, ixl;
 	int64_t explo;
-	GET_LDOUBLE_WORDS64(hx,lx,x);
+	double xhi, xlo;
+
+	ldbl_unpack (x, &xhi, &xlo);
+	EXTRACT_WORDS64 (hx, xhi);
+	EXTRACT_WORDS64 (lx, xlo);
 	ixl = 0x7fffffffffffffffULL&lx;
 	ix =  0x7fffffffffffffffULL&hx;
 	*eptr = 0;
-	if(ix>=0x7ff0000000000000ULL||((ix|ixl)==0)) return x;	/* 0,inf,nan */
+	if(ix>=0x7ff0000000000000ULL||ix==0) return x;	/* 0,inf,nan */
 	if (ix<0x0010000000000000ULL) {		/* subnormal */
 	    x *= two107;
-	    GET_LDOUBLE_MSW64(hx,x);
+	    xhi = ldbl_high (x);
+	    EXTRACT_WORDS64 (hx, xhi);
 	    ix = hx&0x7fffffffffffffffULL;
 	    *eptr = -107;
 	}
@@ -54,7 +59,7 @@ long double __frexpl(long double x, int *eptr)
 	if (ixl != 0ULL) {
 	  explo = (ixl>>52) - (ix>>52) + 0x3fe;
 	  if ((ixl&0x7ff0000000000000ULL) == 0LL) {
-	    /* the lower double is a denomal so we need to correct its
+	    /* the lower double is a denormal so we need to correct its
 	       mantissa and perhaps its exponent.  */
 	    int cnt;
 
@@ -73,7 +78,9 @@ long double __frexpl(long double x, int *eptr)
 	  lx = 0ULL;
 
 	hx = (hx&0x800fffffffffffffULL) | 0x3fe0000000000000ULL;
-	SET_LDOUBLE_WORDS64(x,hx,lx);
+	INSERT_WORDS64 (xhi, hx);
+	INSERT_WORDS64 (xlo, lx);
+	x = ldbl_pack (xhi, xlo);
 	return x;
 }
 #ifdef IS_IN_libm
diff --git a/sysdeps/ieee754/ldbl-128ibm/s_isinf_nsl.c b/sysdeps/ieee754/ldbl-128ibm/s_isinf_nsl.c
index c8dd9ff..54e72c9 100644
--- a/sysdeps/ieee754/ldbl-128ibm/s_isinf_nsl.c
+++ b/sysdeps/ieee754/ldbl-128ibm/s_isinf_nsl.c
@@ -1,6 +1,7 @@
 /*
  * __isinf_nsl(x) returns != 0 if x is ±inf, else 0;
  * no branching!
+ * slightly dodgy in relying on signed shift right copying sign bit
  */
 
 #include <math.h>
@@ -9,8 +10,14 @@
 int
 __isinf_nsl (long double x)
 {
-	int64_t hx,lx;
-	GET_LDOUBLE_WORDS64(hx,lx,x);
-	return !((lx & 0x7fffffffffffffffLL)
-		 | ((hx & 0x7fffffffffffffffLL) ^ 0x7ff0000000000000LL));
+  double xhi;
+  int64_t hx, mask;
+
+  xhi = ldbl_high (x);
+  EXTRACT_WORDS64 (hx, xhi);
+
+  mask = (hx & 0x7fffffffffffffffLL) ^ 0x7ff0000000000000LL;
+  mask |= -mask;
+  mask >>= 63;
+  return ~mask;
 }
diff --git a/sysdeps/ieee754/ldbl-128ibm/s_isinfl.c b/sysdeps/ieee754/ldbl-128ibm/s_isinfl.c
index 5f5b014..6a72822 100644
--- a/sysdeps/ieee754/ldbl-128ibm/s_isinfl.c
+++ b/sysdeps/ieee754/ldbl-128ibm/s_isinfl.c
@@ -11,6 +11,7 @@ static char rcsid[] = "$NetBSD: $";
 /*
  * isinfl(x) returns 1 if x is inf, -1 if x is -inf, else 0;
  * no branching!
+ * slightly dodgy in relying on signed shift right copying sign bit
  */
 
 #include <math.h>
@@ -20,12 +21,16 @@ static char rcsid[] = "$NetBSD: $";
 int
 ___isinfl (long double x)
 {
-	int64_t hx,lx;
-	GET_LDOUBLE_WORDS64(hx,lx,x);
-	lx = (lx & 0x7fffffffffffffffLL);
-	lx |= (hx & 0x7fffffffffffffffLL) ^ 0x7ff0000000000000LL;
-	lx |= -lx;
-	return ~(lx >> 63) & (hx >> 62);
+  double xhi;
+  int64_t hx, mask;
+
+  xhi = ldbl_high (x);
+  EXTRACT_WORDS64 (hx, xhi);
+
+  mask = (hx & 0x7fffffffffffffffLL) ^ 0x7ff0000000000000LL;
+  mask |= -mask;
+  mask >>= 63;
+  return ~mask & (hx >> 62);
 }
 hidden_ver (___isinfl, __isinfl)
 #ifndef IS_IN_libm
diff --git a/sysdeps/ieee754/ldbl-128ibm/s_log1pl.c b/sysdeps/ieee754/ldbl-128ibm/s_log1pl.c
index 77c4fde..a346383 100644
--- a/sysdeps/ieee754/ldbl-128ibm/s_log1pl.c
+++ b/sysdeps/ieee754/ldbl-128ibm/s_log1pl.c
@@ -126,19 +126,18 @@ long double
 __log1pl (long double xm1)
 {
   long double x, y, z, r, s;
-  ieee854_long_double_shape_type u;
-  int32_t hx;
+  double xhi;
+  int32_t hx, lx;
   int e;
 
   /* Test for NaN or infinity input. */
-  u.value = xm1;
-  hx = u.parts32.w0;
+  xhi = ldbl_high (xm1);
+  EXTRACT_WORDS (hx, lx, xhi);
   if (hx >= 0x7ff00000)
     return xm1;
 
   /* log1p(+- 0) = +- 0.  */
-  if (((hx & 0x7fffffff) == 0)
-      && (u.parts32.w1 | (u.parts32.w2 & 0x7fffffff) | u.parts32.w3) == 0)
+  if (((hx & 0x7fffffff) | lx) == 0)
     return xm1;
 
   x = xm1 + 1.0L;
diff --git a/sysdeps/ieee754/ldbl-128ibm/s_modfl.c b/sysdeps/ieee754/ldbl-128ibm/s_modfl.c
index 39de9d4..ed03ce2 100644
--- a/sysdeps/ieee754/ldbl-128ibm/s_modfl.c
+++ b/sysdeps/ieee754/ldbl-128ibm/s_modfl.c
@@ -37,43 +37,54 @@ long double __modfl(long double x, long double *iptr)
 {
 	int64_t i0,i1,j0;
 	u_int64_t i;
-	GET_LDOUBLE_WORDS64(i0,i1,x);
+	double xhi, xlo;
+
+	ldbl_unpack (x, &xhi, &xlo);
+	EXTRACT_WORDS64 (i0, xhi);
+	EXTRACT_WORDS64 (i1, xlo);
 	i1 &= 0x000fffffffffffffLL;
 	j0 = ((i0>>52)&0x7ff)-0x3ff;	/* exponent of x */
 	if(j0<52) {			/* integer part in high x */
 	    if(j0<0) {			/* |x|<1 */
 		/* *iptr = +-0 */
-	        SET_LDOUBLE_WORDS64(*iptr,i0&0x8000000000000000ULL,0);
+		INSERT_WORDS64 (xhi, i0&0x8000000000000000ULL);
+		*iptr = xhi;
 		return x;
 	    } else {
 		i = (0x000fffffffffffffLL)>>j0;
 		if(((i0&i)|(i1&0x7fffffffffffffffLL))==0) {		/* x is integral */
 		    *iptr = x;
 		    /* return +-0 */
-		    SET_LDOUBLE_WORDS64(x,i0&0x8000000000000000ULL,0);
+		    INSERT_WORDS64 (xhi, i0&0x8000000000000000ULL);
+		    x = xhi;
 		    return x;
 		} else {
-		    SET_LDOUBLE_WORDS64(*iptr,i0&(~i),0);
+		    INSERT_WORDS64 (xhi, i0&(~i));
+		    *iptr = xhi;
 		    return x - *iptr;
 		}
 	    }
 	} else if (j0>103) {		/* no fraction part */
 	    *iptr = x*one;
 	    /* We must handle NaNs separately.  */
-	    if (j0 == 0x400 && ((i0 & 0x000fffffffffffffLL) | i1))
+	    if ((i0 & 0x7fffffffffffffffLL) > 0x7ff0000000000000LL)
 	      return x*one;
 	    /* return +-0 */
-	    SET_LDOUBLE_WORDS64(x,i0&0x8000000000000000ULL,0);
+	    INSERT_WORDS64 (xhi, i0&0x8000000000000000ULL);
+	    x = xhi;
 	    return x;
 	} else {			/* fraction part in low x */
 	    i = -1ULL>>(j0-52);
 	    if((i1&i)==0) { 		/* x is integral */
 		*iptr = x;
 		/* return +-0 */
-		SET_LDOUBLE_WORDS64(x,i0&0x8000000000000000ULL,0);
+		INSERT_WORDS64 (xhi, i0&0x8000000000000000ULL);
+		x = xhi;
 		return x;
 	    } else {
-		SET_LDOUBLE_WORDS64(*iptr,i0,i1&(~i));
+		INSERT_WORDS64 (xhi, i0);
+		INSERT_WORDS64 (xlo, i1&(~i));
+		*iptr = ldbl_pack (xhi, xlo);
 		return x - *iptr;
 	    }
 	}
diff --git a/sysdeps/ieee754/ldbl-128ibm/s_nextafterl.c b/sysdeps/ieee754/ldbl-128ibm/s_nextafterl.c
index 7e58127..c050944 100644
--- a/sysdeps/ieee754/ldbl-128ibm/s_nextafterl.c
+++ b/sysdeps/ieee754/ldbl-128ibm/s_nextafterl.c
@@ -30,27 +30,28 @@ static char rcsid[] = "$NetBSD: $";
 
 long double __nextafterl(long double x, long double y)
 {
-	int64_t hx,hy,ihx,ihy,ilx;
-	u_int64_t lx;
-	u_int64_t ly __attribute__ ((unused));
+	int64_t hx,hy,ihx,ihy;
+	uint64_t lx;
+	double xhi, xlo, yhi;
 
-	GET_LDOUBLE_WORDS64(hx,lx,x);
-	GET_LDOUBLE_WORDS64(hy,ly,y);
+	ldbl_unpack (x, &xhi, &xlo);
+	EXTRACT_WORDS64 (hx, xhi);
+	EXTRACT_WORDS64 (lx, xlo);
+	yhi = ldbl_high (y);
+	EXTRACT_WORDS64 (hy, yhi);
 	ihx = hx&0x7fffffffffffffffLL;		/* |hx| */
-	ilx = lx&0x7fffffffffffffffLL;		/* |lx| */
 	ihy = hy&0x7fffffffffffffffLL;		/* |hy| */
 
-	if((((ihx&0x7ff0000000000000LL)==0x7ff0000000000000LL)&&
-	    ((ihx&0x000fffffffffffffLL)!=0)) ||   /* x is nan */
-	   (((ihy&0x7ff0000000000000LL)==0x7ff0000000000000LL)&&
-	    ((ihy&0x000fffffffffffffLL)!=0)))     /* y is nan */
+	if((ihx>0x7ff0000000000000LL) ||	/* x is nan */
+	   (ihy>0x7ff0000000000000LL))		/* y is nan */
 	    return x+y; /* signal the nan */
 	if(x==y)
 	    return y;		/* x=y, return y */
-	if(ihx == 0 && ilx == 0) {			/* x == 0 */
-	    long double u;
+	if(ihx == 0) {				/* x == 0 */
+	    long double u;			/* return +-minsubnormal */
 	    hy = (hy & 0x8000000000000000ULL) | 1;
-	    SET_LDOUBLE_WORDS64(x,hy,0ULL);/* return +-minsubnormal */
+	    INSERT_WORDS64 (yhi, hy);
+	    x = yhi;
 	    u = math_opt_barrier (x);
 	    u = u * u;
 	    math_force_eval (u);		/* raise underflow flag */
@@ -59,10 +60,16 @@ long double __nextafterl(long double x, long double y)
 
 	long double u;
 	if(x > y) {	/* x > y, x -= ulp */
+	    /* This isn't the largest magnitude correctly rounded
+	       long double as you can see from the lowest mantissa
+	       bit being zero.  It is however the largest magnitude
+	       long double with a 106 bit mantissa, and nextafterl
+	       is insane with variable precision.  So to make
+	       nextafterl sane we assume 106 bit precision.  */
 	    if((hx==0xffefffffffffffffLL)&&(lx==0xfc8ffffffffffffeLL))
 	      return x+x;	/* overflow, return -inf */
 	    if (hx >= 0x7ff0000000000000LL) {
-	      SET_LDOUBLE_WORDS64(u,0x7fefffffffffffffLL,0x7c8ffffffffffffeLL);
+	      u = 0x1.fffffffffffff7ffffffffffff8p+1023L;
 	      return u;
 	    }
 	    if(ihx <= 0x0360000000000000LL) {  /* x <= LDBL_MIN */
@@ -77,16 +84,19 @@ long double __nextafterl(long double x, long double y)
 	      return x;
 	    }
 	    if (ihx < 0x06a0000000000000LL) { /* ulp will denormal */
-	      SET_LDOUBLE_WORDS64(u,(hx&0x7ff0000000000000LL),0ULL);
+	      INSERT_WORDS64 (yhi, hx & (0x7ffLL<<52));
+	      u = yhi;
 	      u *= 0x1.0000000000000p-105L;
-	    } else
-	      SET_LDOUBLE_WORDS64(u,(hx&0x7ff0000000000000LL)-0x0690000000000000LL,0ULL);
+	    } else {
+	      INSERT_WORDS64 (yhi, (hx & (0x7ffLL<<52))-(0x069LL<<52));
+	      u = yhi;
+	    }
 	    return x - u;
 	} else {				/* x < y, x += ulp */
 	    if((hx==0x7fefffffffffffffLL)&&(lx==0x7c8ffffffffffffeLL))
 	      return x+x;	/* overflow, return +inf */
-	    if ((u_int64_t) hx >= 0xfff0000000000000ULL) {
-	      SET_LDOUBLE_WORDS64(u,0xffefffffffffffffLL,0xfc8ffffffffffffeLL);
+	    if ((uint64_t) hx >= 0xfff0000000000000ULL) {
+	      u = -0x1.fffffffffffff7ffffffffffff8p+1023L;
 	      return u;
 	    }
 	    if(ihx <= 0x0360000000000000LL) {  /* x <= LDBL_MIN */
@@ -103,10 +113,13 @@ long double __nextafterl(long double x, long double y)
 	      return x;
 	    }
 	    if (ihx < 0x06a0000000000000LL) { /* ulp will denormal */
-	      SET_LDOUBLE_WORDS64(u,(hx&0x7ff0000000000000LL),0ULL);
+	      INSERT_WORDS64 (yhi, hx & (0x7ffLL<<52));
+	      u = yhi;
 	      u *= 0x1.0000000000000p-105L;
-	    } else
-	      SET_LDOUBLE_WORDS64(u,(hx&0x7ff0000000000000LL)-0x0690000000000000LL,0ULL);
+	    } else {
+	      INSERT_WORDS64 (yhi, (hx & (0x7ffLL<<52))-(0x069LL<<52));
+	      u = yhi;
+	    }
 	    return x + u;
 	}
 }
diff --git a/sysdeps/ieee754/ldbl-128ibm/s_nexttoward.c b/sysdeps/ieee754/ldbl-128ibm/s_nexttoward.c
index 7e288a4..b40cf16 100644
--- a/sysdeps/ieee754/ldbl-128ibm/s_nexttoward.c
+++ b/sysdeps/ieee754/ldbl-128ibm/s_nexttoward.c
@@ -34,23 +34,22 @@ double __nexttoward(double x, long double y)
 {
 	int32_t hx,ix;
 	int64_t hy,iy;
-	u_int32_t lx;
-	u_int64_t ly,uly;
+	uint32_t lx;
+	double yhi;
 
 	EXTRACT_WORDS(hx,lx,x);
-	GET_LDOUBLE_WORDS64(hy,ly,y);
+	yhi = ldbl_high (y);
+	EXTRACT_WORDS64(hy,yhi);
 	ix = hx&0x7fffffff;		/* |x| */
 	iy = hy&0x7fffffffffffffffLL;	/* |y| */
-	uly = ly&0x7fffffffffffffffLL;	/* |y| */
 
 	if(((ix>=0x7ff00000)&&((ix-0x7ff00000)|lx)!=0) ||   /* x is nan */
-	   ((iy>=0x7ff0000000000000LL)&&((iy-0x7ff0000000000000LL)|uly)!=0))
-							    /* y is nan */
+	   iy>0x7ff0000000000000LL)			    /* y is nan */
 	   return x+y;
 	if((long double) x==y) return y;	/* x=y, return y */
 	if((ix|lx)==0) {			/* x == 0 */
 	    double u;
-	    INSERT_WORDS(x,(u_int32_t)((hy>>32)&0x80000000),1);/* return +-minsub */
+	    INSERT_WORDS(x,(uint32_t)((hy>>32)&0x80000000),1);/* return +-minsub */
 	    u = math_opt_barrier (x);
 	    u = u * u;
 	    math_force_eval (u);		/* raise underflow flag */
diff --git a/sysdeps/ieee754/ldbl-128ibm/s_nexttowardf.c b/sysdeps/ieee754/ldbl-128ibm/s_nexttowardf.c
index b387a91..19522f4 100644
--- a/sysdeps/ieee754/ldbl-128ibm/s_nexttowardf.c
+++ b/sysdeps/ieee754/ldbl-128ibm/s_nexttowardf.c
@@ -27,16 +27,16 @@ float __nexttowardf(float x, long double y)
 {
 	int32_t hx,ix;
 	int64_t hy,iy;
-	u_int64_t ly, uly;
+	double yhi;
 
 	GET_FLOAT_WORD(hx,x);
-	GET_LDOUBLE_WORDS64(hy,ly,y);
+	yhi = ldbl_high (y);
+	EXTRACT_WORDS64 (hy, yhi);
 	ix = hx&0x7fffffff;		/* |x| */
 	iy = hy&0x7fffffffffffffffLL;	/* |y| */
-	uly = ly&0x7fffffffffffffffLL;	/* |y| */
 
 	if((ix>0x7f800000) ||   /* x is nan */
-	   ((iy>=0x7ff0000000000000LL)&&((iy-0x7ff0000000000000LL)|uly)!=0))
+	   (iy>0x7ff0000000000000LL))
 				/* y is nan */
 	   return x+y;
 	if((long double) x==y) return y;	/* x=y, return y */
diff --git a/sysdeps/ieee754/ldbl-128ibm/s_remquol.c b/sysdeps/ieee754/ldbl-128ibm/s_remquol.c
index f4777a0..195e108 100644
--- a/sysdeps/ieee754/ldbl-128ibm/s_remquol.c
+++ b/sysdeps/ieee754/ldbl-128ibm/s_remquol.c
@@ -33,20 +33,24 @@ __remquol (long double x, long double y, int *quo)
   int64_t hx,hy;
   u_int64_t sx,lx,ly,qs;
   int cquo;
-
-  GET_LDOUBLE_WORDS64 (hx, lx, x);
-  GET_LDOUBLE_WORDS64 (hy, ly, y);
+  double xhi, xlo, yhi, ylo;
+
+  ldbl_unpack (x, &xhi, &xlo);
+  EXTRACT_WORDS64 (hx, xhi);
+  EXTRACT_WORDS64 (lx, xlo);
+  ldbl_unpack (y, &yhi, &ylo);
+  EXTRACT_WORDS64 (hy, yhi);
+  EXTRACT_WORDS64 (ly, ylo);
   sx = hx & 0x8000000000000000ULL;
   qs = sx ^ (hy & 0x8000000000000000ULL);
   hy &= 0x7fffffffffffffffLL;
   hx &= 0x7fffffffffffffffLL;
 
   /* Purge off exception values.  */
-  if ((hy | (ly & 0x7fffffffffffffff)) == 0)
+  if (hy == 0)
     return (x * y) / (x * y); 			/* y = 0 */
   if ((hx >= 0x7ff0000000000000LL)		/* x not finite */
-      || ((hy >= 0x7ff0000000000000LL)		/* y is NaN */
-	  && (((hy - 0x7ff0000000000000LL) | ly) != 0)))
+      || (hy > 0x7ff0000000000000LL))		/* y is NaN */
     return (x * y) / (x * y);
 
   if (hy <= 0x7fbfffffffffffffLL)
diff --git a/sysdeps/ieee754/ldbl-128ibm/s_scalblnl.c b/sysdeps/ieee754/ldbl-128ibm/s_scalblnl.c
index d752568..03d4597 100644
--- a/sysdeps/ieee754/ldbl-128ibm/s_scalblnl.c
+++ b/sysdeps/ieee754/ldbl-128ibm/s_scalblnl.c
@@ -41,11 +41,15 @@ long double __scalblnl (long double x, long int n)
 {
 	int64_t k,l,hx,lx;
 	union { int64_t i; double d; } u;
-	GET_LDOUBLE_WORDS64(hx,lx,x);
+	double xhi, xlo;
+
+	ldbl_unpack (x, &xhi, &xlo);
+	EXTRACT_WORDS64 (hx, xhi);
+	EXTRACT_WORDS64 (lx, xlo);
 	k = (hx>>52)&0x7ff;		/* extract exponent */
 	l = (lx>>52)&0x7ff;
 	if (k==0) {				/* 0 or subnormal x */
-	    if (((hx|lx)&0x7fffffffffffffffULL)==0) return x; /* +-0 */
+	    if ((hx&0x7fffffffffffffffULL)==0) return x; /* +-0 */
 	    u.i = hx;
 	    u.d *= two54;
 	    hx = u.i;
@@ -61,7 +65,9 @@ long double __scalblnl (long double x, long int n)
 	if (k > 0) {				/* normal result */
 	    hx = (hx&0x800fffffffffffffULL)|(k<<52);
 	    if ((lx & 0x7fffffffffffffffULL) == 0) { /* low part +-0 */
-		SET_LDOUBLE_WORDS64(x,hx,lx);
+		INSERT_WORDS64 (xhi, hx);
+		INSERT_WORDS64 (xlo, lx);
+		x = ldbl_pack (xhi, xlo);
 		return x;
 	    }
 	    if (l == 0) { /* low part subnormal */
@@ -81,14 +87,19 @@ long double __scalblnl (long double x, long int n)
 		u.d *= twom54;
 		lx = u.i;
 	    }
-	    SET_LDOUBLE_WORDS64(x,hx,lx);
+	    INSERT_WORDS64 (xhi, hx);
+	    INSERT_WORDS64 (xlo, lx);
+	    x = ldbl_pack (xhi, xlo);
 	    return x;
 	}
 	if (k <= -54)
 	  return tiny*__copysignl(tiny,x); 	/*underflow*/
 	k += 54;				/* subnormal result */
 	lx &= 0x8000000000000000ULL;
-	SET_LDOUBLE_WORDS64(x,(hx&0x800fffffffffffffULL)|(k<<52),lx);
+	hx &= 0x800fffffffffffffULL;
+	INSERT_WORDS64 (xhi, hx|(k<<52));
+	INSERT_WORDS64 (xlo, lx);
+	x = ldbl_pack (xhi, xlo);
 	return x*twolm54;
 }
 long_double_symbol (libm, __scalblnl, scalblnl);
diff --git a/sysdeps/ieee754/ldbl-128ibm/s_scalbnl.c b/sysdeps/ieee754/ldbl-128ibm/s_scalbnl.c
index bcdb23b..161172d 100644
--- a/sysdeps/ieee754/ldbl-128ibm/s_scalbnl.c
+++ b/sysdeps/ieee754/ldbl-128ibm/s_scalbnl.c
@@ -41,11 +41,15 @@ long double __scalbnl (long double x, int n)
 {
 	int64_t k,l,hx,lx;
 	union { int64_t i; double d; } u;
-	GET_LDOUBLE_WORDS64(hx,lx,x);
+	double xhi, xlo;
+
+	ldbl_unpack (x, &xhi, &xlo);
+	EXTRACT_WORDS64 (hx, xhi);
+	EXTRACT_WORDS64 (lx, xlo);
 	k = (hx>>52)&0x7ff;		/* extract exponent */
 	l = (lx>>52)&0x7ff;
 	if (k==0) {				/* 0 or subnormal x */
-	    if (((hx|lx)&0x7fffffffffffffffULL)==0) return x; /* +-0 */
+	    if ((hx&0x7fffffffffffffffULL)==0) return x; /* +-0 */
 	    u.i = hx;
 	    u.d *= two54;
 	    hx = u.i;
@@ -61,7 +65,9 @@ long double __scalbnl (long double x, int n)
 	if (k > 0) {				/* normal result */
 	    hx = (hx&0x800fffffffffffffULL)|(k<<52);
 	    if ((lx & 0x7fffffffffffffffULL) == 0) { /* low part +-0 */
-		SET_LDOUBLE_WORDS64(x,hx,lx);
+		INSERT_WORDS64 (xhi, hx);
+		INSERT_WORDS64 (xlo, lx);
+		x = ldbl_pack (xhi, xlo);
 		return x;
 	    }
 	    if (l == 0) { /* low part subnormal */
@@ -81,14 +87,19 @@ long double __scalbnl (long double x, int n)
 		u.d *= twom54;
 		lx = u.i;
 	    }
-	    SET_LDOUBLE_WORDS64(x,hx,lx);
+	    INSERT_WORDS64 (xhi, hx);
+	    INSERT_WORDS64 (xlo, lx);
+	    x = ldbl_pack (xhi, xlo);
 	    return x;
 	}
 	if (k <= -54)
 	  return tiny*__copysignl(tiny,x); 	/*underflow*/
 	k += 54;				/* subnormal result */
 	lx &= 0x8000000000000000ULL;
-	SET_LDOUBLE_WORDS64(x,(hx&0x800fffffffffffffULL)|(k<<52),lx);
+	hx &= 0x800fffffffffffffULL;
+	INSERT_WORDS64 (xhi, hx|(k<<52));
+	INSERT_WORDS64 (xlo, lx);
+	x = ldbl_pack (xhi, xlo);
 	return x*twolm54;
 }
 #ifdef IS_IN_libm
diff --git a/sysdeps/ieee754/ldbl-128ibm/s_tanhl.c b/sysdeps/ieee754/ldbl-128ibm/s_tanhl.c
index 138b63c..c63e253 100644
--- a/sysdeps/ieee754/ldbl-128ibm/s_tanhl.c
+++ b/sysdeps/ieee754/ldbl-128ibm/s_tanhl.c
@@ -47,10 +47,12 @@ static const long double one=1.0L, two=2.0L, tiny = 1.0e-300L;
 long double __tanhl(long double x)
 {
 	long double t,z;
-	int64_t jx,ix,lx;
+	int64_t jx,ix;
+	double xhi;
 
     /* High word of |x|. */
-	GET_LDOUBLE_WORDS64(jx,lx,x);
+	xhi = ldbl_high (x);
+	EXTRACT_WORDS64 (jx, xhi);
 	ix = jx&0x7fffffffffffffffLL;
 
     /* x is INF or NaN */
@@ -61,7 +63,7 @@ long double __tanhl(long double x)
 
     /* |x| < 22 */
 	if (ix < 0x4036000000000000LL) {		/* |x|<22 */
-	    if ((ix | (lx&0x7fffffffffffffffLL)) == 0)
+	    if (ix == 0)
 		return x;		/* x == +-0 */
 	    if (ix<0x3c60000000000000LL) 	/* |x|<2**-57 */
 		return x*(one+x);    	/* tanh(small) = small */
diff --git a/sysdeps/powerpc/fpu/libm-test-ulps b/sysdeps/powerpc/fpu/libm-test-ulps
index 6fdace9..3dcc344 100644
--- a/sysdeps/powerpc/fpu/libm-test-ulps
+++ b/sysdeps/powerpc/fpu/libm-test-ulps
@@ -6592,6 +6592,9 @@ float: 1
 ifloat: 1
 ildouble: 2
 ldouble: 2
+Test "tan_towardzero (2)":
+ildouble: 1
+ldouble: 1
 Test "tan_towardzero (3)":
 float: 1
 ifloat: 1

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=eac0b9f9daac0ede19f1689e9a0f0aa5aa3ac811

commit eac0b9f9daac0ede19f1689e9a0f0aa5aa3ac811
Author: Alan Modra <amodra@gmail.com>
Date:   Sat Aug 17 18:24:05 2013 +0930

    PowerPC floating point little-endian [2 of 15]
    http://sourceware.org/ml/libc-alpha/2013-08/msg00082.html
    
    This patch replaces occurrences of GET_LDOUBLE_* and SET_LDOUBLE_*
    macros, and union ieee854_long_double_shape_type in ldbl-128ibm/,
    and a stray one in the 32-bit fpu support.  These files have no
    significant changes apart from rewriting the long double bit access.
    
    	* sysdeps/ieee754/ldbl-128ibm/math_ldbl.h (ldbl_high): Define.
    	* sysdeps/ieee754/ldbl-128ibm/e_acoshl.c (__ieee754_acoshl): Rewrite
    	all uses of ieee854 long double macros and unions.
    	* sysdeps/ieee754/ldbl-128ibm/e_acosl.c (__ieee754_acosl): Likewise.
    	* sysdeps/ieee754/ldbl-128ibm/e_asinl.c (__ieee754_asinl): Likewise.
    	* sysdeps/ieee754/ldbl-128ibm/e_atanhl.c (__ieee754_atanhl): Likewise.
    	* sysdeps/ieee754/ldbl-128ibm/e_coshl.c (__ieee754_coshl): Likewise.
    	* sysdeps/ieee754/ldbl-128ibm/e_log2l.c (__ieee754_log2l): Likewise.
    	* sysdeps/ieee754/ldbl-128ibm/e_rem_pio2l.c (__ieee754_rem_pio2l):
    	Likewise.
    	* sysdeps/ieee754/ldbl-128ibm/e_sinhl.c (__ieee754_sinhl): Likewise.
    	* sysdeps/ieee754/ldbl-128ibm/k_cosl.c (__kernel_cosl): Likewise.
    	* sysdeps/ieee754/ldbl-128ibm/k_sincosl.c (__kernel_sincosl): Likewise.
    	* sysdeps/ieee754/ldbl-128ibm/k_sinl.c (__kernel_sinl): Likewise.
    	* sysdeps/ieee754/ldbl-128ibm/s_asinhl.c (__asinhl): Likewise.
    	* sysdeps/ieee754/ldbl-128ibm/s_atanl.c (__atanl): Likewise.
    	Simplify sign and nan test too.
    	* sysdeps/ieee754/ldbl-128ibm/s_cosl.c (__cosl): Likewise.
    	* sysdeps/ieee754/ldbl-128ibm/s_fabsl.c (__fabsl): Likewise.
    	* sysdeps/ieee754/ldbl-128ibm/s_finitel.c (___finitel): Likewise.
    	* sysdeps/ieee754/ldbl-128ibm/s_fpclassifyl.c (___fpclassifyl):
    	Likewise.
    	* sysdeps/ieee754/ldbl-128ibm/s_isnanl.c (___isnanl): Likewise.
    	* sysdeps/ieee754/ldbl-128ibm/s_issignalingl.c (__issignalingl):
    	Likewise.
    	* sysdeps/ieee754/ldbl-128ibm/s_logbl.c (__logbl): Likewise.
    	* sysdeps/ieee754/ldbl-128ibm/s_signbitl.c (___signbitl): Likewise.
    	* sysdeps/ieee754/ldbl-128ibm/s_sincosl.c (__sincosl): Likewise.
    	* sysdeps/ieee754/ldbl-128ibm/s_sinl.c (__sinl): Likewise.
    	* sysdeps/ieee754/ldbl-128ibm/s_tanl.c (__tanl): Likewise.
    	* sysdeps/powerpc/powerpc32/power7/fpu/s_logbl.c (__logbl): Likewise.

diff --git a/ChangeLog b/ChangeLog
index 8bc1698..38a8b7d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,39 @@
 2013-10-04  Alan Modra  <amodra@gmail.com>
 
+	* sysdeps/ieee754/ldbl-128ibm/math_ldbl.h (ldbl_high): Define.
+	* sysdeps/ieee754/ldbl-128ibm/e_acoshl.c (__ieee754_acoshl): Rewrite
+	all uses of ieee854 long double macros and unions.
+	* sysdeps/ieee754/ldbl-128ibm/e_acosl.c (__ieee754_acosl): Likewise.
+	* sysdeps/ieee754/ldbl-128ibm/e_asinl.c (__ieee754_asinl): Likewise.
+	* sysdeps/ieee754/ldbl-128ibm/e_atanhl.c (__ieee754_atanhl): Likewise.
+	* sysdeps/ieee754/ldbl-128ibm/e_coshl.c (__ieee754_coshl): Likewise.
+	* sysdeps/ieee754/ldbl-128ibm/e_log2l.c (__ieee754_log2l): Likewise.
+	* sysdeps/ieee754/ldbl-128ibm/e_rem_pio2l.c (__ieee754_rem_pio2l):
+	Likewise.
+	* sysdeps/ieee754/ldbl-128ibm/e_sinhl.c (__ieee754_sinhl): Likewise.
+	* sysdeps/ieee754/ldbl-128ibm/k_cosl.c (__kernel_cosl): Likewise.
+	* sysdeps/ieee754/ldbl-128ibm/k_sincosl.c (__kernel_sincosl): Likewise.
+	* sysdeps/ieee754/ldbl-128ibm/k_sinl.c (__kernel_sinl): Likewise.
+	* sysdeps/ieee754/ldbl-128ibm/s_asinhl.c (__asinhl): Likewise.
+	* sysdeps/ieee754/ldbl-128ibm/s_atanl.c (__atanl): Likewise.
+	Simplify sign and nan test too.
+	* sysdeps/ieee754/ldbl-128ibm/s_cosl.c (__cosl): Likewise.
+	* sysdeps/ieee754/ldbl-128ibm/s_fabsl.c (__fabsl): Likewise.
+	* sysdeps/ieee754/ldbl-128ibm/s_finitel.c (___finitel): Likewise.
+	* sysdeps/ieee754/ldbl-128ibm/s_fpclassifyl.c (___fpclassifyl):
+	Likewise.
+	* sysdeps/ieee754/ldbl-128ibm/s_isnanl.c (___isnanl): Likewise.
+	* sysdeps/ieee754/ldbl-128ibm/s_issignalingl.c (__issignalingl):
+	Likewise.
+	* sysdeps/ieee754/ldbl-128ibm/s_logbl.c (__logbl): Likewise.
+	* sysdeps/ieee754/ldbl-128ibm/s_signbitl.c (___signbitl): Likewise.
+	* sysdeps/ieee754/ldbl-128ibm/s_sincosl.c (__sincosl): Likewise.
+	* sysdeps/ieee754/ldbl-128ibm/s_sinl.c (__sinl): Likewise.
+	* sysdeps/ieee754/ldbl-128ibm/s_tanl.c (__tanl): Likewise.
+	* sysdeps/powerpc/powerpc32/power7/fpu/s_logbl.c (__logbl): Likewise.
+
+2013-10-04  Alan Modra  <amodra@gmail.com>
+
 	* stdio-common/printf_size.c (__printf_size): Don't use
 	union ieee854_long_double in fpnum union.
 	* stdio-common/printf_fphex.c (__printf_fphex): Likewise.  Use
diff --git a/sysdeps/ieee754/ldbl-128ibm/e_acoshl.c b/sysdeps/ieee754/ldbl-128ibm/e_acoshl.c
index abc78a3..8a4a5bb 100644
--- a/sysdeps/ieee754/ldbl-128ibm/e_acoshl.c
+++ b/sysdeps/ieee754/ldbl-128ibm/e_acoshl.c
@@ -36,8 +36,12 @@ __ieee754_acoshl(long double x)
 {
 	long double t;
 	int64_t hx;
-	u_int64_t lx;
-	GET_LDOUBLE_WORDS64(hx,lx,x);
+	uint64_t lx;
+	double xhi, xlo;
+
+	ldbl_unpack (x, &xhi, &xlo);
+	EXTRACT_WORDS64 (hx, xhi);
+	EXTRACT_WORDS64 (lx, xlo);
 	if(hx<0x3ff0000000000000LL) {		/* x < 1 */
 	    return (x-x)/(x-x);
 	} else if(hx >=0x41b0000000000000LL) {	/* x > 2**28 */
diff --git a/sysdeps/ieee754/ldbl-128ibm/e_acosl.c b/sysdeps/ieee754/ldbl-128ibm/e_acosl.c
index 5d2af30..8663993 100644
--- a/sysdeps/ieee754/ldbl-128ibm/e_acosl.c
+++ b/sysdeps/ieee754/ldbl-128ibm/e_acosl.c
@@ -151,26 +151,25 @@ static const long double
 long double
 __ieee754_acosl (long double x)
 {
-  long double z, r, w, p, q, s, t, f2;
-  ieee854_long_double_shape_type u;
+  long double a, z, r, w, p, q, s, t, f2;
 
-  u.value = __builtin_fabsl (x);
-  if (u.value == 1.0L)
+  a = __builtin_fabsl (x);
+  if (a == 1.0L)
     {
       if (x > 0.0L)
 	return 0.0;		/* acos(1) = 0  */
       else
 	return (2.0 * pio2_hi) + (2.0 * pio2_lo);	/* acos(-1)= pi */
     }
-  else if (u.value > 1.0L)
+  else if (a > 1.0L)
     {
       return (x - x) / (x - x);	/* acos(|x| > 1) is NaN */
     }
-  if (u.value < 0.5L)
+  if (a < 0.5L)
     {
-      if (u.value < 6.938893903907228e-18L)	/* |x| < 2**-57 */
+      if (a < 6.938893903907228e-18L)	/* |x| < 2**-57 */
 	return pio2_hi + pio2_lo;
-      if (u.value < 0.4375L)
+      if (a < 0.4375L)
 	{
 	  /* Arcsine of x.  */
 	  z = x * x;
@@ -199,7 +198,7 @@ __ieee754_acosl (long double x)
 	  return z;
 	}
       /* .4375 <= |x| < .5 */
-      t = u.value - 0.4375L;
+      t = a - 0.4375L;
       p = ((((((((((P10 * t
 		    + P9) * t
 		   + P8) * t
@@ -230,9 +229,9 @@ __ieee754_acosl (long double x)
 	r = acosr4375 + r;
       return r;
     }
-  else if (u.value < 0.625L)
+  else if (a < 0.625L)
     {
-      t = u.value - 0.5625L;
+      t = a - 0.5625L;
       p = ((((((((((rS10 * t
 		    + rS9) * t
 		   + rS8) * t
@@ -264,7 +263,9 @@ __ieee754_acosl (long double x)
     }
   else
     {				/* |x| >= .625 */
-      z = (one - u.value) * 0.5;
+      double shi, slo;
+
+      z = (one - a) * 0.5;
       s = __ieee754_sqrtl (z);
       /* Compute an extended precision square root from
 	 the Newton iteration  s -> 0.5 * (s + z / s).
@@ -273,12 +274,11 @@ __ieee754_acosl (long double x)
 	  Express s = f1 + f2 where f1 * f1 is exactly representable.
 	  w = (z - s^2)/2s = (z - f1^2 - 2 f1 f2 - f2^2)/2s .
 	  s + w has extended precision.  */
-      u.value = s;
-      u.parts32.w2 = 0;
-      u.parts32.w3 = 0;
-      f2 = s - u.value;
-      w = z - u.value * u.value;
-      w = w - 2.0 * u.value * f2;
+      ldbl_unpack (s, &shi, &slo);
+      a = shi;
+      f2 = slo;
+      w = z - a * a;
+      w = w - 2.0 * a * f2;
       w = w - f2 * f2;
       w = w / (2.0 * s);
       /* Arcsine of s.  */
diff --git a/sysdeps/ieee754/ldbl-128ibm/e_asinl.c b/sysdeps/ieee754/ldbl-128ibm/e_asinl.c
index b395439..99a5b85 100644
--- a/sysdeps/ieee754/ldbl-128ibm/e_asinl.c
+++ b/sysdeps/ieee754/ldbl-128ibm/e_asinl.c
@@ -131,19 +131,18 @@ static const long double
 long double
 __ieee754_asinl (long double x)
 {
-  long double t, w, p, q, c, r, s;
+  long double a, t, w, p, q, c, r, s;
   int flag;
-  ieee854_long_double_shape_type u;
 
   flag = 0;
-  u.value = __builtin_fabsl (x);
-  if (u.value == 1.0L)	/* |x|>= 1 */
+  a = __builtin_fabsl (x);
+  if (a == 1.0L)	/* |x|>= 1 */
     return x * pio2_hi + x * pio2_lo;	/* asin(1)=+-pi/2 with inexact */
-  else if (u.value >= 1.0L)
+  else if (a >= 1.0L)
     return (x - x) / (x - x);	/* asin(|x|>1) is NaN */
-  else if (u.value < 0.5L)
+  else if (a < 0.5L)
     {
-      if (u.value < 6.938893903907228e-18L) /* |x| < 2**-57 */
+      if (a < 6.938893903907228e-18L) /* |x| < 2**-57 */
 	{
 	  if (huge + x > one)
 	    return x;		/* return x with inexact if x!=0 */
@@ -155,9 +154,9 @@ __ieee754_asinl (long double x)
 	  flag = 1;
 	}
     }
-  else if (u.value < 0.625L)
+  else if (a < 0.625L)
     {
-      t = u.value - 0.5625;
+      t = a - 0.5625;
       p = ((((((((((rS10 * t
 		    + rS9) * t
 		   + rS8) * t
@@ -190,7 +189,7 @@ __ieee754_asinl (long double x)
   else
     {
       /* 1 > |x| >= 0.625 */
-      w = one - u.value;
+      w = one - a;
       t = w * 0.5;
     }
 
@@ -223,17 +222,14 @@ __ieee754_asinl (long double x)
     }
 
   s = __ieee754_sqrtl (t);
-  if (u.value > 0.975L)
+  if (a > 0.975L)
     {
       w = p / q;
       t = pio2_hi - (2.0 * (s + s * w) - pio2_lo);
     }
   else
     {
-      u.value = s;
-      u.parts32.w3 = 0;
-      u.parts32.w2 = 0;
-      w = u.value;
+      w = ldbl_high (s);
       c = (t - w * w) / (s + w);
       r = p / q;
       p = 2.0 * s * r - (pio2_lo - 2.0 * c);
diff --git a/sysdeps/ieee754/ldbl-128ibm/e_atanhl.c b/sysdeps/ieee754/ldbl-128ibm/e_atanhl.c
index f35182f..29f2e92 100644
--- a/sysdeps/ieee754/ldbl-128ibm/e_atanhl.c
+++ b/sysdeps/ieee754/ldbl-128ibm/e_atanhl.c
@@ -40,8 +40,10 @@ __ieee754_atanhl(long double x)
 {
 	long double t;
 	int64_t hx,ix;
-	u_int64_t lx __attribute__ ((unused));
-	GET_LDOUBLE_WORDS64(hx,lx,x);
+	double xhi;
+
+	xhi = ldbl_high (x);
+	EXTRACT_WORDS64 (hx, xhi);
 	ix = hx&0x7fffffffffffffffLL;
 	if (ix >= 0x3ff0000000000000LL) { /* |x|>=1 */
 	    if (ix > 0x3ff0000000000000LL)
diff --git a/sysdeps/ieee754/ldbl-128ibm/e_coshl.c b/sysdeps/ieee754/ldbl-128ibm/e_coshl.c
index 3e8e187..05683bc 100644
--- a/sysdeps/ieee754/ldbl-128ibm/e_coshl.c
+++ b/sysdeps/ieee754/ldbl-128ibm/e_coshl.c
@@ -41,9 +41,11 @@ __ieee754_coshl (long double x)
 {
 	long double t,w;
 	int64_t ix;
+	double xhi;
 
     /* High word of |x|. */
-	GET_LDOUBLE_MSW64(ix,x);
+	xhi = ldbl_high (x);
+	EXTRACT_WORDS64 (ix, xhi);
 	ix &= 0x7fffffffffffffffLL;
 
     /* x is INF or NaN */
diff --git a/sysdeps/ieee754/ldbl-128ibm/e_log2l.c b/sysdeps/ieee754/ldbl-128ibm/e_log2l.c
index f0098f6..323ded0 100644
--- a/sysdeps/ieee754/ldbl-128ibm/e_log2l.c
+++ b/sysdeps/ieee754/ldbl-128ibm/e_log2l.c
@@ -177,11 +177,13 @@ __ieee754_log2l (x)
   long double z;
   long double y;
   int e;
-  int64_t hx, lx;
+  int64_t hx;
+  double xhi;
 
 /* Test for domain */
-  GET_LDOUBLE_WORDS64 (hx, lx, x);
-  if (((hx & 0x7fffffffffffffffLL) | (lx & 0x7fffffffffffffffLL)) == 0)
+  xhi = ldbl_high (x);
+  EXTRACT_WORDS64 (hx, xhi);
+  if ((hx & 0x7fffffffffffffffLL) == 0)
     return (-1.0L / (x - x));
   if (hx < 0)
     return (x - x) / (x - x);
diff --git a/sysdeps/ieee754/ldbl-128ibm/e_rem_pio2l.c b/sysdeps/ieee754/ldbl-128ibm/e_rem_pio2l.c
index 8885def..36bc032 100644
--- a/sysdeps/ieee754/ldbl-128ibm/e_rem_pio2l.c
+++ b/sysdeps/ieee754/ldbl-128ibm/e_rem_pio2l.c
@@ -200,10 +200,11 @@ int32_t __ieee754_rem_pio2l(long double x, long double *y)
   double tx[8];
   int exp;
   int64_t n, ix, hx, ixd;
-  u_int64_t lx __attribute__ ((unused));
   u_int64_t lxd;
+  double xhi;
 
-  GET_LDOUBLE_WORDS64 (hx, lx, x);
+  xhi = ldbl_high (x);
+  EXTRACT_WORDS64 (hx, xhi);
   ix = hx & 0x7fffffffffffffffLL;
   if (ix <= 0x3fe921fb54442d10LL)	/* x in <-pi/4, pi/4> */
     {
diff --git a/sysdeps/ieee754/ldbl-128ibm/e_sinhl.c b/sysdeps/ieee754/ldbl-128ibm/e_sinhl.c
index 4e8481c..1790bef 100644
--- a/sysdeps/ieee754/ldbl-128ibm/e_sinhl.c
+++ b/sysdeps/ieee754/ldbl-128ibm/e_sinhl.c
@@ -38,9 +38,11 @@ __ieee754_sinhl(long double x)
 {
 	long double t,w,h;
 	int64_t ix,jx;
+	double xhi;
 
     /* High word of |x|. */
-	GET_LDOUBLE_MSW64(jx,x);
+	xhi = ldbl_high (x);
+	EXTRACT_WORDS64 (jx, xhi);
 	ix = jx&0x7fffffffffffffffLL;
 
     /* x is INF or NaN */
diff --git a/sysdeps/ieee754/ldbl-128ibm/k_cosl.c b/sysdeps/ieee754/ldbl-128ibm/k_cosl.c
index 0b81782..046f3b5 100644
--- a/sysdeps/ieee754/ldbl-128ibm/k_cosl.c
+++ b/sysdeps/ieee754/ldbl-128ibm/k_cosl.c
@@ -81,8 +81,11 @@ __kernel_cosl(long double x, long double y)
 {
   long double h, l, z, sin_l, cos_l_m1;
   int64_t ix;
-  u_int32_t tix, hix, index;
-  GET_LDOUBLE_MSW64 (ix, x);
+  uint32_t tix, hix, index;
+  double xhi, hhi;
+
+  xhi = ldbl_high (x);
+  EXTRACT_WORDS64 (ix, xhi);
   tix = ((u_int64_t)ix) >> 32;
   tix &= ~0x80000000;			/* tix = |x|'s high 32 bits */
   if (tix < 0x3fc30000)			/* |x| < 0.1484375 */
@@ -136,7 +139,8 @@ __kernel_cosl(long double x, long double y)
 	case 2: index = (hix - 0x3fc30000) >> 14; break;
 	}
 */
-      SET_LDOUBLE_WORDS64(h, ((u_int64_t)hix) << 32, 0);
+      INSERT_WORDS64 (hhi, ((uint64_t)hix) << 32);
+      h = hhi;
       l = y - (h - x);
       z = l * l;
       sin_l = l*(ONE+z*(SSIN1+z*(SSIN2+z*(SSIN3+z*(SSIN4+z*SSIN5)))));
diff --git a/sysdeps/ieee754/ldbl-128ibm/k_sincosl.c b/sysdeps/ieee754/ldbl-128ibm/k_sincosl.c
index fc1ead6..3ba9d7e 100644
--- a/sysdeps/ieee754/ldbl-128ibm/k_sincosl.c
+++ b/sysdeps/ieee754/ldbl-128ibm/k_sincosl.c
@@ -100,9 +100,12 @@ __kernel_sincosl(long double x, long double y, long double *sinx, long double *c
 {
   long double h, l, z, sin_l, cos_l_m1;
   int64_t ix;
-  u_int32_t tix, hix, index;
-  GET_LDOUBLE_MSW64 (ix, x);
-  tix = ((u_int64_t)ix) >> 32;
+  uint32_t tix, hix, index;
+  double xhi, hhi;
+
+  xhi = ldbl_high (x);
+  EXTRACT_WORDS64 (ix, xhi);
+  tix = ((uint64_t)ix) >> 32;
   tix &= ~0x80000000;			/* tix = |x|'s high 32 bits */
   if (tix < 0x3fc30000)			/* |x| < 0.1484375 */
     {
@@ -164,7 +167,8 @@ __kernel_sincosl(long double x, long double y, long double *sinx, long double *c
 	case 2: index = (hix - 0x3fc30000) >> 14; break;
 	}
 */
-      SET_LDOUBLE_WORDS64(h, ((u_int64_t)hix) << 32, 0);
+      INSERT_WORDS64 (hhi, ((uint64_t)hix) << 32);
+      h = hhi;
       if (iy)
 	l = y - (h - x);
       else
diff --git a/sysdeps/ieee754/ldbl-128ibm/k_sinl.c b/sysdeps/ieee754/ldbl-128ibm/k_sinl.c
index f17c0ae..b12ea13 100644
--- a/sysdeps/ieee754/ldbl-128ibm/k_sinl.c
+++ b/sysdeps/ieee754/ldbl-128ibm/k_sinl.c
@@ -82,7 +82,10 @@ __kernel_sinl(long double x, long double y, int iy)
   long double h, l, z, sin_l, cos_l_m1;
   int64_t ix;
   u_int32_t tix, hix, index;
-  GET_LDOUBLE_MSW64 (ix, x);
+  double xhi, hhi;
+
+  xhi = ldbl_high (x);
+  EXTRACT_WORDS64 (ix, xhi);
   tix = ((u_int64_t)ix) >> 32;
   tix &= ~0x80000000;			/* tix = |x|'s high 32 bits */
   if (tix < 0x3fc30000)			/* |x| < 0.1484375 */
@@ -132,7 +135,8 @@ __kernel_sinl(long double x, long double y, int iy)
 	case 2: index = (hix - 0x3fc30000) >> 14; break;
 	}
 */
-      SET_LDOUBLE_WORDS64(h, ((u_int64_t)hix) << 32, 0);
+      INSERT_WORDS64 (hhi, ((uint64_t)hix) << 32);
+      h = hhi;
       if (iy)
 	l = (ix < 0 ? -y : y) - (h - x);
       else
diff --git a/sysdeps/ieee754/ldbl-128ibm/math_ldbl.h b/sysdeps/ieee754/ldbl-128ibm/math_ldbl.h
index 4bb49c8..8adb081 100644
--- a/sysdeps/ieee754/ldbl-128ibm/math_ldbl.h
+++ b/sysdeps/ieee754/ldbl-128ibm/math_ldbl.h
@@ -192,6 +192,9 @@ default_ldbl_unpack (long double l, double *a, double *aa)
 # define ldbl_unpack default_ldbl_unpack
 #endif
 
+/* Extract high double.  */
+#define ldbl_high(x) ((double) x)
+
 /* Convert a finite long double to canonical form.
    Does not handle +/-Inf properly.  */
 static inline void
diff --git a/sysdeps/ieee754/ldbl-128ibm/s_asinhl.c b/sysdeps/ieee754/ldbl-128ibm/s_asinhl.c
index a833457..63c6edb 100644
--- a/sysdeps/ieee754/ldbl-128ibm/s_asinhl.c
+++ b/sysdeps/ieee754/ldbl-128ibm/s_asinhl.c
@@ -38,7 +38,10 @@ long double __asinhl(long double x)
 {
 	long double t,w;
 	int64_t hx,ix;
-	GET_LDOUBLE_MSW64(hx,x);
+	double xhi;
+
+	xhi = ldbl_high (x);
+	EXTRACT_WORDS64 (hx, xhi);
 	ix = hx&0x7fffffffffffffffLL;
 	if(ix>=0x7ff0000000000000LL) return x+x;	/* x is inf or NaN */
 	if(ix< 0x3e20000000000000LL) {	/* |x|<2**-29 */
diff --git a/sysdeps/ieee754/ldbl-128ibm/s_atanl.c b/sysdeps/ieee754/ldbl-128ibm/s_atanl.c
index 2a36d16..41dde23 100644
--- a/sysdeps/ieee754/ldbl-128ibm/s_atanl.c
+++ b/sysdeps/ieee754/ldbl-128ibm/s_atanl.c
@@ -173,23 +173,20 @@ static const long double
 long double
 __atanl (long double x)
 {
-  int k, sign;
+  int32_t k, sign, lx;
   long double t, u, p, q;
-  ieee854_long_double_shape_type s;
+  double xhi;
 
-  s.value = x;
-  k = s.parts32.w0;
-  if (k & 0x80000000)
-    sign = 1;
-  else
-    sign = 0;
+  xhi = ldbl_high (x);
+  EXTRACT_WORDS (k, lx, xhi);
+  sign = k & 0x80000000;
 
   /* Check for IEEE special cases.  */
   k &= 0x7fffffff;
   if (k >= 0x7ff00000)
     {
       /* NaN. */
-      if ((k & 0xfffff) | s.parts32.w1 )
+      if (((k - 0x7ff00000) | lx) != 0)
 	return (x + x);
 
       /* Infinity. */
diff --git a/sysdeps/ieee754/ldbl-128ibm/s_cosl.c b/sysdeps/ieee754/ldbl-128ibm/s_cosl.c
index 2314839..54c6cc7 100644
--- a/sysdeps/ieee754/ldbl-128ibm/s_cosl.c
+++ b/sysdeps/ieee754/ldbl-128ibm/s_cosl.c
@@ -53,9 +53,11 @@ long double __cosl(long double x)
 {
 	long double y[2],z=0.0L;
 	int64_t n, ix;
+	double xhi;
 
     /* High word of x. */
-	GET_LDOUBLE_MSW64(ix,x);
+	xhi = ldbl_high (x);
+	EXTRACT_WORDS64 (ix, xhi);
 
     /* |x| ~< pi/4 */
 	ix &= 0x7fffffffffffffffLL;
diff --git a/sysdeps/ieee754/ldbl-128ibm/s_fabsl.c b/sysdeps/ieee754/ldbl-128ibm/s_fabsl.c
index 99146d8..c801c97 100644
--- a/sysdeps/ieee754/ldbl-128ibm/s_fabsl.c
+++ b/sysdeps/ieee754/ldbl-128ibm/s_fabsl.c
@@ -29,10 +29,16 @@ static char rcsid[] = "$NetBSD: $";
 long double __fabsl(long double x)
 {
 	u_int64_t hx, lx;
-	GET_LDOUBLE_WORDS64(hx,lx,x);
+	double xhi, xlo;
+
+	ldbl_unpack (x, &xhi, &xlo);
+	EXTRACT_WORDS64 (hx, xhi);
+	EXTRACT_WORDS64 (lx, xlo);
 	lx = lx ^ ( hx & 0x8000000000000000LL );
 	hx = hx & 0x7fffffffffffffffLL;
-	SET_LDOUBLE_WORDS64(x,hx,lx);
+	INSERT_WORDS64 (xhi, hx);
+	INSERT_WORDS64 (xlo, lx);
+	x = ldbl_pack (xhi, xlo);
 	return x;
 }
 long_double_symbol (libm, __fabsl, fabsl);
diff --git a/sysdeps/ieee754/ldbl-128ibm/s_finitel.c b/sysdeps/ieee754/ldbl-128ibm/s_finitel.c
index 8edb341..7b4655f 100644
--- a/sysdeps/ieee754/ldbl-128ibm/s_finitel.c
+++ b/sysdeps/ieee754/ldbl-128ibm/s_finitel.c
@@ -29,10 +29,14 @@ static char rcsid[] = "$NetBSD: $";
 int
 ___finitel (long double x)
 {
-	int64_t hx;
-	GET_LDOUBLE_MSW64(hx,x);
-	return (int)((u_int64_t)((hx&0x7fffffffffffffffLL)
-				 -0x7ff0000000000000LL)>>63);
+  uint64_t hx;
+  double xhi;
+
+  xhi = ldbl_high (x);
+  EXTRACT_WORDS64 (hx, xhi);
+  hx &= 0x7fffffffffffffffLL;
+  hx -= 0x7ff0000000000000LL;
+  return hx >> 63;
 }
 hidden_ver (___finitel, __finitel)
 weak_alias (___finitel, ____finitel)
diff --git a/sysdeps/ieee754/ldbl-128ibm/s_fpclassifyl.c b/sysdeps/ieee754/ldbl-128ibm/s_fpclassifyl.c
index f4a90b0..90586e8 100644
--- a/sysdeps/ieee754/ldbl-128ibm/s_fpclassifyl.c
+++ b/sysdeps/ieee754/ldbl-128ibm/s_fpclassifyl.c
@@ -46,8 +46,10 @@ ___fpclassifyl (long double x)
 {
   u_int64_t hx, lx;
   int retval = FP_NORMAL;
+  double xhi, xlo;
 
-  GET_LDOUBLE_WORDS64 (hx, lx, x);
+  ldbl_unpack (x, &xhi, &xlo);
+  EXTRACT_WORDS64 (hx, xhi);
   if ((hx & 0x7ff0000000000000ULL) == 0x7ff0000000000000ULL) {
       /* +/-NaN or +/-Inf */
       if (hx & 0x000fffffffffffffULL) {
@@ -65,6 +67,7 @@ ___fpclassifyl (long double x)
 	      retval = FP_NORMAL;
 	  } else {
 	      if ((hx & 0x7ff0000000000000ULL) == 0x0360000000000000ULL) {
+		  EXTRACT_WORDS64 (lx, xlo);
 		  if ((lx & 0x7fffffffffffffff)	/* lower is non-zero */
 		  && ((lx^hx) & 0x8000000000000000ULL)) { /* and sign differs */
 		      /* +/- denormal */
diff --git a/sysdeps/ieee754/ldbl-128ibm/s_isnanl.c b/sysdeps/ieee754/ldbl-128ibm/s_isnanl.c
index 264dec7..d12f1d3 100644
--- a/sysdeps/ieee754/ldbl-128ibm/s_isnanl.c
+++ b/sysdeps/ieee754/ldbl-128ibm/s_isnanl.c
@@ -29,12 +29,14 @@ static char rcsid[] = "$NetBSD: $";
 int
 ___isnanl (long double x)
 {
-	int64_t hx;
-	int64_t lx __attribute__ ((unused));
-	GET_LDOUBLE_WORDS64(hx,lx,x);
-	hx &= 0x7fffffffffffffffLL;
-	hx = 0x7ff0000000000000LL - hx;
-	return (int)((u_int64_t)hx>>63);
+  uint64_t hx;
+  double xhi;
+
+  xhi = ldbl_high (x);
+  EXTRACT_WORDS64 (hx, xhi);
+  hx &= 0x7fffffffffffffffLL;
+  hx = 0x7ff0000000000000LL - hx;
+  return (int) (hx >> 63);
 }
 hidden_ver (___isnanl, __isnanl)
 #ifndef IS_IN_libm
diff --git a/sysdeps/ieee754/ldbl-128ibm/s_issignalingl.c b/sysdeps/ieee754/ldbl-128ibm/s_issignalingl.c
index 96fab1a..bdd58f8 100644
--- a/sysdeps/ieee754/ldbl-128ibm/s_issignalingl.c
+++ b/sysdeps/ieee754/ldbl-128ibm/s_issignalingl.c
@@ -22,10 +22,13 @@
 int
 __issignalingl (long double x)
 {
-  u_int64_t xi;
+  uint64_t xi;
   /* For inspecting NaN status, we only have to look at the first of the pair
      of IEEE 754 64-bit precision numbers.  */
-  GET_LDOUBLE_MSW64 (xi, x);
+  double xhi;
+
+  xhi = ldbl_high (x);
+  EXTRACT_WORDS64 (xi, xhi);
 #ifdef HIGH_ORDER_BIT_IS_SET_FOR_SNAN
 # error untested
   /* We only have to care about the high-order bit of x's significand, because
diff --git a/sysdeps/ieee754/ldbl-128ibm/s_logbl.c b/sysdeps/ieee754/ldbl-128ibm/s_logbl.c
index 6cbfcfa..e140288 100644
--- a/sysdeps/ieee754/ldbl-128ibm/s_logbl.c
+++ b/sysdeps/ieee754/ldbl-128ibm/s_logbl.c
@@ -27,9 +27,10 @@ long double
 __logbl (long double x)
 {
   int64_t hx, rhx;
-  int64_t lx __attribute__ ((unused));
+  double xhi;
 
-  GET_LDOUBLE_WORDS64 (hx, lx, x);
+  xhi = ldbl_high (x);
+  EXTRACT_WORDS64 (hx, xhi);
   hx &= 0x7fffffffffffffffLL;	/* high |x| */
   if (hx == 0)
     return -1.0 / fabs (x);
diff --git a/sysdeps/ieee754/ldbl-128ibm/s_signbitl.c b/sysdeps/ieee754/ldbl-128ibm/s_signbitl.c
index ee4aea6..aecb1fd 100644
--- a/sysdeps/ieee754/ldbl-128ibm/s_signbitl.c
+++ b/sysdeps/ieee754/ldbl-128ibm/s_signbitl.c
@@ -25,8 +25,10 @@ int
 ___signbitl (long double x)
 {
   int64_t e;
+  double xhi;
 
-  GET_LDOUBLE_MSW64 (e, x);
+  xhi = ldbl_high (x);
+  EXTRACT_WORDS64 (e, xhi);
   return e < 0;
 }
 #ifdef IS_IN_libm
diff --git a/sysdeps/ieee754/ldbl-128ibm/s_sincosl.c b/sysdeps/ieee754/ldbl-128ibm/s_sincosl.c
index 3b1e547..a9e2f3d 100644
--- a/sysdeps/ieee754/ldbl-128ibm/s_sincosl.c
+++ b/sysdeps/ieee754/ldbl-128ibm/s_sincosl.c
@@ -27,9 +27,11 @@ void
 __sincosl (long double x, long double *sinx, long double *cosx)
 {
   int64_t ix;
+  double xhi;
 
   /* High word of x. */
-  GET_LDOUBLE_MSW64 (ix, x);
+  xhi = ldbl_high (x);
+  EXTRACT_WORDS64 (ix, xhi);
 
   /* |x| ~< pi/4 */
   ix &= 0x7fffffffffffffffLL;
diff --git a/sysdeps/ieee754/ldbl-128ibm/s_sinl.c b/sysdeps/ieee754/ldbl-128ibm/s_sinl.c
index 6fec16f..087921a 100644
--- a/sysdeps/ieee754/ldbl-128ibm/s_sinl.c
+++ b/sysdeps/ieee754/ldbl-128ibm/s_sinl.c
@@ -53,9 +53,11 @@ long double __sinl(long double x)
 {
 	long double y[2],z=0.0L;
 	int64_t n, ix;
+	double xhi;
 
     /* High word of x. */
-	GET_LDOUBLE_MSW64(ix,x);
+	xhi = ldbl_high (x);
+	EXTRACT_WORDS64 (ix, xhi);
 
     /* |x| ~< pi/4 */
 	ix &= 0x7fffffffffffffffLL;
diff --git a/sysdeps/ieee754/ldbl-128ibm/s_tanl.c b/sysdeps/ieee754/ldbl-128ibm/s_tanl.c
index 9967d0c..66b8a06 100644
--- a/sysdeps/ieee754/ldbl-128ibm/s_tanl.c
+++ b/sysdeps/ieee754/ldbl-128ibm/s_tanl.c
@@ -53,9 +53,11 @@ long double __tanl(long double x)
 {
 	long double y[2],z=0.0L;
 	int64_t n, ix;
+	double xhi;
 
     /* High word of x. */
-	GET_LDOUBLE_MSW64(ix,x);
+	xhi = ldbl_high (x);
+	EXTRACT_WORDS64 (ix, xhi);
 
     /* |x| ~< pi/4 */
 	ix &= 0x7fffffffffffffffLL;
diff --git a/sysdeps/powerpc/powerpc32/power7/fpu/s_logbl.c b/sysdeps/powerpc/powerpc32/power7/fpu/s_logbl.c
index e008ed0..1c82577 100644
--- a/sysdeps/powerpc/powerpc32/power7/fpu/s_logbl.c
+++ b/sysdeps/powerpc/powerpc32/power7/fpu/s_logbl.c
@@ -35,14 +35,14 @@ static const union {
 long double
 __logbl (long double x)
 {
-  double xh, xl;
+  double xh;
   double ret;
 
   if (__builtin_expect (x == 0.0L, 0))
     /* Raise FE_DIVBYZERO and return -HUGE_VAL[LF].  */
     return -1.0L / __builtin_fabsl (x);
 
-  ldbl_unpack (x, &xh, &xl);
+  xh = ldbl_high (x);
   /* ret = x & 0x7ff0000000000000;  */
   asm (
     "xxland %x0,%x1,%x2\n"
@@ -58,9 +58,9 @@ __logbl (long double x)
     {
       /* POSIX specifies that denormal number is treated as
          though it were normalized.  */
-      int64_t lx, hx;
+      int64_t hx;
 
-      GET_LDOUBLE_WORDS64 (hx, lx, x);
+      EXTRACT_WORDS64 (hx, xh);
       return (long double) (-1023 - (__builtin_clzll (hx) - 12));
     }
   /* Test to avoid logb_downward (0.0) == -0.0.  */

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=1157aba3b996ce427cc4099d0572dcc2b630fb76

commit 1157aba3b996ce427cc4099d0572dcc2b630fb76
Author: Alan Modra <amodra@gmail.com>
Date:   Sat Aug 17 18:21:58 2013 +0930

    PowerPC floating point little-endian [1 of 15]
    http://sourceware.org/ml/libc-alpha/2013-08/msg00081.html
    
    This is the first of a series of patches to ban ieee854_long_double
    and the ieee854_long_double macros when using IBM long double.  union
    ieee854_long_double just isn't correct for IBM long double, especially
    when little-endian, and pretending it is OK has allowed a number of
    bugs to remain undetected in sysdeps/ieee754/ldbl-128ibm/.
    
    This changes the few places in generic code that use it.
    
    	* stdio-common/printf_size.c (__printf_size): Don't use
    	union ieee854_long_double in fpnum union.
    	* stdio-common/printf_fphex.c (__printf_fphex): Likewise.  Use
    	signbit macro to retrieve sign from long double.
    	* stdio-common/printf_fp.c (___printf_fp): Use signbit macro to
    	retrieve sign from long double.
    	* sysdeps/ieee754/ldbl-128ibm/printf_fphex.c: Adjust for fpnum change.
    	* sysdeps/ieee754/ldbl-128/printf_fphex.c: Likewise.
    	* sysdeps/ieee754/ldbl-96/printf_fphex.c: Likewise.
    	* sysdeps/x86_64/fpu/printf_fphex.c: Likewise.
    	* math/test-misc.c (main): Don't use union ieee854_long_double.
    ports/
    	* sysdeps/ia64/fpu/printf_fphex.c: Adjust for fpnum change.

diff --git a/ChangeLog b/ChangeLog
index 55abf03..8bc1698 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,19 @@
 2013-10-04  Alan Modra  <amodra@gmail.com>
 
+	* stdio-common/printf_size.c (__printf_size): Don't use
+	union ieee854_long_double in fpnum union.
+	* stdio-common/printf_fphex.c (__printf_fphex): Likewise.  Use
+	signbit macro to retrieve sign from long double.
+	* stdio-common/printf_fp.c (___printf_fp): Use signbit macro to
+	retrieve sign from long double.
+	* sysdeps/ieee754/ldbl-128ibm/printf_fphex.c: Adjust for fpnum change.
+	* sysdeps/ieee754/ldbl-128/printf_fphex.c: Likewise.
+	* sysdeps/ieee754/ldbl-96/printf_fphex.c: Likewise.
+	* sysdeps/x86_64/fpu/printf_fphex.c: Likewise.
+	* math/test-misc.c (main): Don't use union ieee854_long_double.
+
+2013-10-04  Alan Modra  <amodra@gmail.com>
+
 	[BZ #15680]
 	* sysdeps/ieee754/ldbl-128ibm/e_rem_pio2l.c: Comment fix.
 	* sysdeps/ieee754/ldbl-128ibm/printf_fphex.c
diff --git a/math/test-misc.c b/math/test-misc.c
index 27d673b..f5276eb 100644
--- a/math/test-misc.c
+++ b/math/test-misc.c
@@ -722,300 +722,161 @@ main (void)
 
 #ifndef NO_LONG_DOUBLE
   {
-    union ieee854_long_double v1;
-    union ieee854_long_double v2;
-    long double ld;
+    long double v1, v2;
 
-    v1.d = ld = LDBL_MIN;
-    if (fpclassify (ld) != FP_NORMAL)
+    v1 = LDBL_MIN;
+    if (fpclassify (v1) != FP_NORMAL)
       {
-	printf ("fpclassify (LDBL_MIN) failed: %d\n", fpclassify (ld));
+	printf ("fpclassify (LDBL_MIN) failed: %d (%La)\n",
+		fpclassify (v1), v1);
 	result = 1;
       }
-    ld = nextafterl (ld, LDBL_MIN / 2.0);
-    if (fpclassify (ld) != FP_SUBNORMAL)
+    v2 = nextafterl (v1, LDBL_MIN / 2.0);
+    if (fpclassify (v2) != FP_SUBNORMAL)
       {
 	printf ("fpclassify (LDBL_MIN-epsilon) failed: %d (%La)\n",
-		fpclassify (ld), ld);
+		fpclassify (v2), v2);
 	result = 1;
       }
-    v2.d = ld = nextafterl (ld, LDBL_MIN);
-    if (fpclassify (ld) != FP_NORMAL)
+    v2 = nextafterl (v2, LDBL_MIN);
+    if (fpclassify (v2) != FP_NORMAL)
       {
 	printf ("fpclassify (LDBL_MIN-epsilon+epsilon) failed: %d (%La)\n",
-		fpclassify (ld), ld);
+		fpclassify (v2), v2);
 	result = 1;
       }
 
-    if (v1.ieee.mantissa0 != v2.ieee.mantissa0)
+    if (v1 != v2)
       {
-	printf ("LDBL_MIN: mantissa0 differs: %8x vs %8x\n",
-		v1.ieee.mantissa0, v2.ieee.mantissa0);
-	result = 1;
-      }
-    if (v1.ieee.mantissa1 != v2.ieee.mantissa1)
-      {
-	printf ("LDBL_MIN: mantissa1 differs: %8x vs %8x\n",
-		v1.ieee.mantissa1, v2.ieee.mantissa1);
-	result = 1;
-      }
-    if (v1.ieee.exponent != v2.ieee.exponent)
-      {
-	printf ("LDBL_MIN: exponent differs: %4x vs %4x\n",
-		v1.ieee.exponent, v2.ieee.exponent);
-	result = 1;
-      }
-    if (v1.ieee.negative != v2.ieee.negative)
-      {
-	printf ("LDBL_MIN: negative differs: %d vs %d\n",
-		v1.ieee.negative, v2.ieee.negative);
+	printf ("LDBL_MIN-epsilon+epsilon != LDBL_MIN: %La vs %La\n", v2, v1);
 	result = 1;
       }
 
-    v1.d = ld = -LDBL_MIN;
-    if (fpclassify (ld) != FP_NORMAL)
+    v1 = -LDBL_MIN;
+    if (fpclassify (v1) != FP_NORMAL)
       {
-	printf ("fpclassify (-LDBL_MIN) failed: %d\n", fpclassify (ld));
+	printf ("fpclassify (-LDBL_MIN) failed: %d (%La)\n",
+		fpclassify (v1), v1);
 	result = 1;
       }
-    ld = nextafterl (ld, -LDBL_MIN / 2.0);
-    if (fpclassify (ld) != FP_SUBNORMAL)
+    v2 = nextafterl (v1, -LDBL_MIN / 2.0);
+    if (fpclassify (v2) != FP_SUBNORMAL)
       {
 	printf ("fpclassify (-LDBL_MIN-epsilon) failed: %d (%La)\n",
-		fpclassify (ld), ld);
+		fpclassify (v2), v2);
 	result = 1;
       }
-    v2.d = ld = nextafterl (ld, -LDBL_MIN);
-    if (fpclassify (ld) != FP_NORMAL)
+    v2 = nextafterl (v2, -LDBL_MIN);
+    if (fpclassify (v2) != FP_NORMAL)
       {
 	printf ("fpclassify (-LDBL_MIN-epsilon+epsilon) failed: %d (%La)\n",
-		fpclassify (ld), ld);
+		fpclassify (v2), v2);
 	result = 1;
       }
 
-    if (v1.ieee.mantissa0 != v2.ieee.mantissa0)
-      {
-	printf ("-LDBL_MIN: mantissa0 differs: %8x vs %8x\n",
-		v1.ieee.mantissa0, v2.ieee.mantissa0);
-	result = 1;
-      }
-    if (v1.ieee.mantissa1 != v2.ieee.mantissa1)
-      {
-	printf ("-LDBL_MIN: mantissa1 differs: %8x vs %8x\n",
-		v1.ieee.mantissa1, v2.ieee.mantissa1);
-	result = 1;
-      }
-    if (v1.ieee.exponent != v2.ieee.exponent)
+    if (v1 != v2)
       {
-	printf ("-LDBL_MIN: exponent differs: %4x vs %4x\n",
-		v1.ieee.exponent, v2.ieee.exponent);
-	result = 1;
-      }
-    if (v1.ieee.negative != v2.ieee.negative)
-      {
-	printf ("-LDBL_MIN: negative differs: %d vs %d\n",
-		v1.ieee.negative, v2.ieee.negative);
+	printf ("-LDBL_MIN-epsilon+epsilon != -LDBL_MIN: %La vs %La\n", v2, v1);
 	result = 1;
       }
 
-    ld = LDBL_MAX;
-    if (fpclassify (ld) != FP_NORMAL)
+    v1 = LDBL_MAX;
+    if (fpclassify (v1) != FP_NORMAL)
       {
-	printf ("fpclassify (LDBL_MAX) failed: %d\n", fpclassify (ld));
+	printf ("fpclassify (LDBL_MAX) failed: %d (%La)\n",
+		fpclassify (v1), v1);
 	result = 1;
       }
-    ld = nextafterl (ld, INFINITY);
-    if (fpclassify (ld) != FP_INFINITE)
+    v2 = nextafterl (v1, INFINITY);
+    if (fpclassify (v2) != FP_INFINITE)
       {
-	printf ("fpclassify (LDBL_MAX+epsilon) failed: %d\n", fpclassify (ld));
+	printf ("fpclassify (LDBL_MAX+epsilon) failed: %d (%La)\n",
+		fpclassify (v2), v2);
 	result = 1;
       }
 
-    ld = -LDBL_MAX;
-    if (fpclassify (ld) != FP_NORMAL)
+    v1 = -LDBL_MAX;
+    if (fpclassify (v1) != FP_NORMAL)
       {
-	printf ("fpclassify (-LDBL_MAX) failed: %d\n", fpclassify (ld));
+	printf ("fpclassify (-LDBL_MAX) failed: %d (%La)\n",
+		fpclassify (v1), v1);
 	result = 1;
       }
-    ld = nextafterl (ld, -INFINITY);
-    if (fpclassify (ld) != FP_INFINITE)
+    v2 = nextafterl (v1, -INFINITY);
+    if (fpclassify (v2) != FP_INFINITE)
       {
-	printf ("fpclassify (-LDBL_MAX-epsilon) failed: %d\n",
-		fpclassify (ld));
+	printf ("fpclassify (-LDBL_MAX-epsilon) failed: %d (%La)\n",
+		fpclassify (v2), v2);
 	result = 1;
       }
 
-    v1.d = ld = 0.0625;
-    ld = nextafterl (ld, 0.0);
-    v2.d = ld = nextafterl (ld, 1.0);
+    v1 = 0.0625;
+    v2 = nextafterl (v1, 0.0);
+    v2 = nextafterl (v2, 1.0);
 
-    if (v1.ieee.mantissa0 != v2.ieee.mantissa0)
-      {
-	printf ("0.0625L down: mantissa0 differs: %8x vs %8x\n",
-		v1.ieee.mantissa0, v2.ieee.mantissa0);
-	result = 1;
-      }
-    if (v1.ieee.mantissa1 != v2.ieee.mantissa1)
-      {
-	printf ("0.0625L down: mantissa1 differs: %8x vs %8x\n",
-		v1.ieee.mantissa1, v2.ieee.mantissa1);
-	result = 1;
-      }
-    if (v1.ieee.exponent != v2.ieee.exponent)
-      {
-	printf ("0.0625L down: exponent differs: %4x vs %4x\n",
-		v1.ieee.exponent, v2.ieee.exponent);
-	result = 1;
-      }
-    if (v1.ieee.negative != v2.ieee.negative)
+    if (v1 != v2)
       {
-	printf ("0.0625L down: negative differs: %d vs %d\n",
-		v1.ieee.negative, v2.ieee.negative);
+	printf ("0.0625L-epsilon+epsilon != 0.0625L: %La vs %La\n", v2, v1);
 	result = 1;
       }
 
-    v1.d = ld = 0.0625;
-    ld = nextafterl (ld, 1.0);
-    v2.d = ld = nextafterl (ld, 0.0);
+    v1 = 0.0625;
+    v2 = nextafterl (v1, 1.0);
+    v2 = nextafterl (v2, 0.0);
 
-    if (v1.ieee.mantissa0 != v2.ieee.mantissa0)
-      {
-	printf ("0.0625L up: mantissa0 differs: %8x vs %8x\n",
-		v1.ieee.mantissa0, v2.ieee.mantissa0);
-	result = 1;
-      }
-    if (v1.ieee.mantissa1 != v2.ieee.mantissa1)
-      {
-	printf ("0.0625L up: mantissa1 differs: %8x vs %8x\n",
-		v1.ieee.mantissa1, v2.ieee.mantissa1);
-	result = 1;
-      }
-    if (v1.ieee.exponent != v2.ieee.exponent)
-      {
-	printf ("0.0625L up: exponent differs: %4x vs %4x\n",
-		v1.ieee.exponent, v2.ieee.exponent);
-	result = 1;
-      }
-    if (v1.ieee.negative != v2.ieee.negative)
+    if (v1 != v2)
       {
-	printf ("0.0625L up: negative differs: %d vs %d\n",
-		v1.ieee.negative, v2.ieee.negative);
+	printf ("0.0625L+epsilon-epsilon != 0.0625L: %La vs %La\n", v2, v1);
 	result = 1;
       }
 
-    v1.d = ld = -0.0625;
-    ld = nextafterl (ld, 0.0);
-    v2.d = ld = nextafterl (ld, -1.0);
+    v1 = -0.0625;
+    v2 = nextafterl (v1, 0.0);
+    v2 = nextafterl (v2, -1.0);
 
-    if (v1.ieee.mantissa0 != v2.ieee.mantissa0)
+    if (v1 != v2)
       {
-	printf ("-0.0625L up: mantissa0 differs: %8x vs %8x\n",
-		v1.ieee.mantissa0, v2.ieee.mantissa0);
-	result = 1;
-      }
-    if (v1.ieee.mantissa1 != v2.ieee.mantissa1)
-      {
-	printf ("-0.0625L up: mantissa1 differs: %8x vs %8x\n",
-		v1.ieee.mantissa1, v2.ieee.mantissa1);
-	result = 1;
-      }
-    if (v1.ieee.exponent != v2.ieee.exponent)
-      {
-	printf ("-0.0625L up: exponent differs: %4x vs %4x\n",
-		v1.ieee.exponent, v2.ieee.exponent);
-	result = 1;
-      }
-    if (v1.ieee.negative != v2.ieee.negative)
-      {
-	printf ("-0.0625L up: negative differs: %d vs %d\n",
-		v1.ieee.negative, v2.ieee.negative);
+	printf ("-0.0625L+epsilon-epsilon != -0.0625L: %La vs %La\n", v2, v1);
 	result = 1;
       }
 
-    v1.d = ld = -0.0625;
-    ld = nextafterl (ld, -1.0);
-    v2.d = ld = nextafterl (ld, 0.0);
+    v1 = -0.0625;
+    v2 = nextafterl (v1, -1.0);
+    v2 = nextafterl (v2, 0.0);
 
-    if (v1.ieee.mantissa0 != v2.ieee.mantissa0)
-      {
-	printf ("-0.0625L down: mantissa0 differs: %8x vs %8x\n",
-		v1.ieee.mantissa0, v2.ieee.mantissa0);
-	result = 1;
-      }
-    if (v1.ieee.mantissa1 != v2.ieee.mantissa1)
-      {
-	printf ("-0.0625L down: mantissa1 differs: %8x vs %8x\n",
-		v1.ieee.mantissa1, v2.ieee.mantissa1);
-	result = 1;
-      }
-    if (v1.ieee.exponent != v2.ieee.exponent)
+    if (v1 != v2)
       {
-	printf ("-0.0625L down: exponent differs: %4x vs %4x\n",
-		v1.ieee.exponent, v2.ieee.exponent);
-	result = 1;
-      }
-    if (v1.ieee.negative != v2.ieee.negative)
-      {
-	printf ("-0.0625L down: negative differs: %d vs %d\n",
-		v1.ieee.negative, v2.ieee.negative);
+	printf ("-0.0625L-epsilon+epsilon != -0.0625L: %La vs %La\n", v2, v1);
 	result = 1;
       }
 
-    v1.d = ld = 0.0;
-    ld = nextafterl (ld, 1.0);
-    v2.d = nextafterl (ld, -1.0);
+    v1 = 0.0;
+    v2 = nextafterl (v1, 1.0);
+    v2 = nextafterl (v2, -1.0);
 
-    if (v1.ieee.mantissa0 != v2.ieee.mantissa0)
-      {
-	printf ("0.0L up: mantissa0 differs: %8x vs %8x\n",
-		v1.ieee.mantissa0, v2.ieee.mantissa0);
-	result = 1;
-      }
-    if (v1.ieee.mantissa1 != v2.ieee.mantissa1)
-      {
-	printf ("0.0L up: mantissa1 differs: %8x vs %8x\n",
-		v1.ieee.mantissa1, v2.ieee.mantissa1);
-	result = 1;
-      }
-    if (v1.ieee.exponent != v2.ieee.exponent)
+    if (v1 != v2)
       {
-	printf ("0.0L up: exponent differs: %4x vs %4x\n",
-		v1.ieee.exponent, v2.ieee.exponent);
+	printf ("0.0+epsilon-epsilon != 0.0L: %La vs %La\n", v2, v1);
 	result = 1;
       }
-    if (0 != v2.ieee.negative)
+    if (signbit (v2))
       {
-	printf ("0.0L up: negative differs: 0 vs %d\n",
-		v2.ieee.negative);
+	printf ("0.0+epsilon-epsilon is negative\n");
 	result = 1;
       }
 
-    v1.d = ld = 0.0;
-    ld = nextafterl (ld, -1.0);
-    v2.d = nextafterl (ld, 1.0);
+    v1 = 0.0;
+    v2 = nextafterl (v1, -1.0);
+    v2 = nextafterl (v2, 1.0);
 
-    if (v1.ieee.mantissa0 != v2.ieee.mantissa0)
-      {
-	printf ("0.0L down: mantissa0 differs: %8x vs %8x\n",
-		v1.ieee.mantissa0, v2.ieee.mantissa0);
-	result = 1;
-      }
-    if (v1.ieee.mantissa1 != v2.ieee.mantissa1)
+    if (v1 != v2)
       {
-	printf ("0.0L down: mantissa1 differs: %8x vs %8x\n",
-		v1.ieee.mantissa1, v2.ieee.mantissa1);
-	result = 1;
-      }
-    if (v1.ieee.exponent != v2.ieee.exponent)
-      {
-	printf ("0.0L down: exponent differs: %4x vs %4x\n",
-		v1.ieee.exponent, v2.ieee.exponent);
+	printf ("0.0-epsilon+epsilon != 0.0L: %La vs %La\n", v2, v1);
 	result = 1;
       }
-    if (1 != v2.ieee.negative)
+    if (!signbit (v2))
       {
-	printf ("0.0L down: negative differs: 1 vs %d\n",
-		v2.ieee.negative);
+	printf ("0.0-epsilon+epsilon is positive\n");
 	result = 1;
       }
 
diff --git a/ports/ChangeLog b/ports/ChangeLog
index fcb58cc..5edce77 100644
--- a/ports/ChangeLog
+++ b/ports/ChangeLog
@@ -1,3 +1,7 @@
+2013-19-04  Alan Modra  <amodra@gmail.com>
+
+	* sysdeps/ia64/fpu/printf_fphex.c: Adjust for fpnum change.
+
 2013-01-02  Joseph Myers  <joseph@codesourcery.com>
 
 	* README: Update copyright dates in example.
diff --git a/ports/sysdeps/ia64/fpu/printf_fphex.c b/ports/sysdeps/ia64/fpu/printf_fphex.c
index ca02142..0698cda 100644
--- a/ports/sysdeps/ia64/fpu/printf_fphex.c
+++ b/ports/sysdeps/ia64/fpu/printf_fphex.c
@@ -25,9 +25,11 @@ do {									      \
       /* The "strange" 80 bit format on ia64 has an explicit		      \
 	 leading digit in the 64 bit mantissa.  */			      \
       unsigned long long int num;					      \
+      union ieee854_long_double u;					      \
+      u.d = fpnum.ldbl;							      \
 									      \
-      num = (((unsigned long long int) fpnum.ldbl.ieee.mantissa0) << 32	      \
-	     | fpnum.ldbl.ieee.mantissa1);				      \
+      num = (((unsigned long long int) u.ieee.mantissa0) << 32		      \
+	     | u.ieee.mantissa1);					      \
 									      \
       zero_mantissa = num == 0;						      \
 									      \
@@ -49,8 +51,8 @@ do {									      \
 									      \
       /* We have 3 bits from the mantissa in the leading nibble.	      \
 	 Therefore we are here using `IEEE854_LONG_DOUBLE_BIAS + 3'.  */      \
-      exponent = fpnum.ldbl.ieee.exponent;				      \
-									     \
+      exponent = u.ieee.exponent;					      \
+									      \
       if (exponent == 0)						      \
 	{								      \
 	  if (zero_mantissa)						      \
diff --git a/stdio-common/printf_fp.c b/stdio-common/printf_fp.c
index e20eab6..2b93e6c 100644
--- a/stdio-common/printf_fp.c
+++ b/stdio-common/printf_fp.c
@@ -332,8 +332,7 @@ ___printf_fp (FILE *fp,
       int res;
       if (__isnanl (fpnum.ldbl))
 	{
-	  union ieee854_long_double u = { .d = fpnum.ldbl };
-	  is_neg = u.ieee.negative != 0;
+	  is_neg = signbit (fpnum.ldbl);
 	  if (isupper (info->spec))
 	    {
 	      special = "NAN";
diff --git a/stdio-common/printf_fphex.c b/stdio-common/printf_fphex.c
index 3da2eec..50b6fbf 100644
--- a/stdio-common/printf_fphex.c
+++ b/stdio-common/printf_fphex.c
@@ -93,7 +93,7 @@ __printf_fphex (FILE *fp,
   union
     {
       union ieee754_double dbl;
-      union ieee854_long_double ldbl;
+      long double ldbl;
     }
   fpnum;
 
@@ -162,12 +162,11 @@ __printf_fphex (FILE *fp,
 #ifndef __NO_LONG_DOUBLE_MATH
   if (info->is_long_double && sizeof (long double) > sizeof (double))
     {
-      fpnum.ldbl.d = *(const long double *) args[0];
+      fpnum.ldbl = *(const long double *) args[0];
 
       /* Check for special values: not a number or infinity.  */
-      if (__isnanl (fpnum.ldbl.d))
+      if (__isnanl (fpnum.ldbl))
 	{
-	  negative = fpnum.ldbl.ieee.negative != 0;
 	  if (isupper (info->spec))
 	    {
 	      special = "NAN";
@@ -181,8 +180,7 @@ __printf_fphex (FILE *fp,
 	}
       else
 	{
-	  int res = __isinfl (fpnum.ldbl.d);
-	  if (res)
+	  if (__isinfl (fpnum.ldbl))
 	    {
 	      if (isupper (info->spec))
 		{
@@ -194,11 +192,9 @@ __printf_fphex (FILE *fp,
 		  special = "inf";
 		  wspecial = L"inf";
 		}
-	      negative = res < 0;
 	    }
-	  else
-	    negative = signbit (fpnum.ldbl.d);
 	}
+      negative = signbit (fpnum.ldbl);
     }
   else
 #endif	/* no long double */
diff --git a/stdio-common/printf_size.c b/stdio-common/printf_size.c
index 2c496e5..dfb3a53 100644
--- a/stdio-common/printf_size.c
+++ b/stdio-common/printf_size.c
@@ -103,7 +103,7 @@ __printf_size (FILE *fp, const struct printf_info *info,
   union
     {
       union ieee754_double dbl;
-      union ieee854_long_double ldbl;
+      long double ldbl;
     }
   fpnum;
   const void *ptr = &fpnum;
@@ -123,25 +123,25 @@ __printf_size (FILE *fp, const struct printf_info *info,
 #ifndef __NO_LONG_DOUBLE_MATH
   if (info->is_long_double && sizeof (long double) > sizeof (double))
     {
-      fpnum.ldbl.d = *(const long double *) args[0];
+      fpnum.ldbl = *(const long double *) args[0];
 
       /* Check for special values: not a number or infinity.  */
-      if (__isnanl (fpnum.ldbl.d))
+      if (__isnanl (fpnum.ldbl))
 	{
 	  special = "nan";
 	  wspecial = L"nan";
 	  // fpnum_sign = 0;	Already zero
 	}
-      else if ((res = __isinfl (fpnum.ldbl.d)))
+      else if ((res = __isinfl (fpnum.ldbl)))
 	{
 	  fpnum_sign = res;
 	  special = "inf";
 	  wspecial = L"inf";
 	}
       else
-	while (fpnum.ldbl.d >= divisor && tag[1] != '\0')
+	while (fpnum.ldbl >= divisor && tag[1] != '\0')
 	  {
-	    fpnum.ldbl.d /= divisor;
+	    fpnum.ldbl /= divisor;
 	    ++tag;
 	  }
     }
diff --git a/sysdeps/ieee754/ldbl-128/printf_fphex.c b/sysdeps/ieee754/ldbl-128/printf_fphex.c
index c9e09a4..e82228a 100644
--- a/sysdeps/ieee754/ldbl-128/printf_fphex.c
+++ b/sysdeps/ieee754/ldbl-128/printf_fphex.c
@@ -24,13 +24,15 @@ do {									      \
 	 digits we use only the implicit digits for the number before	      \
 	 the decimal point.  */						      \
       unsigned long long int num0, num1;				      \
+      union ieee854_long_double u;					      \
+      u.d = fpnum.ldbl;							      \
 									      \
       assert (sizeof (long double) == 16);				      \
 									      \
-      num0 = (((unsigned long long int) fpnum.ldbl.ieee.mantissa0) << 32      \
-	     | fpnum.ldbl.ieee.mantissa1);				      \
-      num1 = (((unsigned long long int) fpnum.ldbl.ieee.mantissa2) << 32      \
-	     | fpnum.ldbl.ieee.mantissa3);				      \
+      num0 = (((unsigned long long int) u.ieee.mantissa0) << 32		      \
+	     | u.ieee.mantissa1);					      \
+      num1 = (((unsigned long long int) u.ieee.mantissa2) << 32		      \
+	     | u.ieee.mantissa3);					      \
 									      \
       zero_mantissa = (num0|num1) == 0;					      \
 									      \
@@ -75,9 +77,9 @@ do {									      \
 	  *--wnumstr = L'0';						      \
 	}								      \
 									      \
-      leading = fpnum.ldbl.ieee.exponent == 0 ? '0' : '1';		      \
+      leading = u.ieee.exponent == 0 ? '0' : '1';			      \
 									      \
-      exponent = fpnum.ldbl.ieee.exponent;				      \
+      exponent = u.ieee.exponent;					      \
 									      \
       if (exponent == 0)						      \
 	{								      \
diff --git a/sysdeps/ieee754/ldbl-128ibm/printf_fphex.c b/sysdeps/ieee754/ldbl-128ibm/printf_fphex.c
index 453c2be..e0ec422 100644
--- a/sysdeps/ieee754/ldbl-128ibm/printf_fphex.c
+++ b/sysdeps/ieee754/ldbl-128ibm/printf_fphex.c
@@ -27,14 +27,14 @@ do {									      \
       unsigned long long hi, lo;					      \
       int ediff;							      \
       union ibm_extended_long_double u;					      \
-      u.ld = fpnum.ldbl.d;						      \
+      u.ld = fpnum.ldbl;						      \
 									      \
       assert (sizeof (long double) == 16);				      \
 									      \
       lo = ((long long)u.d[1].ieee.mantissa0 << 32) | u.d[1].ieee.mantissa1;  \
       hi = ((long long)u.d[0].ieee.mantissa0 << 32) | u.d[0].ieee.mantissa1;  \
       lo <<= 7; /* pre-shift lo to match ieee854.  */			      \
-      /* If the lower double is not a denomal or zero then set the hidden     \
+      /* If the lower double is not a denormal or zero then set the hidden    \
 	 53rd bit.  */							      \
       if (u.d[1].ieee.exponent != 0)					      \
 	lo |= (1ULL << (52 + 7));					      \
diff --git a/sysdeps/ieee754/ldbl-96/printf_fphex.c b/sysdeps/ieee754/ldbl-96/printf_fphex.c
index f356a48..715c93b 100644
--- a/sysdeps/ieee754/ldbl-96/printf_fphex.c
+++ b/sysdeps/ieee754/ldbl-96/printf_fphex.c
@@ -25,11 +25,13 @@ do {									      \
       /* The "strange" 80 bit format on ix86 and m68k has an explicit	      \
 	 leading digit in the 64 bit mantissa.  */			      \
       unsigned long long int num;					      \
+      union ieee854_long_double u;					      \
+      u.d = fpnum.ldbl;							      \
 									      \
       assert (sizeof (long double) == 12);				      \
 									      \
-      num = (((unsigned long long int) fpnum.ldbl.ieee.mantissa0) << 32	      \
-	     | fpnum.ldbl.ieee.mantissa1);				      \
+      num = (((unsigned long long int) u.ieee.mantissa0) << 32		      \
+	     | u.ieee.mantissa1);					      \
 									      \
       zero_mantissa = num == 0;						      \
 									      \
@@ -62,7 +64,7 @@ do {									      \
 									      \
       /* We have 3 bits from the mantissa in the leading nibble.	      \
 	 Therefore we are here using `IEEE854_LONG_DOUBLE_BIAS + 3'.  */      \
-      exponent = fpnum.ldbl.ieee.exponent;				      \
+      exponent = u.ieee.exponent;					      \
 									      \
       if (exponent == 0)						      \
 	{								      \
diff --git a/sysdeps/x86_64/fpu/printf_fphex.c b/sysdeps/x86_64/fpu/printf_fphex.c
index c85d1f7..be55f9c 100644
--- a/sysdeps/x86_64/fpu/printf_fphex.c
+++ b/sysdeps/x86_64/fpu/printf_fphex.c
@@ -25,10 +25,11 @@ do {									      \
       /* The "strange" 80 bit format on ix86 and m68k has an explicit	      \
 	 leading digit in the 64 bit mantissa.  */			      \
       unsigned long long int num;					      \
+      union ieee854_long_double u;					      \
+      u.d = fpnum.ldbl;							      \
 									      \
-									      \
-      num = (((unsigned long long int) fpnum.ldbl.ieee.mantissa0) << 32	      \
-	     | fpnum.ldbl.ieee.mantissa1);				      \
+      num = (((unsigned long long int) u.ieee.mantissa0) << 32		      \
+	     | u.ieee.mantissa1);					      \
 									      \
       zero_mantissa = num == 0;						      \
 									      \
@@ -61,7 +62,7 @@ do {									      \
 									      \
       /* We have 3 bits from the mantissa in the leading nibble.	      \
 	 Therefore we are here using `IEEE854_LONG_DOUBLE_BIAS + 3'.  */      \
-      exponent = fpnum.ldbl.ieee.exponent;				      \
+      exponent = u.ieee.exponent;					      \
 									      \
       if (exponent == 0)						      \
 	{								      \

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=4f36342de3e83319bdf70e4c0442a5d0df33334f

commit 4f36342de3e83319bdf70e4c0442a5d0df33334f
Author: Alan Modra <amodra@gmail.com>
Date:   Sat Aug 17 18:19:44 2013 +0930

    Fix for [BZ #15680] IBM long double inaccuracy
    http://sourceware.org/ml/libc-alpha/2013-06/msg00919.html
    
    I discovered a number of places where denormals and other corner cases
    were being handled wrongly.
    
    - printf_fphex.c: Testing for the low double exponent being zero is
    unnecessary.  If the difference in exponents is less than 53 then the
    high double exponent must be nearing the low end of its range, and the
    low double exponent hit rock bottom.
    
    - ldbl2mpn.c: A denormal (ie. exponent of zero) value is treated as
    if the exponent was one, so shift mantissa left by one.  Code handling
    normalisation of the low double mantissa lacked a test for shift count
    greater than bits in type being shifted, and lacked anything to handle
    the case where the difference in exponents is less than 53 as in
    printf_fphex.c.
    
    - math_ldbl.h (ldbl_extract_mantissa): Same as above, but worse, with
    code testing for exponent > 1 for some reason, probably a typo for >= 1.
    
    - math_ldbl.h (ldbl_insert_mantissa): Round the high double as per
    mpn2ldbl.c (hi is odd or explicit mantissas non-zero) so that the
    number we return won't change when applying ldbl_canonicalize().
    Add missing overflow checks and normalisation of high mantissa.
    Correct misleading comment: "The hidden bit of the lo mantissa is
    zero" is not always true as can be seen from the code rounding the hi
    mantissa.  Also by inspection, lzcount can never be less than zero so
    remove that test.  Lastly, masking bitfields to their widths can be
    left to the compiler.
    
    - mpn2ldbl.c: The overflow checks here on rounding of high double were
    just plain wrong.  Incrementing the exponent must be accompanied by a
    shift right of the mantissa to keep the value unchanged.  Above notes
    for ldbl_insert_mantissa are also relevant.
    
    	[BZ #15680]
    	* sysdeps/ieee754/ldbl-128ibm/e_rem_pio2l.c: Comment fix.
    	* sysdeps/ieee754/ldbl-128ibm/printf_fphex.c
    	(PRINT_FPHEX_LONG_DOUBLE): Tidy code by moving -53 into ediff
    	calculation.  Remove unnecessary test for denormal exponent.
    	* sysdeps/ieee754/ldbl-128ibm/ldbl2mpn.c (__mpn_extract_long_double):
    	Correct handling of denormals.  Avoid undefined shift behaviour.
    	Correct normalisation of low mantissa when low double is denormal.
    	* sysdeps/ieee754/ldbl-128ibm/math_ldbl.h
    	(ldbl_extract_mantissa): Likewise.  Comment.  Use uint64_t* for hi64.
    	(ldbl_insert_mantissa): Make both hi64 and lo64 parms uint64_t.
    	Correct normalisation of low mantissa.  Test for overflow of high
    	mantissa and normalise.
    	(ldbl_nearbyint): Use more readable constant for two52.
    	* sysdeps/ieee754/ldbl-128ibm/mpn2ldbl.c
    	(__mpn_construct_long_double): Fix test for overflow of high
    	mantissa and correct normalisation.  Avoid undefined shift.

diff --git a/ChangeLog b/ChangeLog
index 272795b..55abf03 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,25 @@
 2013-10-04  Alan Modra  <amodra@gmail.com>
 
+	[BZ #15680]
+	* sysdeps/ieee754/ldbl-128ibm/e_rem_pio2l.c: Comment fix.
+	* sysdeps/ieee754/ldbl-128ibm/printf_fphex.c
+	(PRINT_FPHEX_LONG_DOUBLE): Tidy code by moving -53 into ediff
+	calculation.  Remove unnecessary test for denormal exponent.
+	* sysdeps/ieee754/ldbl-128ibm/ldbl2mpn.c (__mpn_extract_long_double):
+	Correct handling of denormals.  Avoid undefined shift behaviour.
+	Correct normalisation of low mantissa when low double is denormal.
+	* sysdeps/ieee754/ldbl-128ibm/math_ldbl.h
+	(ldbl_extract_mantissa): Likewise.  Comment.  Use uint64_t* for hi64.
+	(ldbl_insert_mantissa): Make both hi64 and lo64 parms uint64_t.
+	Correct normalisation of low mantissa.  Test for overflow of high
+	mantissa and normalise.
+	(ldbl_nearbyint): Use more readable constant for two52.
+	* sysdeps/ieee754/ldbl-128ibm/mpn2ldbl.c
+	(__mpn_construct_long_double): Fix test for overflow of high
+	mantissa and correct normalisation.  Avoid undefined shift.
+
+2013-10-04  Alan Modra  <amodra@gmail.com>
+
 	* sysdeps/ieee754/ldbl-128ibm/ieee754.h
 	(union ibm_extended_long_double): Define as an array of ieee754_double.
 	(IBM_EXTENDED_LONG_DOUBLE_BIAS): Delete.
diff --git a/sysdeps/ieee754/ldbl-128ibm/e_rem_pio2l.c b/sysdeps/ieee754/ldbl-128ibm/e_rem_pio2l.c
index 6a72d6a..8885def 100644
--- a/sysdeps/ieee754/ldbl-128ibm/e_rem_pio2l.c
+++ b/sysdeps/ieee754/ldbl-128ibm/e_rem_pio2l.c
@@ -243,7 +243,7 @@ int32_t __ieee754_rem_pio2l(long double x, long double *y)
      We split the 113 bits of the mantissa into 5 24bit integers
      stored in a double array.  */
   /* Make the IBM extended format 105 bit mantissa look like the ieee854 112
-     bit mantissa so the next operatation will give the correct result.  */
+     bit mantissa so the next operation will give the correct result.  */
   ldbl_extract_mantissa (&ixd, &lxd, &exp, x);
   exp = exp - 23;
   /* This is faster than doing this in floating point, because we
diff --git a/sysdeps/ieee754/ldbl-128ibm/ldbl2mpn.c b/sysdeps/ieee754/ldbl-128ibm/ldbl2mpn.c
index 5149ba1..e46fde7 100644
--- a/sysdeps/ieee754/ldbl-128ibm/ldbl2mpn.c
+++ b/sysdeps/ieee754/ldbl-128ibm/ldbl2mpn.c
@@ -36,6 +36,7 @@ __mpn_extract_long_double (mp_ptr res_ptr, mp_size_t size,
   union ibm_extended_long_double u;
   unsigned long long hi, lo;
   int ediff;
+
   u.ld = value;
 
   *is_neg = u.d[0].ieee.negative;
@@ -43,27 +44,36 @@ __mpn_extract_long_double (mp_ptr res_ptr, mp_size_t size,
 
   lo = ((long long) u.d[1].ieee.mantissa0 << 32) | u.d[1].ieee.mantissa1;
   hi = ((long long) u.d[0].ieee.mantissa0 << 32) | u.d[0].ieee.mantissa1;
-  /* If the lower double is not a denomal or zero then set the hidden
+
+  /* If the lower double is not a denormal or zero then set the hidden
      53rd bit.  */
-  if (u.d[1].ieee.exponent > 0)
-    {
-      lo |= 1LL << 52;
+  if (u.d[1].ieee.exponent != 0)
+    lo |= 1ULL << 52;
+  else
+    lo = lo << 1;
 
-      /* The lower double is normalized separately from the upper.  We may
-	 need to adjust the lower manitissa to reflect this.  */
-      ediff = u.d[0].ieee.exponent - u.d[1].ieee.exponent;
-      if (ediff > 53)
-	lo = lo >> (ediff-53);
+  /* The lower double is normalized separately from the upper.  We may
+     need to adjust the lower manitissa to reflect this.  */
+  ediff = u.d[0].ieee.exponent - u.d[1].ieee.exponent - 53;
+  if (ediff > 0)
+    {
+      if (ediff < 64)
+	lo = lo >> ediff;
+      else
+	lo = 0;
     }
+  else if (ediff < 0)
+    lo = lo << -ediff;
+
   /* The high double may be rounded and the low double reflects the
      difference between the long double and the rounded high double
      value.  This is indicated by a differnce between the signs of the
      high and low doubles.  */
-  if ((u.d[0].ieee.negative != u.d[1].ieee.negative)
-      && ((u.d[1].ieee.exponent != 0) && (lo != 0L)))
+  if (u.d[0].ieee.negative != u.d[1].ieee.negative
+      && lo != 0)
     {
       lo = (1ULL << 53) - lo;
-      if (hi == 0LL)
+      if (hi == 0)
 	{
 	  /* we have a borrow from the hidden bit, so shift left 1.  */
 	  hi = 0x0ffffffffffffeLL | (lo >> 51);
diff --git a/sysdeps/ieee754/ldbl-128ibm/math_ldbl.h b/sysdeps/ieee754/ldbl-128ibm/math_ldbl.h
index 3036f14..4bb49c8 100644
--- a/sysdeps/ieee754/ldbl-128ibm/math_ldbl.h
+++ b/sysdeps/ieee754/ldbl-128ibm/math_ldbl.h
@@ -6,6 +6,10 @@
 #include <ieee754.h>
 #include <stdint.h>
 
+/* To suit our callers we return *hi64 and *lo64 as if they came from
+   an ieee854 112 bit mantissa, that is, 48 bits in *hi64 (plus one
+   implicit bit) and 64 bits in *lo64.  */
+
 static inline void
 ldbl_extract_mantissa (int64_t *hi64, uint64_t *lo64, int *exp, long double x)
 {
@@ -14,77 +18,119 @@ ldbl_extract_mantissa (int64_t *hi64, uint64_t *lo64, int *exp, long double x)
      the number before the decimal point and the second implicit bit
      as bit 53 of the mantissa.  */
   uint64_t hi, lo;
-  int ediff;
   union ibm_extended_long_double u;
+
   u.ld = x;
   *exp = u.d[0].ieee.exponent - IEEE754_DOUBLE_BIAS;
 
   lo = ((uint64_t) u.d[1].ieee.mantissa0 << 32) | u.d[1].ieee.mantissa1;
   hi = ((uint64_t) u.d[0].ieee.mantissa0 << 32) | u.d[0].ieee.mantissa1;
-  /* If the lower double is not a denomal or zero then set the hidden
-     53rd bit.  */
-  if (u.d[1].ieee.exponent > 0x001)
-    {
-      lo |= (1ULL << 52);
-      lo = lo << 7; /* pre-shift lo to match ieee854.  */
-      /* The lower double is normalized separately from the upper.  We
-	 may need to adjust the lower manitissa to reflect this.  */
-      ediff = u.d[0].ieee.exponent - u.d[1].ieee.exponent;
-      if (ediff > 53)
-	lo = lo >> (ediff-53);
-      hi |= (1ULL << 52);
-    }
 
-  if ((u.d[0].ieee.negative != u.d[1].ieee.negative)
-      && ((u.d[1].ieee.exponent != 0) && (lo != 0LL)))
+  if (u.d[0].ieee.exponent != 0)
     {
-      hi--;
-      lo = (1ULL << 60) - lo;
-      if (hi < (1ULL << 52))
+      int ediff;
+
+      /* If not a denormal or zero then we have an implicit 53rd bit.  */
+      hi |= (uint64_t) 1 << 52;
+
+      if (u.d[1].ieee.exponent != 0)
+	lo |= (uint64_t) 1 << 52;
+      else
+	/* A denormal is to be interpreted as having a biased exponent
+	   of 1.  */
+	lo = lo << 1;
+
+      /* We are going to shift 4 bits out of hi later, because we only
+	 want 48 bits in *hi64.  That means we want 60 bits in lo, but
+	 we currently only have 53.  Shift the value up.  */
+      lo = lo << 7;
+
+      /* The lower double is normalized separately from the upper.
+	 We may need to adjust the lower mantissa to reflect this.
+	 The difference between the exponents can be larger than 53
+	 when the low double is much less than 1ULP of the upper
+	 (in which case there are significant bits, all 0's or all
+	 1's, between the two significands).  The difference between
+	 the exponents can be less than 53 when the upper double
+	 exponent is nearing its minimum value (in which case the low
+	 double is denormal ie. has an exponent of zero).  */
+      ediff = u.d[0].ieee.exponent - u.d[1].ieee.exponent - 53;
+      if (ediff > 0)
 	{
-	  /* we have a borrow from the hidden bit, so shift left 1.  */
-	  hi = (hi << 1) | (lo >> 59);
-	  lo = 0xfffffffffffffffLL & (lo << 1);
-	  *exp = *exp - 1;
+	  if (ediff < 64)
+	    lo = lo >> ediff;
+	  else
+	    lo = 0;
+	}
+      else if (ediff < 0)
+	lo = lo << -ediff;
+
+      if (u.d[0].ieee.negative != u.d[1].ieee.negative
+	  && lo != 0)
+	{
+	  hi--;
+	  lo = ((uint64_t) 1 << 60) - lo;
+	  if (hi < (uint64_t) 1 << 52)
+	    {
+	      /* We have a borrow from the hidden bit, so shift left 1.  */
+	      hi = (hi << 1) | (lo >> 59);
+	      lo = (((uint64_t) 1 << 60) - 1) & (lo << 1);
+	      *exp = *exp - 1;
+	    }
 	}
     }
+  else
+    /* If the larger magnitude double is denormal then the smaller
+       one must be zero.  */
+    hi = hi << 1;
+
   *lo64 = (hi << 60) | lo;
   *hi64 = hi >> 4;
 }
 
 static inline long double
-ldbl_insert_mantissa (int sign, int exp, int64_t hi64, u_int64_t lo64)
+ldbl_insert_mantissa (int sign, int exp, int64_t hi64, uint64_t lo64)
 {
   union ibm_extended_long_double u;
-  unsigned long hidden2, lzcount;
-  unsigned long long hi, lo;
+  int expnt2;
+  uint64_t hi, lo;
 
   u.d[0].ieee.negative = sign;
   u.d[1].ieee.negative = sign;
   u.d[0].ieee.exponent = exp + IEEE754_DOUBLE_BIAS;
-  u.d[1].ieee.exponent = exp-53 + IEEE754_DOUBLE_BIAS;
+  u.d[1].ieee.exponent = 0;
+  expnt2 = exp - 53 + IEEE754_DOUBLE_BIAS;
+
   /* Expect 113 bits (112 bits + hidden) right justified in two longs.
      The low order 53 bits (52 + hidden) go into the lower double */
-  lo = (lo64 >> 7)& ((1ULL << 53) - 1);
-  hidden2 = (lo64 >> 59) &  1ULL;
+  lo = (lo64 >> 7) & (((uint64_t) 1 << 53) - 1);
   /* The high order 53 bits (52 + hidden) go into the upper double */
-  hi = (lo64 >> 60) & ((1ULL << 11) - 1);
-  hi |= (hi64 << 4);
+  hi = lo64 >> 60;
+  hi |= hi64 << 4;
 
-  if (lo != 0LL)
+  if (lo != 0)
     {
-      /* hidden2 bit of low double controls rounding of the high double.
-	 If hidden2 is '1' then round up hi and adjust lo (2nd mantissa)
+      int lzcount;
+
+      /* hidden bit of low double controls rounding of the high double.
+	 If hidden is '1' and either the explicit mantissa is non-zero
+	 or hi is odd, then round up hi and adjust lo (2nd mantissa)
 	 plus change the sign of the low double to compensate.  */
-      if (hidden2)
+      if ((lo & ((uint64_t) 1 << 52)) != 0
+	  && ((hi & 1) != 0 || (lo & (((uint64_t) 1 << 52) - 1)) != 0))
 	{
 	  hi++;
+	  if ((hi & ((uint64_t) 1 << 53)) != 0)
+	    {
+	      hi = hi >> 1;
+	      u.d[0].ieee.exponent++;
+	    }
 	  u.d[1].ieee.negative = !sign;
-	  lo = (1ULL << 53) - lo;
+	  lo = ((uint64_t) 1 << 53) - lo;
 	}
-      /* The hidden bit of the lo mantissa is zero so we need to
-	 normalize the it for the low double.  Shift it left until the
-	 hidden bit is '1' then adjust the 2nd exponent accordingly.  */
+
+      /* Normalize the low double.  Shift the mantissa left until
+	 the hidden bit is '1' and adjust the exponent accordingly.  */
 
       if (sizeof (lo) == sizeof (long))
 	lzcount = __builtin_clzl (lo);
@@ -92,34 +138,30 @@ ldbl_insert_mantissa (int sign, int exp, int64_t hi64, u_int64_t lo64)
 	lzcount = __builtin_clzl ((long) (lo >> 32));
       else
 	lzcount = __builtin_clzl ((long) lo) + 32;
-      lzcount = lzcount - 11;
-      if (lzcount > 0)
+      lzcount = lzcount - (64 - 53);
+      lo <<= lzcount;
+      expnt2 -= lzcount;
+
+      if (expnt2 >= 1)
+	/* Not denormal.  */
+	u.d[1].ieee.exponent = expnt2;
+      else
 	{
-	  int expnt2 = u.d[1].ieee.exponent - lzcount;
-	  if (expnt2 >= 1)
-	    {
-	      /* Not denormal.  Normalize and set low exponent.  */
-	      lo = lo << lzcount;
-	      u.d[1].ieee.exponent = expnt2;
-	    }
+	  /* Is denormal.  Note that biased exponent of 0 is treated
+	     as if it was 1, hence the extra shift.  */
+	  if (expnt2 > -53)
+	    lo >>= 1 - expnt2;
 	  else
-	    {
-	      /* Is denormal.  */
-	      lo = lo << (lzcount + expnt2);
-	      u.d[1].ieee.exponent = 0;
-	    }
+	    lo = 0;
 	}
     }
   else
-    {
-      u.d[1].ieee.negative = 0;
-      u.d[1].ieee.exponent = 0;
-    }
+    u.d[1].ieee.negative = 0;
 
-  u.d[1].ieee.mantissa1 = lo & ((1ULL << 32) - 1);
-  u.d[1].ieee.mantissa0 = (lo >> 32) & ((1ULL << 20) - 1);
-  u.d[0].ieee.mantissa1 = hi & ((1ULL << 32) - 1);
-  u.d[0].ieee.mantissa0 = (hi >> 32) & ((1ULL << 20) - 1);
+  u.d[1].ieee.mantissa1 = lo;
+  u.d[1].ieee.mantissa0 = lo >> 32;
+  u.d[0].ieee.mantissa1 = hi;
+  u.d[0].ieee.mantissa0 = hi >> 32;
   return u.ld;
 }
 
@@ -163,13 +205,13 @@ ldbl_canonicalize (double *a, double *aa)
   *aa = xl;
 }
 
-/* Simple inline nearbyint (double) function .
+/* Simple inline nearbyint (double) function.
    Only works in the default rounding mode
    but is useful in long double rounding functions.  */
 static inline double
 ldbl_nearbyint (double a)
 {
-  double two52 = 0x10000000000000LL;
+  double two52 = 0x1p52;
 
   if (__builtin_expect ((__builtin_fabs (a) < two52), 1))
     {
diff --git a/sysdeps/ieee754/ldbl-128ibm/mpn2ldbl.c b/sysdeps/ieee754/ldbl-128ibm/mpn2ldbl.c
index c3e42f2..c96852d 100644
--- a/sysdeps/ieee754/ldbl-128ibm/mpn2ldbl.c
+++ b/sysdeps/ieee754/ldbl-128ibm/mpn2ldbl.c
@@ -69,9 +69,9 @@ __mpn_construct_long_double (mp_srcptr frac_ptr, int expt, int sign)
       else
 	lzcount = __builtin_clzl ((long) val) + 32;
       if (hi)
-	lzcount = lzcount - 11;
+	lzcount = lzcount - (64 - 53);
       else
-	lzcount = lzcount + 42;
+	lzcount = lzcount + 53 - (64 - 53);
 
       if (lzcount > u.d[0].ieee.exponent)
 	{
@@ -97,29 +97,27 @@ __mpn_construct_long_double (mp_srcptr frac_ptr, int expt, int sign)
 	}
     }
 
-  if (lo != 0L)
+  if (lo != 0)
     {
-      /* hidden2 bit of low double controls rounding of the high double.
-	 If hidden2 is '1' and either the explicit mantissa is non-zero
+      /* hidden bit of low double controls rounding of the high double.
+	 If hidden is '1' and either the explicit mantissa is non-zero
 	 or hi is odd, then round up hi and adjust lo (2nd mantissa)
 	 plus change the sign of the low double to compensate.  */
       if ((lo & (1LL << 52)) != 0
-	  && ((hi & 1) != 0 || (lo & ((1LL << 52) - 1))))
+	  && ((hi & 1) != 0 || (lo & ((1LL << 52) - 1)) != 0))
 	{
 	  hi++;
-	  if ((hi & ((1LL << 52) - 1)) == 0)
+	  if ((hi & (1LL << 53)) != 0)
 	    {
-	      if ((hi & (1LL << 53)) != 0)
-		hi -= 1LL << 52;
+	      hi >>= 1;
 	      u.d[0].ieee.exponent++;
 	    }
 	  u.d[1].ieee.negative = !sign;
 	  lo = (1LL << 53) - lo;
 	}
 
-      /* The hidden bit of the lo mantissa is zero so we need to normalize
-	 it for the low double.  Shift it left until the hidden bit is '1'
-	 then adjust the 2nd exponent accordingly.  */
+      /* Normalize the low double.  Shift the mantissa left until
+	 the hidden bit is '1' and adjust the exponent accordingly.  */
 
       if (sizeof (lo) == sizeof (long))
 	lzcount = __builtin_clzl (lo);
@@ -127,24 +125,24 @@ __mpn_construct_long_double (mp_srcptr frac_ptr, int expt, int sign)
 	lzcount = __builtin_clzl ((long) (lo >> 32));
       else
 	lzcount = __builtin_clzl ((long) lo) + 32;
-      lzcount = lzcount - 11;
-      if (lzcount > 0)
-	{
-	  lo = lo << lzcount;
-	  exponent2 = exponent2 - lzcount;
-	}
+      lzcount = lzcount - (64 - 53);
+      lo <<= lzcount;
+      exponent2 -= lzcount;
+
       if (exponent2 > 0)
 	u.d[1].ieee.exponent = exponent2;
-      else
+      else if (exponent2 > -53)
 	lo >>= 1 - exponent2;
+      else
+	lo = 0;
     }
   else
     u.d[1].ieee.negative = 0;
 
-  u.d[1].ieee.mantissa1 = lo & 0xffffffffLL;
-  u.d[1].ieee.mantissa0 = (lo >> 32) & 0xfffff;
-  u.d[0].ieee.mantissa1 = hi & 0xffffffffLL;
-  u.d[0].ieee.mantissa0 = (hi >> 32) & ((1LL << (LDBL_MANT_DIG - 86)) - 1);
+  u.d[1].ieee.mantissa1 = lo;
+  u.d[1].ieee.mantissa0 = lo >> 32;
+  u.d[0].ieee.mantissa1 = hi;
+  u.d[0].ieee.mantissa0 = hi >> 32;
 
   return u.ld;
 }
diff --git a/sysdeps/ieee754/ldbl-128ibm/printf_fphex.c b/sysdeps/ieee754/ldbl-128ibm/printf_fphex.c
index 3fe8333..453c2be 100644
--- a/sysdeps/ieee754/ldbl-128ibm/printf_fphex.c
+++ b/sysdeps/ieee754/ldbl-128ibm/printf_fphex.c
@@ -42,15 +42,15 @@ do {									      \
 	lo <<= 1;							      \
       /* The lower double is normalized separately from the upper.  We	      \
 	 may need to adjust the lower manitissa to reflect this.  */	      \
-      ediff = u.d[0].ieee.exponent - u.d[1].ieee.exponent;		      \
-      if (ediff > 53 + 63)						      \
+      ediff = u.d[0].ieee.exponent - u.d[1].ieee.exponent - 53;		      \
+      if (ediff > 63)							      \
 	lo = 0;								      \
-      else if (ediff > 53)						      \
-	lo = lo >> (ediff - 53);					      \
-      else if (u.d[1].ieee.exponent == 0 && ediff < 53)			      \
-	lo = lo << (53 - ediff);					      \
+      else if (ediff > 0)						      \
+	lo = lo >> ediff;						      \
+      else if (ediff < 0)						      \
+	lo = lo << -ediff;						      \
       if (u.d[0].ieee.negative != u.d[1].ieee.negative			      \
-	  && (u.d[1].ieee.exponent != 0 || lo != 0L))			      \
+	  && lo != 0)							      \
 	{								      \
 	  lo = (1ULL << 60) - lo;					      \
 	  if (hi == 0L)							      \

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=5d8d74696a867006ada0ec1586a255a4093422ba

commit 5d8d74696a867006ada0ec1586a255a4093422ba
Author: Alan Modra <amodra@gmail.com>
Date:   Sat Aug 17 18:12:56 2013 +0930

    IBM long double mechanical changes to support little-endian
    http://sourceware.org/ml/libc-alpha/2013-07/msg00001.html
    
    This patch starts the process of supporting powerpc64 little-endian
    long double in glibc.  IBM long double is an array of two ieee
    doubles, so making union ibm_extended_long_double reflect this fact is
    the correct way to access fields of the doubles.
    
    	* sysdeps/ieee754/ldbl-128ibm/ieee754.h
    	(union ibm_extended_long_double): Define as an array of ieee754_double.
    	(IBM_EXTENDED_LONG_DOUBLE_BIAS): Delete.
    	* sysdeps/ieee754/ldbl-128ibm/printf_fphex.c: Update all references
    	to ibm_extended_long_double and IBM_EXTENDED_LONG_DOUBLE_BIAS.
    	* sysdeps/ieee754/ldbl-128ibm/e_exp10l.c: Likewise.
    	* sysdeps/ieee754/ldbl-128ibm/e_expl.c: Likewise.
    	* sysdeps/ieee754/ldbl-128ibm/ldbl2mpn.c: Likewise.
    	* sysdeps/ieee754/ldbl-128ibm/math_ldbl.h: Likewise.
    	* sysdeps/ieee754/ldbl-128ibm/mpn2ldbl.c: Likewise.
    	* sysdeps/ieee754/ldbl-128ibm/s_nearbyintl.c: Likewise.
    	* sysdeps/ieee754/ldbl-128ibm/strtold_l.c: Likewise.
    	* sysdeps/ieee754/ldbl-128ibm/x2y2m1l.c: Likewise.

diff --git a/ChangeLog b/ChangeLog
index 9d04543..272795b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,19 @@
+2013-10-04  Alan Modra  <amodra@gmail.com>
+
+	* sysdeps/ieee754/ldbl-128ibm/ieee754.h
+	(union ibm_extended_long_double): Define as an array of ieee754_double.
+	(IBM_EXTENDED_LONG_DOUBLE_BIAS): Delete.
+	* sysdeps/ieee754/ldbl-128ibm/printf_fphex.c: Update all references
+	to ibm_extended_long_double and IBM_EXTENDED_LONG_DOUBLE_BIAS.
+	* sysdeps/ieee754/ldbl-128ibm/e_exp10l.c: Likewise.
+	* sysdeps/ieee754/ldbl-128ibm/e_expl.c: Likewise.
+	* sysdeps/ieee754/ldbl-128ibm/ldbl2mpn.c: Likewise.
+	* sysdeps/ieee754/ldbl-128ibm/math_ldbl.h: Likewise.
+	* sysdeps/ieee754/ldbl-128ibm/mpn2ldbl.c: Likewise.
+	* sysdeps/ieee754/ldbl-128ibm/s_nearbyintl.c: Likewise.
+	* sysdeps/ieee754/ldbl-128ibm/strtold_l.c: Likewise.
+	* sysdeps/ieee754/ldbl-128ibm/x2y2m1l.c: Likewise.
+
 2013-09-09  Allan McRae  <allan@archlinux.org>
 
 	[BZ #15893]
diff --git a/sysdeps/ieee754/ldbl-128ibm/e_exp10l.c b/sysdeps/ieee754/ldbl-128ibm/e_exp10l.c
index 1eaf2fe..49121ca 100644
--- a/sysdeps/ieee754/ldbl-128ibm/e_exp10l.c
+++ b/sysdeps/ieee754/ldbl-128ibm/e_exp10l.c
@@ -36,9 +36,9 @@ __ieee754_exp10l (long double arg)
   else if (arg > LDBL_MAX_10_EXP + 1)
     return LDBL_MAX * LDBL_MAX;
 
-  u.d = arg;
-  arg_high = u.dd[0];
-  arg_low = u.dd[1];
+  u.ld = arg;
+  arg_high = u.d[0].d;
+  arg_low = u.d[1].d;
   exp_high = arg_high * log10_high;
   exp_low = arg_high * log10_low + arg_low * M_LN10l;
   return __ieee754_expl (exp_high) * __ieee754_expl (exp_low);
diff --git a/sysdeps/ieee754/ldbl-128ibm/e_expl.c b/sysdeps/ieee754/ldbl-128ibm/e_expl.c
index b599f36..9d3d1e3 100644
--- a/sysdeps/ieee754/ldbl-128ibm/e_expl.c
+++ b/sysdeps/ieee754/ldbl-128ibm/e_expl.c
@@ -162,39 +162,39 @@ __ieee754_expl (long double x)
       x = x + xl;
 
       /* Compute ex2 = 2^n_0 e^(argtable[tval1]) e^(argtable[tval2]).  */
-      ex2_u.d = __expl_table[T_EXPL_RES1 + tval1]
-		* __expl_table[T_EXPL_RES2 + tval2];
+      ex2_u.ld = (__expl_table[T_EXPL_RES1 + tval1]
+		  * __expl_table[T_EXPL_RES2 + tval2]);
       n_i = (int)n;
       /* 'unsafe' is 1 iff n_1 != 0.  */
       unsafe = fabsl(n_i) >= -LDBL_MIN_EXP - 1;
-      ex2_u.ieee.exponent += n_i >> unsafe;
+      ex2_u.d[0].ieee.exponent += n_i >> unsafe;
       /* Fortunately, there are no subnormal lowpart doubles in
 	 __expl_table, only normal values and zeros.
 	 But after scaling it can be subnormal.  */
-      exponent2 = ex2_u.ieee.exponent2 + (n_i >> unsafe);
-      if (ex2_u.ieee.exponent2 == 0)
-	/* assert ((ex2_u.ieee.mantissa2|ex2_u.ieee.mantissa3) == 0) */;
+      exponent2 = ex2_u.d[1].ieee.exponent + (n_i >> unsafe);
+      if (ex2_u.d[1].ieee.exponent == 0)
+	/* assert ((ex2_u.d[1].ieee.mantissa0|ex2_u.d[1].ieee.mantissa1) == 0) */;
       else if (exponent2 > 0)
-	ex2_u.ieee.exponent2 = exponent2;
+	ex2_u.d[1].ieee.exponent = exponent2;
       else if (exponent2 <= -54)
 	{
-	  ex2_u.ieee.exponent2 = 0;
-	  ex2_u.ieee.mantissa2 = 0;
-	  ex2_u.ieee.mantissa3 = 0;
+	  ex2_u.d[1].ieee.exponent = 0;
+	  ex2_u.d[1].ieee.mantissa0 = 0;
+	  ex2_u.d[1].ieee.mantissa1 = 0;
 	}
       else
 	{
 	  static const double
 	    two54 = 1.80143985094819840000e+16, /* 4350000000000000 */
 	    twom54 = 5.55111512312578270212e-17; /* 3C90000000000000 */
-	  ex2_u.dd[1] *= two54;
-	  ex2_u.ieee.exponent2 += n_i >> unsafe;
-	  ex2_u.dd[1] *= twom54;
+	  ex2_u.d[1].d *= two54;
+	  ex2_u.d[1].ieee.exponent += n_i >> unsafe;
+	  ex2_u.d[1].d *= twom54;
 	}
 
       /* Compute scale = 2^n_1.  */
-      scale_u.d = 1.0L;
-      scale_u.ieee.exponent += n_i - (n_i >> unsafe);
+      scale_u.ld = 1.0L;
+      scale_u.d[0].ieee.exponent += n_i - (n_i >> unsafe);
 
       /* Approximate e^x2 - 1, using a seventh-degree polynomial,
 	 with maximum error in [-2^-16-2^-53,2^-16+2^-53]
@@ -204,7 +204,7 @@ __ieee754_expl (long double x)
       /* Return result.  */
       fesetenv (&oldenv);
 
-      result = x22 * ex2_u.d + ex2_u.d;
+      result = x22 * ex2_u.ld + ex2_u.ld;
 
       /* Now we can test whether the result is ultimate or if we are unsure.
 	 In the later case we should probably call a mpn based routine to give
@@ -238,7 +238,7 @@ __ieee754_expl (long double x)
       if (!unsafe)
 	return result;
       else
-	return result * scale_u.d;
+	return result * scale_u.ld;
     }
   /* Exceptional cases:  */
   else if (isless (x, himark))
diff --git a/sysdeps/ieee754/ldbl-128ibm/ieee754.h b/sysdeps/ieee754/ldbl-128ibm/ieee754.h
index 9e94f53..0778b1f 100644
--- a/sysdeps/ieee754/ldbl-128ibm/ieee754.h
+++ b/sysdeps/ieee754/ldbl-128ibm/ieee754.h
@@ -179,49 +179,10 @@ union ieee854_long_double
 
 union ibm_extended_long_double
   {
-    long double d;
-    double dd[2];
-
-    /* This is the IBM extended format long double.  */
-    struct
-      { /* Big endian.  There is no other.  */
-
-	unsigned int negative:1;
-	unsigned int exponent:11;
-	/* Together Mantissa0-3 comprise the mantissa.  */
-	unsigned int mantissa0:20;
-	unsigned int mantissa1:32;
-
-	unsigned int negative2:1;
-	unsigned int exponent2:11;
-	/* There is an implied 1 here?  */
-	/* Together these comprise the mantissa.  */
-	unsigned int mantissa2:20;
-	unsigned int mantissa3:32;
-      } ieee;
-
-    /* This format makes it easier to see if a NaN is a signalling NaN.  */
-    struct
-      { /* Big endian.  There is no other.  */
-
-	unsigned int negative:1;
-	unsigned int exponent:11;
-	unsigned int quiet_nan:1;
-	/* Together Mantissa0-3 comprise the mantissa.  */
-	unsigned int mantissa0:19;
-	unsigned int mantissa1:32;
-
-	unsigned int negative2:1;
-	unsigned int exponent2:11;
-	/* There is an implied 1 here?  */
-	/* Together these comprise the mantissa.  */
-	unsigned int mantissa2:20;
-	unsigned int mantissa3:32;
-      } ieee_nan;
+    long double ld;
+    union ieee754_double d[2];
    };
 
-#define IBM_EXTENDED_LONG_DOUBLE_BIAS 0x3ff /* Added to exponent.  */
-
 __END_DECLS
 
 #endif /* ieee754.h */
diff --git a/sysdeps/ieee754/ldbl-128ibm/ldbl2mpn.c b/sysdeps/ieee754/ldbl-128ibm/ldbl2mpn.c
index 00e44b8..5149ba1 100644
--- a/sysdeps/ieee754/ldbl-128ibm/ldbl2mpn.c
+++ b/sysdeps/ieee754/ldbl-128ibm/ldbl2mpn.c
@@ -36,22 +36,22 @@ __mpn_extract_long_double (mp_ptr res_ptr, mp_size_t size,
   union ibm_extended_long_double u;
   unsigned long long hi, lo;
   int ediff;
-  u.d = value;
+  u.ld = value;
 
-  *is_neg = u.ieee.negative;
-  *expt = (int) u.ieee.exponent - IBM_EXTENDED_LONG_DOUBLE_BIAS;
+  *is_neg = u.d[0].ieee.negative;
+  *expt = (int) u.d[0].ieee.exponent - IEEE754_DOUBLE_BIAS;
 
-  lo = ((long long) u.ieee.mantissa2 << 32) | u.ieee.mantissa3;
-  hi = ((long long) u.ieee.mantissa0 << 32) | u.ieee.mantissa1;
+  lo = ((long long) u.d[1].ieee.mantissa0 << 32) | u.d[1].ieee.mantissa1;
+  hi = ((long long) u.d[0].ieee.mantissa0 << 32) | u.d[0].ieee.mantissa1;
   /* If the lower double is not a denomal or zero then set the hidden
      53rd bit.  */
-  if (u.ieee.exponent2 > 0)
+  if (u.d[1].ieee.exponent > 0)
     {
       lo |= 1LL << 52;
 
       /* The lower double is normalized separately from the upper.  We may
 	 need to adjust the lower manitissa to reflect this.  */
-      ediff = u.ieee.exponent - u.ieee.exponent2;
+      ediff = u.d[0].ieee.exponent - u.d[1].ieee.exponent;
       if (ediff > 53)
 	lo = lo >> (ediff-53);
     }
@@ -59,8 +59,8 @@ __mpn_extract_long_double (mp_ptr res_ptr, mp_size_t size,
      difference between the long double and the rounded high double
      value.  This is indicated by a differnce between the signs of the
      high and low doubles.  */
-  if ((u.ieee.negative != u.ieee.negative2)
-      && ((u.ieee.exponent2 != 0) && (lo != 0L)))
+  if ((u.d[0].ieee.negative != u.d[1].ieee.negative)
+      && ((u.d[1].ieee.exponent != 0) && (lo != 0L)))
     {
       lo = (1ULL << 53) - lo;
       if (hi == 0LL)
@@ -92,7 +92,7 @@ __mpn_extract_long_double (mp_ptr res_ptr, mp_size_t size,
 #define NUM_LEADING_ZEROS (BITS_PER_MP_LIMB \
 			   - (LDBL_MANT_DIG - ((N - 1) * BITS_PER_MP_LIMB)))
 
-  if (u.ieee.exponent == 0)
+  if (u.d[0].ieee.exponent == 0)
     {
       /* A biased exponent of zero is a special case.
 	 Either it is a zero or it is a denormal number.  */
diff --git a/sysdeps/ieee754/ldbl-128ibm/math_ldbl.h b/sysdeps/ieee754/ldbl-128ibm/math_ldbl.h
index 046293e..3036f14 100644
--- a/sysdeps/ieee754/ldbl-128ibm/math_ldbl.h
+++ b/sysdeps/ieee754/ldbl-128ibm/math_ldbl.h
@@ -15,28 +15,28 @@ ldbl_extract_mantissa (int64_t *hi64, uint64_t *lo64, int *exp, long double x)
      as bit 53 of the mantissa.  */
   uint64_t hi, lo;
   int ediff;
-  union ibm_extended_long_double eldbl;
-  eldbl.d = x;
-  *exp = eldbl.ieee.exponent - IBM_EXTENDED_LONG_DOUBLE_BIAS;
+  union ibm_extended_long_double u;
+  u.ld = x;
+  *exp = u.d[0].ieee.exponent - IEEE754_DOUBLE_BIAS;
 
-  lo = ((int64_t)eldbl.ieee.mantissa2 << 32) | eldbl.ieee.mantissa3;
-  hi = ((int64_t)eldbl.ieee.mantissa0 << 32) | eldbl.ieee.mantissa1;
+  lo = ((uint64_t) u.d[1].ieee.mantissa0 << 32) | u.d[1].ieee.mantissa1;
+  hi = ((uint64_t) u.d[0].ieee.mantissa0 << 32) | u.d[0].ieee.mantissa1;
   /* If the lower double is not a denomal or zero then set the hidden
      53rd bit.  */
-  if (eldbl.ieee.exponent2 > 0x001)
+  if (u.d[1].ieee.exponent > 0x001)
     {
       lo |= (1ULL << 52);
       lo = lo << 7; /* pre-shift lo to match ieee854.  */
       /* The lower double is normalized separately from the upper.  We
 	 may need to adjust the lower manitissa to reflect this.  */
-      ediff = eldbl.ieee.exponent - eldbl.ieee.exponent2;
+      ediff = u.d[0].ieee.exponent - u.d[1].ieee.exponent;
       if (ediff > 53)
 	lo = lo >> (ediff-53);
       hi |= (1ULL << 52);
     }
 
-  if ((eldbl.ieee.negative != eldbl.ieee.negative2)
-      && ((eldbl.ieee.exponent2 != 0) && (lo != 0LL)))
+  if ((u.d[0].ieee.negative != u.d[1].ieee.negative)
+      && ((u.d[1].ieee.exponent != 0) && (lo != 0LL)))
     {
       hi--;
       lo = (1ULL << 60) - lo;
@@ -59,10 +59,10 @@ ldbl_insert_mantissa (int sign, int exp, int64_t hi64, u_int64_t lo64)
   unsigned long hidden2, lzcount;
   unsigned long long hi, lo;
 
-  u.ieee.negative = sign;
-  u.ieee.negative2 = sign;
-  u.ieee.exponent = exp + IBM_EXTENDED_LONG_DOUBLE_BIAS;
-  u.ieee.exponent2 = exp-53 + IBM_EXTENDED_LONG_DOUBLE_BIAS;
+  u.d[0].ieee.negative = sign;
+  u.d[1].ieee.negative = sign;
+  u.d[0].ieee.exponent = exp + IEEE754_DOUBLE_BIAS;
+  u.d[1].ieee.exponent = exp-53 + IEEE754_DOUBLE_BIAS;
   /* Expect 113 bits (112 bits + hidden) right justified in two longs.
      The low order 53 bits (52 + hidden) go into the lower double */
   lo = (lo64 >> 7)& ((1ULL << 53) - 1);
@@ -79,7 +79,7 @@ ldbl_insert_mantissa (int sign, int exp, int64_t hi64, u_int64_t lo64)
       if (hidden2)
 	{
 	  hi++;
-	  u.ieee.negative2 = !sign;
+	  u.d[1].ieee.negative = !sign;
 	  lo = (1ULL << 53) - lo;
 	}
       /* The hidden bit of the lo mantissa is zero so we need to
@@ -95,32 +95,32 @@ ldbl_insert_mantissa (int sign, int exp, int64_t hi64, u_int64_t lo64)
       lzcount = lzcount - 11;
       if (lzcount > 0)
 	{
-	  int expnt2 = u.ieee.exponent2 - lzcount;
+	  int expnt2 = u.d[1].ieee.exponent - lzcount;
 	  if (expnt2 >= 1)
 	    {
 	      /* Not denormal.  Normalize and set low exponent.  */
 	      lo = lo << lzcount;
-	      u.ieee.exponent2 = expnt2;
+	      u.d[1].ieee.exponent = expnt2;
 	    }
 	  else
 	    {
 	      /* Is denormal.  */
 	      lo = lo << (lzcount + expnt2);
-	      u.ieee.exponent2 = 0;
+	      u.d[1].ieee.exponent = 0;
 	    }
 	}
     }
   else
     {
-      u.ieee.negative2 = 0;
-      u.ieee.exponent2 = 0;
+      u.d[1].ieee.negative = 0;
+      u.d[1].ieee.exponent = 0;
     }
 
-  u.ieee.mantissa3 = lo & ((1ULL << 32) - 1);
-  u.ieee.mantissa2 = (lo >> 32) & ((1ULL << 20) - 1);
-  u.ieee.mantissa1 = hi & ((1ULL << 32) - 1);
-  u.ieee.mantissa0 = (hi >> 32) & ((1ULL << 20) - 1);
-  return u.d;
+  u.d[1].ieee.mantissa1 = lo & ((1ULL << 32) - 1);
+  u.d[1].ieee.mantissa0 = (lo >> 32) & ((1ULL << 20) - 1);
+  u.d[0].ieee.mantissa1 = hi & ((1ULL << 32) - 1);
+  u.d[0].ieee.mantissa0 = (hi >> 32) & ((1ULL << 20) - 1);
+  return u.ld;
 }
 
 /* Handy utility functions to pack/unpack/cononicalize and find the nearbyint
@@ -129,18 +129,18 @@ static inline long double
 default_ldbl_pack (double a, double aa)
 {
   union ibm_extended_long_double u;
-  u.dd[0] = a;
-  u.dd[1] = aa;
-  return u.d;
+  u.d[0].d = a;
+  u.d[1].d = aa;
+  return u.ld;
 }
 
 static inline void
 default_ldbl_unpack (long double l, double *a, double *aa)
 {
   union ibm_extended_long_double u;
-  u.d = l;
-  *a = u.dd[0];
-  *aa = u.dd[1];
+  u.ld = l;
+  *a = u.d[0].d;
+  *aa = u.d[1].d;
 }
 
 #ifndef ldbl_pack
diff --git a/sysdeps/ieee754/ldbl-128ibm/mpn2ldbl.c b/sysdeps/ieee754/ldbl-128ibm/mpn2ldbl.c
index 3df42c5..c3e42f2 100644
--- a/sysdeps/ieee754/ldbl-128ibm/mpn2ldbl.c
+++ b/sysdeps/ieee754/ldbl-128ibm/mpn2ldbl.c
@@ -33,11 +33,11 @@ __mpn_construct_long_double (mp_srcptr frac_ptr, int expt, int sign)
   unsigned long long hi, lo;
   int exponent2;
 
-  u.ieee.negative = sign;
-  u.ieee.negative2 = sign;
-  u.ieee.exponent = expt + IBM_EXTENDED_LONG_DOUBLE_BIAS;
-  u.ieee.exponent2 = 0;
-  exponent2 = expt - 53 + IBM_EXTENDED_LONG_DOUBLE_BIAS;
+  u.d[0].ieee.negative = sign;
+  u.d[1].ieee.negative = sign;
+  u.d[0].ieee.exponent = expt + IEEE754_DOUBLE_BIAS;
+  u.d[1].ieee.exponent = 0;
+  exponent2 = expt - 53 + IEEE754_DOUBLE_BIAS;
 
 #if BITS_PER_MP_LIMB == 32
   /* The low order 53 bits (52 + hidden) go into the lower double */
@@ -73,15 +73,15 @@ __mpn_construct_long_double (mp_srcptr frac_ptr, int expt, int sign)
       else
 	lzcount = lzcount + 42;
 
-      if (lzcount > u.ieee.exponent)
+      if (lzcount > u.d[0].ieee.exponent)
 	{
-	  lzcount = u.ieee.exponent;
-	  u.ieee.exponent = 0;
+	  lzcount = u.d[0].ieee.exponent;
+	  u.d[0].ieee.exponent = 0;
 	  exponent2 -= lzcount;
 	}
       else
 	{
-	  u.ieee.exponent -= (lzcount - 1);
+	  u.d[0].ieee.exponent -= (lzcount - 1);
 	  exponent2 -= (lzcount - 1);
 	}
 
@@ -111,9 +111,9 @@ __mpn_construct_long_double (mp_srcptr frac_ptr, int expt, int sign)
 	    {
 	      if ((hi & (1LL << 53)) != 0)
 		hi -= 1LL << 52;
-	      u.ieee.exponent++;
+	      u.d[0].ieee.exponent++;
 	    }
-	  u.ieee.negative2 = !sign;
+	  u.d[1].ieee.negative = !sign;
 	  lo = (1LL << 53) - lo;
 	}
 
@@ -134,17 +134,17 @@ __mpn_construct_long_double (mp_srcptr frac_ptr, int expt, int sign)
 	  exponent2 = exponent2 - lzcount;
 	}
       if (exponent2 > 0)
-	u.ieee.exponent2 = exponent2;
+	u.d[1].ieee.exponent = exponent2;
       else
 	lo >>= 1 - exponent2;
     }
   else
-    u.ieee.negative2 = 0;
+    u.d[1].ieee.negative = 0;
 
-  u.ieee.mantissa3 = lo & 0xffffffffLL;
-  u.ieee.mantissa2 = (lo >> 32) & 0xfffff;
-  u.ieee.mantissa1 = hi & 0xffffffffLL;
-  u.ieee.mantissa0 = (hi >> 32) & ((1LL << (LDBL_MANT_DIG - 86)) - 1);
+  u.d[1].ieee.mantissa1 = lo & 0xffffffffLL;
+  u.d[1].ieee.mantissa0 = (lo >> 32) & 0xfffff;
+  u.d[0].ieee.mantissa1 = hi & 0xffffffffLL;
+  u.d[0].ieee.mantissa0 = (hi >> 32) & ((1LL << (LDBL_MANT_DIG - 86)) - 1);
 
-  return u.d;
+  return u.ld;
 }
diff --git a/sysdeps/ieee754/ldbl-128ibm/printf_fphex.c b/sysdeps/ieee754/ldbl-128ibm/printf_fphex.c
index 247dc20..3fe8333 100644
--- a/sysdeps/ieee754/ldbl-128ibm/printf_fphex.c
+++ b/sysdeps/ieee754/ldbl-128ibm/printf_fphex.c
@@ -26,31 +26,31 @@ do {									      \
       unsigned long long int num0, num1;				      \
       unsigned long long hi, lo;					      \
       int ediff;							      \
-      union ibm_extended_long_double eldbl;				      \
-      eldbl.d = fpnum.ldbl.d;						      \
+      union ibm_extended_long_double u;					      \
+      u.ld = fpnum.ldbl.d;						      \
 									      \
       assert (sizeof (long double) == 16);				      \
 									      \
-      lo = ((long long)eldbl.ieee.mantissa2 << 32) | eldbl.ieee.mantissa3;    \
-      hi = ((long long)eldbl.ieee.mantissa0 << 32) | eldbl.ieee.mantissa1;    \
+      lo = ((long long)u.d[1].ieee.mantissa0 << 32) | u.d[1].ieee.mantissa1;  \
+      hi = ((long long)u.d[0].ieee.mantissa0 << 32) | u.d[0].ieee.mantissa1;  \
       lo <<= 7; /* pre-shift lo to match ieee854.  */			      \
       /* If the lower double is not a denomal or zero then set the hidden     \
 	 53rd bit.  */							      \
-      if (eldbl.ieee.exponent2 != 0)					      \
+      if (u.d[1].ieee.exponent != 0)					      \
 	lo |= (1ULL << (52 + 7));					      \
       else								      \
 	lo <<= 1;							      \
       /* The lower double is normalized separately from the upper.  We	      \
 	 may need to adjust the lower manitissa to reflect this.  */	      \
-      ediff = eldbl.ieee.exponent - eldbl.ieee.exponent2;		      \
+      ediff = u.d[0].ieee.exponent - u.d[1].ieee.exponent;		      \
       if (ediff > 53 + 63)						      \
 	lo = 0;								      \
       else if (ediff > 53)						      \
 	lo = lo >> (ediff - 53);					      \
-      else if (eldbl.ieee.exponent2 == 0 && ediff < 53)			      \
+      else if (u.d[1].ieee.exponent == 0 && ediff < 53)			      \
 	lo = lo << (53 - ediff);					      \
-      if (eldbl.ieee.negative != eldbl.ieee.negative2			      \
-	  && (eldbl.ieee.exponent2 != 0 || lo != 0L))			      \
+      if (u.d[0].ieee.negative != u.d[1].ieee.negative			      \
+	  && (u.d[1].ieee.exponent != 0 || lo != 0L))			      \
 	{								      \
 	  lo = (1ULL << 60) - lo;					      \
 	  if (hi == 0L)							      \
@@ -58,7 +58,7 @@ do {									      \
 	      /* we have a borrow from the hidden bit, so shift left 1.  */   \
 	      hi = 0xffffffffffffeLL | (lo >> 59);			      \
 	      lo = 0xfffffffffffffffLL & (lo << 1);			      \
-	      eldbl.ieee.exponent--;					      \
+	      u.d[0].ieee.exponent--;					      \
 	    }								      \
 	  else								      \
 	    hi--;							      \
@@ -109,9 +109,9 @@ do {									      \
 	  *--wnumstr = L'0';						      \
 	}								      \
 									      \
-      leading = eldbl.ieee.exponent == 0 ? '0' : '1';			      \
+      leading = u.d[0].ieee.exponent == 0 ? '0' : '1';			      \
 									      \
-      exponent = eldbl.ieee.exponent;					      \
+      exponent = u.d[0].ieee.exponent;					      \
 									      \
       if (exponent == 0)						      \
 	{								      \
@@ -121,18 +121,18 @@ do {									      \
 	    {								      \
 	      /* This is a denormalized number.  */			      \
 	      expnegative = 1;						      \
-	      exponent = IBM_EXTENDED_LONG_DOUBLE_BIAS - 1;		      \
+	      exponent = IEEE754_DOUBLE_BIAS - 1;			      \
 	    }								      \
 	}								      \
-      else if (exponent >= IBM_EXTENDED_LONG_DOUBLE_BIAS)		      \
+      else if (exponent >= IEEE754_DOUBLE_BIAS)				      \
 	{								      \
 	  expnegative = 0;						      \
-	  exponent -= IBM_EXTENDED_LONG_DOUBLE_BIAS;			      \
+	  exponent -= IEEE754_DOUBLE_BIAS;				      \
 	}								      \
       else								      \
 	{								      \
 	  expnegative = 1;						      \
-	  exponent = -(exponent - IBM_EXTENDED_LONG_DOUBLE_BIAS);	      \
+	  exponent = -(exponent - IEEE754_DOUBLE_BIAS);			      \
 	}								      \
 } while (0)
 
diff --git a/sysdeps/ieee754/ldbl-128ibm/s_nearbyintl.c b/sysdeps/ieee754/ldbl-128ibm/s_nearbyintl.c
index bfcd110..92ced52 100644
--- a/sysdeps/ieee754/ldbl-128ibm/s_nearbyintl.c
+++ b/sysdeps/ieee754/ldbl-128ibm/s_nearbyintl.c
@@ -34,11 +34,11 @@ __nearbyintl (long double x)
   fenv_t env;
   static const long double TWO52 = 4503599627370496.0L;
   union ibm_extended_long_double u;
-  u.d = x;
+  u.ld = x;
 
-  if (fabs (u.dd[0]) < TWO52)
+  if (fabs (u.d[0].d) < TWO52)
     {
-      double high = u.dd[0];
+      double high = u.d[0].d;
       feholdexcept (&env);
       if (high > 0.0)
 	{
@@ -52,13 +52,13 @@ __nearbyintl (long double x)
 	  high += TWO52;
           if (high == 0.0) high = -0.0;
 	}
-      u.dd[0] = high;
-      u.dd[1] = 0.0;
-      math_force_eval (u.dd[0]);
-      math_force_eval (u.dd[1]);
+      u.d[0].d = high;
+      u.d[1].d = 0.0;
+      math_force_eval (u.d[0]);
+      math_force_eval (u.d[1]);
       fesetenv (&env);
     }
-  else if (fabs (u.dd[1]) < TWO52 && u.dd[1] != 0.0)
+  else if (fabs (u.d[1].d) < TWO52 && u.d[1].d != 0.0)
     {
       double high, low, tau;
       /* In this case we have to round the low double and handle any
@@ -67,57 +67,57 @@ __nearbyintl (long double x)
          may already be rounded and the low double may have the
          opposite sign to compensate.  */
       feholdexcept (&env);
-      if (u.dd[0] > 0.0)
+      if (u.d[0].d > 0.0)
 	{
-	  if (u.dd[1] > 0.0)
+	  if (u.d[1].d > 0.0)
 	    {
 	      /* If the high/low doubles are the same sign then simply
 	         round the low double.  */
-	      high = u.dd[0];
-	      low = u.dd[1];
+	      high = u.d[0].d;
+	      low = u.d[1].d;
 	    }
-	  else if (u.dd[1] < 0.0)
+	  else if (u.d[1].d < 0.0)
 	    {
 	      /* Else the high double is pre rounded and we need to
 	         adjust for that.  */
 
-	      tau = __nextafter (u.dd[0], 0.0);
-	      tau = (u.dd[0] - tau) * 2.0;
-	      high = u.dd[0] - tau;
-	      low = u.dd[1] + tau;
+	      tau = __nextafter (u.d[0].d, 0.0);
+	      tau = (u.d[0].d - tau) * 2.0;
+	      high = u.d[0].d - tau;
+	      low = u.d[1].d + tau;
 	    }
 	  low += TWO52;
 	  low -= TWO52;
 	}
-      else if (u.dd[0] < 0.0)
+      else if (u.d[0].d < 0.0)
 	{
-	  if (u.dd[1] < 0.0)
+	  if (u.d[1].d < 0.0)
 	    {
 	      /* If the high/low doubles are the same sign then simply
 	         round the low double.  */
-	      high = u.dd[0];
-	      low = u.dd[1];
+	      high = u.d[0].d;
+	      low = u.d[1].d;
 	    }
-	  else if (u.dd[1] > 0.0)
+	  else if (u.d[1].d > 0.0)
 	    {
 	      /* Else the high double is pre rounded and we need to
 	         adjust for that.  */
-	      tau = __nextafter (u.dd[0], 0.0);
-	      tau = (u.dd[0] - tau) * 2.0;
-	      high = u.dd[0] - tau;
-	      low = u.dd[1] + tau;
+	      tau = __nextafter (u.d[0].d, 0.0);
+	      tau = (u.d[0].d - tau) * 2.0;
+	      high = u.d[0].d - tau;
+	      low = u.d[1].d + tau;
 	    }
 	  low = TWO52 - low;
 	  low = -(low - TWO52);
 	}
-      u.dd[0] = high + low;
-      u.dd[1] = high - u.dd[0] + low;
-      math_force_eval (u.dd[0]);
-      math_force_eval (u.dd[1]);
+      u.d[0].d = high + low;
+      u.d[1].d = high - u.d[0].d + low;
+      math_force_eval (u.d[0]);
+      math_force_eval (u.d[1]);
       fesetenv (&env);
     }
 
-  return u.d;
+  return u.ld;
 }
 
 long_double_symbol (libm, __nearbyintl, nearbyintl);
diff --git a/sysdeps/ieee754/ldbl-128ibm/strtold_l.c b/sysdeps/ieee754/ldbl-128ibm/strtold_l.c
index 04e3288..93a80c5 100644
--- a/sysdeps/ieee754/ldbl-128ibm/strtold_l.c
+++ b/sysdeps/ieee754/ldbl-128ibm/strtold_l.c
@@ -43,11 +43,11 @@ libc_hidden_proto (STRTOF)
 #define FLOAT_HUGE_VAL	HUGE_VALL
 # define SET_MANTISSA(flt, mant) \
   do { union ibm_extended_long_double u;				      \
-       u.d = (flt);							      \
-       u.ieee_nan.mantissa0 = (mant) >> 32;				      \
-       u.ieee_nan.mantissa1 = (mant);					      \
-       if ((u.ieee.mantissa0 | u.ieee.mantissa1) != 0)			      \
-	 (flt) = u.d;							      \
+       u.ld = (flt);							      \
+       u.d[0].ieee_nan.mantissa0 = (mant) >> 32;			      \
+       u.d[0].ieee_nan.mantissa1 = (mant);				      \
+       if ((u.d[0].ieee.mantissa0 | u.d[0].ieee.mantissa1) != 0)	      \
+	 (flt) = u.ld;							      \
   } while (0)
 
 #include <strtod_l.c>
diff --git a/sysdeps/ieee754/ldbl-128ibm/x2y2m1l.c b/sysdeps/ieee754/ldbl-128ibm/x2y2m1l.c
index ed0d4a5..06dcf02 100644
--- a/sysdeps/ieee754/ldbl-128ibm/x2y2m1l.c
+++ b/sysdeps/ieee754/ldbl-128ibm/x2y2m1l.c
@@ -89,23 +89,23 @@ __x2y2m1l (long double x, long double y)
   double vals[12];
   SET_RESTORE_ROUND (FE_TONEAREST);
   union ibm_extended_long_double xu, yu;
-  xu.d = x;
-  yu.d = y;
-  if (fabs (xu.dd[1]) < 0x1p-500)
-    xu.dd[1] = 0.0;
-  if (fabs (yu.dd[1]) < 0x1p-500)
-    yu.dd[1] = 0.0;
-  mul_split (&vals[1], &vals[0], xu.dd[0], xu.dd[0]);
-  mul_split (&vals[3], &vals[2], xu.dd[0], xu.dd[1]);
+  xu.ld = x;
+  yu.ld = y;
+  if (fabs (xu.d[1].d) < 0x1p-500)
+    xu.d[1].d = 0.0;
+  if (fabs (yu.d[1].d) < 0x1p-500)
+    yu.d[1].d = 0.0;
+  mul_split (&vals[1], &vals[0], xu.d[0].d, xu.d[0].d);
+  mul_split (&vals[3], &vals[2], xu.d[0].d, xu.d[1].d);
   vals[2] *= 2.0;
   vals[3] *= 2.0;
-  mul_split (&vals[5], &vals[4], xu.dd[1], xu.dd[1]);
-  mul_split (&vals[7], &vals[6], yu.dd[0], yu.dd[0]);
-  mul_split (&vals[9], &vals[8], yu.dd[0], yu.dd[1]);
+  mul_split (&vals[5], &vals[4], xu.d[1].d, xu.d[1].d);
+  mul_split (&vals[7], &vals[6], yu.d[0].d, yu.d[0].d);
+  mul_split (&vals[9], &vals[8], yu.d[0].d, yu.d[1].d);
   vals[8] *= 2.0;
   vals[9] *= 2.0;
-  mul_split (&vals[11], &vals[10], yu.dd[1], yu.dd[1]);
-  if (xu.dd[0] >= 0.75)
+  mul_split (&vals[11], &vals[10], yu.d[1].d, yu.d[1].d);
+  if (xu.d[0].d >= 0.75)
     vals[1] -= 1.0;
   else
     {

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=00db055f5a63816c6c44e2cd7d17252140410fab

commit 00db055f5a63816c6c44e2cd7d17252140410fab
Author: Allan McRae <allan@archlinux.org>
Date:   Mon Sep 9 22:52:58 2013 +1000

    Fix memory leak in stdlib/isomac.c

diff --git a/ChangeLog b/ChangeLog
index 7d32373..9d04543 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,8 @@
 2013-09-09  Allan McRae  <allan@archlinux.org>
 
+	[BZ #15893]
+	* stdlib/isomac.c (get_null_defines): Fix memory leak.
+
 	[BZ #15892]
 	* libio/memstream.c (open_memstream): Fix memory leak.
 	* libio/wmemstream.c (open_wmemstream): Likewise.
diff --git a/NEWS b/NEWS
index e879adb..b25af8e 100644
--- a/NEWS
+++ b/NEWS
@@ -33,7 +33,8 @@ Version 2.18
   15423, 15424, 15426, 15427, 15429, 15431, 15432, 15441, 15442, 15448,
   15465, 15480, 15485, 15488, 15490, 15492, 15493, 15497, 15506, 15522,
   15529, 15532, 15536, 15553, 15577, 15583, 15618, 15627, 15631, 15654,
-  15655, 15666, 15667, 15674, 15711, 15755, 15759, 15797, 15892, 15895.
+  15655, 15666, 15667, 15674, 15711, 15755, 15759, 15797, 15892, 15893,
+  15895.
 
 * CVE-2013-2207 Incorrectly granting access to another user's pseudo-terminal
   has been fixed by disabling the use of pt_chown (Bugzilla #15755).
diff --git a/stdlib/isomac.c b/stdlib/isomac.c
index 2c9009b..621b515 100644
--- a/stdlib/isomac.c
+++ b/stdlib/isomac.c
@@ -263,6 +263,7 @@ get_null_defines (void)
   if (system (command))
     {
       puts ("system() returned nonzero");
+      free (command);
       return NULL;
     }
   free (command);

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=2140e39e13ce3def5dc0e1037f3d7d2be0ab1fd1

commit 2140e39e13ce3def5dc0e1037f3d7d2be0ab1fd1
Author: Allan McRae <allan@archlinux.org>
Date:   Mon Sep 9 22:50:41 2013 +1000

    Fix memory leaks in libio on allocation failure

diff --git a/ChangeLog b/ChangeLog
index 61494ca..7d32373 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+2013-09-09  Allan McRae  <allan@archlinux.org>
+
+	[BZ #15892]
+	* libio/memstream.c (open_memstream): Fix memory leak.
+	* libio/wmemstream.c (open_wmemstream): Likewise.
+
+	[BZ #15895]
+	* nscd/netgroupcache.c: Fix nesting of ifdefs.
+
 2013-09-05  Adhemerval Zanella  <azanella@linux.vnet.ibm.com>
 
 	* sysdeps/powerpc/powerpc32/power7/memrchr.S (__memrchr): Fix invalid
diff --git a/NEWS b/NEWS
index a71d9fa..e879adb 100644
--- a/NEWS
+++ b/NEWS
@@ -9,7 +9,8 @@ Version 2.18.1
 
 * The following bugs are resolved with this release:
 
-  14155, 14699, 15532, 15427, 15522, 15797, 15909, 15996, 16150.
+  14155, 14699, 15532, 15427, 15522, 15797, 15892, 15895, 15909, 15996,
+  16150.
 
 * CVE-2013-4237 The readdir_r function could write more than NAME_MAX bytes
   to the d_name member of struct dirent, or omit the terminating NUL
@@ -21,18 +22,18 @@ Version 2.18
 
   2546, 2560, 5159, 6809, 7006, 10060, 10062, 10283, 10357, 10686, 11120,
   11561, 12310, 12387, 12492, 12515, 12723, 13550, 13889, 13951, 13988,
-  14142, 14176, 14200, 14256, 14280, 14293, 14317, 14327, 14478, 14496,
-  14582, 14686, 14812, 14888, 14894, 14907, 14908, 14909, 14920, 14952,
-  14964, 14981, 14982, 14985, 14991, 14994, 14996, 15000, 15003, 15006,
-  15007, 15014, 15020, 15022, 15023, 15036, 15054, 15055, 15062, 15078,
-  15084, 15085, 15086, 15100, 15160, 15214, 15221, 15232, 15234, 15283,
-  15285, 15287, 15304, 15305, 15307, 15309, 15327, 15330, 15335, 15336,
-  15337, 15339, 15342, 15346, 15359, 15361, 15366, 15380, 15381, 15394,
-  15395, 15405, 15406, 15409, 15416, 15418, 15419, 15423, 15424, 15426,
-  15429, 15431, 15432, 15441, 15442, 15448, 15465, 15480, 15485, 15488,
-  15490, 15492, 15493, 15497, 15506, 15529, 15536, 15553, 15577, 15583,
-  15618, 15627, 15631, 15654, 15655, 15666, 15667, 15674, 15711, 15755,
-  15759, 15985.
+  14142, 14155, 14176, 14200, 14256, 14280, 14293, 14317, 14327, 14478,
+  14496, 14582, 14686, 14699, 14812, 14888, 14894, 14907, 14908, 14909,
+  14920, 14952, 14964, 14981, 14982, 14985, 14991, 14994, 14996, 15000,
+  15003, 15006, 15007, 15014, 15020, 15022, 15023, 15036, 15054, 15055,
+  15062, 15078, 15084, 15085, 15086, 15100, 15160, 15214, 15221, 15232,
+  15234, 15283, 15285, 15287, 15304, 15305, 15307, 15309, 15327, 15330,
+  15331, 15335, 15336, 15337, 15339, 15342, 15346, 15359, 15361, 15366,
+  15380, 15381, 15394, 15395, 15405, 15406, 15409, 15416, 15418, 15419,
+  15423, 15424, 15426, 15427, 15429, 15431, 15432, 15441, 15442, 15448,
+  15465, 15480, 15485, 15488, 15490, 15492, 15493, 15497, 15506, 15522,
+  15529, 15532, 15536, 15553, 15577, 15583, 15618, 15627, 15631, 15654,
+  15655, 15666, 15667, 15674, 15711, 15755, 15759, 15797, 15892, 15895.
 
 * CVE-2013-2207 Incorrectly granting access to another user's pseudo-terminal
   has been fixed by disabling the use of pt_chown (Bugzilla #15755).
diff --git a/libio/memstream.c b/libio/memstream.c
index 34534e2..3cb1bd7 100644
--- a/libio/memstream.c
+++ b/libio/memstream.c
@@ -84,7 +84,10 @@ open_memstream (bufloc, sizeloc)
 
   buf = calloc (1, _IO_BUFSIZ);
   if (buf == NULL)
-    return NULL;
+    {
+      free (new_f);
+      return NULL;
+    }
   _IO_init (&new_f->fp._sf._sbf._f, 0);
   _IO_JUMPS ((struct _IO_FILE_plus *) &new_f->fp._sf._sbf) = &_IO_mem_jumps;
   _IO_str_init_static_internal (&new_f->fp._sf, buf, _IO_BUFSIZ, buf);
diff --git a/libio/wmemstream.c b/libio/wmemstream.c
index 65738d4..fd7fe44 100644
--- a/libio/wmemstream.c
+++ b/libio/wmemstream.c
@@ -85,8 +85,10 @@ open_wmemstream (bufloc, sizeloc)
 
   buf = calloc (1, _IO_BUFSIZ);
   if (buf == NULL)
-    return NULL;
-
+    {
+      free (new_f);
+      return NULL;
+    }
   _IO_no_init (&new_f->fp._sf._sbf._f, 0, 0, &new_f->wd, &_IO_wmem_jumps);
   _IO_fwide (&new_f->fp._sf._sbf._f, 1);
   _IO_wstr_init_static (&new_f->fp._sf._sbf._f, buf,

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=9013984941a46d8c361299f531ea79527fba4d1c

commit 9013984941a46d8c361299f531ea79527fba4d1c
Author: Adhemerval Zanella <azanella@linux.vnet.ibm.com>
Date:   Thu Sep 5 09:32:56 2013 -0500

    PowerPC: fix POWER7 memrchr for some large inputs

diff --git a/ChangeLog b/ChangeLog
index 5ff3fa4..61494ca 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,11 @@
 2013-09-05  Adhemerval Zanella  <azanella@linux.vnet.ibm.com>
 
+	* sysdeps/powerpc/powerpc32/power7/memrchr.S (__memrchr): Fix invalid
+	memory access for final bytes in some large inputs.
+	* sysdeps/powerpc/powerpc64/power7/memrchr.S (__memrchr): Likewise.
+
+2013-09-05  Adhemerval Zanella  <azanella@linux.vnet.ibm.com>
+
 	* string/test-memrchr.c: New file.
 	* string/test-memrchr-ifunc.c: New file.
 	* string/Makefile: Add new memrchr testcase.
diff --git a/sysdeps/powerpc/powerpc32/power7/memrchr.S b/sysdeps/powerpc/powerpc32/power7/memrchr.S
index d1e3fda..defd832 100644
--- a/sysdeps/powerpc/powerpc32/power7/memrchr.S
+++ b/sysdeps/powerpc/powerpc32/power7/memrchr.S
@@ -101,8 +101,8 @@ L(loop):
 	/* We're here because the counter reached 0, and that means we
 	   didn't have any matches for BYTE in the whole range.  Just return
 	   the original range.  */
-	addi	r9,r8,4
-	cmplw	cr6,r9,r7
+	addi	r8,r8,4
+	cmplw	cr6,r8,r7
 	bgt	cr6,L(loop_small)
 	b	L(null)
 
diff --git a/sysdeps/powerpc/powerpc64/power7/memrchr.S b/sysdeps/powerpc/powerpc64/power7/memrchr.S
index d24fbbb..c499952 100644
--- a/sysdeps/powerpc/powerpc64/power7/memrchr.S
+++ b/sysdeps/powerpc/powerpc64/power7/memrchr.S
@@ -102,8 +102,8 @@ L(loop):
 	/* We're here because the counter reached 0, and that means we
 	   didn't have any matches for BYTE in the whole range.  Just return
 	   the original range.  */
-	addi	r9,r8,8
-	cmpld	cr6,r9,r7
+	addi	r8,r8,8
+	cmpld	cr6,r8,r7
 	bgt	cr6,L(loop_small)
 	b	L(null)
 

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=fd51899bbfe36a9649bca1d11f0f14f8d93d5898

commit fd51899bbfe36a9649bca1d11f0f14f8d93d5898
Author: Adhemerval Zanella <azanella@linux.vnet.ibm.com>
Date:   Thu Aug 29 15:28:00 2013 -0300

    Add memrchr testcase

diff --git a/ChangeLog b/ChangeLog
index be77e26..5ff3fa4 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,9 @@
-<<<<<<< HEAD
-=======
+2013-09-05  Adhemerval Zanella  <azanella@linux.vnet.ibm.com>
+
+	* string/test-memrchr.c: New file.
+	* string/test-memrchr-ifunc.c: New file.
+	* string/Makefile: Add new memrchr testcase.
+
 2013-09-03  Joseph Myers  <joseph@codesourcery.com>
 
 	[BZ #15427]
diff --git a/string/Makefile b/string/Makefile
index 0237edd..72d3e29 100644
--- a/string/Makefile
+++ b/string/Makefile
@@ -45,7 +45,7 @@ strop-tests	:= memchr memcmp memcpy memmove mempcpy memset memccpy	\
 		   stpcpy stpncpy strcat strchr strcmp strcpy strcspn	\
 		   strlen strncmp strncpy strpbrk strrchr strspn memmem	\
 		   strstr strcasestr strnlen strcasecmp strncasecmp	\
-		   strncat rawmemchr strchrnul bcopy bzero
+		   strncat rawmemchr strchrnul bcopy bzero memrchr
 tests		:= tester inl-tester noinl-tester testcopy test-ffs	\
 		   tst-strlen stratcliff tst-svc tst-inlcall		\
 		   bug-strncat1 bug-strspn1 bug-strpbrk1 tst-bswap	\
diff --git a/string/test-memrchr-ifunc.c b/string/test-memrchr-ifunc.c
new file mode 100644
index 0000000..100dedb
--- /dev/null
+++ b/string/test-memrchr-ifunc.c
@@ -0,0 +1,20 @@
+/* Test and measure IFUNC implementations of memrchr function.
+   Copyright (C) 2013 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/>.  */
+
+#define TEST_IFUNC 1
+#include "test-memrchr.c"
diff --git a/string/test-memrchr.c b/string/test-memrchr.c
new file mode 100644
index 0000000..a4fe811
--- /dev/null
+++ b/string/test-memrchr.c
@@ -0,0 +1,169 @@
+/* Test and measure memrchr functions.
+   Copyright (C) 2013 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Written by Jakub Jelinek <jakub@redhat.com>, 1999.
+
+   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/>.  */
+
+#define TEST_MAIN
+#define TEST_NAME "memrchr"
+#include "test-string.h"
+
+typedef char *(*proto_t) (const char *, int, size_t);
+char *simple_memrchr (const char *, int, size_t);
+
+IMPL (simple_memrchr, 0)
+IMPL (memrchr, 1)
+
+char *
+simple_memrchr (const char *s, int c, size_t n)
+{
+  s = s + n;
+  while (n--)
+    if (*--s == (char) c)
+      return (char *) s;
+  return NULL;
+}
+
+static void
+do_one_test (impl_t *impl, const char *s, int c, size_t n, char *exp_res)
+{
+  char *res = CALL (impl, s, c, n);
+  if (res != exp_res)
+    {
+      error (0, 0, "Wrong result in function %s %p %p", impl->name,
+	     res, exp_res);
+      ret = 1;
+      return;
+    }
+}
+
+static void
+do_test (size_t align, size_t pos, size_t len, int seek_char)
+{
+  size_t i;
+  char *result;
+
+  align &= 7;
+  if (align + len >= page_size)
+    return;
+
+  for (i = 0; i < len; ++i)
+    {
+      buf1[align + i] = 1 + 23 * i % 127;
+      if (buf1[align + i] == seek_char)
+        buf1[align + i] = seek_char + 1;
+    }
+  buf1[align + len] = 0;
+
+  if (pos < len)
+    {
+      buf1[align + pos] = seek_char;
+      buf1[align + len] = -seek_char;
+      result = (char *) (buf1 + align + pos);
+    }
+  else
+    {
+      result = NULL;
+      buf1[align + len] = seek_char;
+    }
+
+  FOR_EACH_IMPL (impl, 0)
+    do_one_test (impl, (char *) (buf1 + align), seek_char, len, result);
+}
+
+static void
+do_random_tests (void)
+{
+  size_t i, j, n, align, pos, len;
+  int seek_char;
+  char *result;
+  unsigned char *p = buf1 + page_size - 512;
+
+  for (n = 0; n < ITERATIONS; n++)
+    {
+      align = random () & 15;
+      pos = random () & 511;
+      if (pos + align >= 512)
+	pos = 511 - align - (random () & 7);
+      len = random () & 511;
+      if (pos >= len)
+	len = pos + (random () & 7);
+      if (len + align >= 512)
+        len = 512 - align - (random () & 7);
+      seek_char = random () & 255;
+      j = len + align + 64;
+      if (j > 512)
+        j = 512;
+
+      for (i = 0; i < j; i++)
+	{
+	  if (i == pos + align)
+	    p[i] = seek_char;
+	  else
+	    {
+	      p[i] = random () & 255;
+	      if (p[i] == seek_char)
+		p[i] = seek_char + 13;
+	    }
+	}
+
+      if (pos < len)
+	result = (char *) (p + pos + align);
+      else
+	result = NULL;
+
+      FOR_EACH_IMPL (impl, 1)
+	if (CALL (impl, (char *) (p + align), seek_char, len) != result)
+	  {
+	    error (0, 0, "Iteration %zd - wrong result in function %s (%zd, %d, %zd, %zd) %p != %p, p %p",
+		   n, impl->name, align, seek_char, len, pos,
+		   CALL (impl, (char *) (p + align), seek_char, len),
+		   result, p);
+	    ret = 1;
+	  }
+    }
+}
+
+int
+test_main (void)
+{
+  size_t i;
+
+  test_init ();
+
+  printf ("%20s", "");
+  FOR_EACH_IMPL (impl, 0)
+    printf ("\t%s", impl->name);
+  putchar ('\n');
+
+  for (i = 1; i < 8; ++i)
+    {
+      do_test (0, 16 << i, 2048, 23);
+      do_test (i, 64, 256, 23);
+      do_test (0, 16 << i, 2048, 0);
+      do_test (i, 64, 256, 0);
+    }
+  for (i = 1; i < 32; ++i)
+    {
+      do_test (0, i, i + 1, 23);
+      do_test (0, i, i + 1, 0);
+    }
+
+  do_random_tests ();
+  return ret;
+}
+
+#include "../test-skeleton.c"

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=f0f4db2172678512731d2a095bcf5abf0846d3a3

commit f0f4db2172678512731d2a095bcf5abf0846d3a3
Author: Joseph Myers <joseph@codesourcery.com>
Date:   Tue Sep 3 15:32:54 2013 +0000

    Fix lgammaf spurious underflow (bug 15427).

diff --git a/ChangeLog b/ChangeLog
index 443dcfe..be77e26 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,33 @@
+<<<<<<< HEAD
+=======
+2013-09-03  Joseph Myers  <joseph@codesourcery.com>
+
+	[BZ #15427]
+	* sysdeps/ieee754/flt-32/e_lgammaf_r.c (__ieee754_lgammaf_r): Use
+	2**-30 instead of 2**-70 as threshold for returning -log(|x|).
+	* math/libm-test.inc (lgamma_test_data): Add more tests.
+	* sysdeps/i386/fpu/libm-test-ulps: Update.
+	* sysdeps/x86_64/fpu/libm-test-ulps: Likewise.
+
+2013-09-03   OndÅ?ej Bílka  <neleai@seznam.cz>
+
+	* sysdeps/x86_64/multiarch/strcmp-sse2-unaligned.S: New file.
+	* sysdeps/x86_64/multiarch/ifunc-impl-list.c (__libc_ifunc_impl_list):
+	Add ifunc.
+	* sysdeps/x86_64/multiarch/Makefile (sysdep_routines):
+	Add strcmp-sse2-unaligned
+	* sysdeps/x86_64/multiarch/strcmp.S (strcmp): Add ifunc.
+
+2013-09-02  Mike Frysinger  <vapier@gentoo.org>
+
+	* Versions.def (libc): Add GLIBC_2.19.
+
+2013-09-02  Mike Frysinger  <vapier@gentoo.org>
+
+	* sysdeps/unix/sysv/linux/tst-fanotify.c: New test.
+	* sysdeps/unix/sysv/linux/Makefile (tests): Add tst-fanotify.
+
+>>>>>>> ffa3cd7... Fix lgammaf spurious underflow (bug 15427).
 2013-09-02  Joseph Myers  <joseph@codesourcery.com>
 
 	[BZ #14155]
diff --git a/NEWS b/NEWS
index 935b887..a71d9fa 100644
--- a/NEWS
+++ b/NEWS
@@ -9,7 +9,7 @@ Version 2.18.1
 
 * The following bugs are resolved with this release:
 
-  14155, 14699, 15532, 15522, 15797, 15909, 15996, 16150.
+  14155, 14699, 15532, 15427, 15522, 15797, 15909, 15996, 16150.
 
 * CVE-2013-4237 The readdir_r function could write more than NAME_MAX bytes
   to the d_name member of struct dirent, or omit the terminating NUL
diff --git a/math/libm-test.inc b/math/libm-test.inc
index 9d49255..7a11c90 100644
--- a/math/libm-test.inc
+++ b/math/libm-test.inc
@@ -9973,6 +9973,61 @@ static const struct test_f_f1_data lgamma_test_data[] =
     TEST_f_f1 (lgamma, -0.5, M_LOG_2_SQRT_PIl, -1),
     TEST_f_f1 (lgamma, 0.7L, 0.260867246531666514385732417016759578L, 1),
     TEST_f_f1 (lgamma, 1.2L, -0.853740900033158497197028392998854470e-1L, 1),
+
+    TEST_f_f1 (lgamma, 0x1p-5L, 3.4484891277979584796832693452686366085801e+00L, 1),
+    TEST_f_f1 (lgamma, -0x1p-5L, 3.4845895751341394376217526729956836492792e+00L, -1),
+    TEST_f_f1 (lgamma, 0x1p-10L, 6.9309089024194618895406190646600805357273e+00L, 1),
+    TEST_f_f1 (lgamma, -0x1p-10L, 6.9320362775113082175565786721095494761582e+00L, -1),
+    TEST_f_f1 (lgamma, 0x1p-15L, 1.0397190093941001762077888432721419773538e+01L, 1),
+    TEST_f_f1 (lgamma, -0x1p-15L, 1.0397225324389321751118257981741350715545e+01L, -1),
+    TEST_f_f1 (lgamma, 0x1p-20L, 1.3862943060723899573457963336920089012399e+01L, 1),
+    TEST_f_f1 (lgamma, -0x1p-20L, 1.3862944161675408862049886226750366625112e+01L, -1),
+    TEST_f_f1 (lgamma, 0x1p-25L, 1.7328679496796266133304874243201700664713e+01L, 1),
+    TEST_f_f1 (lgamma, -0x1p-25L, 1.7328679531201000798551671833865469674673e+01L, -1),
+    TEST_f_f1 (lgamma, 0x1p-30L, 2.0794415416260785304085859198055798098863e+01L, 1),
+    TEST_f_f1 (lgamma, -0x1p-30L, 2.0794415417335933262374820960532606449975e+01L, -1),
+    TEST_f_f1 (lgamma, 0x1p-40L, 2.7725887222397287402100277256545578941303e+01L, 1),
+    TEST_f_f1 (lgamma, -0x1p-40L, 2.7725887222398337351278293820766115529596e+01L, -1),
+    TEST_f_f1 (lgamma, 0x1p-50L, 3.4657359027997264958191108994508978906983e+01L, 1),
+    TEST_f_f1 (lgamma, -0x1p-50L, 3.4657359027997265983532103151309975524744e+01L, -1),
+    TEST_f_f1 (lgamma, 0x1p-60L, 4.1588830833596718564533272505187468598519e+01L, 1),
+    TEST_f_f1 (lgamma, -0x1p-60L, 4.1588830833596718565534582069793719571779e+01L, -1),
+    TEST_f_f1 (lgamma, 0x1p-64L, 4.4361419555836499802671564849429355013920e+01L, 1),
+    TEST_f_f1 (lgamma, -0x1p-64L, 4.4361419555836499802734146697217245699749e+01L, -1),
+    TEST_f_f1 (lgamma, 0x1p-70L, 4.8520302639196171659205759581386516869302e+01L, 1),
+    TEST_f_f1 (lgamma, -0x1p-70L, 4.8520302639196171659206737422758202661268e+01L, -1),
+    TEST_f_f1 (lgamma, 0x1p-100L, 6.9314718055994530941723212145817201464678e+01L, 1),
+    TEST_f_f1 (lgamma, -0x1p-100L, 6.9314718055994530941723212145818112150422e+01L, -1),
+    TEST_f_f1 (lgamma, 0x1p-126L, 8.7336544750553108986571247303730247577506e+01L, 1),
+    TEST_f_f1 (lgamma, -0x1p-126L, 8.7336544750553108986571247303730247577520e+01L, -1),
+    TEST_f_f1 (lgamma, 0x1p-149L, 1.0327892990343185110316758609726830864325e+02L, 1),
+    TEST_f_f1 (lgamma, -0x1p-149L, 1.0327892990343185110316758609726830864325e+02L, -1),
+#ifndef TEST_FLOAT
+    TEST_f_f1 (lgamma, 0x1p-200L, 1.3862943611198906188344642429163531361510e+02L, 1),
+    TEST_f_f1 (lgamma, -0x1p-200L, 1.3862943611198906188344642429163531361510e+02L, -1),
+    TEST_f_f1 (lgamma, 0x1p-500L, 3.4657359027997265470861606072908828403775e+02L, 1),
+    TEST_f_f1 (lgamma, -0x1p-500L, 3.4657359027997265470861606072908828403775e+02L, -1),
+    TEST_f_f1 (lgamma, 0x1p-1000L, 6.9314718055994530941723212145817656807550e+02L, 1),
+    TEST_f_f1 (lgamma, -0x1p-1000L, 6.9314718055994530941723212145817656807550e+02L, -1),
+    TEST_f_f1 (lgamma, 0x1p-1022L, 7.0839641853226410622441122813025645257316e+02L, 1),
+    TEST_f_f1 (lgamma, -0x1p-1022L, 7.0839641853226410622441122813025645257316e+02L, -1),
+    TEST_f_f1 (lgamma, 0x1p-1074L, 7.4444007192138126231410729844608163411309e+02L, 1),
+    TEST_f_f1 (lgamma, -0x1p-1074L, 7.4444007192138126231410729844608163411309e+02L, -1),
+#endif
+#if defined TEST_LDOUBLE && LDBL_MIN_EXP <= -16381
+    TEST_f_f1 (lgamma, 0x1p-5000L, 3.4657359027997265470861606072908828403775e+03L, 1),
+    TEST_f_f1 (lgamma, -0x1p-5000L, 3.4657359027997265470861606072908828403775e+03L, -1),
+    TEST_f_f1 (lgamma, 0x1p-10000L, 6.9314718055994530941723212145817656807550e+03L, 1),
+    TEST_f_f1 (lgamma, -0x1p-10000L, 6.9314718055994530941723212145817656807550e+03L, -1),
+    TEST_f_f1 (lgamma, 0x1p-16382L, 1.1355137111933024058873096613727848538213e+04L, 1),
+    TEST_f_f1 (lgamma, -0x1p-16382L, 1.1355137111933024058873096613727848538213e+04L, -1),
+    TEST_f_f1 (lgamma, 0x1p-16445L, 1.1398805384308300613366382237379713662002e+04L, 1),
+    TEST_f_f1 (lgamma, -0x1p-16445L, 1.1398805384308300613366382237379713662002e+04L, -1),
+# if LDBL_MANT_DIG >= 113
+    TEST_f_f1 (lgamma, 0x1p-16494L, 1.1432769596155737933527826611331164313837e+04L, 1),
+    TEST_f_f1 (lgamma, -0x1p-16494L, 1.1432769596155737933527826611331164313837e+04L, -1),
+# endif
+#endif
   };
 
 static void
diff --git a/sysdeps/i386/fpu/libm-test-ulps b/sysdeps/i386/fpu/libm-test-ulps
index 8244863..4759aa9 100644
--- a/sysdeps/i386/fpu/libm-test-ulps
+++ b/sysdeps/i386/fpu/libm-test-ulps
@@ -5470,9 +5470,35 @@ double: 1
 idouble: 1
 ildouble: 1
 ldouble: 1
+Test "gamma (-0x1p-10)":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "gamma (-0x1p-15)":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "gamma (-0x1p-20)":
+double: 1
+idouble: 1
+Test "gamma (-0x1p-30)":
+double: 1
+idouble: 1
+ildouble: 1
+ldouble: 1
+Test "gamma (-0x1p-5)":
+double: 1
+idouble: 1
 Test "gamma (0.7)":
 float: 1
 ifloat: 1
+Test "gamma (0x1p-40)":
+ildouble: 1
+ldouble: 1
 Test "gamma (1.2)":
 double: 1
 float: 2
@@ -5723,9 +5749,35 @@ double: 1
 idouble: 1
 ildouble: 1
 ldouble: 1
+Test "lgamma (-0x1p-10)":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "lgamma (-0x1p-15)":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "lgamma (-0x1p-20)":
+double: 1
+idouble: 1
+Test "lgamma (-0x1p-30)":
+double: 1
+idouble: 1
+ildouble: 1
+ldouble: 1
+Test "lgamma (-0x1p-5)":
+double: 1
+idouble: 1
 Test "lgamma (0.7)":
 float: 1
 ifloat: 1
+Test "lgamma (0x1p-40)":
+ildouble: 1
+ldouble: 1
 Test "lgamma (1.2)":
 double: 1
 float: 2
diff --git a/sysdeps/ieee754/flt-32/e_lgammaf_r.c b/sysdeps/ieee754/flt-32/e_lgammaf_r.c
index 2e92269..0dba9af 100644
--- a/sysdeps/ieee754/flt-32/e_lgammaf_r.c
+++ b/sysdeps/ieee754/flt-32/e_lgammaf_r.c
@@ -150,8 +150,8 @@ __ieee754_lgammaf_r(float x, int *signgamp)
 	      *signgamp = -1;
 	    return one/fabsf(x);
 	  }
-	if(__builtin_expect(ix<0x1c800000, 0)) {
-	    /* |x|<2**-70, return -log(|x|) */
+	if(__builtin_expect(ix<0x30800000, 0)) {
+	    /* |x|<2**-30, return -log(|x|) */
 	    if(hx<0) {
 		*signgamp = -1;
 		return -__ieee754_logf(-x);
diff --git a/sysdeps/x86_64/fpu/libm-test-ulps b/sysdeps/x86_64/fpu/libm-test-ulps
index 477eedc..6fbfa64 100644
--- a/sysdeps/x86_64/fpu/libm-test-ulps
+++ b/sysdeps/x86_64/fpu/libm-test-ulps
@@ -6222,11 +6222,39 @@ idouble: 1
 Test "gamma (-0.5)":
 ildouble: 1
 ldouble: 1
+Test "gamma (-0x1p-10)":
+double: 1
+idouble: 1
+ildouble: 1
+ldouble: 1
+Test "gamma (-0x1p-15)":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "gamma (-0x1p-20)":
+double: 1
+idouble: 1
+Test "gamma (-0x1p-30)":
+ildouble: 1
+ldouble: 1
+Test "gamma (-0x1p-5)":
+double: 1
+idouble: 1
 Test "gamma (0.7)":
 double: 1
 float: 1
 idouble: 1
 ifloat: 1
+Test "gamma (0x1p-10)":
+float: 1
+ifloat: 1
+Test "gamma (0x1p-30)":
+double: 1
+idouble: 1
+Test "gamma (0x1p-40)":
+ildouble: 1
+ldouble: 1
 Test "gamma (1.2)":
 double: 1
 float: 2
@@ -6491,11 +6519,39 @@ ldouble: 2
 Test "lgamma (-0.5)":
 ildouble: 1
 ldouble: 1
+Test "lgamma (-0x1p-10)":
+double: 1
+idouble: 1
+ildouble: 1
+ldouble: 1
+Test "lgamma (-0x1p-15)":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "lgamma (-0x1p-20)":
+double: 1
+idouble: 1
+Test "lgamma (-0x1p-30)":
+ildouble: 1
+ldouble: 1
+Test "lgamma (-0x1p-5)":
+double: 1
+idouble: 1
 Test "lgamma (0.7)":
 double: 1
 float: 1
 idouble: 1
 ifloat: 1
+Test "lgamma (0x1p-10)":
+float: 1
+ifloat: 1
+Test "lgamma (0x1p-30)":
+double: 1
+idouble: 1
+Test "lgamma (0x1p-40)":
+ildouble: 1
+ldouble: 1
 Test "lgamma (1.2)":
 double: 1
 float: 2

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=184f9acfeb3bbcaad2404a2e238e4d8f71d220fe

commit 184f9acfeb3bbcaad2404a2e238e4d8f71d220fe
Author: Joseph Myers <joseph@codesourcery.com>
Date:   Mon Sep 2 14:51:24 2013 +0000

    Fix spurious jnf underflows (bug 14155).

diff --git a/ChangeLog b/ChangeLog
index 3921a8c..443dcfe 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,15 @@
+2013-09-02  Joseph Myers  <joseph@codesourcery.com>
+
+	[BZ #14155]
+	* sysdeps/ieee754/flt-32/e_jnf.c (__ieee754_jnf): Use double for
+	intermediate calculations in recurrence.
+	(__ieee754_ynf): Likewise.
+	* math/libm-test.inc (jn_test_data): Do not allow spurious
+	underflow exception.  Add more tests.
+	(yn_test_data): Add more tests.
+	* sysdeps/i386/fpu/libm-test-ulps: Update.
+	* sysdeps/x86_64/fpu/libm-test-ulps: Likewise.
+
 2013-08-29  Thomas Schwinge  <thomas@codesourcery.com>
 
 	[BZ #15522] strtod ("nan(N)") returning a sNaN in some cases
diff --git a/NEWS b/NEWS
index acb6ef8..935b887 100644
--- a/NEWS
+++ b/NEWS
@@ -8,9 +8,8 @@ using `glibc' in the "product" field.
 Version 2.18.1
 
 * The following bugs are resolved with this release:
-
 
-  14699, 15532, 15522, 15797, 15909, 15996, 16150.
+  14155, 14699, 15532, 15522, 15797, 15909, 15996, 16150.
 
 * CVE-2013-4237 The readdir_r function could write more than NAME_MAX bytes
   to the d_name member of struct dirent, or omit the terminating NUL
diff --git a/math/libm-test.inc b/math/libm-test.inc
index 7408c6b..9d49255 100644
--- a/math/libm-test.inc
+++ b/math/libm-test.inc
@@ -9908,8 +9908,14 @@ static const struct test_if_f_data jn_test_data[] =
     TEST_if_f (jn, 8, 2.4048255576957729L, 0.92165786705344923232879022467054148E-4L),
     TEST_if_f (jn, 9, 2.4048255576957729L, 0.12517270977961513005428966643852564E-4L),
 
-    /* Bug 14155: spurious exception may occur.  */
-    TEST_if_f (jn, 2, 0x1.ffff62p+99L, -4.43860668048170034334926693188979974489e-16L, UNDERFLOW_EXCEPTION_OK),
+    TEST_if_f (jn, 2, 0x1.ffff62p+99L, -4.43860668048170034334926693188979974489e-16L),
+    TEST_if_f (jn, 2, 0x1p127L, -6.0784021821505059176832624052765568656702e-20L),
+#ifndef TEST_FLOAT
+    TEST_if_f (jn, 2, 0x1p1023L, 1.5665258060609012834424478437196679802783e-155L),
+#endif
+#if defined TEST_LDOUBLE && LDBL_MAX_EXP >= 16384
+    TEST_if_f (jn, 2, 0x1p16383L, -9.5859502826270374691362975419147645151233e-2467L),
+#endif
   };
 
 static void
@@ -14526,6 +14532,15 @@ static const struct test_if_f_data yn_test_data[] =
     /* Check whether yn returns correct value for LDBL_MIN, DBL_MIN,
        and FLT_MIN.  See Bug 14173.  */
     TEST_if_f (yn, 10, min_value, minus_infty, OVERFLOW_EXCEPTION|ERRNO_ERANGE),
+
+    TEST_if_f (yn, 2, 0x1.ffff62p+99L, -5.5244413477397111790415387179517953221757e-16L),
+    TEST_if_f (yn, 2, 0x1p127L, 6.8569250690166637098111268958532649249771e-21L),
+#ifndef TEST_FLOAT
+    TEST_if_f (yn, 2, 0x1p1023L, -8.2687542933709649327986678723012001545638e-155L),
+#endif
+#if defined TEST_LDOUBLE && LDBL_MAX_EXP >= 16384
+    TEST_if_f (yn, 2, 0x1p16383L, 3.8895531955766020648617743624167352352217e-2467L),
+#endif
   };
 
 static void
diff --git a/sysdeps/i386/fpu/libm-test-ulps b/sysdeps/i386/fpu/libm-test-ulps
index 530dbd7..8244863 100644
--- a/sysdeps/i386/fpu/libm-test-ulps
+++ b/sysdeps/i386/fpu/libm-test-ulps
@@ -5635,9 +5635,9 @@ ildouble: 1
 ldouble: 1
 Test "jn (10, 10.0)":
 double: 1
-float: 1
+float: 2
 idouble: 1
-ifloat: 1
+ifloat: 2
 ildouble: 2
 ldouble: 2
 Test "jn (10, 2.0)":
@@ -5648,6 +5648,14 @@ float: 1
 ifloat: 1
 ildouble: 1
 ldouble: 1
+Test "jn (2, 0x1p1023)":
+double: 1
+idouble: 1
+Test "jn (2, 0x1p127)":
+double: 1
+idouble: 1
+ildouble: 1
+ldouble: 1
 Test "jn (2, 2.4048255576957729)":
 double: 1
 float: 1
@@ -6844,6 +6852,14 @@ ifloat: 1
 Test "yn (10, 2.0)":
 float: 3
 ifloat: 3
+Test "yn (2, 0x1.ffff62p+99)":
+double: 1
+idouble: 1
+ildouble: 1
+ldouble: 1
+Test "yn (2, 0x1p127)":
+float: 2
+ifloat: 2
 Test "yn (3, 0.125)":
 ildouble: 1
 ldouble: 1
diff --git a/sysdeps/ieee754/flt-32/e_jnf.c b/sysdeps/ieee754/flt-32/e_jnf.c
index ad26d7e..5984d94 100644
--- a/sysdeps/ieee754/flt-32/e_jnf.c
+++ b/sysdeps/ieee754/flt-32/e_jnf.c
@@ -54,7 +54,7 @@ __ieee754_jnf(int n, float x)
 	    b = __ieee754_j1f(x);
 	    for(i=1;i<n;i++){
 		temp = b;
-		b = b*((float)(i+i)/x) - a; /* avoid underflow */
+		b = b*((double)(i+i)/x) - a; /* avoid underflow */
 		a = temp;
 	    }
 	} else {
@@ -196,7 +196,7 @@ __ieee754_ynf(int n, float x)
 	GET_FLOAT_WORD(ib,b);
 	for(i=1;i<n&&ib!=0xff800000;i++){
 	    temp = b;
-	    b = ((float)(i+i)/x)*b - a;
+	    b = ((double)(i+i)/x)*b - a;
 	    GET_FLOAT_WORD(ib,b);
 	    a = temp;
 	}
diff --git a/sysdeps/x86_64/fpu/libm-test-ulps b/sysdeps/x86_64/fpu/libm-test-ulps
index d02618a..477eedc 100644
--- a/sysdeps/x86_64/fpu/libm-test-ulps
+++ b/sysdeps/x86_64/fpu/libm-test-ulps
@@ -6403,6 +6403,11 @@ idouble: 2
 ifloat: 2
 ildouble: 1
 ldouble: 1
+Test "jn (2, 0x1p127)":
+double: 1
+idouble: 1
+ildouble: 1
+ldouble: 1
 Test "jn (2, 2.4048255576957729)":
 double: 2
 float: 1
@@ -7728,6 +7733,16 @@ double: 3
 float: 1
 idouble: 3
 ifloat: 1
+Test "yn (2, 0x1.ffff62p+99)":
+double: 1
+idouble: 1
+ildouble: 1
+ldouble: 1
+Test "yn (2, 0x1p127)":
+double: 1
+float: 3
+idouble: 1
+ifloat: 3
 Test "yn (3, 0.125)":
 double: 1
 idouble: 1
@@ -8428,9 +8443,9 @@ ldouble: 2
 
 Function: "yn":
 double: 3
-float: 2
+float: 3
 idouble: 3
-ifloat: 2
+ifloat: 3
 ildouble: 4
 ldouble: 4
 

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=9a2afcedaef354324ea08392a6191beb614e9359

commit 9a2afcedaef354324ea08392a6191beb614e9359
Author: Thomas Schwinge <thomas@codesourcery.com>
Date:   Thu May 23 18:00:10 2013 +0200

    [BZ #15522] strtod ("nan(N)") returning a sNaN in some cases

diff --git a/ChangeLog b/ChangeLog
index 649b282..3921a8c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,29 @@
+2013-08-29  Thomas Schwinge  <thomas@codesourcery.com>
+
+	[BZ #15522] strtod ("nan(N)") returning a sNaN in some cases
+
+	* stdlib/strtof_l.c (SET_MANTISSA): Rewrite.
+	* stdlib/strtod_l.c (SET_MANTISSA): Likewise.
+	* sysdeps/ieee754/ldbl-64-128/strtold_l.c (SET_MANTISSA):
+	Likewise.
+	* sysdeps/ieee754/ldbl-96/strtold_l.c (SET_MANTISSA): Likewise.
+	* sysdeps/ieee754/ldbl-128/strtold_l.c (SET_MANTISSA): Likewise.
+	* sysdeps/ieee754/ldbl-128ibm/strtold_l.c (SET_MANTISSA):
+	Likewise.
+	* sysdeps/ieee754/ldbl-128ibm/ieee754.h
+	(ibm_extended_long_double): Add ieee_nan member.
+	* stdlib/tst-strtod6.c (test): New function, renamed from do_test.
+	(do_test): New function.
+
+	* math/basic-test.c (TEST_CONVERT): New macro, renamed from
+	TEST_TRUNC.
+	(convert_dfsf_test, convert_tfsf_test, convert_tfdf_test): New
+	functions, renamed from truncdfsf_test, trunctfsf_test,
+	trunctfdf_test.
+	(convert_sfdf_test, convert_sftf_test, convert_dftf_test): New
+	functions.
+	(do_test): Run all these.
+
 2013-08-23  Joseph Myers  <joseph@codesourcery.com>
 
 	[BZ #15532]
diff --git a/NEWS b/NEWS
index 55009cb..acb6ef8 100644
--- a/NEWS
+++ b/NEWS
@@ -8,8 +8,9 @@ using `glibc' in the "product" field.
 Version 2.18.1
 
 * The following bugs are resolved with this release:
+
 
-  14699, 15532, 15797, 15909, 15996, 16150.
+  14699, 15532, 15522, 15797, 15909, 15996, 16150.
 
 * CVE-2013-4237 The readdir_r function could write more than NAME_MAX bytes
   to the d_name member of struct dirent, or omit the terminating NUL
diff --git a/stdlib/strtod_l.c b/stdlib/strtod_l.c
index 5b41e2b..8f60653 100644
--- a/stdlib/strtod_l.c
+++ b/stdlib/strtod_l.c
@@ -42,11 +42,10 @@ extern unsigned long long int ____strtoull_l_internal (const char *, char **,
 # define SET_MANTISSA(flt, mant) \
   do { union ieee754_double u;						      \
        u.d = (flt);							      \
-       if ((mant & 0xfffffffffffffULL) == 0)				      \
-	 mant = 0x8000000000000ULL;					      \
-       u.ieee.mantissa0 = ((mant) >> 32) & 0xfffff;			      \
-       u.ieee.mantissa1 = (mant) & 0xffffffff;				      \
-       (flt) = u.d;							      \
+       u.ieee_nan.mantissa0 = (mant) >> 32;				      \
+       u.ieee_nan.mantissa1 = (mant);					      \
+       if ((u.ieee.mantissa0 | u.ieee.mantissa1) != 0)			      \
+	 (flt) = u.d;							      \
   } while (0)
 #endif
 /* End of configuration part.  */
diff --git a/stdlib/strtof_l.c b/stdlib/strtof_l.c
index 6fb44bd..c4c1c1f 100644
--- a/stdlib/strtof_l.c
+++ b/stdlib/strtof_l.c
@@ -37,10 +37,9 @@ extern unsigned long long int ____strtoull_l_internal (const char *, char **,
 #define SET_MANTISSA(flt, mant) \
   do { union ieee754_float u;						      \
        u.f = (flt);							      \
-       if ((mant & 0x7fffff) == 0)					      \
-	 mant = 0x400000;						      \
-       u.ieee.mantissa = (mant) & 0x7fffff;				      \
-       (flt) = u.f;							      \
+       u.ieee_nan.mantissa = (mant);					      \
+       if (u.ieee.mantissa != 0)					      \
+	 (flt) = u.f;							      \
   } while (0)
 
 #include "strtod_l.c"
diff --git a/stdlib/tst-strtod6.c b/stdlib/tst-strtod6.c
index 1d87266..15e79fd 100644
--- a/stdlib/tst-strtod6.c
+++ b/stdlib/tst-strtod6.c
@@ -4,12 +4,13 @@
 #include <string.h>
 
 static int
-do_test (void)
+test (const char str[])
 {
-  static const char str[] = "NaN(blabla)something";
   char *endp;
   int result = 0;
 
+  puts (str);
+
   double d = strtod (str, &endp);
   if (!isnan (d))
     {
@@ -64,5 +65,24 @@ do_test (void)
   return result;
 }
 
+static int
+do_test (void)
+{
+  int result = 0;
+
+  result |= test ("NaN(blabla)something");
+  result |= test ("NaN(1234)something");
+  /* UINT32_MAX.  */
+  result |= test ("NaN(4294967295)something");
+  /* UINT64_MAX.  */
+  result |= test ("NaN(18446744073709551615)something");
+  /* The case of zero is special in that "something" has to be done to make the
+     mantissa different from zero, which would mean infinity instead of
+     NaN.  */
+  result |= test ("NaN(0)something");
+
+  return result;
+}
+
 #define TEST_FUNCTION do_test ()
 #include "../test-skeleton.c"
diff --git a/sysdeps/ieee754/ldbl-128/strtold_l.c b/sysdeps/ieee754/ldbl-128/strtold_l.c
index 8e0bc03..d3a1d1e 100644
--- a/sysdeps/ieee754/ldbl-128/strtold_l.c
+++ b/sysdeps/ieee754/ldbl-128/strtold_l.c
@@ -34,11 +34,13 @@
 #define SET_MANTISSA(flt, mant) \
   do { union ieee854_long_double u;					      \
        u.d = (flt);							      \
-       u.ieee.mantissa0 = 0x8000;					      \
-       u.ieee.mantissa1 = 0;						      \
-       u.ieee.mantissa2 = ((mant) >> 32);	      			      \
-       u.ieee.mantissa3 = (mant) & 0xffffffff;				      \
-       (flt) = u.d;							      \
+       u.ieee_nan.mantissa0 = 0;					      \
+       u.ieee_nan.mantissa1 = 0;					      \
+       u.ieee_nan.mantissa2 = (mant) >> 32;				      \
+       u.ieee_nan.mantissa3 = (mant);					      \
+       if ((u.ieee.mantissa0 | u.ieee.mantissa1				      \
+	    | u.ieee.mantissa2 | u.ieee.mantissa3) != 0)		      \
+	 (flt) = u.d;							      \
   } while (0)
 
 #include <strtod_l.c>
diff --git a/sysdeps/ieee754/ldbl-128ibm/ieee754.h b/sysdeps/ieee754/ldbl-128ibm/ieee754.h
index e5644f5..9e94f53 100644
--- a/sysdeps/ieee754/ldbl-128ibm/ieee754.h
+++ b/sysdeps/ieee754/ldbl-128ibm/ieee754.h
@@ -199,6 +199,25 @@ union ibm_extended_long_double
 	unsigned int mantissa2:20;
 	unsigned int mantissa3:32;
       } ieee;
+
+    /* This format makes it easier to see if a NaN is a signalling NaN.  */
+    struct
+      { /* Big endian.  There is no other.  */
+
+	unsigned int negative:1;
+	unsigned int exponent:11;
+	unsigned int quiet_nan:1;
+	/* Together Mantissa0-3 comprise the mantissa.  */
+	unsigned int mantissa0:19;
+	unsigned int mantissa1:32;
+
+	unsigned int negative2:1;
+	unsigned int exponent2:11;
+	/* There is an implied 1 here?  */
+	/* Together these comprise the mantissa.  */
+	unsigned int mantissa2:20;
+	unsigned int mantissa3:32;
+      } ieee_nan;
    };
 
 #define IBM_EXTENDED_LONG_DOUBLE_BIAS 0x3ff /* Added to exponent.  */
diff --git a/sysdeps/ieee754/ldbl-128ibm/strtold_l.c b/sysdeps/ieee754/ldbl-128ibm/strtold_l.c
index 93415f0..04e3288 100644
--- a/sysdeps/ieee754/ldbl-128ibm/strtold_l.c
+++ b/sysdeps/ieee754/ldbl-128ibm/strtold_l.c
@@ -44,11 +44,10 @@ libc_hidden_proto (STRTOF)
 # define SET_MANTISSA(flt, mant) \
   do { union ibm_extended_long_double u;				      \
        u.d = (flt);							      \
-       if ((mant & 0xfffffffffffffULL) == 0)				      \
-	 mant = 0x8000000000000ULL;					      \
-       u.ieee.mantissa0 = ((mant) >> 32) & 0xfffff;			      \
-       u.ieee.mantissa1 = (mant) & 0xffffffff;				      \
-       (flt) = u.d;							      \
+       u.ieee_nan.mantissa0 = (mant) >> 32;				      \
+       u.ieee_nan.mantissa1 = (mant);					      \
+       if ((u.ieee.mantissa0 | u.ieee.mantissa1) != 0)			      \
+	 (flt) = u.d;							      \
   } while (0)
 
 #include <strtod_l.c>
diff --git a/sysdeps/ieee754/ldbl-64-128/strtold_l.c b/sysdeps/ieee754/ldbl-64-128/strtold_l.c
index 8182b2b..e9b33f2 100644
--- a/sysdeps/ieee754/ldbl-64-128/strtold_l.c
+++ b/sysdeps/ieee754/ldbl-64-128/strtold_l.c
@@ -44,11 +44,13 @@ libc_hidden_proto (STRTOF)
 #define SET_MANTISSA(flt, mant) \
   do { union ieee854_long_double u;					      \
        u.d = (flt);							      \
-       u.ieee.mantissa0 = 0x8000;					      \
-       u.ieee.mantissa1 = 0;						      \
-       u.ieee.mantissa2 = ((mant) >> 32);	      			      \
-       u.ieee.mantissa3 = (mant) & 0xffffffff;				      \
-       (flt) = u.d;							      \
+       u.ieee_nan.mantissa0 = 0;					      \
+       u.ieee_nan.mantissa1 = 0;					      \
+       u.ieee_nan.mantissa2 = (mant) >> 32;				      \
+       u.ieee_nan.mantissa3 = (mant);					      \
+       if ((u.ieee.mantissa0 | u.ieee.mantissa1				      \
+	    | u.ieee.mantissa2 | u.ieee.mantissa3) != 0)		      \
+	 (flt) = u.d;							      \
   } while (0)
 
 #include <strtod_l.c>
diff --git a/sysdeps/ieee754/ldbl-96/strtold_l.c b/sysdeps/ieee754/ldbl-96/strtold_l.c
index ded84f3..dccf98c 100644
--- a/sysdeps/ieee754/ldbl-96/strtold_l.c
+++ b/sysdeps/ieee754/ldbl-96/strtold_l.c
@@ -34,11 +34,10 @@
 #define SET_MANTISSA(flt, mant) \
   do { union ieee854_long_double u;					      \
        u.d = (flt);							      \
-       if ((mant & 0x7fffffffffffffffULL) == 0)				      \
-	 mant = 0x4000000000000000ULL;					      \
-       u.ieee.mantissa0 = (((mant) >> 32) & 0x7fffffff) | 0x80000000;	      \
-       u.ieee.mantissa1 = (mant) & 0xffffffff;				      \
-       (flt) = u.d;							      \
+       u.ieee_nan.mantissa0 = (mant) >> 32;				      \
+       u.ieee_nan.mantissa1 = (mant);					      \
+       if ((u.ieee.mantissa0 | u.ieee.mantissa1) != 0)			      \
+	 (flt) = u.d;							      \
   } while (0)
 
 #include <stdlib/strtod_l.c>

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=85248b2448e4614414aa30ae31ac479bdfd87696

commit 85248b2448e4614414aa30ae31ac479bdfd87696
Author: Joseph Myers <joseph@codesourcery.com>
Date:   Fri Aug 23 19:45:38 2013 +0000

    Fix cexp (NaN + i0) (bug 15532).

diff --git a/ChangeLog b/ChangeLog
index 346f699..649b282 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+2013-08-23  Joseph Myers  <joseph@codesourcery.com>
+
+	[BZ #15532]
+	* math/s_cexp.c (__cexp): Return NaN + i0 for NaN + i0 argument.
+	* math/s_cexpf.c (__cexpf): Likewise.
+	* math/s_cexpl.c (__cexpl): Likewise.
+	* math/libm-test.inc (cexp_test_data): Correct expected return
+	value for NaN + i0.  Add another test.
+
 2013-08-21  Joseph Myers  <joseph@codesourcery.com>
 
 	[BZ #15797]
diff --git a/math/libm-test.inc b/math/libm-test.inc
index 8c1dcac..7408c6b 100644
--- a/math/libm-test.inc
+++ b/math/libm-test.inc
@@ -6193,7 +6193,8 @@ static const struct test_c_c_data cexp_test_data[] =
 
     TEST_c_c (cexp, plus_infty, qnan_value, plus_infty, qnan_value),
 
-    TEST_c_c (cexp, qnan_value, 0.0, qnan_value, qnan_value, INVALID_EXCEPTION_OK),
+    TEST_c_c (cexp, qnan_value, 0.0, qnan_value, 0.0),
+    TEST_c_c (cexp, qnan_value, minus_zero, qnan_value, minus_zero),
     TEST_c_c (cexp, qnan_value, 1.0, qnan_value, qnan_value, INVALID_EXCEPTION_OK),
 
     TEST_c_c (cexp, qnan_value, plus_infty, qnan_value, qnan_value, INVALID_EXCEPTION_OK),
diff --git a/math/s_cexp.c b/math/s_cexp.c
index 655e4e8..40e0e51 100644
--- a/math/s_cexp.c
+++ b/math/s_cexp.c
@@ -145,12 +145,18 @@ __cexp (__complex__ double x)
     }
   else
     {
-      /* If the real part is NaN the result is NaN + iNaN.  */
+      /* If the real part is NaN the result is NaN + iNaN unless the
+	 imaginary part is zero.  */
       __real__ retval = __nan ("");
-      __imag__ retval = __nan ("");
+      if (icls == FP_ZERO)
+	__imag__ retval = __imag__ x;
+      else
+	{
+	  __imag__ retval = __nan ("");
 
-      if (rcls != FP_NAN || icls != FP_NAN)
-	feraiseexcept (FE_INVALID);
+	  if (rcls != FP_NAN || icls != FP_NAN)
+	    feraiseexcept (FE_INVALID);
+	}
     }
 
   return retval;
diff --git a/math/s_cexpf.c b/math/s_cexpf.c
index fa942d3..7c42205 100644
--- a/math/s_cexpf.c
+++ b/math/s_cexpf.c
@@ -145,12 +145,18 @@ __cexpf (__complex__ float x)
     }
   else
     {
-      /* If the real part is NaN the result is NaN + iNaN.  */
+      /* If the real part is NaN the result is NaN + iNaN unless the
+	 imaginary part is zero.  */
       __real__ retval = __nanf ("");
-      __imag__ retval = __nanf ("");
+      if (icls == FP_ZERO)
+	__imag__ retval = __imag__ x;
+      else
+	{
+	  __imag__ retval = __nanf ("");
 
-      if (rcls != FP_NAN || icls != FP_NAN)
-	feraiseexcept (FE_INVALID);
+	  if (rcls != FP_NAN || icls != FP_NAN)
+	    feraiseexcept (FE_INVALID);
+	}
     }
 
   return retval;
diff --git a/math/s_cexpl.c b/math/s_cexpl.c
index d827bc3..0c35603 100644
--- a/math/s_cexpl.c
+++ b/math/s_cexpl.c
@@ -145,12 +145,18 @@ __cexpl (__complex__ long double x)
     }
   else
     {
-      /* If the real part is NaN the result is NaN + iNaN.  */
+      /* If the real part is NaN the result is NaN + iNaN unless the
+	 imaginary part is zero.  */
       __real__ retval = __nanl ("");
-      __imag__ retval = __nanl ("");
+      if (icls == FP_ZERO)
+	__imag__ retval = __imag__ x;
+      else
+	{
+	  __imag__ retval = __nanl ("");
 
-      if (rcls != FP_NAN || icls != FP_NAN)
-	feraiseexcept (FE_INVALID);
+	  if (rcls != FP_NAN || icls != FP_NAN)
+	    feraiseexcept (FE_INVALID);
+	}
     }
 
   return retval;

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=72993206c61252fbb7cc3d605b420fb04f2f8c43

commit 72993206c61252fbb7cc3d605b420fb04f2f8c43
Author: Joseph Myers <joseph@codesourcery.com>
Date:   Wed Aug 21 19:56:48 2013 +0000

    Fix fdim handling of infinities (bug 15797).

diff --git a/ChangeLog b/ChangeLog
index 37617d8..346f699 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+2013-08-21  Joseph Myers  <joseph@codesourcery.com>
+
+	[BZ #15797]
+	* math/s_fdim.c (__fdim): Check for infinite arguments if result
+	is infinite, not alongside NaN test.
+	* math/s_fdimf.c (__fdimf): Likewise.
+	* math/s_fdiml.c (__fdiml): Likewise.
+	* math/libm-test.inc (fdim_test_data): Add more tests.  Test that
+	errno is unchanged.
+
 2013-07-23  Adhemerval Zanella  <azanella@linux.vnet.ibm.com>
 
 	[BZ #15867]
diff --git a/NEWS b/NEWS
index ae05edc..55009cb 100644
--- a/NEWS
+++ b/NEWS
@@ -9,7 +9,7 @@ Version 2.18.1
 
 * The following bugs are resolved with this release:
 
-  14699, 15532, 15909, 15996, 16150.
+  14699, 15532, 15797, 15909, 15996, 16150.
 
 * CVE-2013-4237 The readdir_r function could write more than NAME_MAX bytes
   to the d_name member of struct dirent, or omit the terminating NUL
diff --git a/math/libm-test.inc b/math/libm-test.inc
index 3b382af..8c1dcac 100644
--- a/math/libm-test.inc
+++ b/math/libm-test.inc
@@ -8139,33 +8139,37 @@ fabs_test (void)
 
 static const struct test_ff_f_data fdim_test_data[] =
   {
-    TEST_ff_f (fdim, 0, 0, 0, NO_INEXACT_EXCEPTION),
-    TEST_ff_f (fdim, 9, 0, 9, NO_INEXACT_EXCEPTION),
-    TEST_ff_f (fdim, 0, 9, 0, NO_INEXACT_EXCEPTION),
-    TEST_ff_f (fdim, -9, 0, 0, NO_INEXACT_EXCEPTION),
-    TEST_ff_f (fdim, 0, -9, 9, NO_INEXACT_EXCEPTION),
-
-    TEST_ff_f (fdim, plus_infty, 9, plus_infty, NO_INEXACT_EXCEPTION),
-    TEST_ff_f (fdim, plus_infty, -9, plus_infty, NO_INEXACT_EXCEPTION),
-    TEST_ff_f (fdim, minus_infty, 9, 0, NO_INEXACT_EXCEPTION),
-    TEST_ff_f (fdim, minus_infty, -9, 0, NO_INEXACT_EXCEPTION),
-    TEST_ff_f (fdim, 9, minus_infty, plus_infty, NO_INEXACT_EXCEPTION),
-    TEST_ff_f (fdim, -9, minus_infty, plus_infty, NO_INEXACT_EXCEPTION),
-    TEST_ff_f (fdim, 9, plus_infty, 0, NO_INEXACT_EXCEPTION),
-    TEST_ff_f (fdim, -9, plus_infty, 0, NO_INEXACT_EXCEPTION),
-
-    TEST_ff_f (fdim, 0, qnan_value, qnan_value, NO_INEXACT_EXCEPTION),
-    TEST_ff_f (fdim, 9, qnan_value, qnan_value, NO_INEXACT_EXCEPTION),
-    TEST_ff_f (fdim, -9, qnan_value, qnan_value, NO_INEXACT_EXCEPTION),
-    TEST_ff_f (fdim, qnan_value, 9, qnan_value, NO_INEXACT_EXCEPTION),
-    TEST_ff_f (fdim, qnan_value, -9, qnan_value, NO_INEXACT_EXCEPTION),
-    TEST_ff_f (fdim, plus_infty, qnan_value, qnan_value, NO_INEXACT_EXCEPTION),
-    TEST_ff_f (fdim, minus_infty, qnan_value, qnan_value, NO_INEXACT_EXCEPTION),
-    TEST_ff_f (fdim, qnan_value, plus_infty, qnan_value, NO_INEXACT_EXCEPTION),
-    TEST_ff_f (fdim, qnan_value, minus_infty, qnan_value, NO_INEXACT_EXCEPTION),
-    TEST_ff_f (fdim, qnan_value, qnan_value, qnan_value, NO_INEXACT_EXCEPTION),
-
-    TEST_ff_f (fdim, plus_infty, plus_infty, 0, NO_INEXACT_EXCEPTION),
+    TEST_ff_f (fdim, 0, 0, 0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_ff_f (fdim, 9, 0, 9, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_ff_f (fdim, 0, 9, 0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_ff_f (fdim, -9, 0, 0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_ff_f (fdim, 0, -9, 9, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+
+    TEST_ff_f (fdim, plus_infty, 9, plus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_ff_f (fdim, plus_infty, -9, plus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_ff_f (fdim, minus_infty, 9, 0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_ff_f (fdim, minus_infty, -9, 0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_ff_f (fdim, 9, minus_infty, plus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_ff_f (fdim, -9, minus_infty, plus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_ff_f (fdim, 9, plus_infty, 0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_ff_f (fdim, -9, plus_infty, 0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+
+    TEST_ff_f (fdim, 0, qnan_value, qnan_value, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_ff_f (fdim, 9, qnan_value, qnan_value, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_ff_f (fdim, -9, qnan_value, qnan_value, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_ff_f (fdim, qnan_value, 0, qnan_value, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_ff_f (fdim, qnan_value, 9, qnan_value, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_ff_f (fdim, qnan_value, -9, qnan_value, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_ff_f (fdim, plus_infty, qnan_value, qnan_value, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_ff_f (fdim, minus_infty, qnan_value, qnan_value, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_ff_f (fdim, qnan_value, plus_infty, qnan_value, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_ff_f (fdim, qnan_value, minus_infty, qnan_value, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_ff_f (fdim, qnan_value, qnan_value, qnan_value, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+
+    TEST_ff_f (fdim, plus_infty, plus_infty, 0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_ff_f (fdim, plus_infty, minus_infty, plus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_ff_f (fdim, minus_infty, plus_infty, 0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_ff_f (fdim, minus_infty, minus_infty, 0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
   };
 
 static void
diff --git a/math/s_fdim.c b/math/s_fdim.c
index 2f97948..f8fd804 100644
--- a/math/s_fdim.c
+++ b/math/s_fdim.c
@@ -26,16 +26,16 @@ __fdim (double x, double y)
   int clsx = fpclassify (x);
   int clsy = fpclassify (y);
 
-  if (clsx == FP_NAN || clsy == FP_NAN
-      || (y < 0 && clsx == FP_INFINITE && clsy == FP_INFINITE))
-    /* Raise invalid flag.  */
+  if (clsx == FP_NAN || clsy == FP_NAN)
+    /* Raise invalid flag for signaling but not quiet NaN.  */
     return x - y;
 
   if (x <= y)
     return 0.0;
 
   double r = x - y;
-  if (fpclassify (r) == FP_INFINITE)
+  if (fpclassify (r) == FP_INFINITE
+      && clsx != FP_INFINITE && clsy != FP_INFINITE)
     __set_errno (ERANGE);
 
   return r;
diff --git a/math/s_fdimf.c b/math/s_fdimf.c
index 03810b5..86efe6e 100644
--- a/math/s_fdimf.c
+++ b/math/s_fdimf.c
@@ -26,16 +26,16 @@ __fdimf (float x, float y)
   int clsx = fpclassify (x);
   int clsy = fpclassify (y);
 
-  if (clsx == FP_NAN || clsy == FP_NAN
-      || (y < 0 && clsx == FP_INFINITE && clsy == FP_INFINITE))
-    /* Raise invalid flag.  */
+  if (clsx == FP_NAN || clsy == FP_NAN)
+    /* Raise invalid flag for signaling but not quiet NaN.  */
     return x - y;
 
   if (x <= y)
     return 0.0f;
 
   float r = x - y;
-  if (fpclassify (r) == FP_INFINITE)
+  if (fpclassify (r) == FP_INFINITE
+      && clsx != FP_INFINITE && clsy != FP_INFINITE)
     __set_errno (ERANGE);
 
   return r;
diff --git a/math/s_fdiml.c b/math/s_fdiml.c
index 5604532..030fcc2 100644
--- a/math/s_fdiml.c
+++ b/math/s_fdiml.c
@@ -26,16 +26,16 @@ __fdiml (long double x, long double y)
   int clsx = fpclassify (x);
   int clsy = fpclassify (y);
 
-  if (clsx == FP_NAN || clsy == FP_NAN
-      || (y < 0 && clsx == FP_INFINITE && clsy == FP_INFINITE))
-    /* Raise invalid flag.  */
+  if (clsx == FP_NAN || clsy == FP_NAN)
+    /* Raise invalid flag for signaling but not quiet NaN.  */
     return x - y;
 
   if (x <= y)
     return 0.0f;
 
   long double r = x - y;
-  if (fpclassify (r) == FP_INFINITE)
+  if (fpclassify (r) == FP_INFINITE
+      && clsx != FP_INFINITE && clsy != FP_INFINITE)
     __set_errno (ERANGE);
 
   return r;

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=a44cf86eab2f01195d414347f5d0b786562537f0

commit a44cf86eab2f01195d414347f5d0b786562537f0
Author: Adhemerval Zanella <azanella@linux.vnet.ibm.com>
Date:   Tue Aug 20 15:01:59 2013 -0500

    PowerPC: fix backtrace to handle signal trampolines
    
    This patch fixes backtrace for PPC32 and PPC64 to correctly handle
    signal trampolines. The 'debug/tst-backtrace6.c' also check for
    SA_SIGINFO handling, where is triggers another vDSO symbols for PPC32.

diff --git a/ChangeLog b/ChangeLog
index 00f0c7b..37617d8 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,20 @@
+2013-07-23  Adhemerval Zanella  <azanella@linux.vnet.ibm.com>
+
+	[BZ #15867]
+	* sysdeps/powerpc/powerpc32/backtrace.c (__backtrace): Handle signal
+	trampoline stack frame information.
+	* sysdeps/powerpc/powerpc64/backtrace.c (__backtrace): Likewise.
+	* sysdeps/unix/sysv/linux/powerpc/bits/libc-vdso.h
+	(__vdso_sigtramp_rt64): New variable: PPC64 signal trampoline.
+	(__vdso_sigtramp32): New variable: PPC32 signal trampoline.
+	(__vdso_sigtramp_rt32): New variable: PPC32 signal trampoline.
+	* sysdeps/unix/sysv/linux/powerpc/init-first.c
+	(_libc_vdso_platform_setup): Initialize the signal trampolines.
+	* debug/tst-backtrace5.c (fn): Add an option set modify sigaction
+	sa_flags value.
+	* debug/tst-backtrace6.c: New file: check backtrace for signal frames,
+	interrupting a syscall and set with option SA_SIGINFO.
+
 2013-08-20  Joseph Myers  <joseph@codesourcery.com>
 
 	[BZ #15531]
diff --git a/debug/Makefile b/debug/Makefile
index 779741f..13ee5c8 100644
--- a/debug/Makefile
+++ b/debug/Makefile
@@ -130,16 +130,18 @@ CFLAGS-tst-backtrace2.c += -funwind-tables
 CFLAGS-tst-backtrace3.c += -funwind-tables
 CFLAGS-tst-backtrace4.c += -funwind-tables
 CFLAGS-tst-backtrace5.c += -funwind-tables
+CFLAGS-tst-backtrace6.c += -funwind-tables
 LDFLAGS-tst-backtrace2 = -rdynamic
 LDFLAGS-tst-backtrace3 = -rdynamic
 LDFLAGS-tst-backtrace4 = -rdynamic
 LDFLAGS-tst-backtrace5 = -rdynamic
+LDFLAGS-tst-backtrace6 = -rdynamic
 
 tests = backtrace-tst tst-longjmp_chk tst-chk1 tst-chk2 tst-chk3 \
 	tst-lfschk1 tst-lfschk2 tst-lfschk3 test-strcpy_chk test-stpcpy_chk \
 	tst-chk4 tst-chk5 tst-chk6 tst-lfschk4 tst-lfschk5 tst-lfschk6 \
 	tst-longjmp_chk2 tst-backtrace2 tst-backtrace3 tst-backtrace4 \
-	tst-backtrace5
+	tst-backtrace5 tst-backtrace6
 
 tests-ifunc := $(stpcpy_chk strcpy_chk:%=test-%-ifunc)
 tests += $(tests-ifunc)
diff --git a/debug/tst-backtrace5.c b/debug/tst-backtrace5.c
index ca47437..51180c1 100644
--- a/debug/tst-backtrace5.c
+++ b/debug/tst-backtrace5.c
@@ -28,6 +28,10 @@
 
 #include "tst-backtrace.h"
 
+#ifndef SIGACTION_FLAGS
+# define SIGACTION_FLAGS 0
+#endif
+
 static int do_test (void);
 #define TEST_FUNCTION do_test ()
 #include "../test-skeleton.c"
@@ -91,7 +95,7 @@ handle_signal (int signum)
 }
 
 NO_INLINE int
-fn (int c)
+fn (int c, int flags)
 {
   pid_t parent_pid, child_pid;
   int pipefd[2];
@@ -100,12 +104,13 @@ fn (int c)
 
   if (c > 0)
     {
-      fn (c - 1);
+      fn (c - 1, flags);
       return x;
     }
 
   memset (&act, 0, sizeof (act));
   act.sa_handler = handle_signal;
+  act.sa_flags = flags;
   sigemptyset (&act.sa_mask);
   sigaction (SIGUSR1, &act, NULL);
   parent_pid = getpid ();
@@ -131,6 +136,6 @@ fn (int c)
 NO_INLINE static int
 do_test (void)
 {
-  fn (2);
+  fn (2, SIGACTION_FLAGS);
   return ret;
 }
diff --git a/debug/tst-backtrace6.c b/debug/tst-backtrace6.c
new file mode 100644
index 0000000..cd8dbcd
--- /dev/null
+++ b/debug/tst-backtrace6.c
@@ -0,0 +1,21 @@
+/* Test backtrace and backtrace_symbols for signal frames, where a
+   system call was interrupted by a signal.
+   Copyright (C) 2013 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/>.  */
+
+#define SIGACTION_FLAGS SA_SIGINFO
+#include <debug/tst-backtrace5.c>
diff --git a/sysdeps/powerpc/powerpc32/backtrace.c b/sysdeps/powerpc/powerpc32/backtrace.c
index b4b11dd..8d413e6 100644
--- a/sysdeps/powerpc/powerpc32/backtrace.c
+++ b/sysdeps/powerpc/powerpc32/backtrace.c
@@ -18,6 +18,9 @@
 
 #include <execinfo.h>
 #include <stddef.h>
+#include <string.h>
+#include <signal.h>
+#include <bits/libc-vdso.h>
 
 /* This is the stack layout we see with every stack frame.
    Note that every routine is required by the ABI to lay out the stack
@@ -35,6 +38,46 @@ struct layout
   void *return_address;
 };
 
+#define SIGNAL_FRAMESIZE 64
+
+/* Since the signal handler is just like any other function it needs to
+   save/restore its LR and it will save it into callers stack frame.
+   Since a signal handler doesn't have a caller, the kernel creates a
+   dummy frame to make it look like it has a caller.  */
+struct signal_frame_32 {
+  char               dummy[SIGNAL_FRAMESIZE];
+  struct sigcontext  sctx;
+  mcontext_t         mctx;
+  /* We don't care about the rest, since IP value is at 'mctx' field.  */
+};
+
+static inline int
+is_sigtramp_address (unsigned int nip)
+{
+#ifdef SHARED
+  if (nip == (unsigned int)__vdso_sigtramp32)
+    return 1;
+#endif
+  return 0;
+}
+
+struct rt_signal_frame_32 {
+  char               dummy[SIGNAL_FRAMESIZE + 16];
+  siginfo_t          info;
+  struct ucontext    uc;
+  /* We don't care about the rest, since IP value is at 'uc' field.  */
+};
+
+static inline int
+is_sigtramp_address_rt (unsigned int nip)
+{
+#ifdef SHARED
+  if (nip == (unsigned int)__vdso_sigtramp_rt32)
+    return 1;
+#endif
+  return 0;
+}
+
 int
 __backtrace (void **array, int size)
 {
@@ -50,7 +93,28 @@ __backtrace (void **array, int size)
   for (				count = 0;
        current != NULL && 	count < size;
        current = current->next, count++)
-    array[count] = current->return_address;
+    {
+      gregset_t *gregset = NULL;
+
+      array[count] = current->return_address;
+
+      /* Check if the symbol is the signal trampoline and get the interrupted
+       * symbol address from the trampoline saved area.  */
+      if (is_sigtramp_address ((unsigned int)current->return_address))
+	{
+	  struct signal_frame_32 *sigframe =
+	    (struct signal_frame_32*) current;
+          gregset = &sigframe->mctx.gregs;
+        }
+      else if (is_sigtramp_address_rt ((unsigned int)current->return_address))
+	{
+	  struct rt_signal_frame_32 *sigframe =
+            (struct rt_signal_frame_32*) current;
+          gregset = &sigframe->uc.uc_mcontext.uc_regs->gregs;
+        }
+      if (gregset)
+	array[++count] = (void*)((*gregset)[PT_NIP]);
+    }
 
   /* It's possible the second-last stack frame can't return
      (that is, it's __libc_start_main), in which case
diff --git a/sysdeps/powerpc/powerpc64/backtrace.c b/sysdeps/powerpc/powerpc64/backtrace.c
index 2d3e051..9b9a9f1 100644
--- a/sysdeps/powerpc/powerpc64/backtrace.c
+++ b/sysdeps/powerpc/powerpc64/backtrace.c
@@ -18,6 +18,9 @@
 
 #include <execinfo.h>
 #include <stddef.h>
+#include <string.h>
+#include <signal.h>
+#include <bits/libc-vdso.h>
 
 /* This is the stack layout we see with every stack frame.
    Note that every routine is required by the ABI to lay out the stack
@@ -38,6 +41,27 @@ struct layout
   void *return_address;
 };
 
+/* Since the signal handler is just like any other function it needs to
+   save/restore its LR and it will save it into callers stack frame.
+   Since a signal handler doesn't have a caller, the kernel creates a
+   dummy frame to make it look like it has a caller.  */
+struct signal_frame_64 {
+#define SIGNAL_FRAMESIZE 128
+  char            dummy[SIGNAL_FRAMESIZE];
+  struct ucontext uc;
+  /* We don't care about the rest, since the IP value is at 'uc' field.  */
+};
+
+static inline int
+is_sigtramp_address (unsigned long nip)
+{
+#ifdef SHARED
+  if (nip == (unsigned long)__vdso_sigtramp_rt64)
+    return 1;
+#endif
+  return 0;
+}
+
 int
 __backtrace (void **array, int size)
 {
@@ -53,7 +77,17 @@ __backtrace (void **array, int size)
   for (				count = 0;
        current != NULL && 	count < size;
        current = current->next, count++)
-    array[count] = current->return_address;
+    {
+      array[count] = current->return_address;
+
+      /* Check if the symbol is the signal trampoline and get the interrupted
+       * symbol address from the trampoline saved area.  */
+      if (is_sigtramp_address ((unsigned long)current->return_address))
+        {
+	  struct signal_frame_64 *sigframe = (struct signal_frame_64*) current;
+          array[++count] = (void*)sigframe->uc.uc_mcontext.gp_regs[PT_NIP];
+	}
+    }
 
   /* It's possible the second-last stack frame can't return
      (that is, it's __libc_start_main), in which case
diff --git a/sysdeps/unix/sysv/linux/powerpc/bits/libc-vdso.h b/sysdeps/unix/sysv/linux/powerpc/bits/libc-vdso.h
index 8b195db..ba54de4 100644
--- a/sysdeps/unix/sysv/linux/powerpc/bits/libc-vdso.h
+++ b/sysdeps/unix/sysv/linux/powerpc/bits/libc-vdso.h
@@ -34,6 +34,13 @@ extern void *__vdso_getcpu;
 
 extern void *__vdso_time;
 
+#if defined(__PPC64__) || defined(__powerpc64__)
+extern void *__vdso_sigtramp_rt64;
+#else
+extern void *__vdso_sigtramp32;
+extern void *__vdso_sigtramp_rt32;
+#endif
+
 /* This macro is needed for PPC64 to return a skeleton OPD entry of a vDSO
    symbol.  This works because _dl_vdso_vsym always return the function
    address, and no vDSO symbols use the TOC or chain pointers from the OPD
diff --git a/sysdeps/unix/sysv/linux/powerpc/init-first.c b/sysdeps/unix/sysv/linux/powerpc/init-first.c
index f6f05f0..061715f 100644
--- a/sysdeps/unix/sysv/linux/powerpc/init-first.c
+++ b/sysdeps/unix/sysv/linux/powerpc/init-first.c
@@ -29,6 +29,12 @@ void *__vdso_clock_getres;
 void *__vdso_get_tbfreq;
 void *__vdso_getcpu;
 void *__vdso_time;
+#if defined(__PPC64__) || defined(__powerpc64__)
+void *__vdso_sigtramp_rt64;
+#else
+void *__vdso_sigtramp32;
+void *__vdso_sigtramp_rt32;
+#endif
 
 static inline void
 _libc_vdso_platform_setup (void)
@@ -46,6 +52,16 @@ _libc_vdso_platform_setup (void)
   __vdso_getcpu = _dl_vdso_vsym ("__kernel_getcpu", &linux2615);
 
   __vdso_time = _dl_vdso_vsym ("__kernel_time", &linux2615);
+
+  /* PPC64 uses only one signal trampoline symbol, while PPC32 will use
+     two depending if SA_SIGINFO is used (__kernel_sigtramp_rt32) or not
+     (__kernel_sigtramp32).  */
+#if defined(__PPC64__) || defined(__powerpc64__)
+  __vdso_sigtramp_rt64 = _dl_vdso_vsym ("__kernel_sigtramp_rt64", &linux2615);
+#else
+  __vdso_sigtramp32 = _dl_vdso_vsym ("__kernel_sigtramp32", &linux2615);
+  __vdso_sigtramp_rt32 = _dl_vdso_vsym ("__kernel_sigtramp_rt32", &linux2615);
+#endif
 }
 
 # define VDSO_SETUP _libc_vdso_platform_setup

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=2eca8c3c19866af93c014a61badba27dd272a40c

commit 2eca8c3c19866af93c014a61badba27dd272a40c
Author: Joseph Myers <joseph@codesourcery.com>
Date:   Tue Aug 20 19:41:15 2013 +0000

    Fix cproj handling of (finite, NaN) arguments (bug 15531).

diff --git a/ChangeLog b/ChangeLog
index 2ded8ae..00f0c7b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,19 @@
+2013-08-20  Joseph Myers  <joseph@codesourcery.com>
+
+	[BZ #15531]
+	* math/s_cproj.c (__cproj): Only return an infinity if one part of
+	argument is infinite.
+	* math/s_cprojf.c (__cprojf): Likewise.
+	* math/s_cprojl.c (__cprojl): Likewise.
+	* sysdeps/ieee754/ldbl-128ibm/s_cprojl.c (__cprojl): Likewise.
+	* math/libm-test.inc (cproj_test_data): Add more tests.
+
+	* sysdeps/unix/sysv/linux/mmap64.c: Include <string.h>.
+
+	* sysdeps/unix/sysv/linux/mmap64.c (__mmap64)
+	[MMAP2_PAGE_SHIFT == -1]: Use __getpagesize to determine page
+	size.  Use __ffs to determine corresponding shift.
+
 2013-08-20  Andreas Arnez  <arnez@linux.vnet.ibm.com>
 
 	* elf/setup-vdso.h (setup_vdso): Fix missing string termination.
diff --git a/NEWS b/NEWS
index d6bc721..ae05edc 100644
--- a/NEWS
+++ b/NEWS
@@ -9,7 +9,7 @@ Version 2.18.1
 
 * The following bugs are resolved with this release:
 
-  14699, 15909, 15996, 16150.
+  14699, 15532, 15909, 15996, 16150.
 
 * CVE-2013-4237 The readdir_r function could write more than NAME_MAX bytes
   to the d_name member of struct dirent, or omit the terminating NUL
diff --git a/math/libm-test.inc b/math/libm-test.inc
index 2324d4f..3b382af 100644
--- a/math/libm-test.inc
+++ b/math/libm-test.inc
@@ -7061,11 +7061,51 @@ static const struct test_c_c_data cproj_test_data[] =
 
     TEST_c_c (cproj, qnan_value, qnan_value, qnan_value, qnan_value, NO_INEXACT_EXCEPTION),
 
+    TEST_c_c (cproj, plus_zero, qnan_value, plus_zero, qnan_value, NO_INEXACT_EXCEPTION),
+    TEST_c_c (cproj, minus_zero, qnan_value, minus_zero, qnan_value, NO_INEXACT_EXCEPTION),
+    TEST_c_c (cproj, qnan_value, plus_zero, qnan_value, plus_zero, NO_INEXACT_EXCEPTION),
+    TEST_c_c (cproj, qnan_value, minus_zero, qnan_value, minus_zero, NO_INEXACT_EXCEPTION),
+
+    TEST_c_c (cproj, 1.0, qnan_value, 1.0, qnan_value, NO_INEXACT_EXCEPTION),
+    TEST_c_c (cproj, -1.0, qnan_value, -1.0, qnan_value, NO_INEXACT_EXCEPTION),
+    TEST_c_c (cproj, qnan_value, 1.0, qnan_value, 1.0, NO_INEXACT_EXCEPTION),
+    TEST_c_c (cproj, qnan_value, -1.0, qnan_value, -1.0, NO_INEXACT_EXCEPTION),
+
     TEST_c_c (cproj, plus_infty, plus_infty, plus_infty, 0.0, NO_INEXACT_EXCEPTION),
     TEST_c_c (cproj, plus_infty, minus_infty, plus_infty, minus_zero, NO_INEXACT_EXCEPTION),
     TEST_c_c (cproj, minus_infty, plus_infty, plus_infty, 0.0, NO_INEXACT_EXCEPTION),
     TEST_c_c (cproj, minus_infty, minus_infty, plus_infty, minus_zero, NO_INEXACT_EXCEPTION),
 
+    TEST_c_c (cproj, plus_infty, plus_zero, plus_infty, 0.0, NO_INEXACT_EXCEPTION),
+    TEST_c_c (cproj, plus_infty, minus_zero, plus_infty, minus_zero, NO_INEXACT_EXCEPTION),
+    TEST_c_c (cproj, minus_infty, plus_zero, plus_infty, 0.0, NO_INEXACT_EXCEPTION),
+    TEST_c_c (cproj, minus_infty, minus_zero, plus_infty, minus_zero, NO_INEXACT_EXCEPTION),
+
+    TEST_c_c (cproj, plus_zero, plus_infty, plus_infty, 0.0, NO_INEXACT_EXCEPTION),
+    TEST_c_c (cproj, plus_zero, minus_infty, plus_infty, minus_zero, NO_INEXACT_EXCEPTION),
+    TEST_c_c (cproj, minus_zero, plus_infty, plus_infty, 0.0, NO_INEXACT_EXCEPTION),
+    TEST_c_c (cproj, minus_zero, minus_infty, plus_infty, minus_zero, NO_INEXACT_EXCEPTION),
+
+    TEST_c_c (cproj, plus_infty, 1.0, plus_infty, 0.0, NO_INEXACT_EXCEPTION),
+    TEST_c_c (cproj, plus_infty, -1.0, plus_infty, minus_zero, NO_INEXACT_EXCEPTION),
+    TEST_c_c (cproj, minus_infty, 1.0, plus_infty, 0.0, NO_INEXACT_EXCEPTION),
+    TEST_c_c (cproj, minus_infty, -1.0, plus_infty, minus_zero, NO_INEXACT_EXCEPTION),
+
+    TEST_c_c (cproj, 1.0, plus_infty, plus_infty, 0.0, NO_INEXACT_EXCEPTION),
+    TEST_c_c (cproj, 1.0, minus_infty, plus_infty, minus_zero, NO_INEXACT_EXCEPTION),
+    TEST_c_c (cproj, -1.0, plus_infty, plus_infty, 0.0, NO_INEXACT_EXCEPTION),
+    TEST_c_c (cproj, -1.0, minus_infty, plus_infty, minus_zero, NO_INEXACT_EXCEPTION),
+
+    TEST_c_c (cproj, plus_infty, qnan_value, plus_infty, 0.0, NO_INEXACT_EXCEPTION),
+    TEST_c_c (cproj, plus_infty, -qnan_value, plus_infty, minus_zero, NO_INEXACT_EXCEPTION),
+    TEST_c_c (cproj, minus_infty, qnan_value, plus_infty, 0.0, NO_INEXACT_EXCEPTION),
+    TEST_c_c (cproj, minus_infty, -qnan_value, plus_infty, minus_zero, NO_INEXACT_EXCEPTION),
+
+    TEST_c_c (cproj, qnan_value, plus_infty, plus_infty, 0.0, NO_INEXACT_EXCEPTION),
+    TEST_c_c (cproj, qnan_value, minus_infty, plus_infty, minus_zero, NO_INEXACT_EXCEPTION),
+    TEST_c_c (cproj, -qnan_value, plus_infty, plus_infty, 0.0, NO_INEXACT_EXCEPTION),
+    TEST_c_c (cproj, -qnan_value, minus_infty, plus_infty, minus_zero, NO_INEXACT_EXCEPTION),
+
     TEST_c_c (cproj, 1.0, 0.0, 1.0, 0.0, NO_INEXACT_EXCEPTION),
     TEST_c_c (cproj, 2.0, 3.0, 2.0, 3.0, NO_INEXACT_EXCEPTION),
   };
diff --git a/math/s_cproj.c b/math/s_cproj.c
index c0be461..98f1a4c 100644
--- a/math/s_cproj.c
+++ b/math/s_cproj.c
@@ -24,9 +24,7 @@
 __complex__ double
 __cproj (__complex__ double x)
 {
-  if (isnan (__real__ x) && isnan (__imag__ x))
-    return x;
-  else if (!isfinite (__real__ x) || !isfinite (__imag__ x))
+  if (__isinf_ns (__real__ x) || __isinf_ns (__imag__ x))
     {
       __complex__ double res;
 
diff --git a/math/s_cprojf.c b/math/s_cprojf.c
index 188bbe3..e4dbc18 100644
--- a/math/s_cprojf.c
+++ b/math/s_cprojf.c
@@ -24,9 +24,7 @@
 __complex__ float
 __cprojf (__complex__ float x)
 {
-  if (isnan (__real__ x) && isnan (__imag__ x))
-    return x;
-  else if (!isfinite (__real__ x) || !isfinite (__imag__ x))
+  if (__isinf_nsf (__real__ x) || __isinf_nsf (__imag__ x))
     {
       __complex__ float res;
 
diff --git a/math/s_cprojl.c b/math/s_cprojl.c
index fbdf279..b564a83 100644
--- a/math/s_cprojl.c
+++ b/math/s_cprojl.c
@@ -24,9 +24,7 @@
 __complex__ long double
 __cprojl (__complex__ long double x)
 {
-  if (isnan (__real__ x) && isnan (__imag__ x))
-    return x;
-  else if (!isfinite (__real__ x) || !isfinite (__imag__ x))
+  if (__isinf_nsl (__real__ x) || __isinf_nsl (__imag__ x))
     {
       __complex__ long double res;
 
diff --git a/sysdeps/ieee754/ldbl-128ibm/s_cprojl.c b/sysdeps/ieee754/ldbl-128ibm/s_cprojl.c
index 3b4af54..a344e92 100644
--- a/sysdeps/ieee754/ldbl-128ibm/s_cprojl.c
+++ b/sysdeps/ieee754/ldbl-128ibm/s_cprojl.c
@@ -24,9 +24,7 @@
 __complex__ long double
 __cprojl (__complex__ long double x)
 {
-  if (isnan (__real__ x) && isnan (__imag__ x))
-    return x;
-  else if (!isfinite (__real__ x) || !isfinite (__imag__ x))
+  if (__isinf_nsl (__real__ x) || __isinf_nsl (__imag__ x))
     {
       __complex__ long double res;
 

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=1d3c75f2a03be1a9686203ee2b32b0e5fb5e847b

commit 1d3c75f2a03be1a9686203ee2b32b0e5fb5e847b
Author: Andreas Arnez <arnez@linux.vnet.ibm.com>
Date:   Tue Aug 20 14:03:04 2013 +0200

    * elf/setup-vdso.h (setup_vdso): Fix missing string termination.

diff --git a/ChangeLog b/ChangeLog
index cdcbd3d..2ded8ae 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
+2013-08-20  Andreas Arnez  <arnez@linux.vnet.ibm.com>
+
+	* elf/setup-vdso.h (setup_vdso): Fix missing string termination.
+
 2013-08-16  Florian Weimer  <fweimer@redhat.com>
 
 	[BZ #14699]
diff --git a/elf/setup-vdso.h b/elf/setup-vdso.h
index a98dfec..056d885 100644
--- a/elf/setup-vdso.h
+++ b/elf/setup-vdso.h
@@ -89,7 +89,7 @@ setup_vdso (struct link_map *main_map __attribute__ ((unused)),
 	     addresses in the vsyscall DSO pages in writev() calls.  */
 	  const char *dsoname = ((char *) D_PTR (l, l_info[DT_STRTAB])
 				 + l->l_info[DT_SONAME]->d_un.d_val);
-	  size_t len = strlen (dsoname);
+	  size_t len = strlen (dsoname) + 1;
 	  char *copy = malloc (len);
 	  if (copy == NULL)
 	    _dl_fatal_printf ("out of memory\n");

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=b5f581e49c151ea062a747e3006b9b400ee94d83

commit b5f581e49c151ea062a747e3006b9b400ee94d83
Author: Florian Weimer <fweimer@redhat.com>
Date:   Fri Aug 16 09:38:52 2013 +0200

    CVE-2013-4237, BZ #14699: Buffer overflow in readdir_r
    
    	* sysdeps/posix/dirstream.h (struct __dirstream): Add errcode
    	member.
    	* sysdeps/posix/opendir.c (__alloc_dir): Initialize errcode
    	member.
    	* sysdeps/posix/rewinddir.c (rewinddir): Reset errcode member.
    	* sysdeps/posix/readdir_r.c (__READDIR_R): Enforce NAME_MAX limit.
    	Return delayed error code.  Remove GETDENTS_64BIT_ALIGNED
    	conditional.
    	* sysdeps/unix/sysv/linux/wordsize-64/readdir_r.c: Do not define
    	GETDENTS_64BIT_ALIGNED.
    	* sysdeps/unix/sysv/linux/i386/readdir64_r.c: Likewise.
    	* manual/filesys.texi (Reading/Closing Directory): Document
    	ENAMETOOLONG return value of readdir_r.  Recommend readdir more
    	strongly.
    	* manual/conf.texi (Limits for Files): Add portability note to
    	NAME_MAX, PATH_MAX.
    	(Pathconf): Add portability note for _PC_NAME_MAX, _PC_PATH_MAX.

diff --git a/ChangeLog b/ChangeLog
index 1e5efa7..cdcbd3d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,25 @@
+2013-08-16  Florian Weimer  <fweimer@redhat.com>
+
+	[BZ #14699]
+	CVE-2013-4237
+	* sysdeps/posix/dirstream.h (struct __dirstream): Add errcode
+	member.
+	* sysdeps/posix/opendir.c (__alloc_dir): Initialize errcode
+	member.
+	* sysdeps/posix/rewinddir.c (rewinddir): Reset errcode member.
+	* sysdeps/posix/readdir_r.c (__READDIR_R): Enforce NAME_MAX limit.
+	Return delayed error code.  Remove GETDENTS_64BIT_ALIGNED
+	conditional.
+	* sysdeps/unix/sysv/linux/wordsize-64/readdir_r.c: Do not define
+	GETDENTS_64BIT_ALIGNED.
+	* sysdeps/unix/sysv/linux/i386/readdir64_r.c: Likewise.
+	* manual/filesys.texi (Reading/Closing Directory): Document
+	ENAMETOOLONG return value of readdir_r.  Recommend readdir more
+	strongly.
+	* manual/conf.texi (Limits for Files): Add portability note to
+	NAME_MAX, PATH_MAX.
+	(Pathconf): Add portability note for _PC_NAME_MAX, _PC_PATH_MAX.
+
 2013-11-11  David S. Miller  <davem@davemloft.net>
 
 	[BZ #16150]
diff --git a/NEWS b/NEWS
index df97235..d6bc721 100644
--- a/NEWS
+++ b/NEWS
@@ -9,7 +9,11 @@ Version 2.18.1
 
 * The following bugs are resolved with this release:
 
-  15909, 15996, 16150.
+  14699, 15909, 15996, 16150.
+
+* CVE-2013-4237 The readdir_r function could write more than NAME_MAX bytes
+  to the d_name member of struct dirent, or omit the terminating NUL
+  character.  (Bugzilla #14699).
 
 Version 2.18
 
diff --git a/manual/conf.texi b/manual/conf.texi
index 7eb8b36..c720063 100644
--- a/manual/conf.texi
+++ b/manual/conf.texi
@@ -1149,6 +1149,9 @@ typed ahead as input.  @xref{I/O Queues}.
 @deftypevr Macro int NAME_MAX
 The uniform system limit (if any) for the length of a file name component, not
 including the terminating null character.
+
+@strong{Portability Note:} On some systems, @theglibc{} defines
+@code{NAME_MAX}, but does not actually enforce this limit.
 @end deftypevr
 
 @comment limits.h
@@ -1157,6 +1160,9 @@ including the terminating null character.
 The uniform system limit (if any) for the length of an entire file name (that
 is, the argument given to system calls such as @code{open}), including the
 terminating null character.
+
+@strong{Portability Note:} @Theglibc{} does not enforce this limit
+even if @code{PATH_MAX} is defined.
 @end deftypevr
 
 @cindex limits, pipe buffer size
@@ -1476,6 +1482,9 @@ Inquire about the value of @code{POSIX_REC_MIN_XFER_SIZE}.
 Inquire about the value of @code{POSIX_REC_XFER_ALIGN}.
 @end table
 
+@strong{Portability Note:} On some systems, @theglibc{} does not
+enforce @code{_PC_NAME_MAX} or @code{_PC_PATH_MAX} limits.
+
 @node Utility Limits
 @section Utility Program Capacity Limits
 
diff --git a/manual/filesys.texi b/manual/filesys.texi
index 1df9cf2..814c210 100644
--- a/manual/filesys.texi
+++ b/manual/filesys.texi
@@ -444,9 +444,9 @@ symbols are declared in the header file @file{dirent.h}.
 @comment POSIX.1
 @deftypefun {struct dirent *} readdir (DIR *@var{dirstream})
 This function reads the next entry from the directory.  It normally
-returns a pointer to a structure containing information about the file.
-This structure is statically allocated and can be rewritten by a
-subsequent call.
+returns a pointer to a structure containing information about the
+file.  This structure is associated with the @var{dirstream} handle
+and can be rewritten by a subsequent call.
 
 @strong{Portability Note:} On some systems @code{readdir} may not
 return entries for @file{.} and @file{..}, even though these are always
@@ -461,19 +461,61 @@ conditions are defined for this function:
 The @var{dirstream} argument is not valid.
 @end table
 
-@code{readdir} is not thread safe.  Multiple threads using
-@code{readdir} on the same @var{dirstream} may overwrite the return
-value.  Use @code{readdir_r} when this is critical.
+To distinguish between an end-of-directory condition or an error, you
+must set @code{errno} to zero before calling @code{readdir}.  To avoid
+entering an infinite loop, you should stop reading from the directory
+after the first error.
+
+In POSIX.1-2008, @code{readdir} is not thread-safe.  In @theglibc{}
+implementation, it is safe to call @code{readdir} concurrently on
+different @var{dirstream}s, but multiple threads accessing the same
+@var{dirstream} result in undefined behavior.  @code{readdir_r} is a
+fully thread-safe alternative, but suffers from poor portability (see
+below).  It is recommended that you use @code{readdir}, with external
+locking if multiple threads access the same @var{dirstream}.
 @end deftypefun
 
 @comment dirent.h
 @comment GNU
 @deftypefun int readdir_r (DIR *@var{dirstream}, struct dirent *@var{entry}, struct dirent **@var{result})
-This function is the reentrant version of @code{readdir}.  Like
-@code{readdir} it returns the next entry from the directory.  But to
-prevent conflicts between simultaneously running threads the result is
-not stored in statically allocated memory.  Instead the argument
-@var{entry} points to a place to store the result.
+This function is a version of @code{readdir} which performs internal
+locking.  Like @code{readdir} it returns the next entry from the
+directory.  To prevent conflicts between simultaneously running
+threads the result is stored inside the @var{entry} object.
+
+@strong{Portability Note:} It is recommended to use @code{readdir}
+instead of @code{readdir_r} for the following reasons:
+
+@itemize @bullet
+@item
+On systems which do not define @code{NAME_MAX}, it may not be possible
+to use @code{readdir_r} safely because the caller does not specify the
+length of the buffer for the directory entry.
+
+@item
+On some systems, @code{readdir_r} cannot read directory entries with
+very long names.  If such a name is encountered, @theglibc{}
+implementation of @code{readdir_r} returns with an error code of
+@code{ENAMETOOLONG} after the final directory entry has been read.  On
+other systems, @code{readdir_r} may return successfully, but the
+@code{d_name} member may not be NUL-terminated or may be truncated.
+
+@item
+POSIX-1.2008 does not guarantee that @code{readdir} is thread-safe,
+even when access to the same @var{dirstream} is serialized.  But in
+current implementations (including @theglibc{}), it is safe to call
+@code{readdir} concurrently on different @var{dirstream}s, so there is
+no need to use @code{readdir_r} in most multi-threaded programs.  In
+the rare case that multiple threads need to read from the same
+@var{dirstream}, it is still better to use @code{readdir} and external
+synchronization.
+
+@item
+It is expected that future versions of POSIX will obsolete
+@code{readdir_r} and mandate the level of thread safety for
+@code{readdir} which is provided by @theglibc{} and other
+implementations today.
+@end itemize
 
 Normally @code{readdir_r} returns zero and sets @code{*@var{result}}
 to @var{entry}.  If there are no more entries in the directory or an
@@ -481,15 +523,6 @@ error is detected, @code{readdir_r} sets @code{*@var{result}} to a
 null pointer and returns a nonzero error code, also stored in
 @code{errno}, as described for @code{readdir}.
 
-@strong{Portability Note:} On some systems @code{readdir_r} may not
-return a NUL terminated string for the file name, even when there is no
-@code{d_reclen} field in @code{struct dirent} and the file
-name is the maximum allowed size.  Modern systems all have the
-@code{d_reclen} field, and on old systems multi-threading is not
-critical.  In any case there is no such problem with the @code{readdir}
-function, so that even on systems without the @code{d_reclen} member one
-could use multiple threads by using external locking.
-
 It is also important to look at the definition of the @code{struct
 dirent} type.  Simply passing a pointer to an object of this type for
 the second parameter of @code{readdir_r} might not be enough.  Some
diff --git a/sysdeps/posix/dirstream.h b/sysdeps/posix/dirstream.h
index a7a074d..8e8570d 100644
--- a/sysdeps/posix/dirstream.h
+++ b/sysdeps/posix/dirstream.h
@@ -39,6 +39,8 @@ struct __dirstream
 
     off_t filepos;		/* Position of next entry to read.  */
 
+    int errcode;		/* Delayed error code.  */
+
     /* Directory block.  */
     char data[0] __attribute__ ((aligned (__alignof__ (void*))));
   };
diff --git a/sysdeps/posix/opendir.c b/sysdeps/posix/opendir.c
index ddfc3a7..fc05b0f 100644
--- a/sysdeps/posix/opendir.c
+++ b/sysdeps/posix/opendir.c
@@ -231,6 +231,7 @@ __alloc_dir (int fd, bool close_fd, int flags, const struct stat64 *statp)
   dirp->size = 0;
   dirp->offset = 0;
   dirp->filepos = 0;
+  dirp->errcode = 0;
 
   return dirp;
 }
diff --git a/sysdeps/posix/readdir_r.c b/sysdeps/posix/readdir_r.c
index b5a8e2e..8ed5c3f 100644
--- a/sysdeps/posix/readdir_r.c
+++ b/sysdeps/posix/readdir_r.c
@@ -40,6 +40,7 @@ __READDIR_R (DIR *dirp, DIRENT_TYPE *entry, DIRENT_TYPE **result)
   DIRENT_TYPE *dp;
   size_t reclen;
   const int saved_errno = errno;
+  int ret;
 
   __libc_lock_lock (dirp->lock);
 
@@ -70,10 +71,10 @@ __READDIR_R (DIR *dirp, DIRENT_TYPE *entry, DIRENT_TYPE **result)
 		  bytes = 0;
 		  __set_errno (saved_errno);
 		}
+	      if (bytes < 0)
+		dirp->errcode = errno;
 
 	      dp = NULL;
-	      /* Reclen != 0 signals that an error occurred.  */
-	      reclen = bytes != 0;
 	      break;
 	    }
 	  dirp->size = (size_t) bytes;
@@ -106,29 +107,46 @@ __READDIR_R (DIR *dirp, DIRENT_TYPE *entry, DIRENT_TYPE **result)
       dirp->filepos += reclen;
 #endif
 
-      /* Skip deleted files.  */
+#ifdef NAME_MAX
+      if (reclen > offsetof (DIRENT_TYPE, d_name) + NAME_MAX + 1)
+	{
+	  /* The record is very long.  It could still fit into the
+	     caller-supplied buffer if we can skip padding at the
+	     end.  */
+	  size_t namelen = _D_EXACT_NAMLEN (dp);
+	  if (namelen <= NAME_MAX)
+	    reclen = offsetof (DIRENT_TYPE, d_name) + namelen + 1;
+	  else
+	    {
+	      /* The name is too long.  Ignore this file.  */
+	      dirp->errcode = ENAMETOOLONG;
+	      dp->d_ino = 0;
+	      continue;
+	    }
+	}
+#endif
+
+      /* Skip deleted and ignored files.  */
     }
   while (dp->d_ino == 0);
 
   if (dp != NULL)
     {
-#ifdef GETDENTS_64BIT_ALIGNED
-      /* The d_reclen value might include padding which is not part of
-	 the DIRENT_TYPE data structure.  */
-      reclen = MIN (reclen,
-		    offsetof (DIRENT_TYPE, d_name) + sizeof (dp->d_name));
-#endif
       *result = memcpy (entry, dp, reclen);
-#ifdef GETDENTS_64BIT_ALIGNED
+#ifdef _DIRENT_HAVE_D_RECLEN
       entry->d_reclen = reclen;
 #endif
+      ret = 0;
     }
   else
-    *result = NULL;
+    {
+      *result = NULL;
+      ret = dirp->errcode;
+    }
 
   __libc_lock_unlock (dirp->lock);
 
-  return dp != NULL ? 0 : reclen ? errno : 0;
+  return ret;
 }
 
 #ifdef __READDIR_R_ALIAS
diff --git a/sysdeps/posix/rewinddir.c b/sysdeps/posix/rewinddir.c
index 2935a8e..d4991ad 100644
--- a/sysdeps/posix/rewinddir.c
+++ b/sysdeps/posix/rewinddir.c
@@ -33,6 +33,7 @@ rewinddir (dirp)
   dirp->filepos = 0;
   dirp->offset = 0;
   dirp->size = 0;
+  dirp->errcode = 0;
 #ifndef NOT_IN_libc
   __libc_lock_unlock (dirp->lock);
 #endif
diff --git a/sysdeps/unix/sysv/linux/i386/readdir64_r.c b/sysdeps/unix/sysv/linux/i386/readdir64_r.c
index 8ebbcfd..a7d114e 100644
--- a/sysdeps/unix/sysv/linux/i386/readdir64_r.c
+++ b/sysdeps/unix/sysv/linux/i386/readdir64_r.c
@@ -18,7 +18,6 @@
 #define __READDIR_R __readdir64_r
 #define __GETDENTS __getdents64
 #define DIRENT_TYPE struct dirent64
-#define GETDENTS_64BIT_ALIGNED 1
 
 #include <sysdeps/posix/readdir_r.c>
 
diff --git a/sysdeps/unix/sysv/linux/wordsize-64/readdir_r.c b/sysdeps/unix/sysv/linux/wordsize-64/readdir_r.c
index 5ed8e95..290f2c8 100644
--- a/sysdeps/unix/sysv/linux/wordsize-64/readdir_r.c
+++ b/sysdeps/unix/sysv/linux/wordsize-64/readdir_r.c
@@ -1,5 +1,4 @@
 #define readdir64_r __no_readdir64_r_decl
-#define GETDENTS_64BIT_ALIGNED 1
 #include <sysdeps/posix/readdir_r.c>
 #undef readdir64_r
 weak_alias (__readdir_r, readdir64_r)

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=df2b535be8dcc810706211d89d26967e4df24504

commit df2b535be8dcc810706211d89d26967e4df24504
Author: Tulio Magno Quites Machado Filho <tuliom@linux.vnet.ibm.com>
Date:   Fri Nov 15 07:44:20 2013 -0600

    Partially revert commit 2663b74f8103a2a8a46b4896439b7a452480fc7c
    
    This change is necessary in order to avoid the issue documented at
    http://sourceware.org/ml/libc-alpha/2013-05/msg00350.html.

diff --git a/localedata/locales/bo_CN b/localedata/locales/bo_CN
index aa8ff07..cd61856 100644
--- a/localedata/locales/bo_CN
+++ b/localedata/locales/bo_CN
@@ -144,8 +144,7 @@ END LC_MEASUREMENT
 
 LC_NAME
 % FIXME
-
-name_fmt  ""
+name_fmt	"FIXME"
 % name_gen	"FIXME"
 % name_miss	"FIXME"
 % name_mr	"FIXME"
diff --git a/localedata/locales/bo_IN b/localedata/locales/bo_IN
index 9e9c4ff..c90db17 100644
--- a/localedata/locales/bo_IN
+++ b/localedata/locales/bo_IN
@@ -70,7 +70,7 @@ END LC_MEASUREMENT
 
 LC_NAME
 % FIXME
-name_fmt	""
+name_fmt	"FIXME"
 % name_gen	"FIXME"
 % name_miss	"FIXME"
 % name_mr	"FIXME"

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=d19762a5fd946ef86fb2922eb5710aac8000ab25

commit d19762a5fd946ef86fb2922eb5710aac8000ab25
Author: Ryan S. Arnold <rsa@linux.vnet.ibm.com>
Date:   Fri Nov 15 07:42:33 2013 -0600

    Remove assert() if DT_RUNPATH and DT_RPATH flags are found in ld.so.

diff --git a/elf/get-dynamic-info.h b/elf/get-dynamic-info.h
index 3cc1073..1c30c44 100644
--- a/elf/get-dynamic-info.h
+++ b/elf/get-dynamic-info.h
@@ -130,8 +130,8 @@ elf_get_dynamic_info (struct link_map *l, ElfW(Dyn) *temp)
   assert (info[DT_FLAGS] == NULL
 	  || (info[DT_FLAGS]->d_un.d_val & ~DF_BIND_NOW) == 0);
   /* Flags must not be set for ld.so.  */
-  assert (info[DT_RUNPATH] == NULL);
-  assert (info[DT_RPATH] == NULL);
+  info[DT_RUNPATH] == NULL;
+  info[DT_RPATH] == NULL;
 #else
   if (info[DT_FLAGS] != NULL)
     {

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=38bf8b39f1b9dc7acf3af57b9545ed425e9d5417

commit 38bf8b39f1b9dc7acf3af57b9545ed425e9d5417
Author: Adhemerval Zanella <azanella@linux.vnet.ibm.com>
Date:   Thu Nov 7 05:34:22 2013 -0600

    PowerPC: Fix vDSO missing ODP entries
    
    This patch fixes the vDSO symbol used directed in IFUNC resolver where
    they do not have an associated ODP entry leading to undefined behavior
    in some cases. It adds an artificial OPD static entry to such cases
    and set its TOC to non 0 to avoid triggering lazy resolutions.

diff --git a/ChangeLog b/ChangeLog
index b0048f5..6c0e914 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2013-11-08  Adhemerval Zanella  <azanella@linux.vnet.ibm.com>
+
+	* sysdeps/unix/sysv/linux/powerpc/bits/libc-vdso.h (VDSO_IFUNC_RET):
+	Add artificial ODP entry for vDSO symbol for PPC64.
+	* sysdeps/unix/sysv/linux/powerpc/gettimeofday.c: Adjust includes.
+	* sysdeps/unix/sysv/linux/powerpc/time.c: Likewise.
+
 2013-09-25  Adhemerval Zanella  <azanella@linux.vnet.ibm.com>
 
 	* sysdeps/powerpc/powerpc64/stackguard-macros.h (POINTER_CHK_GUARD:
diff --git a/sysdeps/unix/sysv/linux/powerpc/bits/libc-vdso.h b/sysdeps/unix/sysv/linux/powerpc/bits/libc-vdso.h
index ba54de4..d189169 100644
--- a/sysdeps/unix/sysv/linux/powerpc/bits/libc-vdso.h
+++ b/sysdeps/unix/sysv/linux/powerpc/bits/libc-vdso.h
@@ -41,12 +41,32 @@ extern void *__vdso_sigtramp32;
 extern void *__vdso_sigtramp_rt32;
 #endif
 
-/* This macro is needed for PPC64 to return a skeleton OPD entry of a vDSO
-   symbol.  This works because _dl_vdso_vsym always return the function
-   address, and no vDSO symbols use the TOC or chain pointers from the OPD
-   so we can allow them to be garbage.  */
 #if defined(__PPC64__) || defined(__powerpc64__)
-#define VDSO_IFUNC_RET(value)  ((void *) &(value))
+/* The correct solution is for _dl_vdso_vsym to return the address of the OPD
+   for the kernel VDSO function.  That address would then be stored in the
+   __vdso_* variables and returned as the result of the IFUNC resolver function.
+   Yet, the kernel does not contain any OPD entries for the VDSO functions
+   (incomplete implementation).  However, PLT relocations for IFUNCs still expect
+   the address of an OPD to be returned from the IFUNC resolver function (since
+   PLT entries on PPC64 are just copies of OPDs).  The solution for now is to
+   create an artificial static OPD for each VDSO function returned by a resolver
+   function.  The TOC value is set to a non-zero value to avoid triggering lazy
+   symbol resolution via .glink0/.plt0 for a zero TOC (requires thread-safe PLT
+   sequences) when the dynamic linker isn't prepared for it e.g. RTLD_NOW.  None
+   of the kernel VDSO routines use the TOC or AUX values so any non-zero value
+   will work.  Note that function pointer comparisons will not use this artificial
+   static OPD since those are resolved via ADDR64 relocations and will point at
+   the non-IFUNC default OPD for the symbol.  Lastly, because the IFUNC relocations
+   are processed immediately at startup the resolver functions and this code need
+   not be thread-safe, but if the caller writes to a PLT slot it must do so in a
+   thread-safe manner with all the required barriers.  */
+#define VDSO_IFUNC_RET(value)                            \
+  ({                                                     \
+    static Elf64_FuncDesc vdso_opd = { .fd_toc = ~0x0 }; \
+    vdso_opd.fd_func = (Elf64_Addr)value;                \
+    &vdso_opd;                                           \
+  })
+
 #else
 #define VDSO_IFUNC_RET(value)  ((void *) (value))
 #endif
diff --git a/sysdeps/unix/sysv/linux/powerpc/gettimeofday.c b/sysdeps/unix/sysv/linux/powerpc/gettimeofday.c
index 6506d75..48c3f84 100644
--- a/sysdeps/unix/sysv/linux/powerpc/gettimeofday.c
+++ b/sysdeps/unix/sysv/linux/powerpc/gettimeofday.c
@@ -22,6 +22,7 @@
 
 # include <dl-vdso.h>
 # include <bits/libc-vdso.h>
+# include <dl-machine.h>
 
 void *gettimeofday_ifunc (void) __asm__ ("__gettimeofday");
 
diff --git a/sysdeps/unix/sysv/linux/powerpc/time.c b/sysdeps/unix/sysv/linux/powerpc/time.c
index 66b4eb3..2d77ece 100644
--- a/sysdeps/unix/sysv/linux/powerpc/time.c
+++ b/sysdeps/unix/sysv/linux/powerpc/time.c
@@ -20,7 +20,9 @@
 
 # include <time.h>
 # include <sysdep.h>
+# include <dl-vdso.h>
 # include <bits/libc-vdso.h>
+# include <dl-machine.h>
 
 void *time_ifunc (void) asm ("time");
 

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=dc3a1f98dc4c86cb454474f4912ae325573655cb

commit dc3a1f98dc4c86cb454474f4912ae325573655cb
Author: Adhemerval Zanella <azanella@linux.vnet.ibm.com>
Date:   Wed Sep 25 13:43:04 2013 -0500

    PowerPC: Fix POINTER_CHK_GUARD thread register for PPC64

diff --git a/ChangeLog b/ChangeLog
index e658237..b0048f5 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2013-09-25  Adhemerval Zanella  <azanella@linux.vnet.ibm.com>
+
+	* sysdeps/powerpc/powerpc64/stackguard-macros.h (POINTER_CHK_GUARD:
+	Fix thread ID register.
+
 2013-09-11  Will Newton  <will.newton@linaro.org>
 
 	[BZ #15857]
diff --git a/sysdeps/powerpc/powerpc64/stackguard-macros.h b/sysdeps/powerpc/powerpc64/stackguard-macros.h
index 4620f96..e80a683 100644
--- a/sysdeps/powerpc/powerpc64/stackguard-macros.h
+++ b/sysdeps/powerpc/powerpc64/stackguard-macros.h
@@ -6,7 +6,7 @@
 #define POINTER_CHK_GUARD \
   ({												\
      uintptr_t x;										\
-     asm ("ld %0,%1(2)"										\
+     asm ("ld %0,%1(13)"										\
 	  : "=r" (x)										\
 	  : "i" (offsetof (tcbhead_t, pointer_guard) - TLS_TCB_OFFSET - sizeof (tcbhead_t))	\
          );											\

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=e20644b3a6f96eb053ab4c2c900f7bef7f472916

commit e20644b3a6f96eb053ab4c2c900f7bef7f472916
Author: Will Newton <will.newton@linaro.org>
Date:   Fri Sep 13 09:26:02 2013 +0100

    Add CVE-2013-4332 to NEWS.

diff --git a/NEWS b/NEWS
index e8f1099..ef92d7c 100644
--- a/NEWS
+++ b/NEWS
@@ -25,6 +25,11 @@ Version 2.18
   15654, 15655, 15666, 15667, 15674, 15711, 15755, 15759, 15797, 15892,
   15893, 15895, 15917, 15988, 16072.
 
+* CVE-2013-4332 The pvalloc, valloc, memalign, posix_memalign and
+  aligned_alloc functions could allocate too few bytes or corrupt the
+  heap when passed very large allocation size values (Bugzilla #15855,
+  #15856, #15857).
+
 * CVE-2013-4788 The pointer guard used for pointer mangling was not
   initialized for static applications resulting in the security feature
   being disabled. The pointer guard is now correctly initialized to a

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=c51d675c459aefef8d84d5a0b114010f916ea278

commit c51d675c459aefef8d84d5a0b114010f916ea278
Author: Will Newton <will.newton@linaro.org>
Date:   Fri Aug 16 12:54:29 2013 +0100

    malloc: Check for integer overflow in memalign.
    
    A large bytes parameter to memalign could cause an integer overflow
    and corrupt allocator internals. Check the overflow does not occur
    before continuing with the allocation.
    
    ChangeLog:
    
    2013-09-11  Will Newton  <will.newton@linaro.org>
    
    	[BZ #15857]
    	* malloc/malloc.c (__libc_memalign): Check the value of bytes
    	does not overflow.

diff --git a/ChangeLog b/ChangeLog
index 7edeac3..e658237 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,11 @@
 2013-09-11  Will Newton  <will.newton@linaro.org>
 
+	[BZ #15857]
+	* malloc/malloc.c (__libc_memalign): Check the value of bytes
+	does not overflow.
+
+2013-09-11  Will Newton  <will.newton@linaro.org>
+
 	[BZ #15856]
 	* malloc/malloc.c (__libc_valloc): Check the value of bytes
 	does not overflow.
diff --git a/malloc/malloc.c b/malloc/malloc.c
index 31e2dfa..ebbe86d 100644
--- a/malloc/malloc.c
+++ b/malloc/malloc.c
@@ -3015,6 +3015,13 @@ __libc_memalign(size_t alignment, size_t bytes)
   /* Otherwise, ensure that it is at least a minimum chunk size */
   if (alignment <  MINSIZE) alignment = MINSIZE;
 
+  /* Check for overflow.  */
+  if (bytes > SIZE_MAX - alignment - MINSIZE)
+    {
+      __set_errno (ENOMEM);
+      return 0;
+    }
+
   arena_get(ar_ptr, bytes + alignment + MINSIZE);
   if(!ar_ptr)
     return 0;

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=6a6a386a3040726053a5fb8582ff26dc85d84741

commit 6a6a386a3040726053a5fb8582ff26dc85d84741
Author: Will Newton <will.newton@linaro.org>
Date:   Fri Aug 16 11:59:37 2013 +0100

    malloc: Check for integer overflow in valloc.
    
    A large bytes parameter to valloc could cause an integer overflow
    and corrupt allocator internals. Check the overflow does not occur
    before continuing with the allocation.
    
    ChangeLog:
    
    2013-09-11  Will Newton  <will.newton@linaro.org>
    
    	[BZ #15856]
    	* malloc/malloc.c (__libc_valloc): Check the value of bytes
    	does not overflow.

diff --git a/ChangeLog b/ChangeLog
index 855cc5f..7edeac3 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,11 @@
 2013-09-11  Will Newton  <will.newton@linaro.org>
 
+	[BZ #15856]
+	* malloc/malloc.c (__libc_valloc): Check the value of bytes
+	does not overflow.
+
+2013-09-11  Will Newton  <will.newton@linaro.org>
+
 	[BZ #15855]
 	* malloc/malloc.c (__libc_pvalloc): Check the value of bytes
 	does not overflow.
diff --git a/malloc/malloc.c b/malloc/malloc.c
index bcc08c4..31e2dfa 100644
--- a/malloc/malloc.c
+++ b/malloc/malloc.c
@@ -3046,6 +3046,13 @@ __libc_valloc(size_t bytes)
 
   size_t pagesz = GLRO(dl_pagesize);
 
+  /* Check for overflow.  */
+  if (bytes > SIZE_MAX - pagesz - MINSIZE)
+    {
+      __set_errno (ENOMEM);
+      return 0;
+    }
+
   void *(*hook) (size_t, size_t, const void *) =
     force_reg (__memalign_hook);
   if (__builtin_expect (hook != NULL, 0))

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=7e0e64ead52591b968df582b0ddc247ba5c4eab4

commit 7e0e64ead52591b968df582b0ddc247ba5c4eab4
Author: Will Newton <will.newton@linaro.org>
Date:   Mon Aug 12 15:08:02 2013 +0100

    malloc: Check for integer overflow in pvalloc.
    
    A large bytes parameter to pvalloc could cause an integer overflow
    and corrupt allocator internals. Check the overflow does not occur
    before continuing with the allocation.
    
    ChangeLog:
    
    2013-09-11  Will Newton  <will.newton@linaro.org>
    
    	[BZ #15855]
    	* malloc/malloc.c (__libc_pvalloc): Check the value of bytes
    	does not overflow.

diff --git a/ChangeLog b/ChangeLog
index ea92d46..855cc5f 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2013-09-11  Will Newton  <will.newton@linaro.org>
+
+	[BZ #15855]
+	* malloc/malloc.c (__libc_pvalloc): Check the value of bytes
+	does not overflow.
+
 2013-09-23  Carlos O'Donell  <carlos@redhat.com>
 
 	[BZ #15754]
diff --git a/malloc/malloc.c b/malloc/malloc.c
index be472b2..bcc08c4 100644
--- a/malloc/malloc.c
+++ b/malloc/malloc.c
@@ -3082,6 +3082,13 @@ __libc_pvalloc(size_t bytes)
   size_t page_mask = GLRO(dl_pagesize) - 1;
   size_t rounded_bytes = (bytes + page_mask) & ~(page_mask);
 
+  /* Check for overflow.  */
+  if (bytes > SIZE_MAX - 2*pagesz - MINSIZE)
+    {
+      __set_errno (ENOMEM);
+      return 0;
+    }
+
   void *(*hook) (size_t, size_t, const void *) =
     force_reg (__memalign_hook);
   if (__builtin_expect (hook != NULL, 0))

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=c779e9df75256f19c7be8d12b2d163e2016a63f4

commit c779e9df75256f19c7be8d12b2d163e2016a63f4
Author: Carlos O'Donell <carlos@redhat.com>
Date:   Mon Sep 23 00:52:09 2013 -0400

    BZ #15754: CVE-2013-4788
    
    The pointer guard used for pointer mangling was not initialized for
    static applications resulting in the security feature being disabled.
    The pointer guard is now correctly initialized to a random value for
    static applications. Existing static applications need to be
    recompiled to take advantage of the fix.
    
    The test tst-ptrguard1-static and tst-ptrguard1 add regression
    coverage to ensure the pointer guards are sufficiently random
    and initialized to a default value.

diff --git a/ChangeLog b/ChangeLog
index 45f8e4e..ea92d46 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,21 @@
+2013-09-23  Carlos O'Donell  <carlos@redhat.com>
+
+	[BZ #15754]
+	* elf/Makefile (tests): Add tst-ptrguard1.
+	(tests-static): Add tst-ptrguard1-static.
+	(tst-ptrguard1-ARGS): Define.
+	(tst-ptrguard1-static-ARGS): Define.
+	* elf/tst-ptrguard1.c: New file.
+	* elf/tst-ptrguard1-static.c: New file.
+	* sysdeps/x86_64/stackguard-macros.h: Define POINTER_CHK_GUARD.
+	* sysdeps/i386/stackguard-macros.h: Likewise.
+	* sysdeps/powerpc/powerpc32/stackguard-macros.h: Likewise.
+	* sysdeps/powerpc/powerpc64/stackguard-macros.h: Likewise.
+	* sysdeps/s390/s390-32/stackguard-macros.h: Likewise.
+	* sysdeps/s390/s390-64/stackguard-macros.h: Likewise.
+	* sysdeps/sparc/sparc32/stackguard-macros.h: Likewise.
+	* sysdeps/sparc/sparc64/stackguard-macros.h: Likewise.
+
 2013-09-23  Siddhesh Poyarekar  <siddhesh@redhat.com>
 
 	[BZ #14547]
diff --git a/NEWS b/NEWS
index 37601e6..e8f1099 100644
--- a/NEWS
+++ b/NEWS
@@ -25,6 +25,12 @@ Version 2.18
   15654, 15655, 15666, 15667, 15674, 15711, 15755, 15759, 15797, 15892,
   15893, 15895, 15917, 15988, 16072.
 
+* CVE-2013-4788 The pointer guard used for pointer mangling was not
+  initialized for static applications resulting in the security feature
+  being disabled. The pointer guard is now correctly initialized to a
+  random value for static applications. Existing static applications need
+  to be recompiled to take advantage of the fix (bug 15754).
+
 * CVE-2012-4412 The strcoll implementation caches indices and rules for
   large collation sequences to optimize multiple passes.  This cache
   computation may overflow for large collation sequences and may cause a
diff --git a/csu/libc-start.c b/csu/libc-start.c
index e5da3ef..c898d06 100644
--- a/csu/libc-start.c
+++ b/csu/libc-start.c
@@ -37,6 +37,12 @@ extern void __pthread_initialize_minimal (void);
    in thread local area.  */
 uintptr_t __stack_chk_guard attribute_relro;
 # endif
+# ifndef  THREAD_SET_POINTER_GUARD
+/* Only exported for architectures that don't store the pointer guard
+   value in thread local area.  */
+uintptr_t __pointer_chk_guard_local
+	attribute_relro attribute_hidden __attribute__ ((nocommon));
+# endif
 #endif
 
 #ifdef HAVE_PTR_NTHREADS
@@ -195,6 +201,16 @@ LIBC_START_MAIN (int (*main) (int, char **, char ** MAIN_AUXVEC_DECL),
 # else
   __stack_chk_guard = stack_chk_guard;
 # endif
+
+  /* Set up the pointer guard value.  */
+  uintptr_t pointer_chk_guard = _dl_setup_pointer_guard (_dl_random,
+							 stack_chk_guard);
+# ifdef THREAD_SET_POINTER_GUARD
+  THREAD_SET_POINTER_GUARD (pointer_chk_guard);
+# else
+  __pointer_chk_guard_local = pointer_chk_guard;
+# endif
+
 #endif
 
   /* Register the destructor of the dynamic linker if there is any.  */
diff --git a/elf/Makefile b/elf/Makefile
index 3b58649..98834f4 100644
--- a/elf/Makefile
+++ b/elf/Makefile
@@ -121,7 +121,8 @@ endif
 tests = tst-tls1 tst-tls2 tst-tls9 tst-leaks1 \
 	tst-array1 tst-array2 tst-array3 tst-array4 tst-array5
 tests-static = tst-tls1-static tst-tls2-static tst-stackguard1-static \
-	       tst-leaks1-static tst-array1-static tst-array5-static
+	       tst-leaks1-static tst-array1-static tst-array5-static \
+	       tst-ptrguard1-static
 ifeq (yes,$(build-shared))
 tests-static += tst-tls9-static
 tst-tls9-static-ENV = \
@@ -145,7 +146,8 @@ tests += loadtest restest1 preloadtest loadfail multiload origtest resolvfail \
 	 tst-audit1 tst-audit2 tst-audit8 \
 	 tst-stackguard1 tst-addr1 tst-thrlock \
 	 tst-unique1 tst-unique2 tst-unique3 tst-unique4 \
-	 tst-initorder tst-initorder2 tst-relsort1 tst-null-argv
+	 tst-initorder tst-initorder2 tst-relsort1 tst-null-argv \
+	 tst-ptrguard1
 #	 reldep9
 test-srcs = tst-pathopt
 selinux-enabled := $(shell cat /selinux/enforce 2> /dev/null)
@@ -1016,6 +1018,9 @@ LDFLAGS-order2mod2.so = $(no-as-needed)
 tst-stackguard1-ARGS = --command "$(host-test-program-cmd) --child"
 tst-stackguard1-static-ARGS = --command "$(objpfx)tst-stackguard1-static --child"
 
+tst-ptrguard1-ARGS = --command "$(host-test-program-cmd) --child"
+tst-ptrguard1-static-ARGS = --command "$(objpfx)tst-ptrguard1-static --child"
+
 $(objpfx)tst-leaks1: $(libdl)
 $(objpfx)tst-leaks1-mem: $(objpfx)tst-leaks1.out
 	$(common-objpfx)malloc/mtrace $(objpfx)tst-leaks1.mtrace > $@
diff --git a/elf/tst-ptrguard1-static.c b/elf/tst-ptrguard1-static.c
new file mode 100644
index 0000000..7aff3b7
--- /dev/null
+++ b/elf/tst-ptrguard1-static.c
@@ -0,0 +1 @@
+#include "tst-ptrguard1.c"
diff --git a/elf/tst-ptrguard1.c b/elf/tst-ptrguard1.c
new file mode 100644
index 0000000..c344a04
--- /dev/null
+++ b/elf/tst-ptrguard1.c
@@ -0,0 +1,202 @@
+/* Copyright (C) 2013 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/>.  */
+
+#include <errno.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/wait.h>
+#include <stackguard-macros.h>
+#include <tls.h>
+#include <unistd.h>
+
+#ifndef POINTER_CHK_GUARD
+extern uintptr_t __pointer_chk_guard;
+# define POINTER_CHK_GUARD __pointer_chk_guard
+#endif
+
+static const char *command;
+static bool child;
+static uintptr_t ptr_chk_guard_copy;
+static bool ptr_chk_guard_copy_set;
+static int fds[2];
+
+static void __attribute__ ((constructor))
+con (void)
+{
+  ptr_chk_guard_copy = POINTER_CHK_GUARD;
+  ptr_chk_guard_copy_set = true;
+}
+
+static int
+uintptr_t_cmp (const void *a, const void *b)
+{
+  if (*(uintptr_t *) a < *(uintptr_t *) b)
+    return 1;
+  if (*(uintptr_t *) a > *(uintptr_t *) b)
+    return -1;
+  return 0;
+}
+
+static int
+do_test (void)
+{
+  if (!ptr_chk_guard_copy_set)
+    {
+      puts ("constructor has not been run");
+      return 1;
+    }
+
+  if (ptr_chk_guard_copy != POINTER_CHK_GUARD)
+    {
+      puts ("POINTER_CHK_GUARD changed between constructor and do_test");
+      return 1;
+    }
+
+  if (child)
+    {
+      write (2, &ptr_chk_guard_copy, sizeof (ptr_chk_guard_copy));
+      return 0;
+    }
+
+  if (command == NULL)
+    {
+      puts ("missing --command or --child argument");
+      return 1;
+    }
+
+#define N 16
+  uintptr_t child_ptr_chk_guards[N + 1];
+  child_ptr_chk_guards[N] = ptr_chk_guard_copy;
+  int i;
+  for (i = 0; i < N; ++i)
+    {
+      if (pipe (fds) < 0)
+	{
+	  printf ("couldn't create pipe: %m\n");
+	  return 1;
+	}
+
+      pid_t pid = fork ();
+      if (pid < 0)
+	{
+	  printf ("fork failed: %m\n");
+	  return 1;
+	}
+
+      if (!pid)
+	{
+	  if (ptr_chk_guard_copy != POINTER_CHK_GUARD)
+	    {
+	      puts ("POINTER_CHK_GUARD changed after fork");
+	      exit (1);
+	    }
+
+	  close (fds[0]);
+	  close (2);
+	  dup2 (fds[1], 2);
+	  close (fds[1]);
+
+	  system (command);
+	  exit (0);
+	}
+
+      close (fds[1]);
+
+      if (TEMP_FAILURE_RETRY (read (fds[0], &child_ptr_chk_guards[i],
+				    sizeof (uintptr_t))) != sizeof (uintptr_t))
+	{
+	  puts ("could not read ptr_chk_guard value from child");
+	  return 1;
+	}
+
+      close (fds[0]);
+
+      pid_t termpid;
+      int status;
+      termpid = TEMP_FAILURE_RETRY (waitpid (pid, &status, 0));
+      if (termpid == -1)
+	{
+	  printf ("waitpid failed: %m\n");
+	  return 1;
+	}
+      else if (termpid != pid)
+	{
+	  printf ("waitpid returned %ld != %ld\n",
+		  (long int) termpid, (long int) pid);
+	  return 1;
+	}
+      else if (!WIFEXITED (status) || WEXITSTATUS (status))
+	{
+	  puts ("child hasn't exited with exit status 0");
+	  return 1;
+	}
+    }
+
+  qsort (child_ptr_chk_guards, N + 1, sizeof (uintptr_t), uintptr_t_cmp);
+
+  /* The default pointer guard is the same as the default stack guard.
+     They are only set to default if dl_random is NULL.  */
+  uintptr_t default_guard = 0;
+  unsigned char *p = (unsigned char *) &default_guard;
+  p[sizeof (uintptr_t) - 1] = 255;
+  p[sizeof (uintptr_t) - 2] = '\n';
+  p[0] = 0;
+
+  /* Test if the pointer guard canaries are either randomized,
+     or equal to the default pointer guard value.
+     Even with randomized pointer guards it might happen
+     that the random number generator generates the same
+     values, but if that happens in more than half from
+     the 16 runs, something is very wrong.  */
+  int ndifferences = 0;
+  int ndefaults = 0;
+  for (i = 0; i < N; ++i)
+    {
+      if (child_ptr_chk_guards[i] != child_ptr_chk_guards[i+1])
+	ndifferences++;
+      else if (child_ptr_chk_guards[i] == default_guard)
+	ndefaults++;
+    }
+
+  printf ("differences %d defaults %d\n", ndifferences, ndefaults);
+
+  if (ndifferences < N / 2 && ndefaults < N / 2)
+    {
+      puts ("pointer guard values are not randomized enough");
+      puts ("nor equal to the default value");
+      return 1;
+    }
+
+  return 0;
+}
+
+#define OPT_COMMAND	10000
+#define OPT_CHILD	10001
+#define CMDLINE_OPTIONS	\
+  { "command", required_argument, NULL, OPT_COMMAND },  \
+  { "child", no_argument, NULL, OPT_CHILD },
+#define CMDLINE_PROCESS	\
+  case OPT_COMMAND:	\
+    command = optarg;	\
+    break;		\
+  case OPT_CHILD:	\
+    child = true;	\
+    break;
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/ports/ChangeLog.ia64 b/ports/ChangeLog.ia64
index 92b81cb..f61f37f 100644
--- a/ports/ChangeLog.ia64
+++ b/ports/ChangeLog.ia64
@@ -1,3 +1,8 @@
+2013-09-22  Carlos O'Donell  <carlos@redhat.com>
+
+	[BZ #15754]
+	* sysdeps/ia64/stackguard-macros.h: Define POINTER_CHK_GUARD.
+
 2013-07-04  Andreas Jaeger  <aj@suse.de>
 
 	* sysdeps/unix/sysv/linux/ia64/sys/ptrace.h (PTRACE_LISTEN):
diff --git a/ports/ChangeLog.tile b/ports/ChangeLog.tile
index a2ec5e1..972bd81 100644
--- a/ports/ChangeLog.tile
+++ b/ports/ChangeLog.tile
@@ -1,3 +1,8 @@
+2013-09-22  Carlos O'Donell  <carlos@redhat.com>
+
+	[BZ #15754]
+	* sysdeps/tile/stackguard-macros.h: Define POINTER_CHK_GUARD.
+
 2013-07-22  Chris Metcalf  <cmetcalf@tilera.com>
 
 	[BZ #15759]
diff --git a/ports/sysdeps/ia64/stackguard-macros.h b/ports/sysdeps/ia64/stackguard-macros.h
index dc683c2..3907293 100644
--- a/ports/sysdeps/ia64/stackguard-macros.h
+++ b/ports/sysdeps/ia64/stackguard-macros.h
@@ -2,3 +2,6 @@
 
 #define STACK_CHK_GUARD \
   ({ uintptr_t x; asm ("adds %0 = -8, r13;; ld8 %0 = [%0]" : "=r" (x)); x; })
+
+#define POINTER_CHK_GUARD \
+  ({ uintptr_t x; asm ("adds %0 = -16, r13;; ld8 %0 = [%0]" : "=r" (x)); x; })
diff --git a/ports/sysdeps/tile/stackguard-macros.h b/ports/sysdeps/tile/stackguard-macros.h
index 589ea2b..f2e041b 100644
--- a/ports/sysdeps/tile/stackguard-macros.h
+++ b/ports/sysdeps/tile/stackguard-macros.h
@@ -4,11 +4,17 @@
 # if __WORDSIZE == 64
 #  define STACK_CHK_GUARD \
   ({ uintptr_t x; asm ("addi %0, tp, -16; ld %0, %0" : "=r" (x)); x; })
+#  define POINTER_CHK_GUARD \
+  ({ uintptr_t x; asm ("addi %0, tp, -24; ld %0, %0" : "=r" (x)); x; })
 # else
 #  define STACK_CHK_GUARD \
   ({ uintptr_t x; asm ("addi %0, tp, -8; ld4s %0, %0" : "=r" (x)); x; })
+#  define POINTER_CHK_GUARD \
+  ({ uintptr_t x; asm ("addi %0, tp, -12; ld4s %0, %0" : "=r" (x)); x; })
 # endif
 #else
 # define STACK_CHK_GUARD \
   ({ uintptr_t x; asm ("addi %0, tp, -8; lw %0, %0" : "=r" (x)); x; })
+# define POINTER_CHK_GUARD \
+  ({ uintptr_t x; asm ("addi %0, tp, -12; lw %0, %0" : "=r" (x)); x; })
 #endif
diff --git a/sysdeps/generic/stackguard-macros.h b/sysdeps/generic/stackguard-macros.h
index ababf65..4fa3d96 100644
--- a/sysdeps/generic/stackguard-macros.h
+++ b/sysdeps/generic/stackguard-macros.h
@@ -2,3 +2,6 @@
 
 extern uintptr_t __stack_chk_guard;
 #define STACK_CHK_GUARD __stack_chk_guard
+
+extern uintptr_t __pointer_chk_guard_local;
+#define POINTER_CHK_GUARD __pointer_chk_guard_local
diff --git a/sysdeps/i386/stackguard-macros.h b/sysdeps/i386/stackguard-macros.h
index 8c31e19..0397629 100644
--- a/sysdeps/i386/stackguard-macros.h
+++ b/sysdeps/i386/stackguard-macros.h
@@ -2,3 +2,11 @@
 
 #define STACK_CHK_GUARD \
   ({ uintptr_t x; asm ("movl %%gs:0x14, %0" : "=r" (x)); x; })
+
+#define POINTER_CHK_GUARD \
+  ({							\
+     uintptr_t x;					\
+     asm ("movl %%gs:%c1, %0" : "=r" (x)		\
+	  : "i" (offsetof (tcbhead_t, pointer_guard)));	\
+     x;							\
+   })
diff --git a/sysdeps/powerpc/powerpc32/stackguard-macros.h b/sysdeps/powerpc/powerpc32/stackguard-macros.h
index 839f6a4..b3d0af8 100644
--- a/sysdeps/powerpc/powerpc32/stackguard-macros.h
+++ b/sysdeps/powerpc/powerpc32/stackguard-macros.h
@@ -2,3 +2,13 @@
 
 #define STACK_CHK_GUARD \
   ({ uintptr_t x; asm ("lwz %0,-28680(2)" : "=r" (x)); x; })
+
+#define POINTER_CHK_GUARD \
+  ({												\
+     uintptr_t x;										\
+     asm ("lwz %0,%1(2)"									\
+	  : "=r" (x)										\
+	  : "i" (offsetof (tcbhead_t, pointer_guard) - TLS_TCB_OFFSET - sizeof (tcbhead_t))	\
+         );											\
+     x;												\
+   })
diff --git a/sysdeps/powerpc/powerpc64/stackguard-macros.h b/sysdeps/powerpc/powerpc64/stackguard-macros.h
index 9da879c..4620f96 100644
--- a/sysdeps/powerpc/powerpc64/stackguard-macros.h
+++ b/sysdeps/powerpc/powerpc64/stackguard-macros.h
@@ -2,3 +2,13 @@
 
 #define STACK_CHK_GUARD \
   ({ uintptr_t x; asm ("ld %0,-28688(13)" : "=r" (x)); x; })
+
+#define POINTER_CHK_GUARD \
+  ({												\
+     uintptr_t x;										\
+     asm ("ld %0,%1(2)"										\
+	  : "=r" (x)										\
+	  : "i" (offsetof (tcbhead_t, pointer_guard) - TLS_TCB_OFFSET - sizeof (tcbhead_t))	\
+         );											\
+     x;												\
+   })
diff --git a/sysdeps/s390/s390-32/stackguard-macros.h b/sysdeps/s390/s390-32/stackguard-macros.h
index b74c579..449e8d4 100644
--- a/sysdeps/s390/s390-32/stackguard-macros.h
+++ b/sysdeps/s390/s390-32/stackguard-macros.h
@@ -2,3 +2,14 @@
 
 #define STACK_CHK_GUARD \
   ({ uintptr_t x; asm ("ear %0,%%a0; l %0,0x14(%0)" : "=a" (x)); x; })
+
+/* On s390/s390x there is no unique pointer guard, instead we use the
+   same value as the stack guard.  */
+#define POINTER_CHK_GUARD \
+  ({							\
+     uintptr_t x;					\
+     asm ("ear %0,%%a0; l %0,%1(%0)"			\
+	  : "=a" (x)					\
+	  : "i" (offsetof (tcbhead_t, stack_guard)));	\
+     x;							\
+   })
diff --git a/sysdeps/s390/s390-64/stackguard-macros.h b/sysdeps/s390/s390-64/stackguard-macros.h
index 0cebb5f..c8270fb 100644
--- a/sysdeps/s390/s390-64/stackguard-macros.h
+++ b/sysdeps/s390/s390-64/stackguard-macros.h
@@ -2,3 +2,17 @@
 
 #define STACK_CHK_GUARD \
   ({ uintptr_t x; asm ("ear %0,%%a0; sllg %0,%0,32; ear %0,%%a1; lg %0,0x28(%0)" : "=a" (x)); x; })
+
+/* On s390/s390x there is no unique pointer guard, instead we use the
+   same value as the stack guard.  */
+#define POINTER_CHK_GUARD \
+  ({							\
+     uintptr_t x;					\
+     asm ("ear %0,%%a0;"				\
+	  "sllg %0,%0,32;"				\
+	  "ear %0,%%a1;"				\
+	  "lg %0,%1(%0)"				\
+	 : "=a" (x)					\
+	 : "i" (offsetof (tcbhead_t, stack_guard)));	\
+     x;							\
+   })
diff --git a/sysdeps/sparc/sparc32/stackguard-macros.h b/sysdeps/sparc/sparc32/stackguard-macros.h
index c0b02b0..1eef0f1 100644
--- a/sysdeps/sparc/sparc32/stackguard-macros.h
+++ b/sysdeps/sparc/sparc32/stackguard-macros.h
@@ -2,3 +2,6 @@
 
 #define STACK_CHK_GUARD \
   ({ uintptr_t x; asm ("ld [%%g7+0x14], %0" : "=r" (x)); x; })
+
+#define POINTER_CHK_GUARD \
+  ({ uintptr_t x; asm ("ld [%%g7+0x18], %0" : "=r" (x)); x; })
diff --git a/sysdeps/sparc/sparc64/stackguard-macros.h b/sysdeps/sparc/sparc64/stackguard-macros.h
index 80f0635..cc0c12c 100644
--- a/sysdeps/sparc/sparc64/stackguard-macros.h
+++ b/sysdeps/sparc/sparc64/stackguard-macros.h
@@ -2,3 +2,6 @@
 
 #define STACK_CHK_GUARD \
   ({ uintptr_t x; asm ("ldx [%%g7+0x28], %0" : "=r" (x)); x; })
+
+#define POINTER_CHK_GUARD \
+  ({ uintptr_t x; asm ("ldx [%%g7+0x30], %0" : "=r" (x)); x; })
diff --git a/sysdeps/x86_64/stackguard-macros.h b/sysdeps/x86_64/stackguard-macros.h
index d7fedb3..1948800 100644
--- a/sysdeps/x86_64/stackguard-macros.h
+++ b/sysdeps/x86_64/stackguard-macros.h
@@ -4,3 +4,8 @@
   ({ uintptr_t x;						\
      asm ("mov %%fs:%c1, %0" : "=r" (x)				\
 	  : "i" (offsetof (tcbhead_t, stack_guard))); x; })
+
+#define POINTER_CHK_GUARD \
+  ({ uintptr_t x;						\
+     asm ("mov %%fs:%c1, %0" : "=r" (x)				\
+	  : "i" (offsetof (tcbhead_t, pointer_guard))); x; })

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=c4733da3f8e4c54e30f048c9e8d2b2fe2f53fd24

commit c4733da3f8e4c54e30f048c9e8d2b2fe2f53fd24
Author: Siddhesh Poyarekar <siddhesh@redhat.com>
Date:   Mon Sep 23 11:24:30 2013 +0530

    Check for integer overflow in cache size computation in strcoll
    
    strcoll is implemented using a cache for indices and weights of
    collation sequences in the strings so that subsequent passes do not
    have to search through collation data again.  For very large string
    inputs, the cache size computation could overflow.  In such a case,
    use the fallback function that does not cache indices and weights of
    collation sequences.
    
    Fixes CVE-2012-4412.

diff --git a/ChangeLog b/ChangeLog
index eb05e4f..45f8e4e 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,6 +1,12 @@
 2013-09-23  Siddhesh Poyarekar  <siddhesh@redhat.com>
 
 	[BZ #14547]
+	* string/tst-strcoll-overflow.c: New test case.
+	* string/Makefile (xtests): Add tst-strcoll-overflow.
+	* string/strcoll_l.c (STRCOLL): Skip allocating memory for
+	cache if string sizes may cause integer overflow.
+
+	[BZ #14547]
 	* string/strcoll_l.c (coll_seq): New members rule, idx,
 	save_idx and back_us.
 	(get_next_seq_nocache): New function.
diff --git a/NEWS b/NEWS
index cd49f6e..37601e6 100644
--- a/NEWS
+++ b/NEWS
@@ -25,6 +25,12 @@ Version 2.18
   15654, 15655, 15666, 15667, 15674, 15711, 15755, 15759, 15797, 15892,
   15893, 15895, 15917, 15988, 16072.
 
+* CVE-2012-4412 The strcoll implementation caches indices and rules for
+  large collation sequences to optimize multiple passes.  This cache
+  computation may overflow for large collation sequences and may cause a
+  stack or buffer overflow.  This is now fixed to use a slower algorithm
+  which does not use a cache if there is an integer overflow.
+
 * CVE-2013-2207 Incorrectly granting access to another user's pseudo-terminal
   has been fixed by disabling the use of pt_chown (Bugzilla #15755).
   Distributions can re-enable building and using pt_chown via the new configure
diff --git a/string/Makefile b/string/Makefile
index 72d3e29..17f9d68 100644
--- a/string/Makefile
+++ b/string/Makefile
@@ -57,6 +57,8 @@ tests		:= tester inl-tester noinl-tester testcopy test-ffs	\
 tests-ifunc := $(strop-tests:%=test-%-ifunc)
 tests += $(tests-ifunc)
 
+xtests = tst-strcoll-overflow
+
 include ../Rules
 
 tester-ENV = LANGUAGE=C
diff --git a/string/strcoll_l.c b/string/strcoll_l.c
index eb042ff..4ee101a 100644
--- a/string/strcoll_l.c
+++ b/string/strcoll_l.c
@@ -524,7 +524,15 @@ STRCOLL (const STRING_TYPE *s1, const STRING_TYPE *s2, __locale_t l)
   memset (&seq1, 0, sizeof (seq1));
   seq2 = seq1;
 
-  if (! __libc_use_alloca ((s1len + s2len) * (sizeof (int32_t) + 1)))
+  size_t size_max = SIZE_MAX / (sizeof (int32_t) + 1);
+
+  if (MIN (s1len, s2len) > size_max
+      || MAX (s1len, s2len) > size_max - MIN (s1len, s2len))
+    {
+      /* If the strings are long enough to cause overflow in the size request,
+         then skip the allocation and proceed with the non-cached routines.  */
+    }
+  else if (! __libc_use_alloca ((s1len + s2len) * (sizeof (int32_t) + 1)))
     {
       seq1.idxarr = (int32_t *) malloc ((s1len + s2len) * (sizeof (int32_t) + 1));
 
diff --git a/string/tst-strcoll-overflow.c b/string/tst-strcoll-overflow.c
new file mode 100644
index 0000000..bb665ac
--- /dev/null
+++ b/string/tst-strcoll-overflow.c
@@ -0,0 +1,61 @@
+/* Copyright (C) 2013 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/>.  */
+
+#include <locale.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+/* Verify that strcoll does not crash for large strings for which it cannot
+   cache weight lookup results.  The size is large enough to cause integer
+   overflows on 32-bit as well as buffer overflows on 64-bit.  The test should
+   work reasonably reliably when overcommit is disabled, but it obviously
+   depends on how much memory the system has.  There's a limitation to this
+   test in that it does not run to completion.  Actually collating such a
+   large string can take days and we can't have xcheck running that long.  For
+   that reason, we run the test for about 5 minutes and then assume that
+   everything is fine if there are no crashes.  */
+#define SIZE 0x40000000ul
+
+int
+do_test (void)
+{
+  if (setlocale (LC_COLLATE, "en_GB.UTF-8") == NULL)
+    {
+      puts ("setlocale failed, cannot test for overflow");
+      return 0;
+    }
+
+  char *p = malloc (SIZE);
+
+  if (p == NULL)
+    {
+      puts ("could not allocate memory");
+      return 1;
+    }
+
+  memset (p, 'x', SIZE - 1);
+  p[SIZE - 1] = 0;
+  printf ("%d\n", strcoll (p, p));
+  return 0;
+}
+
+#define TIMEOUT 300
+#define EXPECTED_SIGNAL SIGALRM
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=b8053c6138c8835fb27d30c7e034e240e92bce0f

commit b8053c6138c8835fb27d30c7e034e240e92bce0f
Author: Siddhesh Poyarekar <siddhesh@redhat.com>
Date:   Mon Sep 23 11:20:02 2013 +0530

    Fall back to non-cached sequence traversal and comparison on malloc fail
    
    strcoll currently falls back to alloca if malloc fails, resulting in a
    possible stack overflow.  This patch implements sequence traversal and
    comparison without caching indices and rules.
    
    Fixes CVE-2012-4424.

diff --git a/ChangeLog b/ChangeLog
index 1738c87..eb05e4f 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,4 +1,12 @@
-2013-08-20  Siddhesh Poyarekar  <siddhesh@redhat.com>
+2013-09-23  Siddhesh Poyarekar  <siddhesh@redhat.com>
+
+	[BZ #14547]
+	* string/strcoll_l.c (coll_seq): New members rule, idx,
+	save_idx and back_us.
+	(get_next_seq_nocache): New function.
+	(do_compare_nocache): New function.
+	(STRCOLL): Use get_next_seq_nocache and do_compare_nocache
+	when malloc fails.
 
 	* string/strcoll_l.c (coll_seq): New structure.
 	(get_next_seq_cached): New function.
diff --git a/NEWS b/NEWS
index 2970338..cd49f6e 100644
--- a/NEWS
+++ b/NEWS
@@ -12,18 +12,18 @@ Version 2.18
   2546, 2560, 5159, 6809, 7006, 10060, 10062, 10283, 10357, 10686, 11120,
   11561, 12310, 12387, 12492, 12515, 12723, 13550, 13889, 13951, 13988,
   14142, 14155, 14176, 14200, 14256, 14280, 14293, 14317, 14327, 14478,
-  14496, 14582, 14686, 14699, 14812, 14888, 14894, 14907, 14908, 14909,
-  14920, 14952, 14964, 14981, 14982, 14985, 14991, 14994, 14996, 15000,
-  15003, 15006, 15007, 15014, 15020, 15022, 15023, 15036, 15054, 15055,
-  15062, 15078, 15084, 15085, 15086, 15100, 15160, 15214, 15221, 15232,
-  15234, 15283, 15285, 15287, 15304, 15305, 15307, 15309, 15327, 15330,
-  15331, 15335, 15336, 15337, 15339, 15342, 15346, 15359, 15361, 15366,
-  15380, 15381, 15394, 15395, 15405, 15406, 15409, 15416, 15418, 15419,
-  15423, 15424, 15426, 15427, 15429, 15431, 15432, 15441, 15442, 15448,
-  15465, 15480, 15485, 15488, 15490, 15492, 15493, 15497, 15506, 15522,
-  15529, 15532, 15536, 15553, 15577, 15583, 15618, 15627, 15631, 15654,
-  15655, 15666, 15667, 15674, 15711, 15755, 15759, 15797, 15892, 15893,
-  15895, 15917, 15988, 16072.
+  14496, 14547, 14582, 14686, 14699, 14812, 14888, 14894, 14907, 14908,
+  14909, 14920, 14952, 14964, 14981, 14982, 14985, 14991, 14994, 14996,
+  15000, 15003, 15006, 15007, 15014, 15020, 15022, 15023, 15036, 15054,
+  15055, 15062, 15078, 15084, 15085, 15086, 15100, 15160, 15214, 15221,
+  15232, 15234, 15283, 15285, 15287, 15304, 15305, 15307, 15309, 15327,
+  15330, 15331, 15335, 15336, 15337, 15339, 15342, 15346, 15359, 15361,
+  15366, 15380, 15381, 15394, 15395, 15405, 15406, 15409, 15416, 15418,
+  15419, 15423, 15424, 15426, 15427, 15429, 15431, 15432, 15441, 15442,
+  15448, 15465, 15480, 15485, 15488, 15490, 15492, 15493, 15497, 15506,
+  15522, 15529, 15532, 15536, 15553, 15577, 15583, 15618, 15627, 15631,
+  15654, 15655, 15666, 15667, 15674, 15711, 15755, 15759, 15797, 15892,
+  15893, 15895, 15917, 15988, 16072.
 
 * CVE-2013-2207 Incorrectly granting access to another user's pseudo-terminal
   has been fixed by disabling the use of pt_chown (Bugzilla #15755).
@@ -45,6 +45,12 @@ Version 2.18
 * CVE-2013-4458 Stack overflow in getaddrinfo with large number of results
   for AF_INET6 has been fixed (Bugzilla #16072).
 
+* CVE-2012-4424 The strcoll implementation uses malloc to cache indices and
+  rules for large collation sequences to optimize multiple passes and falls
+  back to alloca if malloc fails, resulting in a possible stack overflow.
+  The implementation now falls back to an uncached collation sequence lookup
+  if malloc fails.
+
 * Add support for calling C++11 thread_local object destructors on thread
   and program exit.  This needs compiler support for offloading C++11
   destructor calls to glibc.
diff --git a/string/strcoll_l.c b/string/strcoll_l.c
index 50ed84d..eb042ff 100644
--- a/string/strcoll_l.c
+++ b/string/strcoll_l.c
@@ -45,7 +45,7 @@
 typedef struct
 {
   int len;			/* Length of the current sequence.  */
-  int val;			/* Position of the sequence relative to the
+  size_t val;			/* Position of the sequence relative to the
 				   previous non-ignored sequence.  */
   size_t idxnow;		/* Current index in sequences.  */
   size_t idxmax;		/* Maximum index in sequences.  */
@@ -55,6 +55,12 @@ typedef struct
   const USTRING_TYPE *us;	/* The string.  */
   int32_t *idxarr;		/* Array to cache weight indices.  */
   unsigned char *rulearr;	/* Array to cache rules.  */
+  unsigned char rule;		/* Saved rule for the first sequence.  */
+  int32_t idx;			/* Index to weight of the current sequence.  */
+  int32_t save_idx;		/* Save looked up index of a forward
+				   sequence after the last backward
+				   sequence.  */
+  const USTRING_TYPE *back_us;	/* Beginning of the backward sequence.  */
 } coll_seq;
 
 /* Get next sequence.  The weight indices are cached, so we don't need to
@@ -64,7 +70,7 @@ get_next_seq_cached (coll_seq *seq, int nrules, int pass,
 		     const unsigned char *rulesets,
 		     const USTRING_TYPE *weights)
 {
-  int val = seq->val = 0;
+  size_t val = seq->val = 0;
   int len = seq->len;
   size_t backw_stop = seq->backw_stop;
   size_t backw = seq->backw;
@@ -146,7 +152,7 @@ get_next_seq (coll_seq *seq, int nrules, const unsigned char *rulesets,
 	      const USTRING_TYPE *extra, const int32_t *indirect)
 {
 #include WEIGHT_H
-  int val = seq->val = 0;
+  size_t val = seq->val = 0;
   int len = seq->len;
   size_t backw_stop = seq->backw_stop;
   size_t backw = seq->backw;
@@ -162,7 +168,7 @@ get_next_seq (coll_seq *seq, int nrules, const unsigned char *rulesets,
       ++val;
       if (backw_stop != ~0ul)
 	{
-	  /* The is something pushed.  */
+	  /* There is something pushed.  */
 	  if (backw == backw_stop)
 	    {
 	      /* The last pushed character was handled.  Continue
@@ -227,15 +233,199 @@ get_next_seq (coll_seq *seq, int nrules, const unsigned char *rulesets,
   seq->us = us;
 }
 
-/* Compare two sequences.  */
+/* Get next sequence.  Traverse the string as required.  This function does not
+   set or use any index or rule cache.  */
+static void
+get_next_seq_nocache (coll_seq *seq, int nrules, const unsigned char *rulesets,
+		      const USTRING_TYPE *weights, const int32_t *table,
+		      const USTRING_TYPE *extra, const int32_t *indirect,
+		      int pass)
+{
+#include WEIGHT_H
+  size_t val = seq->val = 0;
+  int len = seq->len;
+  size_t backw_stop = seq->backw_stop;
+  size_t backw = seq->backw;
+  size_t idxcnt = seq->idxcnt;
+  size_t idxmax = seq->idxmax;
+  int32_t idx = seq->idx;
+  const USTRING_TYPE *us = seq->us;
+
+  while (len == 0)
+    {
+      ++val;
+      if (backw_stop != ~0ul)
+	{
+	  /* There is something pushed.  */
+	  if (backw == backw_stop)
+	    {
+	      /* The last pushed character was handled.  Continue
+		 with forward characters.  */
+	      if (idxcnt < idxmax)
+		{
+		  idx = seq->save_idx;
+		  backw_stop = ~0ul;
+		}
+	      else
+		{
+		  /* Nothing anymore.  The backward sequence ended with
+		     the last sequence in the string.  Note that len is
+		     still zero.  */
+		  idx = 0;
+		  break;
+	        }
+	    }
+	  else
+	    {
+	      /* XXX Traverse BACKW sequences from the beginning of
+		 BACKW_STOP to get the next sequence.  Is ther a quicker way
+	         to do this?  */
+	      size_t i = backw_stop;
+	      us = seq->back_us;
+	      while (i < backw)
+		{
+		  int32_t tmp = findidx (&us, -1);
+		  idx = tmp & 0xffffff;
+		  i++;
+		}
+	      --backw;
+	      us = seq->us;
+	    }
+	}
+      else
+	{
+	  backw_stop = idxmax;
+	  int32_t prev_idx = idx;
+
+	  while (*us != L('\0'))
+	    {
+	      int32_t tmp = findidx (&us, -1);
+	      unsigned char rule = tmp >> 24;
+	      prev_idx = idx;
+	      idx = tmp & 0xffffff;
+	      idxcnt = idxmax++;
+
+	      /* Save the rule for the first sequence.  */
+	      if (__glibc_unlikely (idxcnt == 0))
+	        seq->rule = rule;
+
+	      if ((rulesets[rule * nrules + pass]
+		   & sort_backward) == 0)
+		/* No more backward characters to push.  */
+		break;
+	      ++idxcnt;
+	    }
+
+	  if (backw_stop >= idxcnt)
+	    {
+	      /* No sequence at all or just one.  */
+	      if (idxcnt == idxmax || backw_stop > idxcnt)
+		/* Note that len is still zero.  */
+		break;
+
+	      backw_stop = ~0ul;
+	    }
+	  else
+	    {
+	      /* We pushed backward sequences.  If the stream ended with the
+		 backward sequence, then we process the last sequence we
+		 found.  Otherwise we process the sequence before the last
+		 one since the last one was a forward sequence.  */
+	      seq->back_us = seq->us;
+	      seq->us = us;
+	      backw = idxcnt;
+	      if (idxmax > idxcnt)
+		{
+		  backw--;
+		  seq->save_idx = idx;
+		  idx = prev_idx;
+		}
+	      if (backw > backw_stop)
+		backw--;
+	    }
+	}
+
+      len = weights[idx++];
+      /* Skip over indices of previous levels.  */
+      for (int i = 0; i < pass; i++)
+	{
+	  idx += len;
+	  len = weights[idx];
+	  idx++;
+	}
+    }
+
+  /* Update the structure.  */
+  seq->val = val;
+  seq->len = len;
+  seq->backw_stop = backw_stop;
+  seq->backw = backw;
+  seq->idxcnt = idxcnt;
+  seq->idxmax = idxmax;
+  seq->us = us;
+  seq->idx = idx;
+}
+
+/* Compare two sequences.  This version does not use the index and rules
+   cache.  */
+static int
+do_compare_nocache (coll_seq *seq1, coll_seq *seq2, int position,
+		    const USTRING_TYPE *weights)
+{
+  int seq1len = seq1->len;
+  int seq2len = seq2->len;
+  size_t val1 = seq1->val;
+  size_t val2 = seq2->val;
+  int idx1 = seq1->idx;
+  int idx2 = seq2->idx;
+  int result = 0;
+
+  /* Test for position if necessary.  */
+  if (position && val1 != val2)
+    {
+      result = val1 > val2 ? 1 : -1;
+      goto out;
+    }
+
+  /* Compare the two sequences.  */
+  do
+    {
+      if (weights[idx1] != weights[idx2])
+	{
+	  /* The sequences differ.  */
+	  result = weights[idx1] - weights[idx2];
+	  goto out;
+	}
+
+      /* Increment the offsets.  */
+      ++idx1;
+      ++idx2;
+
+      --seq1len;
+      --seq2len;
+    }
+  while (seq1len > 0 && seq2len > 0);
+
+  if (position && seq1len != seq2len)
+    result = seq1len - seq2len;
+
+out:
+  seq1->len = seq1len;
+  seq2->len = seq2len;
+  seq1->idx = idx1;
+  seq2->idx = idx2;
+  return result;
+}
+
+/* Compare two sequences using the index cache.  */
 static int
 do_compare (coll_seq *seq1, coll_seq *seq2, int position,
 	    const USTRING_TYPE *weights)
 {
   int seq1len = seq1->len;
   int seq2len = seq2->len;
-  int val1 = seq1->val;
-  int val2 = seq2->val;
+  size_t val1 = seq1->val;
+  size_t val2 = seq2->val;
   int32_t *idx1arr = seq1->idxarr;
   int32_t *idx2arr = seq2->idxarr;
   int idx1now = seq1->idxnow;
@@ -245,7 +435,7 @@ do_compare (coll_seq *seq1, coll_seq *seq2, int position,
   /* Test for position if necessary.  */
   if (position && val1 != val2)
     {
-      result = val1 - val2;
+      result = val1 > val2 ? 1 : -1;
       goto out;
     }
 
@@ -334,57 +524,62 @@ STRCOLL (const STRING_TYPE *s1, const STRING_TYPE *s2, __locale_t l)
   memset (&seq1, 0, sizeof (seq1));
   seq2 = seq1;
 
-  /* We need the elements of the strings as unsigned values since they
-     are used as indices.  */
-  seq1.us = (const USTRING_TYPE *) s1;
-  seq2.us = (const USTRING_TYPE *) s2;
-
   if (! __libc_use_alloca ((s1len + s2len) * (sizeof (int32_t) + 1)))
     {
       seq1.idxarr = (int32_t *) malloc ((s1len + s2len) * (sizeof (int32_t) + 1));
-      seq2.idxarr = &seq1.idxarr[s1len];
-      seq1.rulearr = (unsigned char *) &seq2.idxarr[s2len];
-      seq2.rulearr = &seq1.rulearr[s1len];
-
-      if (seq1.idxarr == NULL)
-	/* No memory.  Well, go with the stack then.
-
-	   XXX Once this implementation is stable we will handle this
-	   differently.  Instead of precomputing the indices we will
-	   do this in time.  This means, though, that this happens for
-	   every pass again.  */
-	goto try_stack;
-      use_malloc = true;
+
+      /* If we failed to allocate memory, we leave everything as NULL so that
+	 we use the nocache version of traversal and comparison functions.  */
+      if (seq1.idxarr != NULL)
+	{
+	  seq2.idxarr = &seq1.idxarr[s1len];
+	  seq1.rulearr = (unsigned char *) &seq2.idxarr[s2len];
+	  seq2.rulearr = &seq1.rulearr[s1len];
+	  use_malloc = true;
+	}
     }
   else
     {
-    try_stack:
       seq1.idxarr = (int32_t *) alloca (s1len * sizeof (int32_t));
       seq2.idxarr = (int32_t *) alloca (s2len * sizeof (int32_t));
       seq1.rulearr = (unsigned char *) alloca (s1len);
       seq2.rulearr = (unsigned char *) alloca (s2len);
     }
 
-  seq1.rulearr[0] = 0;
+  int rule = 0;
 
   /* Cache values in the first pass and if needed, use them in subsequent
      passes.  */
   for (int pass = 0; pass < nrules; ++pass)
     {
       seq1.idxcnt = 0;
+      seq1.idx = 0;
+      seq2.idx = 0;
       seq1.backw_stop = ~0ul;
       seq1.backw = ~0ul;
       seq2.idxcnt = 0;
       seq2.backw_stop = ~0ul;
       seq2.backw = ~0ul;
 
+      /* We need the elements of the strings as unsigned values since they
+	 are used as indices.  */
+      seq1.us = (const USTRING_TYPE *) s1;
+      seq2.us = (const USTRING_TYPE *) s2;
+
       /* We assume that if a rule has defined `position' in one section
 	 this is true for all of them.  */
-      int position = rulesets[seq1.rulearr[0] * nrules + pass] & sort_position;
+      int position = rulesets[rule * nrules + pass] & sort_position;
 
       while (1)
 	{
-	  if (pass == 0)
+	  if (__glibc_unlikely (seq1.idxarr == NULL))
+	    {
+	      get_next_seq_nocache (&seq1, nrules, rulesets, weights, table,
+				    extra, indirect, pass);
+	      get_next_seq_nocache (&seq2, nrules, rulesets, weights, table,
+				    extra, indirect, pass);
+	    }
+	  else if (pass == 0)
 	    {
 	      get_next_seq (&seq1, nrules, rulesets, weights, table, extra,
 			    indirect);
@@ -411,10 +606,18 @@ STRCOLL (const STRING_TYPE *s1, const STRING_TYPE *s2, __locale_t l)
 	      goto free_and_return;
 	    }
 
-	  result = do_compare (&seq1, &seq2, position, weights);
+	  if (__glibc_unlikely (seq1.idxarr == NULL))
+	    result = do_compare_nocache (&seq1, &seq2, position, weights);
+	  else
+	    result = do_compare (&seq1, &seq2, position, weights);
 	  if (result != 0)
 	    goto free_and_return;
 	}
+
+      if (__glibc_likely (seq1.rulearr != NULL))
+	rule = seq1.rulearr[0];
+      else
+	rule = seq1.rule;
     }
 
   /* Free the memory if needed.  */

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=37d4728976aea69db23a061830828787a2fd05ed

commit 37d4728976aea69db23a061830828787a2fd05ed
Author: Siddhesh Poyarekar <siddhesh@redhat.com>
Date:   Tue Aug 20 08:40:05 2013 +0530

    Simplify strcoll implementation
    
    Break up strcoll into simpler functions so that the logic is easier to
    follow and maintain.

diff --git a/ChangeLog b/ChangeLog
index c83db92..1738c87 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+2013-08-20  Siddhesh Poyarekar  <siddhesh@redhat.com>
+
+	* string/strcoll_l.c (coll_seq): New structure.
+	(get_next_seq_cached): New function.
+	(get_next_seq): New function.
+	(do_compare): New function.
+	(STRCOLL): Use GNU style definition.  Simplify implementation
+	by using get_next_seq, get_next_seq_cached and do_compare.
+
 2013-10-31  Andreas Schwab  <schwab@suse.de>
 
 	[BZ# 15917]
diff --git a/string/strcoll_l.c b/string/strcoll_l.c
index ecda08f..50ed84d 100644
--- a/string/strcoll_l.c
+++ b/string/strcoll_l.c
@@ -41,11 +41,244 @@
 
 #include "../locale/localeinfo.h"
 
+/* Track status while looking for sequences in a string.  */
+typedef struct
+{
+  int len;			/* Length of the current sequence.  */
+  int val;			/* Position of the sequence relative to the
+				   previous non-ignored sequence.  */
+  size_t idxnow;		/* Current index in sequences.  */
+  size_t idxmax;		/* Maximum index in sequences.  */
+  size_t idxcnt;		/* Current count of indices.  */
+  size_t backw;			/* Current Backward sequence index.  */
+  size_t backw_stop;		/* Index where the backward sequences stop.  */
+  const USTRING_TYPE *us;	/* The string.  */
+  int32_t *idxarr;		/* Array to cache weight indices.  */
+  unsigned char *rulearr;	/* Array to cache rules.  */
+} coll_seq;
+
+/* Get next sequence.  The weight indices are cached, so we don't need to
+   traverse the string.  */
+static void
+get_next_seq_cached (coll_seq *seq, int nrules, int pass,
+		     const unsigned char *rulesets,
+		     const USTRING_TYPE *weights)
+{
+  int val = seq->val = 0;
+  int len = seq->len;
+  size_t backw_stop = seq->backw_stop;
+  size_t backw = seq->backw;
+  size_t idxcnt = seq->idxcnt;
+  size_t idxmax = seq->idxmax;
+  size_t idxnow = seq->idxnow;
+  unsigned char *rulearr = seq->rulearr;
+  int32_t *idxarr = seq->idxarr;
+
+  while (len == 0)
+    {
+      ++val;
+      if (backw_stop != ~0ul)
+	{
+	  /* There is something pushed.  */
+	  if (backw == backw_stop)
+	    {
+	      /* The last pushed character was handled.  Continue
+		 with forward characters.  */
+	      if (idxcnt < idxmax)
+		{
+		  idxnow = idxcnt;
+		  backw_stop = ~0ul;
+		}
+	      else
+		{
+		  /* Nothing any more.  The backward sequence
+		     ended with the last sequence in the string.  */
+		  idxnow = ~0ul;
+		  break;
+		}
+	    }
+	  else
+	    idxnow = --backw;
+	}
+      else
+	{
+	  backw_stop = idxcnt;
+
+	  while (idxcnt < idxmax)
+	    {
+	      if ((rulesets[rulearr[idxcnt] * nrules + pass]
+		   & sort_backward) == 0)
+		/* No more backward characters to push.  */
+		break;
+	      ++idxcnt;
+	    }
+
+	  if (backw_stop == idxcnt)
+	    {
+	      /* No sequence at all or just one.  */
+	      if (idxcnt == idxmax)
+		/* Note that LEN is still zero.  */
+		break;
+
+	      backw_stop = ~0ul;
+	      idxnow = idxcnt++;
+	    }
+	  else
+	    /* We pushed backward sequences.  */
+	    idxnow = backw = idxcnt - 1;
+	}
+      len = weights[idxarr[idxnow]++];
+    }
+
+  /* Update the structure.  */
+  seq->val = val;
+  seq->len = len;
+  seq->backw_stop = backw_stop;
+  seq->backw = backw;
+  seq->idxcnt = idxcnt;
+  seq->idxnow = idxnow;
+}
+
+/* Get next sequence.  Traverse the string as required.  */
+static void
+get_next_seq (coll_seq *seq, int nrules, const unsigned char *rulesets,
+	      const USTRING_TYPE *weights, const int32_t *table,
+	      const USTRING_TYPE *extra, const int32_t *indirect)
+{
+#include WEIGHT_H
+  int val = seq->val = 0;
+  int len = seq->len;
+  size_t backw_stop = seq->backw_stop;
+  size_t backw = seq->backw;
+  size_t idxcnt = seq->idxcnt;
+  size_t idxmax = seq->idxmax;
+  size_t idxnow = seq->idxnow;
+  unsigned char *rulearr = seq->rulearr;
+  int32_t *idxarr = seq->idxarr;
+  const USTRING_TYPE *us = seq->us;
+
+  while (len == 0)
+    {
+      ++val;
+      if (backw_stop != ~0ul)
+	{
+	  /* The is something pushed.  */
+	  if (backw == backw_stop)
+	    {
+	      /* The last pushed character was handled.  Continue
+		 with forward characters.  */
+	      if (idxcnt < idxmax)
+		{
+		  idxnow = idxcnt;
+		  backw_stop = ~0ul;
+		}
+	      else
+		/* Nothing any more.  The backward sequence ended with
+		   the last sequence in the string.  Note that LEN
+		   is still zero.  */
+		break;
+	    }
+	  else
+	    idxnow = --backw;
+	}
+      else
+	{
+	  backw_stop = idxmax;
+
+	  while (*us != L('\0'))
+	    {
+	      int32_t tmp = findidx (&us, -1);
+	      rulearr[idxmax] = tmp >> 24;
+	      idxarr[idxmax] = tmp & 0xffffff;
+	      idxcnt = idxmax++;
+
+	      if ((rulesets[rulearr[idxcnt] * nrules]
+		   & sort_backward) == 0)
+		/* No more backward characters to push.  */
+		break;
+	      ++idxcnt;
+	    }
+
+	  if (backw_stop >= idxcnt)
+	    {
+	      /* No sequence at all or just one.  */
+	      if (idxcnt == idxmax || backw_stop > idxcnt)
+		/* Note that LEN is still zero.  */
+		break;
+
+	      backw_stop = ~0ul;
+	      idxnow = idxcnt;
+	    }
+	  else
+	    /* We pushed backward sequences.  */
+	    idxnow = backw = idxcnt - 1;
+	}
+      len = weights[idxarr[idxnow]++];
+    }
+
+  /* Update the structure.  */
+  seq->val = val;
+  seq->len = len;
+  seq->backw_stop = backw_stop;
+  seq->backw = backw;
+  seq->idxcnt = idxcnt;
+  seq->idxmax = idxmax;
+  seq->idxnow = idxnow;
+  seq->us = us;
+}
+
+/* Compare two sequences.  */
+static int
+do_compare (coll_seq *seq1, coll_seq *seq2, int position,
+	    const USTRING_TYPE *weights)
+{
+  int seq1len = seq1->len;
+  int seq2len = seq2->len;
+  int val1 = seq1->val;
+  int val2 = seq2->val;
+  int32_t *idx1arr = seq1->idxarr;
+  int32_t *idx2arr = seq2->idxarr;
+  int idx1now = seq1->idxnow;
+  int idx2now = seq2->idxnow;
+  int result = 0;
+
+  /* Test for position if necessary.  */
+  if (position && val1 != val2)
+    {
+      result = val1 - val2;
+      goto out;
+    }
+
+  /* Compare the two sequences.  */
+  do
+    {
+      if (weights[idx1arr[idx1now]] != weights[idx2arr[idx2now]])
+	{
+	  /* The sequences differ.  */
+	  result = weights[idx1arr[idx1now]] - weights[idx2arr[idx2now]];
+	  goto out;
+	}
+
+      /* Increment the offsets.  */
+      ++idx1arr[idx1now];
+      ++idx2arr[idx2now];
+
+      --seq1len;
+      --seq2len;
+    }
+  while (seq1len > 0 && seq2len > 0);
+
+  if (position && seq1len != seq2len)
+    result = seq1len - seq2len;
+
+out:
+  seq1->len = seq1len;
+  seq2->len = seq2len;
+  return result;
+}
+
 int
-STRCOLL (s1, s2, l)
-     const STRING_TYPE *s1;
-     const STRING_TYPE *s2;
-     __locale_t l;
+STRCOLL (const STRING_TYPE *s1, const STRING_TYPE *s2, __locale_t l)
 {
   struct __locale_data *current = l->__locales[LC_COLLATE];
   uint_fast32_t nrules = current->values[_NL_ITEM_INDEX (_NL_COLLATE_NRULES)].word;
@@ -56,34 +289,6 @@ STRCOLL (s1, s2, l)
   const USTRING_TYPE *weights;
   const USTRING_TYPE *extra;
   const int32_t *indirect;
-  uint_fast32_t pass;
-  int result = 0;
-  const USTRING_TYPE *us1;
-  const USTRING_TYPE *us2;
-  size_t s1len;
-  size_t s2len;
-  int32_t *idx1arr;
-  int32_t *idx2arr;
-  unsigned char *rule1arr;
-  unsigned char *rule2arr;
-  size_t idx1max;
-  size_t idx2max;
-  size_t idx1cnt;
-  size_t idx2cnt;
-  size_t idx1now;
-  size_t idx2now;
-  size_t backw1_stop;
-  size_t backw2_stop;
-  size_t backw1;
-  size_t backw2;
-  int val1;
-  int val2;
-  int position;
-  int seq1len;
-  int seq2len;
-  int use_malloc;
-
-#include WEIGHT_H
 
   if (nrules == 0)
     return STRCMP (s1, s2);
@@ -98,7 +303,6 @@ STRCOLL (s1, s2, l)
     current->values[_NL_ITEM_INDEX (CONCAT(_NL_COLLATE_EXTRA,SUFFIX))].string;
   indirect = (const int32_t *)
     current->values[_NL_ITEM_INDEX (CONCAT(_NL_COLLATE_INDIRECT,SUFFIX))].string;
-  use_malloc = 0;
 
   assert (((uintptr_t) table) % __alignof__ (table[0]) == 0);
   assert (((uintptr_t) weights) % __alignof__ (weights[0]) == 0);
@@ -106,18 +310,13 @@ STRCOLL (s1, s2, l)
   assert (((uintptr_t) indirect) % __alignof__ (indirect[0]) == 0);
 
   /* We need this a few times.  */
-  s1len = STRLEN (s1);
-  s2len = STRLEN (s2);
+  size_t s1len = STRLEN (s1);
+  size_t s2len = STRLEN (s2);
 
   /* Catch empty strings.  */
-  if (__builtin_expect (s1len == 0, 0) || __builtin_expect (s2len == 0, 0))
+  if (__glibc_unlikely (s1len == 0) || __glibc_unlikely (s2len == 0))
     return (s1len != 0) - (s2len != 0);
 
-  /* We need the elements of the strings as unsigned values since they
-     are used as indeces.  */
-  us1 = (const USTRING_TYPE *) s1;
-  us2 = (const USTRING_TYPE *) s2;
-
   /* Perform the first pass over the string and while doing this find
      and store the weights for each character.  Since we want this to
      be as fast as possible we are using `alloca' to store the temporary
@@ -127,411 +326,101 @@ STRCOLL (s1, s2, l)
 
      Please note that the localedef programs makes sure that `position'
      is not used at the first level.  */
+
+  coll_seq seq1, seq2;
+  bool use_malloc = false;
+  int result = 0;
+
+  memset (&seq1, 0, sizeof (seq1));
+  seq2 = seq1;
+
+  /* We need the elements of the strings as unsigned values since they
+     are used as indices.  */
+  seq1.us = (const USTRING_TYPE *) s1;
+  seq2.us = (const USTRING_TYPE *) s2;
+
   if (! __libc_use_alloca ((s1len + s2len) * (sizeof (int32_t) + 1)))
     {
-      idx1arr = (int32_t *) malloc ((s1len + s2len) * (sizeof (int32_t) + 1));
-      idx2arr = &idx1arr[s1len];
-      rule1arr = (unsigned char *) &idx2arr[s2len];
-      rule2arr = &rule1arr[s1len];
+      seq1.idxarr = (int32_t *) malloc ((s1len + s2len) * (sizeof (int32_t) + 1));
+      seq2.idxarr = &seq1.idxarr[s1len];
+      seq1.rulearr = (unsigned char *) &seq2.idxarr[s2len];
+      seq2.rulearr = &seq1.rulearr[s1len];
 
-      if (idx1arr == NULL)
+      if (seq1.idxarr == NULL)
 	/* No memory.  Well, go with the stack then.
 
 	   XXX Once this implementation is stable we will handle this
-	   differently.  Instead of precomputing the indeces we will
+	   differently.  Instead of precomputing the indices we will
 	   do this in time.  This means, though, that this happens for
 	   every pass again.  */
 	goto try_stack;
-      use_malloc = 1;
+      use_malloc = true;
     }
   else
     {
     try_stack:
-      idx1arr = (int32_t *) alloca (s1len * sizeof (int32_t));
-      idx2arr = (int32_t *) alloca (s2len * sizeof (int32_t));
-      rule1arr = (unsigned char *) alloca (s1len);
-      rule2arr = (unsigned char *) alloca (s2len);
+      seq1.idxarr = (int32_t *) alloca (s1len * sizeof (int32_t));
+      seq2.idxarr = (int32_t *) alloca (s2len * sizeof (int32_t));
+      seq1.rulearr = (unsigned char *) alloca (s1len);
+      seq2.rulearr = (unsigned char *) alloca (s2len);
     }
 
-  idx1cnt = 0;
-  idx2cnt = 0;
-  idx1max = 0;
-  idx2max = 0;
-  idx1now = 0;
-  idx2now = 0;
-  backw1_stop = ~0ul;
-  backw2_stop = ~0ul;
-  backw1 = ~0ul;
-  backw2 = ~0ul;
-  seq1len = 0;
-  seq2len = 0;
-  position = rulesets[0] & sort_position;
-  while (1)
-    {
-      val1 = 0;
-      val2 = 0;
-
-      /* Get the next non-IGNOREd element for string `s1'.  */
-      if (seq1len == 0)
-	do
-	  {
-	    ++val1;
-
-	    if (backw1_stop != ~0ul)
-	      {
-		/* The is something pushed.  */
-		if (backw1 == backw1_stop)
-		  {
-		    /* The last pushed character was handled.  Continue
-		       with forward characters.  */
-		    if (idx1cnt < idx1max)
-		      {
-			idx1now = idx1cnt;
-			backw1_stop = ~0ul;
-		      }
-		    else
-		      /* Nothing anymore.  The backward sequence ended with
-			 the last sequence in the string.  Note that seq1len
-			 is still zero.  */
-		      break;
-		  }
-		else
-		  idx1now = --backw1;
-	      }
-	    else
-	      {
-		backw1_stop = idx1max;
-
-		while (*us1 != L('\0'))
-		  {
-		    int32_t tmp = findidx (&us1, -1);
-		    rule1arr[idx1max] = tmp >> 24;
-		    idx1arr[idx1max] = tmp & 0xffffff;
-		    idx1cnt = idx1max++;
-
-		    if ((rulesets[rule1arr[idx1cnt] * nrules]
-			 & sort_backward) == 0)
-		      /* No more backward characters to push.  */
-		      break;
-		    ++idx1cnt;
-		  }
-
-		if (backw1_stop >= idx1cnt)
-		  {
-		    /* No sequence at all or just one.  */
-		    if (idx1cnt == idx1max || backw1_stop > idx1cnt)
-		      /* Note that seq1len is still zero.  */
-		      break;
-
-		    backw1_stop = ~0ul;
-		    idx1now = idx1cnt;
-		  }
-		else
-		  /* We pushed backward sequences.  */
-		  idx1now = backw1 = idx1cnt - 1;
-	      }
-	  }
-	while ((seq1len = weights[idx1arr[idx1now]++]) == 0);
-
-      /* And the same for string `s2'.  */
-      if (seq2len == 0)
-	do
-	  {
-	    ++val2;
-
-	    if (backw2_stop != ~0ul)
-	      {
-		/* The is something pushed.  */
-		if (backw2 == backw2_stop)
-		  {
-		    /* The last pushed character was handled.  Continue
-		       with forward characters.  */
-		    if (idx2cnt < idx2max)
-		      {
-			idx2now = idx2cnt;
-			backw2_stop = ~0ul;
-		      }
-		    else
-		      /* Nothing anymore.  The backward sequence ended with
-			 the last sequence in the string.  Note that seq2len
-			 is still zero.  */
-		      break;
-		  }
-		else
-		  idx2now = --backw2;
-	      }
-	    else
-	      {
-		backw2_stop = idx2max;
-
-		while (*us2 != L('\0'))
-		  {
-		    int32_t tmp = findidx (&us2, -1);
-		    rule2arr[idx2max] = tmp >> 24;
-		    idx2arr[idx2max] = tmp & 0xffffff;
-		    idx2cnt = idx2max++;
-
-		    if ((rulesets[rule2arr[idx2cnt] * nrules]
-			 & sort_backward) == 0)
-		      /* No more backward characters to push.  */
-		      break;
-		    ++idx2cnt;
-		  }
-
-		if (backw2_stop >= idx2cnt)
-		  {
-		    /* No sequence at all or just one.  */
-		    if (idx2cnt == idx2max || backw2_stop > idx2cnt)
-		      /* Note that seq1len is still zero.  */
-		      break;
-
-		    backw2_stop = ~0ul;
-		    idx2now = idx2cnt;
-		  }
-		else
-		  /* We pushed backward sequences.  */
-		  idx2now = backw2 = idx2cnt - 1;
-	      }
-	  }
-	while ((seq2len = weights[idx2arr[idx2now]++]) == 0);
-
-      /* See whether any or both strings are empty.  */
-      if (seq1len == 0 || seq2len == 0)
-	{
-	  if (seq1len == seq2len)
-	    /* Both ended.  So far so good, both strings are equal at the
-	       first level.  */
-	    break;
-
-	  /* This means one string is shorter than the other.  Find out
-	     which one and return an appropriate value.  */
-	  result = seq1len == 0 ? -1 : 1;
-	  goto free_and_return;
-	}
-
-      /* Test for position if necessary.  */
-      if (position && val1 != val2)
-	{
-	  result = val1 - val2;
-	  goto free_and_return;
-	}
-
-      /* Compare the two sequences.  */
-      do
-	{
-	  if (weights[idx1arr[idx1now]] != weights[idx2arr[idx2now]])
-	    {
-	      /* The sequences differ.  */
-	      result = weights[idx1arr[idx1now]] - weights[idx2arr[idx2now]];
-	      goto free_and_return;
-	    }
-
-	  /* Increment the offsets.  */
-	  ++idx1arr[idx1now];
-	  ++idx2arr[idx2now];
+  seq1.rulearr[0] = 0;
 
-	  --seq1len;
-	  --seq2len;
-	}
-      while (seq1len > 0 && seq2len > 0);
-
-      if (position && seq1len != seq2len)
-	{
-	  result = seq1len - seq2len;
-	  goto free_and_return;
-	}
-    }
-
-  /* Now the remaining passes over the weights.  We now use the
-     indeces we found before.  */
-  for (pass = 1; pass < nrules; ++pass)
+  /* Cache values in the first pass and if needed, use them in subsequent
+     passes.  */
+  for (int pass = 0; pass < nrules; ++pass)
     {
+      seq1.idxcnt = 0;
+      seq1.backw_stop = ~0ul;
+      seq1.backw = ~0ul;
+      seq2.idxcnt = 0;
+      seq2.backw_stop = ~0ul;
+      seq2.backw = ~0ul;
+
       /* We assume that if a rule has defined `position' in one section
 	 this is true for all of them.  */
-      idx1cnt = 0;
-      idx2cnt = 0;
-      backw1_stop = ~0ul;
-      backw2_stop = ~0ul;
-      backw1 = ~0ul;
-      backw2 = ~0ul;
-      position = rulesets[rule1arr[0] * nrules + pass] & sort_position;
+      int position = rulesets[seq1.rulearr[0] * nrules + pass] & sort_position;
 
       while (1)
 	{
-	  val1 = 0;
-	  val2 = 0;
-
-	  /* Get the next non-IGNOREd element for string `s1'.  */
-	  if (seq1len == 0)
-	    do
-	      {
-		++val1;
-
-		if (backw1_stop != ~0ul)
-		  {
-		    /* The is something pushed.  */
-		    if (backw1 == backw1_stop)
-		      {
-			/* The last pushed character was handled.  Continue
-			   with forward characters.  */
-			if (idx1cnt < idx1max)
-			  {
-			    idx1now = idx1cnt;
-			    backw1_stop = ~0ul;
-			  }
-			else
-			  {
-			    /* Nothing anymore.  The backward sequence
-			       ended with the last sequence in the string.  */
-			    idx1now = ~0ul;
-			    break;
-			  }
-		      }
-		    else
-		      idx1now = --backw1;
-		  }
-		else
-		  {
-		    backw1_stop = idx1cnt;
-
-		    while (idx1cnt < idx1max)
-		      {
-			if ((rulesets[rule1arr[idx1cnt] * nrules + pass]
-			     & sort_backward) == 0)
-			  /* No more backward characters to push.  */
-			  break;
-			++idx1cnt;
-		      }
-
-		    if (backw1_stop == idx1cnt)
-		      {
-			/* No sequence at all or just one.  */
-			if (idx1cnt == idx1max)
-			  /* Note that seq1len is still zero.  */
-			  break;
-
-			backw1_stop = ~0ul;
-			idx1now = idx1cnt++;
-		      }
-		    else
-		      /* We pushed backward sequences.  */
-		      idx1now = backw1 = idx1cnt - 1;
-		  }
-	      }
-	    while ((seq1len = weights[idx1arr[idx1now]++]) == 0);
-
-	  /* And the same for string `s2'.  */
-	  if (seq2len == 0)
-	    do
-	      {
-		++val2;
-
-		if (backw2_stop != ~0ul)
-		  {
-		    /* The is something pushed.  */
-		    if (backw2 == backw2_stop)
-		      {
-			/* The last pushed character was handled.  Continue
-			   with forward characters.  */
-			if (idx2cnt < idx2max)
-			  {
-			    idx2now = idx2cnt;
-			    backw2_stop = ~0ul;
-			  }
-			else
-			  {
-			    /* Nothing anymore.  The backward sequence
-			       ended with the last sequence in the string.  */
-			    idx2now = ~0ul;
-			    break;
-			  }
-		      }
-		    else
-		      idx2now = --backw2;
-		  }
-		else
-		  {
-		    backw2_stop = idx2cnt;
-
-		    while (idx2cnt < idx2max)
-		      {
-			if ((rulesets[rule2arr[idx2cnt] * nrules + pass]
-			     & sort_backward) == 0)
-			  /* No more backward characters to push.  */
-			  break;
-			++idx2cnt;
-		      }
-
-		    if (backw2_stop == idx2cnt)
-		      {
-			/* No sequence at all or just one.  */
-			if (idx2cnt == idx2max)
-			  /* Note that seq2len is still zero.  */
-			  break;
-
-			backw2_stop = ~0ul;
-			idx2now = idx2cnt++;
-		      }
-		    else
-		      /* We pushed backward sequences.  */
-		      idx2now = backw2 = idx2cnt - 1;
-		  }
-	      }
-	    while ((seq2len = weights[idx2arr[idx2now]++]) == 0);
+	  if (pass == 0)
+	    {
+	      get_next_seq (&seq1, nrules, rulesets, weights, table, extra,
+			    indirect);
+	      get_next_seq (&seq2, nrules, rulesets, weights, table, extra,
+			    indirect);
+	    }
+	  else
+	    {
+	      get_next_seq_cached (&seq1, nrules, pass, rulesets, weights);
+	      get_next_seq_cached (&seq2, nrules, pass, rulesets, weights);
+	    }
 
 	  /* See whether any or both strings are empty.  */
-	  if (seq1len == 0 || seq2len == 0)
+	  if (seq1.len == 0 || seq2.len == 0)
 	    {
-	      if (seq1len == seq2len)
+	      if (seq1.len == seq2.len)
 		/* Both ended.  So far so good, both strings are equal
 		   at this level.  */
 		break;
 
 	      /* This means one string is shorter than the other.  Find out
 		 which one and return an appropriate value.  */
-	      result = seq1len == 0 ? -1 : 1;
+	      result = seq1.len == 0 ? -1 : 1;
 	      goto free_and_return;
 	    }
 
-	  /* Test for position if necessary.  */
-	  if (position && val1 != val2)
-	    {
-	      result = val1 - val2;
-	      goto free_and_return;
-	    }
-
-	  /* Compare the two sequences.  */
-	  do
-	    {
-	      if (weights[idx1arr[idx1now]] != weights[idx2arr[idx2now]])
-		{
-		  /* The sequences differ.  */
-		  result = (weights[idx1arr[idx1now]]
-			    - weights[idx2arr[idx2now]]);
-		  goto free_and_return;
-		}
-
-	      /* Increment the offsets.  */
-	      ++idx1arr[idx1now];
-	      ++idx2arr[idx2now];
-
-	      --seq1len;
-	      --seq2len;
-	    }
-	  while (seq1len > 0 && seq2len > 0);
-
-	  if (position && seq1len != seq2len)
-	    {
-	      result = seq1len - seq2len;
-	      goto free_and_return;
-	    }
+	  result = do_compare (&seq1, &seq2, position, weights);
+	  if (result != 0)
+	    goto free_and_return;
 	}
     }
 
   /* Free the memory if needed.  */
  free_and_return:
   if (use_malloc)
-    free (idx1arr);
+    free (seq1.idxarr);
 
   return result;
 }

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=1034d41c8fe7b31ba8ba304d1fff93cecb183520

commit 1034d41c8fe7b31ba8ba304d1fff93cecb183520
Author: Andreas Schwab <schwab@suse.de>
Date:   Thu Oct 31 12:51:03 2013 +0100

    Fix parsing of 0e+0 as float

diff --git a/ChangeLog b/ChangeLog
index b0cab3f..c83db92 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2013-10-31  Andreas Schwab  <schwab@suse.de>
+
+	[BZ# 15917]
+	* stdio-common/vfscanf.c (_IO_vfwscanf): Handle leading '0' not
+	followed by 'x' as part of digit sequence.
+	* stdio-common/tst-sscanf.c (double_tests2): New tests.
+
 2013-10-04  Adhemerval Zanella  <azanella@linux.vnet.ibm.com>
 
 	* sysdeps/powerpc/powerpc64/strcpy.S (strcpy): Add word load/store
diff --git a/NEWS b/NEWS
index f0a9346..2970338 100644
--- a/NEWS
+++ b/NEWS
@@ -23,7 +23,7 @@ Version 2.18
   15465, 15480, 15485, 15488, 15490, 15492, 15493, 15497, 15506, 15522,
   15529, 15532, 15536, 15553, 15577, 15583, 15618, 15627, 15631, 15654,
   15655, 15666, 15667, 15674, 15711, 15755, 15759, 15797, 15892, 15893,
-  15895, 15988, 16072.
+  15895, 15917, 15988, 16072.
 
 * CVE-2013-2207 Incorrectly granting access to another user's pseudo-terminal
   has been fixed by disabling the use of pt_chown (Bugzilla #15755).
diff --git a/stdio-common/tst-sscanf.c b/stdio-common/tst-sscanf.c
index 1edb227..3c34f58 100644
--- a/stdio-common/tst-sscanf.c
+++ b/stdio-common/tst-sscanf.c
@@ -109,6 +109,19 @@ struct test double_tests[] =
   { L("-inf"), L("%g"), 1 }
 };
 
+struct test2
+{
+  const CHAR *str;
+  const CHAR *fmt;
+  int retval;
+  char residual;
+} double_tests2[] =
+{
+  { L("0e+0"), L("%g%c"), 1, 0 },
+  { L("0xe+0"), L("%g%c"), 2, '+' },
+  { L("0x.e+0"), L("%g%c"), 2, '+' },
+};
+
 int
 main (void)
 {
@@ -196,5 +209,26 @@ main (void)
 	}
     }
 
+  for (i = 0; i < sizeof (double_tests2) / sizeof (double_tests2[0]); ++i)
+    {
+      double dummy;
+      int ret;
+      char c = 0;
+
+      if ((ret = SSCANF (double_tests2[i].str, double_tests2[i].fmt,
+			 &dummy, &c)) != double_tests2[i].retval)
+	{
+	  printf ("double_tests2[%d] returned %d != %d\n",
+		  i, ret, double_tests2[i].retval);
+	  result = 1;
+	}
+      else if (ret == 2 && c != double_tests2[i].residual)
+	{
+	  printf ("double_tests2[%d] stopped at '%c' != '%c'\n",
+		  i, c, double_tests2[i].residual);
+	  result = 1;
+	}
+    }
+
   return result;
 }
diff --git a/stdio-common/vfscanf.c b/stdio-common/vfscanf.c
index 3430567..093c8b0 100644
--- a/stdio-common/vfscanf.c
+++ b/stdio-common/vfscanf.c
@@ -1966,6 +1966,8 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr,
 		  if (width > 0)
 		    --width;
 		}
+	      else
+		got_digit = 1;
 	    }
 
 	  while (1)

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=3874aa022b6f0f9aca9ad1ef703a77be1bc97b36

commit 3874aa022b6f0f9aca9ad1ef703a77be1bc97b36
Author: Adhemerval Zanella <azanella@linux.vnet.ibm.com>
Date:   Thu Sep 26 09:29:19 2013 -0500

    PowerPC: strcpy/stpcpy optimization for PPC64/POWER7
    
    This patch intends to unify both strcpy and stpcpy implementationsi
    for PPC64 and PPC64/POWER7. The idead default powerpc64 implementation
    is to provide both doubleword and word aligned memory access.
    
    For PPC64/POWER7 is also provide doubleword and word memory access,
    remove the branch hints, use the cmpb instruction for compare
    doubleword/words, and add an optimization for inputs of same alignment.

diff --git a/ChangeLog b/ChangeLog
index ed41494..b0cab3f 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+2013-10-04  Adhemerval Zanella  <azanella@linux.vnet.ibm.com>
+
+	* sysdeps/powerpc/powerpc64/strcpy.S (strcpy): Add word load/store
+	to provide a boost for large inputs with word alignment.
+	* sysdeps/powerpc/powerpc64/stpcpy.S (__stpcpy): Rewrite
+	implementation based on optimized PPC64 strcpy.
+	* sysdeps/powerpc/powerpc64/power7/strcpy.S: New file: optimized
+	strcpy for PPC64/POWER7 based on both doubleword and word load/store.
+	* sysdeps/powerpc/powerpc64/power7/stpcpy.S: New file: optimized
+	stpcpy for PPC64/POWER7 based on PPC64/POWER7 strcpy.
+
 2013-10-25  Siddhesh Poyarekar  <siddhesh@redhat.com>
 
 	[BZ #16072]
diff --git a/sysdeps/powerpc/powerpc64/power7/stpcpy.S b/sysdeps/powerpc/powerpc64/power7/stpcpy.S
new file mode 100644
index 0000000..727dd06
--- /dev/null
+++ b/sysdeps/powerpc/powerpc64/power7/stpcpy.S
@@ -0,0 +1,24 @@
+/* Optimized stpcpy implementation for PowerPC64/POWER7.
+   Copyright (C) 2013 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/>.  */
+
+#define USE_AS_STPCPY
+#include <sysdeps/powerpc/powerpc64/power7/strcpy.S>
+
+weak_alias (__stpcpy, stpcpy)
+libc_hidden_def (__stpcpy)
+libc_hidden_builtin_def (stpcpy)
diff --git a/sysdeps/powerpc/powerpc64/power7/strcpy.S b/sysdeps/powerpc/powerpc64/power7/strcpy.S
new file mode 100644
index 0000000..5c341a1
--- /dev/null
+++ b/sysdeps/powerpc/powerpc64/power7/strcpy.S
@@ -0,0 +1,274 @@
+/* Optimized strcpy/stpcpy implementation for PowerPC64/POWER7.
+   Copyright (C) 2013 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/>.  */
+
+#include <sysdep.h>
+
+/* Implements the function
+
+   char * [r3] strcpy (char *dest [r3], const char *src [r4])
+
+   or
+
+   char * [r3] strcpy (char *dest [r3], const char *src [r4])
+
+   if USE_AS_STPCPY is defined. It tries to use aligned memory accesses
+   when possible using the following algorithm:
+
+   if (((((uintptr_t)dst & 0x7UL) == 0) && ((uintptr_t)src & 0x7UL) == 0))
+     goto aligned_doubleword_copy;
+   if (((((uintptr_t)dst & 0x3UL) == 0) && ((uintptr_t)src & 0x3UL) == 0))
+     goto aligned_word_copy;
+   if (((uintptr_t)dst & 0x7UL) == ((uintptr_t)src & 0x7UL))
+     goto same_alignment;
+   goto unaligned;
+
+   The aligned comparison are made using cmpb instructions.  */
+
+#ifdef USE_AS_STPCPY
+# define FUNC_NAME __stpcpy
+#else
+# define FUNC_NAME strcpy
+#endif
+
+	.machine  power7
+EALIGN (FUNC_NAME, 4, 0)
+	CALL_MCOUNT 2
+
+#define rTMP	r0
+#ifdef USE_AS_STPCPY
+#define rRTN	r3	/* pointer to previous word/doubleword in dest */
+#else
+#define rRTN	r12	/* pointer to previous word/doubleword in dest */
+#endif
+#define rSRC	r4	/* pointer to previous word/doubleword in src */
+#define rMASK	r5	/* mask 0xffffffff | 0xffffffffffffffff */
+#define rWORD	r6	/* current word from src */
+#define rALT	r7	/* alternate word from src */
+#define rRTNAL	r8	/* alignment of return pointer */
+#define rSRCAL	r9	/* alignment of source pointer */
+#define rALCNT	r10	/* bytes to read to reach 8 bytes alignment */
+#define rSUBAL	r11	/* doubleword minus unaligned displacement */
+
+#ifndef USE_AS_STPCPY
+/* Save the dst pointer to use as return value.  */
+	mr	rRTN, r3
+#endif
+	or	rTMP, rSRC, rRTN
+	clrldi.	rTMP, rTMP, 61
+	bne	L(check_word_alignment)
+	b	L(aligned_doubleword_copy)
+
+L(same_alignment):
+/* Src and dst with same alignment: align both to doubleword.  */
+	mr	rALCNT, rRTN
+	lbz	rWORD, 0(rSRC)
+	subfic	rSUBAL, rRTNAL, 8
+	addi	rRTN, rRTN, 1
+	addi	rSRC, rSRC, 1
+	cmpdi	cr7, rWORD, 0
+	stb	rWORD, 0(rALCNT)
+	beq	cr7, L(s2)
+
+	add	rALCNT, rALCNT, rSUBAL
+	subf	rALCNT, rRTN, rALCNT
+	addi	rALCNT, rALCNT, 1
+	mtctr	rALCNT
+	b	L(s1)
+
+	.align 4
+L(s0):
+	addi	rSRC, rSRC, 1
+	lbz	rWORD, -1(rSRC)
+	cmpdi	cr7, rWORD, 0
+	stb	rWORD, -1(rALCNT)
+	beqlr	cr7
+	mr	rRTN, rALCNT
+L(s1):
+	addi	rALCNT, rRTN,1
+	bdnz	L(s0)
+	b L(aligned_doubleword_copy)
+	.align 4
+L(s2):
+	mr	rRTN, rALCNT
+	blr
+
+/* For doubleword aligned memory, operate using doubleword load and stores.  */
+	.align 4
+L(aligned_doubleword_copy):
+	li	rMASK, 0
+	addi	rRTN, rRTN, -8
+	ld	rWORD, 0(rSRC)
+	b	L(g2)
+
+	.align 4
+L(g0):	ldu	rALT, 8(rSRC)
+	stdu	rWORD, 8(rRTN)
+	cmpb	rTMP, rALT, rMASK
+	cmpdi	rTMP, 0
+	bne	L(g1)
+	ldu	rWORD, 8(rSRC)
+	stdu	rALT, 8(rRTN)
+L(g2):	cmpb	rTMP, rWORD, rMASK
+	cmpdi	rTMP, 0		/* If rTMP is 0, no null's have been found.  */
+	beq	L(g0)
+
+	mr	rALT, rWORD
+/* We've hit the end of the string.  Do the rest byte-by-byte.  */
+L(g1):
+#ifdef __LITTLE_ENDIAN__
+	extrdi.	rTMP, rALT, 8, 56
+	stbu	rALT, 8(rRTN)
+	beqlr-
+	extrdi.	rTMP, rALT, 8, 48
+	stbu	rTMP, 1(rRTN)
+	beqlr-
+	extrdi.	rTMP, rALT, 8, 40
+	stbu	rTMP, 1(rRTN)
+	beqlr-
+	extrdi.	rTMP, rALT, 8, 32
+	stbu	rTMP, 1(rRTN)
+	beqlr-
+	extrdi.	rTMP, rALT, 8, 24
+	stbu	rTMP, 1(rRTN)
+	beqlr-
+	extrdi.	rTMP, rALT, 8, 16
+	stbu	rTMP, 1(rRTN)
+	beqlr-
+	extrdi.	rTMP, rALT, 8, 8
+	stbu	rTMP, 1(rRTN)
+	beqlr-
+	extrdi	rTMP, rALT, 8, 0
+	stbu	rTMP, 1(rRTN)
+#else
+	extrdi.	rTMP, rALT, 8, 0
+	stbu	rTMP, 8(rRTN)
+	beqlr
+	extrdi.	rTMP, rALT, 8, 8
+	stbu	rTMP, 1(rRTN)
+	beqlr
+	extrdi.	rTMP, rALT, 8, 16
+	stbu	rTMP, 1(rRTN)
+	beqlr
+	extrdi.	rTMP, rALT, 8, 24
+	stbu	rTMP, 1(rRTN)
+	beqlr
+	extrdi.	rTMP, rALT, 8, 32
+	stbu	rTMP, 1(rRTN)
+	beqlr
+	extrdi.	rTMP, rALT, 8, 40
+	stbu	rTMP, 1(rRTN)
+	beqlr
+	extrdi.	rTMP, rALT, 8, 48
+	stbu	rTMP, 1(rRTN)
+	beqlr
+	stbu	rALT, 1(rRTN)
+#endif
+	blr
+
+L(check_word_alignment):
+	clrldi. rTMP, rTMP, 62
+	beq	L(aligned_word_copy)
+	rldicl	rRTNAL, rRTN, 0, 61
+	rldicl	rSRCAL, rSRC, 0, 61
+	cmpld	cr7, rSRCAL, rRTNAL
+	beq	cr7, L(same_alignment)
+	b	L(unaligned)
+
+/* For word aligned memory, operate using word load and stores.  */
+	.align	4
+L(aligned_word_copy):
+	li	rMASK, 0
+	addi	rRTN, rRTN, -4
+	lwz	rWORD, 0(rSRC)
+	b	L(g5)
+
+	.align	4
+L(g3):	lwzu	rALT, 4(rSRC)
+	stwu	rWORD, 4(rRTN)
+	cmpb	rTMP, rALT, rMASK
+	cmpwi	rTMP, 0
+	bne	L(g4)
+	lwzu	rWORD, 4(rSRC)
+	stwu	rALT, 4(rRTN)
+L(g5):	cmpb	rTMP, rWORD, rMASK
+	cmpwi	rTMP, 0		/* If rTMP is 0, no null in word.  */
+	beq	L(g3)
+
+	mr      rALT, rWORD
+/* We've hit the end of the string.  Do the rest byte-by-byte.  */
+L(g4):
+#ifdef __LITTLE_ENDIAN__
+	rlwinm.	rTMP, rALT, 0, 24, 31
+	stbu	rALT, 4(rRTN)
+	beqlr-
+	rlwinm.	rTMP, rALT, 24, 24, 31
+	stbu	rTMP, 1(rRTN)
+	beqlr-
+	rlwinm.	rTMP, rALT, 16, 24, 31
+	stbu	rTMP, 1(rRTN)
+	beqlr-
+	rlwinm	rTMP, rALT, 8, 24, 31
+	stbu	rTMP, 1(rRTN)
+#else
+	rlwinm. rTMP, rALT, 8, 24, 31
+	stbu    rTMP, 4(rRTN)
+	beqlr
+	rlwinm. rTMP, rALT, 16, 24, 31
+	stbu    rTMP, 1(rRTN)
+	beqlr
+	rlwinm. rTMP, rALT, 24, 24, 31
+	stbu    rTMP, 1(rRTN)
+	beqlr
+	stbu    rALT, 1(rRTN)
+#endif
+	blr
+
+/* Oh well.  In this case, we just do a byte-by-byte copy.  */
+	.align	4
+L(unaligned):
+	lbz	rWORD, 0(rSRC)
+	addi	rRTN, rRTN, -1
+	cmpdi	rWORD, 0
+	beq	L(u2)
+
+	.align 	5
+L(u0):	lbzu	rALT, 1(rSRC)
+	stbu	rWORD, 1(rRTN)
+	cmpdi	rALT, 0
+	beq	L(u1)
+	lbzu	rWORD, 1(rSRC)
+	stbu	rALT, 1(rRTN)
+	cmpdi	rWORD, 0
+	beq	L(u2)
+	lbzu	rALT, 1(rSRC)
+	stbu	rWORD, 1(rRTN)
+	cmpdi	rALT, 0
+	beq	L(u1)
+	lbzu	rWORD, 1(rSRC)
+	stbu	rALT, 1(rRTN)
+	cmpdi	rWORD, 0
+	bne	L(u0)
+L(u2):	stbu	rWORD, 1(rRTN)
+	blr
+L(u1):	stbu	rALT, 1(rRTN)
+	blr
+END (FUNC_NAME)
+
+#ifndef USE_AS_STPCPY
+libc_hidden_builtin_def (strcpy)
+#endif
diff --git a/sysdeps/powerpc/powerpc64/stpcpy.S b/sysdeps/powerpc/powerpc64/stpcpy.S
index 070cd46..09aa3be 100644
--- a/sysdeps/powerpc/powerpc64/stpcpy.S
+++ b/sysdeps/powerpc/powerpc64/stpcpy.S
@@ -16,87 +16,8 @@
    License along with the GNU C Library; if not, see
    <http://www.gnu.org/licenses/>.  */
 
-#include <sysdep.h>
-
-/* See strlen.s for comments on how the end-of-string testing works.  */
-
-/* char * [r3] stpcpy (char *dest [r3], const char *src [r4])  */
-
-EALIGN (__stpcpy, 4, 0)
-	CALL_MCOUNT 2
-
-#define rTMP	r0
-#define rRTN	r3
-#define rDEST	r3		/* pointer to previous word in dest */
-#define rSRC	r4		/* pointer to previous word in src */
-#define rWORD	r6		/* current word from src */
-#define rFEFE	r7		/* 0xfefefeff */
-#define r7F7F	r8		/* 0x7f7f7f7f */
-#define rNEG	r9		/* ~(word in src | 0x7f7f7f7f) */
-#define rALT	r10		/* alternate word from src */
-
-	or	rTMP, rSRC, rDEST
-	clrldi.	rTMP, rTMP, 62
-	addi	rDEST, rDEST, -4
-	bne	L(unaligned)
-
-	lis	rFEFE, -0x101
-	lis	r7F7F, 0x7f7f
-	lwz	rWORD, 0(rSRC)
-	addi	rFEFE, rFEFE, -0x101
-	addi	r7F7F, r7F7F, 0x7f7f
-	b	L(g2)
-
-L(g0):	lwzu	rALT, 4(rSRC)
-	stwu	rWORD, 4(rDEST)
-	add	rTMP, rFEFE, rALT
-	nor	rNEG, r7F7F, rALT
-	and.	rTMP, rTMP, rNEG
-	bne-	L(g1)
-	lwzu	rWORD, 4(rSRC)
-	stwu	rALT, 4(rDEST)
-L(g2):	add	rTMP, rFEFE, rWORD
-	nor	rNEG, r7F7F, rWORD
-	and.	rTMP, rTMP, rNEG
-	beq+	L(g0)
-
-	mr	rALT, rWORD
-/* We've hit the end of the string.  Do the rest byte-by-byte.  */
-L(g1):	rlwinm.	rTMP, rALT, 8, 24, 31
-	stbu	rTMP, 4(rDEST)
-	beqlr-
-	rlwinm.	rTMP, rALT, 16, 24, 31
-	stbu	rTMP, 1(rDEST)
-	beqlr-
-	rlwinm.	rTMP, rALT, 24, 24, 31
-	stbu	rTMP, 1(rDEST)
-	beqlr-
-	stbu	rALT, 1(rDEST)
-	blr
-
-/* Oh well.  In this case, we just do a byte-by-byte copy.  */
-	.align 4
-	nop
-L(unaligned):
-	lbz	rWORD, 0(rSRC)
-	addi	rDEST, rDEST, 3
-	cmpwi	rWORD, 0
-	beq-	L(u2)
-
-L(u0):	lbzu	rALT, 1(rSRC)
-	stbu	rWORD, 1(rDEST)
-	cmpwi	rALT, 0
-	beq-	L(u1)
-	nop		/* Let 601 load start of loop.  */
-	lbzu	rWORD, 1(rSRC)
-	stbu	rALT, 1(rDEST)
-	cmpwi	rWORD, 0
-	bne+	L(u0)
-L(u2):	stbu	rWORD, 1(rDEST)
-	blr
-L(u1):	stbu	rALT, 1(rDEST)
-	blr
-END (__stpcpy)
+#define USE_AS_STPCPY
+#include <sysdeps/powerpc/powerpc64/strcpy.S>
 
 weak_alias (__stpcpy, stpcpy)
 libc_hidden_def (__stpcpy)
diff --git a/sysdeps/powerpc/powerpc64/strcpy.S b/sysdeps/powerpc/powerpc64/strcpy.S
index 4c6fd3f..793325d 100644
--- a/sysdeps/powerpc/powerpc64/strcpy.S
+++ b/sysdeps/powerpc/powerpc64/strcpy.S
@@ -22,25 +22,38 @@
 
 /* char * [r3] strcpy (char *dest [r3], const char *src [r4])  */
 
-EALIGN (strcpy, 4, 0)
+#ifdef USE_AS_STPCPY
+# define FUNC_NAME __stpcpy
+#else
+# define FUNC_NAME strcpy
+#endif
+
+EALIGN (FUNC_NAME, 4, 0)
 	CALL_MCOUNT 2
 
 #define rTMP	r0
-#define rRTN	r3	/* incoming DEST arg preserved as result */
-#define rSRC	r4	/* pointer to previous word in src */
-#define rDEST	r5	/* pointer to previous word in dest */
+#ifdef USE_AS_STPCPY
+#define rRTN    r3      /* pointer to previous word/doubleword in dest */
+#else
+#define rRTN    r12     /* pointer to previous word/doubleword in dest */
+#endif
+#define rSRC	r4	/* pointer to previous word/doubleword in src */
 #define rWORD	r6	/* current word from src */
-#define rFEFE	r7	/* constant 0xfefefefefefefeff (-0x0101010101010101) */
-#define r7F7F	r8	/* constant 0x7f7f7f7f7f7f7f7f */
-#define rNEG	r9	/* ~(word in s1 | 0x7f7f7f7f7f7f7f7f) */
+#define rFEFE	r7	/* constant 0xfefefeff | 0xfefefefefefefeff */
+#define r7F7F	r8	/* constant 0x7f7f7f7f | 0x7f7f7f7f7f7f7f7f */
+#define rNEG	r9	/* ~(word in s1 | r7F7F) */
 #define rALT	r10	/* alternate word from src */
 
-	dcbt	0,rSRC
+#ifndef USE_AS_STPCPY
+/* Save the dst pointer to use as return value.  */
+	mr      rRTN, r3
+#endif
 	or	rTMP, rSRC, rRTN
 	clrldi.	rTMP, rTMP, 61
-	addi	rDEST, rRTN, -8
-	dcbtst	0,rRTN
-	bne	L(unaligned)
+	bne	L(check_word_alignment)
+
+/* For doubleword aligned memory, operate using doubleword load and stores.  */
+	addi	rRTN, rRTN, -8
 
 	lis	rFEFE, -0x101
 	lis	r7F7F, 0x7f7f
@@ -53,13 +66,13 @@ EALIGN (strcpy, 4, 0)
 	b	L(g2)
 
 L(g0):	ldu	rALT, 8(rSRC)
-	stdu	rWORD, 8(rDEST)
+	stdu	rWORD, 8(rRTN)
 	add	rTMP, rFEFE, rALT
 	nor	rNEG, r7F7F, rALT
 	and.	rTMP, rTMP, rNEG
 	bne-	L(g1)
 	ldu	rWORD, 8(rSRC)
-	stdu	rALT, 8(rDEST)
+	stdu	rALT, 8(rRTN)
 L(g2):	add	rTMP, rFEFE, rWORD
 	nor	rNEG, r7F7F, rWORD
 	and.	rTMP, rTMP, rNEG
@@ -68,28 +81,110 @@ L(g2):	add	rTMP, rFEFE, rWORD
 	mr	rALT, rWORD
 /* We've hit the end of the string.  Do the rest byte-by-byte.  */
 L(g1):
+#ifdef __LITTLE_ENDIAN__
+	extrdi.	rTMP, rALT, 8, 56
+	stbu	rALT, 8(rRTN)
+	beqlr-
+	extrdi.	rTMP, rALT, 8, 48
+	stbu	rTMP, 1(rRTN)
+	beqlr-
+	extrdi.	rTMP, rALT, 8, 40
+	stbu	rTMP, 1(rRTN)
+	beqlr-
+	extrdi.	rTMP, rALT, 8, 32
+	stbu	rTMP, 1(rRTN)
+	beqlr-
+	extrdi.	rTMP, rALT, 8, 24
+	stbu	rTMP, 1(rRTN)
+	beqlr-
+	extrdi.	rTMP, rALT, 8, 16
+	stbu	rTMP, 1(rRTN)
+	beqlr-
+	extrdi.	rTMP, rALT, 8, 8
+	stbu	rTMP, 1(rRTN)
+	beqlr-
+	extrdi	rTMP, rALT, 8, 0
+	stbu	rTMP, 1(rRTN)
+#else
 	extrdi.	rTMP, rALT, 8, 0
-	stb	rTMP, 8(rDEST)
+	stbu	rTMP, 8(rRTN)
 	beqlr-
 	extrdi.	rTMP, rALT, 8, 8
-	stb	rTMP, 9(rDEST)
+	stbu	rTMP, 1(rRTN)
 	beqlr-
 	extrdi.	rTMP, rALT, 8, 16
-	stb	rTMP, 10(rDEST)
+	stbu	rTMP, 1(rRTN)
 	beqlr-
 	extrdi.	rTMP, rALT, 8, 24
-	stb	rTMP, 11(rDEST)
+	stbu	rTMP, 1(rRTN)
 	beqlr-
 	extrdi.	rTMP, rALT, 8, 32
-	stb	rTMP, 12(rDEST)
-	beqlr-
+	stbu	rTMP, 1(rRTN)
+	beqlr
 	extrdi.	rTMP, rALT, 8, 40
-	stb	rTMP, 13(rDEST)
+	stbu	rTMP, 1(rRTN)
 	beqlr-
 	extrdi.	rTMP, rALT, 8, 48
-	stb	rTMP, 14(rDEST)
+	stbu	rTMP, 1(rRTN)
+	beqlr-
+	stbu	rALT, 1(rRTN)
+#endif
+	blr
+
+L(check_word_alignment):
+	clrldi. rTMP, rTMP, 62
+	bne     L(unaligned)
+
+/* For word aligned memory, operate using word load and stores.  */
+	addi	rRTN, rRTN, -4
+
+	lis	rFEFE, -0x101
+	lis	r7F7F, 0x7f7f
+	lwz	rWORD, 0(rSRC)
+	addi	rFEFE, rFEFE, -0x101
+	addi	r7F7F, r7F7F, 0x7f7f
+	b	L(g5)
+
+L(g3):	lwzu	rALT, 4(rSRC)
+	stwu	rWORD, 4(rRTN)
+	add	rTMP, rFEFE, rALT
+	nor	rNEG, r7F7F, rALT
+	and.	rTMP, rTMP, rNEG
+	bne-	L(g4)
+	lwzu	rWORD, 4(rSRC)
+	stwu	rALT, 4(rRTN)
+L(g5):	add	rTMP, rFEFE, rWORD
+	nor	rNEG, r7F7F, rWORD
+	and.	rTMP, rTMP, rNEG
+	beq+	L(g3)
+
+	mr	rALT, rWORD
+/* We've hit the end of the string.  Do the rest byte-by-byte.  */
+L(g4):
+#ifdef __LITTLE_ENDIAN__
+	rlwinm.	rTMP, rALT, 0, 24, 31
+	stbu	rALT, 4(rRTN)
+	beqlr-
+	rlwinm.	rTMP, rALT, 24, 24, 31
+	stbu	rTMP, 1(rRTN)
+	beqlr-
+	rlwinm.	rTMP, rALT, 16, 24, 31
+	stbu	rTMP, 1(rRTN)
+	beqlr-
+	rlwinm	rTMP, rALT, 8, 24, 31
+	stbu	rTMP, 1(rRTN)
+#else
+	rlwinm.	rTMP, rALT, 8, 24, 31
+	stbu	rTMP, 4(rRTN)
+	beqlr-
+	rlwinm.	rTMP, rALT, 16, 24, 31
+	stbu	rTMP, 1(rRTN)
+	beqlr-
+	rlwinm.	rTMP, rALT, 24, 24, 31
+	stbu	rTMP, 1(rRTN)
 	beqlr-
-	stb	rALT, 15(rDEST)
+	stbu	rALT, 1(rRTN)
+#endif
 	blr
 
 /* Oh well.  In this case, we just do a byte-by-byte copy.  */
@@ -97,23 +192,25 @@ L(g1):
 	nop
 L(unaligned):
 	lbz	rWORD, 0(rSRC)
-	addi	rDEST, rRTN, -1
+	addi	rRTN, rRTN, -1
 	cmpwi	rWORD, 0
 	beq-	L(u2)
 
 L(u0):	lbzu	rALT, 1(rSRC)
-	stbu	rWORD, 1(rDEST)
+	stbu	rWORD, 1(rRTN)
 	cmpwi	rALT, 0
 	beq-	L(u1)
 	nop		/* Let 601 load start of loop.  */
 	lbzu	rWORD, 1(rSRC)
-	stbu	rALT, 1(rDEST)
+	stbu	rALT, 1(rRTN)
 	cmpwi	rWORD, 0
 	bne+	L(u0)
-L(u2):	stb	rWORD, 1(rDEST)
+L(u2):	stbu	rWORD, 1(rRTN)
 	blr
-L(u1):	stb	rALT, 1(rDEST)
+L(u1):	stbu	rALT, 1(rRTN)
 	blr
+END (FUNC_NAME)
 
-END (strcpy)
+#ifndef USE_AS_STPCPY
 libc_hidden_builtin_def (strcpy)
+#endif

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=6f95434fd488e9b72117f9b93ec2e2dbf397a4d3

commit 6f95434fd488e9b72117f9b93ec2e2dbf397a4d3
Author: Siddhesh Poyarekar <siddhesh@redhat.com>
Date:   Fri Oct 25 10:22:12 2013 +0530

    Fix stack overflow due to large AF_INET6 requests
    
    Resolves #16072 (CVE-2013-4458).
    
    This patch fixes another stack overflow in getaddrinfo when it is
    called with AF_INET6.  The AF_UNSPEC case was fixed as CVE-2013-1914,
    but the AF_INET6 case went undetected back then.

diff --git a/ChangeLog b/ChangeLog
index 3805278..ed41494 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,76 +1,9 @@
-2013-10-10  Joseph Myers  <joseph@codsourcery.com>
+2013-10-25  Siddhesh Poyarekar  <siddhesh@redhat.com>
 
-	* sysdeps/ieee754/ldbl-128ibm/e_acosl.c (__ieee754_acosl): Check
-	for NaNs before doing comparisons on argument.
-	* sysdeps/ieee754/ldbl-128ibm/e_asinl.c (__ieee754_asinl):
-	Likewise.
-
-2013-10-04  Anton Blanchard <anton@au1.ibm.com>
-	    Alistair Popple <alistair@ozlabs.au.ibm.com>
-	    Alan Modra <amodra@gmail.com>
-
-	[BZ #15723]
-	* sysdeps/powerpc/jmpbuf-offsets.h: Comment fix.
-	* sysdeps/powerpc/powerpc32/fpu/__longjmp-common.S: Correct
-	_dl_hwcap access for little-endian.
-	* sysdeps/powerpc/powerpc32/fpu/setjmp-common.S: Likewise.  Don't
-	destroy vmx regs when saving unaligned.
-	* sysdeps/powerpc/powerpc64/__longjmp-common.S: Correct CR load.
-	* sysdeps/powerpc/powerpc64/setjmp-common.S: Likewise CR save.  Don't
-	destroy vmx regs when saving unaligned.
-
-2013-09-09  Allan McRae  <allan@archlinux.org>
-
-	[BZ #15893]
-	* stdlib/isomac.c (get_null_defines): Fix memory leak.
-
-	[BZ #15892]
-	* libio/memstream.c (open_memstream): Fix memory leak.
-	* libio/wmemstream.c (open_wmemstream): Likewise.
-
-	[BZ #15895]
-	* nscd/netgroupcache.c: Fix nesting of ifdefs.
-
-2013-09-05  Adhemerval Zanella  <azanella@linux.vnet.ibm.com>
-
-	* sysdeps/powerpc/powerpc32/power7/memrchr.S (__memrchr): Fix invalid
-	memory access for final bytes in some large inputs.
-	* sysdeps/powerpc/powerpc64/power7/memrchr.S (__memrchr): Likewise.
-
-2013-09-05  Adhemerval Zanella  <azanella@linux.vnet.ibm.com>
-
-	* string/test-memrchr.c: New file.
-	* string/test-memrchr-ifunc.c: New file.
-	* string/Makefile: Add new memrchr testcase.
-
-2013-09-03  Joseph Myers  <joseph@codesourcery.com>
-
-	[BZ #15427]
-	* sysdeps/ieee754/flt-32/e_lgammaf_r.c (__ieee754_lgammaf_r): Use
-	2**-30 instead of 2**-70 as threshold for returning -log(|x|).
-	* math/libm-test.inc (lgamma_test_data): Add more tests.
-	* sysdeps/i386/fpu/libm-test-ulps: Update.
-	* sysdeps/x86_64/fpu/libm-test-ulps: Likewise.
-
-2013-09-03   OndÅ?ej Bílka  <neleai@seznam.cz>
-
-	* sysdeps/x86_64/multiarch/strcmp-sse2-unaligned.S: New file.
-	* sysdeps/x86_64/multiarch/ifunc-impl-list.c (__libc_ifunc_impl_list):
-	Add ifunc.
-	* sysdeps/x86_64/multiarch/Makefile (sysdep_routines):
-	Add strcmp-sse2-unaligned
-	* sysdeps/x86_64/multiarch/strcmp.S (strcmp): Add ifunc.
-
-2013-09-02  Mike Frysinger  <vapier@gentoo.org>
-
-	* Versions.def (libc): Add GLIBC_2.19.
-
-2013-09-02  Mike Frysinger  <vapier@gentoo.org>
-
-	* sysdeps/unix/sysv/linux/tst-fanotify.c: New test.
-	* sysdeps/unix/sysv/linux/Makefile (tests): Add tst-fanotify.
+	[BZ #16072]
+	* sysdeps/posix/getaddrinfo.c (gethosts): Allocate tmpbuf on
+	heap for large requests.
 
->>>>>>> ffa3cd7... Fix lgammaf spurious underflow (bug 15427).
 2013-09-02  Joseph Myers  <joseph@codesourcery.com>
 
 	[BZ #14155]
diff --git a/NEWS b/NEWS
index 8689dd0..f0a9346 100644
--- a/NEWS
+++ b/NEWS
@@ -23,7 +23,7 @@ Version 2.18
   15465, 15480, 15485, 15488, 15490, 15492, 15493, 15497, 15506, 15522,
   15529, 15532, 15536, 15553, 15577, 15583, 15618, 15627, 15631, 15654,
   15655, 15666, 15667, 15674, 15711, 15755, 15759, 15797, 15892, 15893,
-  15895, 15988.
+  15895, 15988, 16072.
 
 * CVE-2013-2207 Incorrectly granting access to another user's pseudo-terminal
   has been fixed by disabling the use of pt_chown (Bugzilla #15755).
@@ -42,6 +42,9 @@ Version 2.18
   to the d_name member of struct dirent, or omit the terminating NUL
   character.  (Bugzilla #14699).
 
+* CVE-2013-4458 Stack overflow in getaddrinfo with large number of results
+  for AF_INET6 has been fixed (Bugzilla #16072).
+
 * Add support for calling C++11 thread_local object destructors on thread
   and program exit.  This needs compiler support for offloading C++11
   destructor calls to glibc.
diff --git a/sysdeps/posix/getaddrinfo.c b/sysdeps/posix/getaddrinfo.c
index 7bb3ded..2e97255 100644
--- a/sysdeps/posix/getaddrinfo.c
+++ b/sysdeps/posix/getaddrinfo.c
@@ -197,7 +197,22 @@ gaih_inet_serv (const char *servicename, const struct gaih_typeproto *tp,
 				&rc, &herrno, NULL, &localcanon));	      \
     if (rc != ERANGE || herrno != NETDB_INTERNAL)			      \
       break;								      \
-    tmpbuf = extend_alloca (tmpbuf, tmpbuflen, 2 * tmpbuflen);		      \
+    if (!malloc_tmpbuf && __libc_use_alloca (alloca_used + 2 * tmpbuflen))    \
+      tmpbuf = extend_alloca_account (tmpbuf, tmpbuflen, 2 * tmpbuflen,	      \
+				      alloca_used);			      \
+    else								      \
+      {									      \
+	char *newp = realloc (malloc_tmpbuf ? tmpbuf : NULL,		      \
+			      2 * tmpbuflen);				      \
+	if (newp == NULL)						      \
+	  {								      \
+	    result = -EAI_MEMORY;					      \
+	    goto free_and_return;					      \
+	  }								      \
+	tmpbuf = newp;							      \
+	malloc_tmpbuf = true;						      \
+	tmpbuflen = 2 * tmpbuflen;					      \
+      }									      \
   }									      \
   if (status == NSS_STATUS_SUCCESS && rc == 0)				      \
     h = &th;								      \
@@ -209,7 +224,8 @@ gaih_inet_serv (const char *servicename, const struct gaih_typeproto *tp,
 	{								      \
 	  __set_h_errno (herrno);					      \
 	  _res.options |= old_res_options & RES_USE_INET6;		      \
-	  return -EAI_SYSTEM;						      \
+	  result = -EAI_SYSTEM;						      \
+	  goto free_and_return;						      \
 	}								      \
       if (herrno == TRY_AGAIN)						      \
 	no_data = EAI_AGAIN;						      \

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=4a3abd22ecbda2d7b718b133fae2d2abfdfab614

commit 4a3abd22ecbda2d7b718b133fae2d2abfdfab614
Author: Joseph Myers <joseph@codesourcery.com>
Date:   Thu Oct 10 19:11:30 2013 +0000

    Avoid ordered comparisons of NaNs in ldbl-128ibm acosl and asinl.

diff --git a/ChangeLog b/ChangeLog
index 28960dc..3805278 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2013-10-10  Joseph Myers  <joseph@codsourcery.com>
+
+	* sysdeps/ieee754/ldbl-128ibm/e_acosl.c (__ieee754_acosl): Check
+	for NaNs before doing comparisons on argument.
+	* sysdeps/ieee754/ldbl-128ibm/e_asinl.c (__ieee754_asinl):
+	Likewise.
+
 2013-10-04  Anton Blanchard <anton@au1.ibm.com>
 	    Alistair Popple <alistair@ozlabs.au.ibm.com>
 	    Alan Modra <amodra@gmail.com>
diff --git a/sysdeps/ieee754/ldbl-128ibm/e_acosl.c b/sysdeps/ieee754/ldbl-128ibm/e_acosl.c
index 5d2af30..4b61281 100644
--- a/sysdeps/ieee754/ldbl-128ibm/e_acosl.c
+++ b/sysdeps/ieee754/ldbl-128ibm/e_acosl.c
@@ -151,11 +151,13 @@ static const long double
 long double
 __ieee754_acosl (long double x)
 {
-  long double z, r, w, p, q, s, t, f2;
+  long double a, z, r, w, p, q, s, t, f2;
   ieee854_long_double_shape_type u;
 
-  u.value = __builtin_fabsl (x);
-  if (u.value == 1.0L)
+  if (__glibc_unlikely (__isnanl (x)))
+    return x + x;
+  a = __builtin_fabsl (x);
+  if (a == 1.0L)
     {
       if (x > 0.0L)
 	return 0.0;		/* acos(1) = 0  */
diff --git a/sysdeps/ieee754/ldbl-128ibm/e_asinl.c b/sysdeps/ieee754/ldbl-128ibm/e_asinl.c
index b395439..bb69402 100644
--- a/sysdeps/ieee754/ldbl-128ibm/e_asinl.c
+++ b/sysdeps/ieee754/ldbl-128ibm/e_asinl.c
@@ -135,6 +135,8 @@ __ieee754_asinl (long double x)
   int flag;
   ieee854_long_double_shape_type u;
 
+  if (__glibc_unlikely (__isnanl (x)))
+    return x + x;
   flag = 0;
   u.value = __builtin_fabsl (x);
   if (u.value == 1.0L)	/* |x|>= 1 */

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=d1aac9a6ff01c226c42bb934c170dd1c00ba8071

commit d1aac9a6ff01c226c42bb934c170dd1c00ba8071
Author: Anton Blanchard <anton@au1.ibm.com>
Date:   Sat Aug 17 18:34:40 2013 +0930

    PowerPC LE setjmp/longjmp
    
    http://sourceware.org/ml/libc-alpha/2013-08/msg00089.html
    
    Little-endian fixes for setjmp/longjmp.  When writing these I noticed
    the setjmp code corrupts the non volatile VMX registers when using an
    unaligned buffer.  Anton fixed this, and also simplified it quite a
    bit.
    
    The current code uses boilerplate for the case where we want to store
    16 bytes to an unaligned address.  For that we have to do a
    read/modify/write of two aligned 16 byte quantities.  In our case we
    are storing a bunch of back to back data (consective VMX registers),
    and only the start and end of the region need the read/modify/write.
    
    	[BZ #15723]
    	* sysdeps/powerpc/jmpbuf-offsets.h: Comment fix.
    	* sysdeps/powerpc/powerpc32/fpu/__longjmp-common.S: Correct
    	_dl_hwcap access for little-endian.
    	* sysdeps/powerpc/powerpc32/fpu/setjmp-common.S: Likewise.  Don't
    	destroy vmx regs when saving unaligned.
    	* sysdeps/powerpc/powerpc64/__longjmp-common.S: Correct CR load.
    	* sysdeps/powerpc/powerpc64/setjmp-common.S: Likewise CR save.  Don't
    	destroy vmx regs when saving unaligned.

diff --git a/ChangeLog b/ChangeLog
index b9239a5..28960dc 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,17 @@
+2013-10-04  Anton Blanchard <anton@au1.ibm.com>
+	    Alistair Popple <alistair@ozlabs.au.ibm.com>
+	    Alan Modra <amodra@gmail.com>
+
+	[BZ #15723]
+	* sysdeps/powerpc/jmpbuf-offsets.h: Comment fix.
+	* sysdeps/powerpc/powerpc32/fpu/__longjmp-common.S: Correct
+	_dl_hwcap access for little-endian.
+	* sysdeps/powerpc/powerpc32/fpu/setjmp-common.S: Likewise.  Don't
+	destroy vmx regs when saving unaligned.
+	* sysdeps/powerpc/powerpc64/__longjmp-common.S: Correct CR load.
+	* sysdeps/powerpc/powerpc64/setjmp-common.S: Likewise CR save.  Don't
+	destroy vmx regs when saving unaligned.
+
 2013-09-09  Allan McRae  <allan@archlinux.org>
 
 	[BZ #15893]
diff --git a/sysdeps/powerpc/jmpbuf-offsets.h b/sysdeps/powerpc/jmpbuf-offsets.h
index 64c658a..f2116bd 100644
--- a/sysdeps/powerpc/jmpbuf-offsets.h
+++ b/sysdeps/powerpc/jmpbuf-offsets.h
@@ -21,12 +21,10 @@
 #define JB_LR     2  /* The address we will return to */
 #if __WORDSIZE == 64
 # define JB_GPRS   3  /* GPRs 14 through 31 are saved, 18*2 words total.  */
-# define JB_CR     21 /* Condition code registers with the VRSAVE at */
-                       /* offset 172 (low half of the double word.  */
+# define JB_CR     21 /* Shared dword with VRSAVE.  CR word at offset 172.  */
 # define JB_FPRS   22 /* FPRs 14 through 31 are saved, 18*2 words total.  */
 # define JB_SIZE   (64 * 8) /* As per PPC64-VMX ABI.  */
-# define JB_VRSAVE 21 /* VRSAVE shares a double word with the CR at offset */
-                       /* 168 (high half of the double word).  */
+# define JB_VRSAVE 21 /* Shared dword with CR.  VRSAVE word at offset 168.  */
 # define JB_VRS    40 /* VRs 20 through 31 are saved, 12*4 words total.  */
 #else
 # define JB_GPRS   3  /* GPRs 14 through 31 are saved, 18 in total.  */
diff --git a/sysdeps/powerpc/powerpc32/fpu/setjmp-common.S b/sysdeps/powerpc/powerpc32/fpu/setjmp-common.S
index 46ea2b0..17bd0ca 100644
--- a/sysdeps/powerpc/powerpc32/fpu/setjmp-common.S
+++ b/sysdeps/powerpc/powerpc32/fpu/setjmp-common.S
@@ -111,44 +111,43 @@ ENTRY (__sigsetjmp)
 	stw	r0,((JB_VRSAVE)*4)(3)
 	addi	r6,r5,16
 	beq+	L(aligned_save_vmx)
-	lvsr	v0,0,r5
-	vspltisb v1,-1         /* set v1 to all 1's */
-	vspltisb v2,0          /* set v2 to all 0's */
-	vperm   v3,v2,v1,v0   /* v3 contains shift mask with num all 1 bytes on left = misalignment  */
 
+	lvsr	v0,0,r5
+	lvsl	v1,0,r5
+	addi	r6,r5,-16
 
-	/* Special case for v20 we need to preserve what is in save area below v20 before obliterating it */
-	lvx     v5,0,r5
-	vperm   v20,v20,v20,v0
-	vsel    v5,v5,v20,v3
-	vsel    v20,v20,v2,v3
-	stvx    v5,0,r5
+# define save_misaligned_vmx(savevr,prevvr,shiftvr,tmpvr,savegpr,addgpr) \
+	addi	addgpr,addgpr,32;					 \
+	vperm	tmpvr,prevvr,savevr,shiftvr;				 \
+	stvx	tmpvr,0,savegpr
 
-#define save_2vmx_partial(savevr,prev_savevr,hivr,shiftvr,maskvr,savegpr,addgpr) \
-	addi    addgpr,addgpr,32; \
-	vperm   savevr,savevr,savevr,shiftvr; \
-	vsel    hivr,prev_savevr,savevr,maskvr; \
-	stvx    hivr,0,savegpr;
+	/*
+	 * We have to be careful not to corrupt the data below v20 and
+	 * above v31. To keep things simple we just rotate both ends in
+	 * the opposite direction to our main permute so we can use
+	 * the common macro.
+	 */
 
-	save_2vmx_partial(v21,v20,v5,v0,v3,r6,r5)
-	save_2vmx_partial(v22,v21,v5,v0,v3,r5,r6)
-	save_2vmx_partial(v23,v22,v5,v0,v3,r6,r5)
-	save_2vmx_partial(v24,v23,v5,v0,v3,r5,r6)
-	save_2vmx_partial(v25,v24,v5,v0,v3,r6,r5)
-	save_2vmx_partial(v26,v25,v5,v0,v3,r5,r6)
-	save_2vmx_partial(v27,v26,v5,v0,v3,r6,r5)
-	save_2vmx_partial(v28,v27,v5,v0,v3,r5,r6)
-	save_2vmx_partial(v29,v28,v5,v0,v3,r6,r5)
-	save_2vmx_partial(v30,v29,v5,v0,v3,r5,r6)
+	/* load and rotate data below v20 */
+	lvx	v2,0,r5
+	vperm	v2,v2,v2,v1
+	save_misaligned_vmx(v20,v2,v0,v3,r5,r6)
+	save_misaligned_vmx(v21,v20,v0,v3,r6,r5)
+	save_misaligned_vmx(v22,v21,v0,v3,r5,r6)
+	save_misaligned_vmx(v23,v22,v0,v3,r6,r5)
+	save_misaligned_vmx(v24,v23,v0,v3,r5,r6)
+	save_misaligned_vmx(v25,v24,v0,v3,r6,r5)
+	save_misaligned_vmx(v26,v25,v0,v3,r5,r6)
+	save_misaligned_vmx(v27,v26,v0,v3,r6,r5)
+	save_misaligned_vmx(v28,v27,v0,v3,r5,r6)
+	save_misaligned_vmx(v29,v28,v0,v3,r6,r5)
+	save_misaligned_vmx(v30,v29,v0,v3,r5,r6)
+	save_misaligned_vmx(v31,v30,v0,v3,r6,r5)
+	/* load and rotate data above v31 */
+	lvx	v2,0,r6
+	vperm	v2,v2,v2,v1
+	save_misaligned_vmx(v2,v31,v0,v3,r5,r6)
 
-	/* Special case for r31 we need to preserve what is in save area above v31 before obliterating it */
-	addi    r5,r5,32
-	vperm   v31,v31,v31,v0
-	lvx     v4,0,r5
-	vsel    v5,v30,v31,v3
-	stvx    v5,0,r6
-	vsel    v4,v31,v4,v3
-	stvx    v4,0,r5
 	b	L(no_vmx)
 
 L(aligned_save_vmx):
diff --git a/sysdeps/powerpc/powerpc64/__longjmp-common.S b/sysdeps/powerpc/powerpc64/__longjmp-common.S
index 70c3704..4f1e3c8 100644
--- a/sysdeps/powerpc/powerpc64/__longjmp-common.S
+++ b/sysdeps/powerpc/powerpc64/__longjmp-common.S
@@ -57,7 +57,7 @@ ENTRY (__longjmp)
 	beq	L(no_vmx)
 	la	r5,((JB_VRS)*8)(3)
 	andi.	r6,r5,0xf
-	lwz	r0,((JB_VRSAVE)*8)(3)
+	lwz	r0,((JB_VRSAVE)*8)(3)	/* 32-bit VRSAVE.  */
 	mtspr	VRSAVE,r0
 	beq+	L(aligned_restore_vmx)
 	addi    r6,r5,16
@@ -153,7 +153,7 @@ L(no_vmx):
 	lfd fp21,((JB_FPRS+7)*8)(r3)
 	ld r22,((JB_GPRS+8)*8)(r3)
 	lfd fp22,((JB_FPRS+8)*8)(r3)
-	ld r0,(JB_CR*8)(r3)
+	lwz r0,((JB_CR*8)+4)(r3)	/* 32-bit CR.  */
 	ld r23,((JB_GPRS+9)*8)(r3)
 	lfd fp23,((JB_FPRS+9)*8)(r3)
 	ld r24,((JB_GPRS+10)*8)(r3)
diff --git a/sysdeps/powerpc/powerpc64/setjmp-common.S b/sysdeps/powerpc/powerpc64/setjmp-common.S
index 58ec610..1829b9a 100644
--- a/sysdeps/powerpc/powerpc64/setjmp-common.S
+++ b/sysdeps/powerpc/powerpc64/setjmp-common.S
@@ -95,7 +95,7 @@ JUMPTARGET(GLUE(__sigsetjmp,_ent)):
 	mfcr r0
 	std  r16,((JB_GPRS+2)*8)(3)
 	stfd fp16,((JB_FPRS+2)*8)(3)
-	std  r0,(JB_CR*8)(3)
+	stw  r0,((JB_CR*8)+4)(3)	/* 32-bit CR.  */
 	std  r17,((JB_GPRS+3)*8)(3)
 	stfd fp17,((JB_FPRS+3)*8)(3)
 	std  r18,((JB_GPRS+4)*8)(3)
@@ -139,50 +139,46 @@ JUMPTARGET(GLUE(__sigsetjmp,_ent)):
 	la	r5,((JB_VRS)*8)(3)
 	andi.	r6,r5,0xf
 	mfspr	r0,VRSAVE
-	stw	r0,((JB_VRSAVE)*8)(3)
+	stw	r0,((JB_VRSAVE)*8)(3)	/* 32-bit VRSAVE.  */
 	addi	r6,r5,16
 	beq+	L(aligned_save_vmx)
-	lvsr	v0,0,r5
-	vspltisb v1,-1         /* set v1 to all 1's */
-	vspltisb v2,0          /* set v2 to all 0's */
-	vperm   v3,v2,v1,v0   /* v3 contains shift mask with num all 1 bytes
-				 on left = misalignment  */
 
+	lvsr	v0,0,r5
+	lvsl	v1,0,r5
+	addi	r6,r5,-16
 
-	/* Special case for v20 we need to preserve what is in save area
-	   below v20 before obliterating it */
-	lvx     v5,0,r5
-	vperm   v20,v20,v20,v0
-	vsel    v5,v5,v20,v3
-	vsel    v20,v20,v2,v3
-	stvx    v5,0,r5
+# define save_misaligned_vmx(savevr,prevvr,shiftvr,tmpvr,savegpr,addgpr) \
+	addi	addgpr,addgpr,32;					 \
+	vperm	tmpvr,prevvr,savevr,shiftvr;				 \
+	stvx	tmpvr,0,savegpr
 
-# define save_2vmx_partial(savevr,prev_savevr,hivr,shiftvr,maskvr,savegpr,addgpr) \
-	addi    addgpr,addgpr,32; \
-	vperm   savevr,savevr,savevr,shiftvr; \
-	vsel    hivr,prev_savevr,savevr,maskvr; \
-	stvx    hivr,0,savegpr;
+	/*
+	 * We have to be careful not to corrupt the data below v20 and
+	 * above v31. To keep things simple we just rotate both ends in
+	 * the opposite direction to our main permute so we can use
+	 * the common macro.
+	 */
 
-	save_2vmx_partial(v21,v20,v5,v0,v3,r6,r5)
-	save_2vmx_partial(v22,v21,v5,v0,v3,r5,r6)
-	save_2vmx_partial(v23,v22,v5,v0,v3,r6,r5)
-	save_2vmx_partial(v24,v23,v5,v0,v3,r5,r6)
-	save_2vmx_partial(v25,v24,v5,v0,v3,r6,r5)
-	save_2vmx_partial(v26,v25,v5,v0,v3,r5,r6)
-	save_2vmx_partial(v27,v26,v5,v0,v3,r6,r5)
-	save_2vmx_partial(v28,v27,v5,v0,v3,r5,r6)
-	save_2vmx_partial(v29,v28,v5,v0,v3,r6,r5)
-	save_2vmx_partial(v30,v29,v5,v0,v3,r5,r6)
+	/* load and rotate data below v20 */
+	lvx	v2,0,r5
+	vperm	v2,v2,v2,v1
+	save_misaligned_vmx(v20,v2,v0,v3,r5,r6)
+	save_misaligned_vmx(v21,v20,v0,v3,r6,r5)
+	save_misaligned_vmx(v22,v21,v0,v3,r5,r6)
+	save_misaligned_vmx(v23,v22,v0,v3,r6,r5)
+	save_misaligned_vmx(v24,v23,v0,v3,r5,r6)
+	save_misaligned_vmx(v25,v24,v0,v3,r6,r5)
+	save_misaligned_vmx(v26,v25,v0,v3,r5,r6)
+	save_misaligned_vmx(v27,v26,v0,v3,r6,r5)
+	save_misaligned_vmx(v28,v27,v0,v3,r5,r6)
+	save_misaligned_vmx(v29,v28,v0,v3,r6,r5)
+	save_misaligned_vmx(v30,v29,v0,v3,r5,r6)
+	save_misaligned_vmx(v31,v30,v0,v3,r6,r5)
+	/* load and rotate data above v31 */
+	lvx	v2,0,r6
+	vperm	v2,v2,v2,v1
+	save_misaligned_vmx(v2,v31,v0,v3,r5,r6)
 
-	/* Special case for r31 we need to preserve what is in save area
-	   above v31 before obliterating it */
-	addi    r5,r5,32
-	vperm   v31,v31,v31,v0
-	lvx     v4,0,r5
-	vsel    v5,v30,v31,v3
-	stvx    v5,0,r6
-	vsel    v4,v31,v4,v3
-	stvx    v4,0,r5
 	b	L(no_vmx)
 
 L(aligned_save_vmx):

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=860ec8e62a01a9c9e5087aa4cfd3b5e03fc7649b

commit 860ec8e62a01a9c9e5087aa4cfd3b5e03fc7649b
Author: Siddhesh Poyarekar <siddhesh@redhat.com>
Date:   Tue Oct 1 20:35:28 2013 +0530

    Fix PI mutex check in pthread_cond_broadcast and pthread_cond_signal
    
    Fixes BZ #15988.
    
    The check had a typo - it checked for PTHREAD_MUTEX_ROBUST_NP instead
    of PTHREAD_MUTEX_ROBUST_NORMAL_NP.  It has now been replaced by the
    already existing convenience macro USE_REQUEUE_PI.

diff --git a/NEWS b/NEWS
index 9d7ca62..8689dd0 100644
--- a/NEWS
+++ b/NEWS
@@ -23,7 +23,7 @@ Version 2.18
   15465, 15480, 15485, 15488, 15490, 15492, 15493, 15497, 15506, 15522,
   15529, 15532, 15536, 15553, 15577, 15583, 15618, 15627, 15631, 15654,
   15655, 15666, 15667, 15674, 15711, 15755, 15759, 15797, 15892, 15893,
-  15895.
+  15895, 15988.
 
 * CVE-2013-2207 Incorrectly granting access to another user's pseudo-terminal
   has been fixed by disabling the use of pt_chown (Bugzilla #15755).
diff --git a/nptl/ChangeLog b/nptl/ChangeLog
index eae5079..26ee387 100644
--- a/nptl/ChangeLog
+++ b/nptl/ChangeLog
@@ -1,3 +1,12 @@
+2013-10-01  Siddhesh Poyarekar  <siddhesh@redhat.com>
+
+	[BZ #15988]
+	* pthread_cond_broadcast.c (__pthread_cond_broadcast)
+	[lll_futex_cmp_requeue_pi && __ASSUME_REQUEUE_PI]: Use
+	USE_REQUEUE_PI.
+	* pthread_cond_signal.c (__pthread_cond_signal)
+	[lll_futex_cmd_requeue_pi && __ASSUME_REQUEUE_PI]: Likewise.
+
 2013-07-23  David S. Miller  <davem@davemloft.net>
 
 	* tst-cancel4.c (WRITE_BUFFER_SIZE): Adjust comment.
diff --git a/nptl/pthread_cond_broadcast.c b/nptl/pthread_cond_broadcast.c
index 0702ec0..7ba9efa 100644
--- a/nptl/pthread_cond_broadcast.c
+++ b/nptl/pthread_cond_broadcast.c
@@ -63,10 +63,7 @@ __pthread_cond_broadcast (cond)
 
 #if (defined lll_futex_cmp_requeue_pi \
      && defined __ASSUME_REQUEUE_PI)
-      int pi_flag = PTHREAD_MUTEX_PRIO_INHERIT_NP | PTHREAD_MUTEX_ROBUST_NP;
-      pi_flag &= mut->__data.__kind;
-
-      if (pi_flag == PTHREAD_MUTEX_PRIO_INHERIT_NP)
+      if (USE_REQUEUE_PI (mut))
 	{
 	  if (lll_futex_cmp_requeue_pi (&cond->__data.__futex, 1, INT_MAX,
 					&mut->__data.__lock, futex_val,
diff --git a/nptl/pthread_cond_signal.c b/nptl/pthread_cond_signal.c
index 102d0b3..ffc35dc 100644
--- a/nptl/pthread_cond_signal.c
+++ b/nptl/pthread_cond_signal.c
@@ -49,14 +49,9 @@ __pthread_cond_signal (cond)
 
 #if (defined lll_futex_cmp_requeue_pi \
      && defined __ASSUME_REQUEUE_PI)
-      int pi_flag = PTHREAD_MUTEX_PRIO_INHERIT_NP | PTHREAD_MUTEX_ROBUST_NP;
       pthread_mutex_t *mut = cond->__data.__mutex;
 
-      /* Do not use requeue for pshared condvars.  */
-      if (mut != (void *) ~0l)
-	pi_flag &= mut->__data.__kind;
-
-      if (__builtin_expect (pi_flag == PTHREAD_MUTEX_PRIO_INHERIT_NP, 0)
+      if (USE_REQUEUE_PI (mut)
 	/* This can only really fail with a ENOSYS, since nobody can modify
 	   futex while we have the cond_lock.  */
 	  && lll_futex_cmp_requeue_pi (&cond->__data.__futex, 1, 0,

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=3f71830d35d7bf4ac11664f0c48c3c68d250618b

commit 3f71830d35d7bf4ac11664f0c48c3c68d250618b
Author: Allan McRae <allan@archlinux.org>
Date:   Mon Sep 9 22:52:58 2013 +1000

    Fix memory leak in stdlib/isomac.c

diff --git a/ChangeLog b/ChangeLog
index 68909c8..b9239a5 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,8 @@
 2013-09-09  Allan McRae  <allan@archlinux.org>
 
+	[BZ #15893]
+	* stdlib/isomac.c (get_null_defines): Fix memory leak.
+
 	[BZ #15892]
 	* libio/memstream.c (open_memstream): Fix memory leak.
 	* libio/wmemstream.c (open_wmemstream): Likewise.
diff --git a/NEWS b/NEWS
index 90ff993..9d7ca62 100644
--- a/NEWS
+++ b/NEWS
@@ -22,7 +22,8 @@ Version 2.18
   15423, 15424, 15426, 15427, 15429, 15431, 15432, 15441, 15442, 15448,
   15465, 15480, 15485, 15488, 15490, 15492, 15493, 15497, 15506, 15522,
   15529, 15532, 15536, 15553, 15577, 15583, 15618, 15627, 15631, 15654,
-  15655, 15666, 15667, 15674, 15711, 15755, 15759, 15797, 15892, 15895.
+  15655, 15666, 15667, 15674, 15711, 15755, 15759, 15797, 15892, 15893,
+  15895.
 
 * CVE-2013-2207 Incorrectly granting access to another user's pseudo-terminal
   has been fixed by disabling the use of pt_chown (Bugzilla #15755).
diff --git a/stdlib/isomac.c b/stdlib/isomac.c
index 2c9009b..621b515 100644
--- a/stdlib/isomac.c
+++ b/stdlib/isomac.c
@@ -263,6 +263,7 @@ get_null_defines (void)
   if (system (command))
     {
       puts ("system() returned nonzero");
+      free (command);
       return NULL;
     }
   free (command);

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=8e395175c4786ad9679851e3ed3c0c54a6f4e1f0

commit 8e395175c4786ad9679851e3ed3c0c54a6f4e1f0
Author: Allan McRae <allan@archlinux.org>
Date:   Mon Sep 9 22:50:41 2013 +1000

    Fix memory leaks in libio on allocation failure

diff --git a/ChangeLog b/ChangeLog
index 2f9dea5..68909c8 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+2013-09-09  Allan McRae  <allan@archlinux.org>
+
+	[BZ #15892]
+	* libio/memstream.c (open_memstream): Fix memory leak.
+	* libio/wmemstream.c (open_wmemstream): Likewise.
+
+	[BZ #15895]
+	* nscd/netgroupcache.c: Fix nesting of ifdefs.
+
 2013-09-05  Adhemerval Zanella  <azanella@linux.vnet.ibm.com>
 
 	* sysdeps/powerpc/powerpc32/power7/memrchr.S (__memrchr): Fix invalid
diff --git a/NEWS b/NEWS
index 6a62ddf..90ff993 100644
--- a/NEWS
+++ b/NEWS
@@ -22,7 +22,7 @@ Version 2.18
   15423, 15424, 15426, 15427, 15429, 15431, 15432, 15441, 15442, 15448,
   15465, 15480, 15485, 15488, 15490, 15492, 15493, 15497, 15506, 15522,
   15529, 15532, 15536, 15553, 15577, 15583, 15618, 15627, 15631, 15654,
-  15655, 15666, 15667, 15674, 15711, 15755, 15759, 15797.
+  15655, 15666, 15667, 15674, 15711, 15755, 15759, 15797, 15892, 15895.
 
 * CVE-2013-2207 Incorrectly granting access to another user's pseudo-terminal
   has been fixed by disabling the use of pt_chown (Bugzilla #15755).
diff --git a/libio/memstream.c b/libio/memstream.c
index 34534e2..3cb1bd7 100644
--- a/libio/memstream.c
+++ b/libio/memstream.c
@@ -84,7 +84,10 @@ open_memstream (bufloc, sizeloc)
 
   buf = calloc (1, _IO_BUFSIZ);
   if (buf == NULL)
-    return NULL;
+    {
+      free (new_f);
+      return NULL;
+    }
   _IO_init (&new_f->fp._sf._sbf._f, 0);
   _IO_JUMPS ((struct _IO_FILE_plus *) &new_f->fp._sf._sbf) = &_IO_mem_jumps;
   _IO_str_init_static_internal (&new_f->fp._sf, buf, _IO_BUFSIZ, buf);
diff --git a/libio/wmemstream.c b/libio/wmemstream.c
index 65738d4..fd7fe44 100644
--- a/libio/wmemstream.c
+++ b/libio/wmemstream.c
@@ -85,8 +85,10 @@ open_wmemstream (bufloc, sizeloc)
 
   buf = calloc (1, _IO_BUFSIZ);
   if (buf == NULL)
-    return NULL;
-
+    {
+      free (new_f);
+      return NULL;
+    }
   _IO_no_init (&new_f->fp._sf._sbf._f, 0, 0, &new_f->wd, &_IO_wmem_jumps);
   _IO_fwide (&new_f->fp._sf._sbf._f, 1);
   _IO_wstr_init_static (&new_f->fp._sf._sbf._f, buf,

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=b51679672648410c6627a4bd169e076c5b36f47b

commit b51679672648410c6627a4bd169e076c5b36f47b
Author: Adhemerval Zanella <azanella@linux.vnet.ibm.com>
Date:   Thu Sep 5 09:32:56 2013 -0500

    PowerPC: fix POWER7 memrchr for some large inputs

diff --git a/ChangeLog b/ChangeLog
index f4bbcf1..2f9dea5 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,11 @@
 2013-09-05  Adhemerval Zanella  <azanella@linux.vnet.ibm.com>
 
+	* sysdeps/powerpc/powerpc32/power7/memrchr.S (__memrchr): Fix invalid
+	memory access for final bytes in some large inputs.
+	* sysdeps/powerpc/powerpc64/power7/memrchr.S (__memrchr): Likewise.
+
+2013-09-05  Adhemerval Zanella  <azanella@linux.vnet.ibm.com>
+
 	* string/test-memrchr.c: New file.
 	* string/test-memrchr-ifunc.c: New file.
 	* string/Makefile: Add new memrchr testcase.
diff --git a/sysdeps/powerpc/powerpc32/power7/memrchr.S b/sysdeps/powerpc/powerpc32/power7/memrchr.S
index d1e3fda..defd832 100644
--- a/sysdeps/powerpc/powerpc32/power7/memrchr.S
+++ b/sysdeps/powerpc/powerpc32/power7/memrchr.S
@@ -101,8 +101,8 @@ L(loop):
 	/* We're here because the counter reached 0, and that means we
 	   didn't have any matches for BYTE in the whole range.  Just return
 	   the original range.  */
-	addi	r9,r8,4
-	cmplw	cr6,r9,r7
+	addi	r8,r8,4
+	cmplw	cr6,r8,r7
 	bgt	cr6,L(loop_small)
 	b	L(null)
 
diff --git a/sysdeps/powerpc/powerpc64/power7/memrchr.S b/sysdeps/powerpc/powerpc64/power7/memrchr.S
index d24fbbb..c499952 100644
--- a/sysdeps/powerpc/powerpc64/power7/memrchr.S
+++ b/sysdeps/powerpc/powerpc64/power7/memrchr.S
@@ -102,8 +102,8 @@ L(loop):
 	/* We're here because the counter reached 0, and that means we
 	   didn't have any matches for BYTE in the whole range.  Just return
 	   the original range.  */
-	addi	r9,r8,8
-	cmpld	cr6,r9,r7
+	addi	r8,r8,8
+	cmpld	cr6,r8,r7
 	bgt	cr6,L(loop_small)
 	b	L(null)
 

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=a4faadaff25e19abf295556a23b7b889b4bf6df4

commit a4faadaff25e19abf295556a23b7b889b4bf6df4
Author: Adhemerval Zanella <azanella@linux.vnet.ibm.com>
Date:   Thu Aug 29 15:28:00 2013 -0300

    Add memrchr testcase

diff --git a/ChangeLog b/ChangeLog
index ff223e7..f4bbcf1 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,9 @@
-<<<<<<< HEAD
-=======
+2013-09-05  Adhemerval Zanella  <azanella@linux.vnet.ibm.com>
+
+	* string/test-memrchr.c: New file.
+	* string/test-memrchr-ifunc.c: New file.
+	* string/Makefile: Add new memrchr testcase.
+
 2013-09-03  Joseph Myers  <joseph@codesourcery.com>
 
 	[BZ #15427]
diff --git a/string/Makefile b/string/Makefile
index 0237edd..72d3e29 100644
--- a/string/Makefile
+++ b/string/Makefile
@@ -45,7 +45,7 @@ strop-tests	:= memchr memcmp memcpy memmove mempcpy memset memccpy	\
 		   stpcpy stpncpy strcat strchr strcmp strcpy strcspn	\
 		   strlen strncmp strncpy strpbrk strrchr strspn memmem	\
 		   strstr strcasestr strnlen strcasecmp strncasecmp	\
-		   strncat rawmemchr strchrnul bcopy bzero
+		   strncat rawmemchr strchrnul bcopy bzero memrchr
 tests		:= tester inl-tester noinl-tester testcopy test-ffs	\
 		   tst-strlen stratcliff tst-svc tst-inlcall		\
 		   bug-strncat1 bug-strspn1 bug-strpbrk1 tst-bswap	\
diff --git a/string/test-memrchr-ifunc.c b/string/test-memrchr-ifunc.c
new file mode 100644
index 0000000..100dedb
--- /dev/null
+++ b/string/test-memrchr-ifunc.c
@@ -0,0 +1,20 @@
+/* Test and measure IFUNC implementations of memrchr function.
+   Copyright (C) 2013 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/>.  */
+
+#define TEST_IFUNC 1
+#include "test-memrchr.c"
diff --git a/string/test-memrchr.c b/string/test-memrchr.c
new file mode 100644
index 0000000..a4fe811
--- /dev/null
+++ b/string/test-memrchr.c
@@ -0,0 +1,169 @@
+/* Test and measure memrchr functions.
+   Copyright (C) 2013 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Written by Jakub Jelinek <jakub@redhat.com>, 1999.
+
+   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/>.  */
+
+#define TEST_MAIN
+#define TEST_NAME "memrchr"
+#include "test-string.h"
+
+typedef char *(*proto_t) (const char *, int, size_t);
+char *simple_memrchr (const char *, int, size_t);
+
+IMPL (simple_memrchr, 0)
+IMPL (memrchr, 1)
+
+char *
+simple_memrchr (const char *s, int c, size_t n)
+{
+  s = s + n;
+  while (n--)
+    if (*--s == (char) c)
+      return (char *) s;
+  return NULL;
+}
+
+static void
+do_one_test (impl_t *impl, const char *s, int c, size_t n, char *exp_res)
+{
+  char *res = CALL (impl, s, c, n);
+  if (res != exp_res)
+    {
+      error (0, 0, "Wrong result in function %s %p %p", impl->name,
+	     res, exp_res);
+      ret = 1;
+      return;
+    }
+}
+
+static void
+do_test (size_t align, size_t pos, size_t len, int seek_char)
+{
+  size_t i;
+  char *result;
+
+  align &= 7;
+  if (align + len >= page_size)
+    return;
+
+  for (i = 0; i < len; ++i)
+    {
+      buf1[align + i] = 1 + 23 * i % 127;
+      if (buf1[align + i] == seek_char)
+        buf1[align + i] = seek_char + 1;
+    }
+  buf1[align + len] = 0;
+
+  if (pos < len)
+    {
+      buf1[align + pos] = seek_char;
+      buf1[align + len] = -seek_char;
+      result = (char *) (buf1 + align + pos);
+    }
+  else
+    {
+      result = NULL;
+      buf1[align + len] = seek_char;
+    }
+
+  FOR_EACH_IMPL (impl, 0)
+    do_one_test (impl, (char *) (buf1 + align), seek_char, len, result);
+}
+
+static void
+do_random_tests (void)
+{
+  size_t i, j, n, align, pos, len;
+  int seek_char;
+  char *result;
+  unsigned char *p = buf1 + page_size - 512;
+
+  for (n = 0; n < ITERATIONS; n++)
+    {
+      align = random () & 15;
+      pos = random () & 511;
+      if (pos + align >= 512)
+	pos = 511 - align - (random () & 7);
+      len = random () & 511;
+      if (pos >= len)
+	len = pos + (random () & 7);
+      if (len + align >= 512)
+        len = 512 - align - (random () & 7);
+      seek_char = random () & 255;
+      j = len + align + 64;
+      if (j > 512)
+        j = 512;
+
+      for (i = 0; i < j; i++)
+	{
+	  if (i == pos + align)
+	    p[i] = seek_char;
+	  else
+	    {
+	      p[i] = random () & 255;
+	      if (p[i] == seek_char)
+		p[i] = seek_char + 13;
+	    }
+	}
+
+      if (pos < len)
+	result = (char *) (p + pos + align);
+      else
+	result = NULL;
+
+      FOR_EACH_IMPL (impl, 1)
+	if (CALL (impl, (char *) (p + align), seek_char, len) != result)
+	  {
+	    error (0, 0, "Iteration %zd - wrong result in function %s (%zd, %d, %zd, %zd) %p != %p, p %p",
+		   n, impl->name, align, seek_char, len, pos,
+		   CALL (impl, (char *) (p + align), seek_char, len),
+		   result, p);
+	    ret = 1;
+	  }
+    }
+}
+
+int
+test_main (void)
+{
+  size_t i;
+
+  test_init ();
+
+  printf ("%20s", "");
+  FOR_EACH_IMPL (impl, 0)
+    printf ("\t%s", impl->name);
+  putchar ('\n');
+
+  for (i = 1; i < 8; ++i)
+    {
+      do_test (0, 16 << i, 2048, 23);
+      do_test (i, 64, 256, 23);
+      do_test (0, 16 << i, 2048, 0);
+      do_test (i, 64, 256, 0);
+    }
+  for (i = 1; i < 32; ++i)
+    {
+      do_test (0, i, i + 1, 23);
+      do_test (0, i, i + 1, 0);
+    }
+
+  do_random_tests ();
+  return ret;
+}
+
+#include "../test-skeleton.c"

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=b502a3756d6979439130f1e46c2c27b62f493acd

commit b502a3756d6979439130f1e46c2c27b62f493acd
Author: Joseph Myers <joseph@codesourcery.com>
Date:   Tue Sep 3 15:32:54 2013 +0000

    Fix lgammaf spurious underflow (bug 15427).

diff --git a/ChangeLog b/ChangeLog
index a2e0a9f..ff223e7 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,33 @@
+<<<<<<< HEAD
+=======
+2013-09-03  Joseph Myers  <joseph@codesourcery.com>
+
+	[BZ #15427]
+	* sysdeps/ieee754/flt-32/e_lgammaf_r.c (__ieee754_lgammaf_r): Use
+	2**-30 instead of 2**-70 as threshold for returning -log(|x|).
+	* math/libm-test.inc (lgamma_test_data): Add more tests.
+	* sysdeps/i386/fpu/libm-test-ulps: Update.
+	* sysdeps/x86_64/fpu/libm-test-ulps: Likewise.
+
+2013-09-03   OndÅ?ej Bílka  <neleai@seznam.cz>
+
+	* sysdeps/x86_64/multiarch/strcmp-sse2-unaligned.S: New file.
+	* sysdeps/x86_64/multiarch/ifunc-impl-list.c (__libc_ifunc_impl_list):
+	Add ifunc.
+	* sysdeps/x86_64/multiarch/Makefile (sysdep_routines):
+	Add strcmp-sse2-unaligned
+	* sysdeps/x86_64/multiarch/strcmp.S (strcmp): Add ifunc.
+
+2013-09-02  Mike Frysinger  <vapier@gentoo.org>
+
+	* Versions.def (libc): Add GLIBC_2.19.
+
+2013-09-02  Mike Frysinger  <vapier@gentoo.org>
+
+	* sysdeps/unix/sysv/linux/tst-fanotify.c: New test.
+	* sysdeps/unix/sysv/linux/Makefile (tests): Add tst-fanotify.
+
+>>>>>>> ffa3cd7... Fix lgammaf spurious underflow (bug 15427).
 2013-09-02  Joseph Myers  <joseph@codesourcery.com>
 
 	[BZ #14155]
diff --git a/NEWS b/NEWS
index 751b9aa..6a62ddf 100644
--- a/NEWS
+++ b/NEWS
@@ -4,21 +4,6 @@ See the end for copying conditions.
 
 Please send GNU C library bug reports via <http://sourceware.org/bugzilla/>
 using `glibc' in the "product" field.
-<<<<<<< HEAD
-=======
-
-Version 2.19
-
-* The following bugs are resolved with this release:
-
-<<<<<<< HEAD
-  14699, 15522, 15531, 15532, 15736, 15749, 15797, 15867, 15890, 15897,
-  15905.
->>>>>>> 0007fc9... [BZ #15522] strtod ("nan(N)") returning a sNaN in some cases
-=======
-  14155, 14699, 15522, 15531, 15532, 15736, 15749, 15797, 15867, 15890,
-  15897, 15905, 15909.
->>>>>>> b7835e3... Fix spurious jnf underflows (bug 14155).
 
 Version 2.18
 
@@ -34,10 +19,10 @@ Version 2.18
   15234, 15283, 15285, 15287, 15304, 15305, 15307, 15309, 15327, 15330,
   15331, 15335, 15336, 15337, 15339, 15342, 15346, 15359, 15361, 15366,
   15380, 15381, 15394, 15395, 15405, 15406, 15409, 15416, 15418, 15419,
-  15423, 15424, 15426, 15429, 15431, 15432, 15441, 15442, 15448, 15465,
-  15480, 15485, 15488, 15490, 15492, 15493, 15497, 15506, 15522, 15529,
-  15532, 15536, 15553, 15577, 15583, 15618, 15627, 15631, 15654, 15655,
-  15666, 15667, 15674, 15711, 15755, 15759, 15797.
+  15423, 15424, 15426, 15427, 15429, 15431, 15432, 15441, 15442, 15448,
+  15465, 15480, 15485, 15488, 15490, 15492, 15493, 15497, 15506, 15522,
+  15529, 15532, 15536, 15553, 15577, 15583, 15618, 15627, 15631, 15654,
+  15655, 15666, 15667, 15674, 15711, 15755, 15759, 15797.
 
 * CVE-2013-2207 Incorrectly granting access to another user's pseudo-terminal
   has been fixed by disabling the use of pt_chown (Bugzilla #15755).
diff --git a/math/libm-test.inc b/math/libm-test.inc
index 9d49255..7a11c90 100644
--- a/math/libm-test.inc
+++ b/math/libm-test.inc
@@ -9973,6 +9973,61 @@ static const struct test_f_f1_data lgamma_test_data[] =
     TEST_f_f1 (lgamma, -0.5, M_LOG_2_SQRT_PIl, -1),
     TEST_f_f1 (lgamma, 0.7L, 0.260867246531666514385732417016759578L, 1),
     TEST_f_f1 (lgamma, 1.2L, -0.853740900033158497197028392998854470e-1L, 1),
+
+    TEST_f_f1 (lgamma, 0x1p-5L, 3.4484891277979584796832693452686366085801e+00L, 1),
+    TEST_f_f1 (lgamma, -0x1p-5L, 3.4845895751341394376217526729956836492792e+00L, -1),
+    TEST_f_f1 (lgamma, 0x1p-10L, 6.9309089024194618895406190646600805357273e+00L, 1),
+    TEST_f_f1 (lgamma, -0x1p-10L, 6.9320362775113082175565786721095494761582e+00L, -1),
+    TEST_f_f1 (lgamma, 0x1p-15L, 1.0397190093941001762077888432721419773538e+01L, 1),
+    TEST_f_f1 (lgamma, -0x1p-15L, 1.0397225324389321751118257981741350715545e+01L, -1),
+    TEST_f_f1 (lgamma, 0x1p-20L, 1.3862943060723899573457963336920089012399e+01L, 1),
+    TEST_f_f1 (lgamma, -0x1p-20L, 1.3862944161675408862049886226750366625112e+01L, -1),
+    TEST_f_f1 (lgamma, 0x1p-25L, 1.7328679496796266133304874243201700664713e+01L, 1),
+    TEST_f_f1 (lgamma, -0x1p-25L, 1.7328679531201000798551671833865469674673e+01L, -1),
+    TEST_f_f1 (lgamma, 0x1p-30L, 2.0794415416260785304085859198055798098863e+01L, 1),
+    TEST_f_f1 (lgamma, -0x1p-30L, 2.0794415417335933262374820960532606449975e+01L, -1),
+    TEST_f_f1 (lgamma, 0x1p-40L, 2.7725887222397287402100277256545578941303e+01L, 1),
+    TEST_f_f1 (lgamma, -0x1p-40L, 2.7725887222398337351278293820766115529596e+01L, -1),
+    TEST_f_f1 (lgamma, 0x1p-50L, 3.4657359027997264958191108994508978906983e+01L, 1),
+    TEST_f_f1 (lgamma, -0x1p-50L, 3.4657359027997265983532103151309975524744e+01L, -1),
+    TEST_f_f1 (lgamma, 0x1p-60L, 4.1588830833596718564533272505187468598519e+01L, 1),
+    TEST_f_f1 (lgamma, -0x1p-60L, 4.1588830833596718565534582069793719571779e+01L, -1),
+    TEST_f_f1 (lgamma, 0x1p-64L, 4.4361419555836499802671564849429355013920e+01L, 1),
+    TEST_f_f1 (lgamma, -0x1p-64L, 4.4361419555836499802734146697217245699749e+01L, -1),
+    TEST_f_f1 (lgamma, 0x1p-70L, 4.8520302639196171659205759581386516869302e+01L, 1),
+    TEST_f_f1 (lgamma, -0x1p-70L, 4.8520302639196171659206737422758202661268e+01L, -1),
+    TEST_f_f1 (lgamma, 0x1p-100L, 6.9314718055994530941723212145817201464678e+01L, 1),
+    TEST_f_f1 (lgamma, -0x1p-100L, 6.9314718055994530941723212145818112150422e+01L, -1),
+    TEST_f_f1 (lgamma, 0x1p-126L, 8.7336544750553108986571247303730247577506e+01L, 1),
+    TEST_f_f1 (lgamma, -0x1p-126L, 8.7336544750553108986571247303730247577520e+01L, -1),
+    TEST_f_f1 (lgamma, 0x1p-149L, 1.0327892990343185110316758609726830864325e+02L, 1),
+    TEST_f_f1 (lgamma, -0x1p-149L, 1.0327892990343185110316758609726830864325e+02L, -1),
+#ifndef TEST_FLOAT
+    TEST_f_f1 (lgamma, 0x1p-200L, 1.3862943611198906188344642429163531361510e+02L, 1),
+    TEST_f_f1 (lgamma, -0x1p-200L, 1.3862943611198906188344642429163531361510e+02L, -1),
+    TEST_f_f1 (lgamma, 0x1p-500L, 3.4657359027997265470861606072908828403775e+02L, 1),
+    TEST_f_f1 (lgamma, -0x1p-500L, 3.4657359027997265470861606072908828403775e+02L, -1),
+    TEST_f_f1 (lgamma, 0x1p-1000L, 6.9314718055994530941723212145817656807550e+02L, 1),
+    TEST_f_f1 (lgamma, -0x1p-1000L, 6.9314718055994530941723212145817656807550e+02L, -1),
+    TEST_f_f1 (lgamma, 0x1p-1022L, 7.0839641853226410622441122813025645257316e+02L, 1),
+    TEST_f_f1 (lgamma, -0x1p-1022L, 7.0839641853226410622441122813025645257316e+02L, -1),
+    TEST_f_f1 (lgamma, 0x1p-1074L, 7.4444007192138126231410729844608163411309e+02L, 1),
+    TEST_f_f1 (lgamma, -0x1p-1074L, 7.4444007192138126231410729844608163411309e+02L, -1),
+#endif
+#if defined TEST_LDOUBLE && LDBL_MIN_EXP <= -16381
+    TEST_f_f1 (lgamma, 0x1p-5000L, 3.4657359027997265470861606072908828403775e+03L, 1),
+    TEST_f_f1 (lgamma, -0x1p-5000L, 3.4657359027997265470861606072908828403775e+03L, -1),
+    TEST_f_f1 (lgamma, 0x1p-10000L, 6.9314718055994530941723212145817656807550e+03L, 1),
+    TEST_f_f1 (lgamma, -0x1p-10000L, 6.9314718055994530941723212145817656807550e+03L, -1),
+    TEST_f_f1 (lgamma, 0x1p-16382L, 1.1355137111933024058873096613727848538213e+04L, 1),
+    TEST_f_f1 (lgamma, -0x1p-16382L, 1.1355137111933024058873096613727848538213e+04L, -1),
+    TEST_f_f1 (lgamma, 0x1p-16445L, 1.1398805384308300613366382237379713662002e+04L, 1),
+    TEST_f_f1 (lgamma, -0x1p-16445L, 1.1398805384308300613366382237379713662002e+04L, -1),
+# if LDBL_MANT_DIG >= 113
+    TEST_f_f1 (lgamma, 0x1p-16494L, 1.1432769596155737933527826611331164313837e+04L, 1),
+    TEST_f_f1 (lgamma, -0x1p-16494L, 1.1432769596155737933527826611331164313837e+04L, -1),
+# endif
+#endif
   };
 
 static void
diff --git a/sysdeps/i386/fpu/libm-test-ulps b/sysdeps/i386/fpu/libm-test-ulps
index 8244863..4759aa9 100644
--- a/sysdeps/i386/fpu/libm-test-ulps
+++ b/sysdeps/i386/fpu/libm-test-ulps
@@ -5470,9 +5470,35 @@ double: 1
 idouble: 1
 ildouble: 1
 ldouble: 1
+Test "gamma (-0x1p-10)":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "gamma (-0x1p-15)":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "gamma (-0x1p-20)":
+double: 1
+idouble: 1
+Test "gamma (-0x1p-30)":
+double: 1
+idouble: 1
+ildouble: 1
+ldouble: 1
+Test "gamma (-0x1p-5)":
+double: 1
+idouble: 1
 Test "gamma (0.7)":
 float: 1
 ifloat: 1
+Test "gamma (0x1p-40)":
+ildouble: 1
+ldouble: 1
 Test "gamma (1.2)":
 double: 1
 float: 2
@@ -5723,9 +5749,35 @@ double: 1
 idouble: 1
 ildouble: 1
 ldouble: 1
+Test "lgamma (-0x1p-10)":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "lgamma (-0x1p-15)":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "lgamma (-0x1p-20)":
+double: 1
+idouble: 1
+Test "lgamma (-0x1p-30)":
+double: 1
+idouble: 1
+ildouble: 1
+ldouble: 1
+Test "lgamma (-0x1p-5)":
+double: 1
+idouble: 1
 Test "lgamma (0.7)":
 float: 1
 ifloat: 1
+Test "lgamma (0x1p-40)":
+ildouble: 1
+ldouble: 1
 Test "lgamma (1.2)":
 double: 1
 float: 2
diff --git a/sysdeps/ieee754/flt-32/e_lgammaf_r.c b/sysdeps/ieee754/flt-32/e_lgammaf_r.c
index 2e92269..0dba9af 100644
--- a/sysdeps/ieee754/flt-32/e_lgammaf_r.c
+++ b/sysdeps/ieee754/flt-32/e_lgammaf_r.c
@@ -150,8 +150,8 @@ __ieee754_lgammaf_r(float x, int *signgamp)
 	      *signgamp = -1;
 	    return one/fabsf(x);
 	  }
-	if(__builtin_expect(ix<0x1c800000, 0)) {
-	    /* |x|<2**-70, return -log(|x|) */
+	if(__builtin_expect(ix<0x30800000, 0)) {
+	    /* |x|<2**-30, return -log(|x|) */
 	    if(hx<0) {
 		*signgamp = -1;
 		return -__ieee754_logf(-x);
diff --git a/sysdeps/x86_64/fpu/libm-test-ulps b/sysdeps/x86_64/fpu/libm-test-ulps
index 477eedc..6fbfa64 100644
--- a/sysdeps/x86_64/fpu/libm-test-ulps
+++ b/sysdeps/x86_64/fpu/libm-test-ulps
@@ -6222,11 +6222,39 @@ idouble: 1
 Test "gamma (-0.5)":
 ildouble: 1
 ldouble: 1
+Test "gamma (-0x1p-10)":
+double: 1
+idouble: 1
+ildouble: 1
+ldouble: 1
+Test "gamma (-0x1p-15)":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "gamma (-0x1p-20)":
+double: 1
+idouble: 1
+Test "gamma (-0x1p-30)":
+ildouble: 1
+ldouble: 1
+Test "gamma (-0x1p-5)":
+double: 1
+idouble: 1
 Test "gamma (0.7)":
 double: 1
 float: 1
 idouble: 1
 ifloat: 1
+Test "gamma (0x1p-10)":
+float: 1
+ifloat: 1
+Test "gamma (0x1p-30)":
+double: 1
+idouble: 1
+Test "gamma (0x1p-40)":
+ildouble: 1
+ldouble: 1
 Test "gamma (1.2)":
 double: 1
 float: 2
@@ -6491,11 +6519,39 @@ ldouble: 2
 Test "lgamma (-0.5)":
 ildouble: 1
 ldouble: 1
+Test "lgamma (-0x1p-10)":
+double: 1
+idouble: 1
+ildouble: 1
+ldouble: 1
+Test "lgamma (-0x1p-15)":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "lgamma (-0x1p-20)":
+double: 1
+idouble: 1
+Test "lgamma (-0x1p-30)":
+ildouble: 1
+ldouble: 1
+Test "lgamma (-0x1p-5)":
+double: 1
+idouble: 1
 Test "lgamma (0.7)":
 double: 1
 float: 1
 idouble: 1
 ifloat: 1
+Test "lgamma (0x1p-10)":
+float: 1
+ifloat: 1
+Test "lgamma (0x1p-30)":
+double: 1
+idouble: 1
+Test "lgamma (0x1p-40)":
+ildouble: 1
+ldouble: 1
 Test "lgamma (1.2)":
 double: 1
 float: 2

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=b3c7503940022f70ec8272c2c0d0a0e4489ae992

commit b3c7503940022f70ec8272c2c0d0a0e4489ae992
Author: Joseph Myers <joseph@codesourcery.com>
Date:   Mon Sep 2 14:51:24 2013 +0000

    Fix spurious jnf underflows (bug 14155).

diff --git a/ChangeLog b/ChangeLog
index 13486b0..a2e0a9f 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,15 @@
+2013-09-02  Joseph Myers  <joseph@codesourcery.com>
+
+	[BZ #14155]
+	* sysdeps/ieee754/flt-32/e_jnf.c (__ieee754_jnf): Use double for
+	intermediate calculations in recurrence.
+	(__ieee754_ynf): Likewise.
+	* math/libm-test.inc (jn_test_data): Do not allow spurious
+	underflow exception.  Add more tests.
+	(yn_test_data): Add more tests.
+	* sysdeps/i386/fpu/libm-test-ulps: Update.
+	* sysdeps/x86_64/fpu/libm-test-ulps: Likewise.
+
 2013-08-29  Thomas Schwinge  <thomas@codesourcery.com>
 
 	[BZ #15522] strtod ("nan(N)") returning a sNaN in some cases
diff --git a/NEWS b/NEWS
index 18cf053..751b9aa 100644
--- a/NEWS
+++ b/NEWS
@@ -11,9 +11,14 @@ Version 2.19
 
 * The following bugs are resolved with this release:
 
+<<<<<<< HEAD
   14699, 15522, 15531, 15532, 15736, 15749, 15797, 15867, 15890, 15897,
   15905.
 >>>>>>> 0007fc9... [BZ #15522] strtod ("nan(N)") returning a sNaN in some cases
+=======
+  14155, 14699, 15522, 15531, 15532, 15736, 15749, 15797, 15867, 15890,
+  15897, 15905, 15909.
+>>>>>>> b7835e3... Fix spurious jnf underflows (bug 14155).
 
 Version 2.18
 
@@ -21,18 +26,18 @@ Version 2.18
 
   2546, 2560, 5159, 6809, 7006, 10060, 10062, 10283, 10357, 10686, 11120,
   11561, 12310, 12387, 12492, 12515, 12723, 13550, 13889, 13951, 13988,
-  14142, 14176, 14200, 14256, 14280, 14293, 14317, 14327, 14478, 14496,
-  14582, 14686, 14699, 14812, 14888, 14894, 14907, 14908, 14909, 14920,
-  14952, 14964, 14981, 14982, 14985, 14991, 14994, 14996, 15000, 15003,
-  15006, 15007, 15014, 15020, 15022, 15023, 15036, 15054, 15055, 15062,
-  15078, 15084, 15085, 15086, 15100, 15160, 15214, 15221, 15232, 15234,
-  15283, 15285, 15287, 15304, 15305, 15307, 15309, 15327, 15330, 15331,
-  15335, 15336, 15337, 15339, 15342, 15346, 15359, 15361, 15366, 15380,
-  15381, 15394, 15395, 15405, 15406, 15409, 15416, 15418, 15419, 15423,
-  15424, 15426, 15429, 15431, 15432, 15441, 15442, 15448, 15465, 15480,
-  15485, 15488, 15490, 15492, 15493, 15497, 15506, 15522, 15529, 15532,
-  15536, 15553, 15577, 15583, 15618, 15627, 15631, 15654, 15655, 15666,
-  15667, 15674, 15711, 15755, 15759, 15797.
+  14142, 14155, 14176, 14200, 14256, 14280, 14293, 14317, 14327, 14478,
+  14496, 14582, 14686, 14699, 14812, 14888, 14894, 14907, 14908, 14909,
+  14920, 14952, 14964, 14981, 14982, 14985, 14991, 14994, 14996, 15000,
+  15003, 15006, 15007, 15014, 15020, 15022, 15023, 15036, 15054, 15055,
+  15062, 15078, 15084, 15085, 15086, 15100, 15160, 15214, 15221, 15232,
+  15234, 15283, 15285, 15287, 15304, 15305, 15307, 15309, 15327, 15330,
+  15331, 15335, 15336, 15337, 15339, 15342, 15346, 15359, 15361, 15366,
+  15380, 15381, 15394, 15395, 15405, 15406, 15409, 15416, 15418, 15419,
+  15423, 15424, 15426, 15429, 15431, 15432, 15441, 15442, 15448, 15465,
+  15480, 15485, 15488, 15490, 15492, 15493, 15497, 15506, 15522, 15529,
+  15532, 15536, 15553, 15577, 15583, 15618, 15627, 15631, 15654, 15655,
+  15666, 15667, 15674, 15711, 15755, 15759, 15797.
 
 * CVE-2013-2207 Incorrectly granting access to another user's pseudo-terminal
   has been fixed by disabling the use of pt_chown (Bugzilla #15755).
diff --git a/math/libm-test.inc b/math/libm-test.inc
index 7408c6b..9d49255 100644
--- a/math/libm-test.inc
+++ b/math/libm-test.inc
@@ -9908,8 +9908,14 @@ static const struct test_if_f_data jn_test_data[] =
     TEST_if_f (jn, 8, 2.4048255576957729L, 0.92165786705344923232879022467054148E-4L),
     TEST_if_f (jn, 9, 2.4048255576957729L, 0.12517270977961513005428966643852564E-4L),
 
-    /* Bug 14155: spurious exception may occur.  */
-    TEST_if_f (jn, 2, 0x1.ffff62p+99L, -4.43860668048170034334926693188979974489e-16L, UNDERFLOW_EXCEPTION_OK),
+    TEST_if_f (jn, 2, 0x1.ffff62p+99L, -4.43860668048170034334926693188979974489e-16L),
+    TEST_if_f (jn, 2, 0x1p127L, -6.0784021821505059176832624052765568656702e-20L),
+#ifndef TEST_FLOAT
+    TEST_if_f (jn, 2, 0x1p1023L, 1.5665258060609012834424478437196679802783e-155L),
+#endif
+#if defined TEST_LDOUBLE && LDBL_MAX_EXP >= 16384
+    TEST_if_f (jn, 2, 0x1p16383L, -9.5859502826270374691362975419147645151233e-2467L),
+#endif
   };
 
 static void
@@ -14526,6 +14532,15 @@ static const struct test_if_f_data yn_test_data[] =
     /* Check whether yn returns correct value for LDBL_MIN, DBL_MIN,
        and FLT_MIN.  See Bug 14173.  */
     TEST_if_f (yn, 10, min_value, minus_infty, OVERFLOW_EXCEPTION|ERRNO_ERANGE),
+
+    TEST_if_f (yn, 2, 0x1.ffff62p+99L, -5.5244413477397111790415387179517953221757e-16L),
+    TEST_if_f (yn, 2, 0x1p127L, 6.8569250690166637098111268958532649249771e-21L),
+#ifndef TEST_FLOAT
+    TEST_if_f (yn, 2, 0x1p1023L, -8.2687542933709649327986678723012001545638e-155L),
+#endif
+#if defined TEST_LDOUBLE && LDBL_MAX_EXP >= 16384
+    TEST_if_f (yn, 2, 0x1p16383L, 3.8895531955766020648617743624167352352217e-2467L),
+#endif
   };
 
 static void
diff --git a/sysdeps/i386/fpu/libm-test-ulps b/sysdeps/i386/fpu/libm-test-ulps
index 530dbd7..8244863 100644
--- a/sysdeps/i386/fpu/libm-test-ulps
+++ b/sysdeps/i386/fpu/libm-test-ulps
@@ -5635,9 +5635,9 @@ ildouble: 1
 ldouble: 1
 Test "jn (10, 10.0)":
 double: 1
-float: 1
+float: 2
 idouble: 1
-ifloat: 1
+ifloat: 2
 ildouble: 2
 ldouble: 2
 Test "jn (10, 2.0)":
@@ -5648,6 +5648,14 @@ float: 1
 ifloat: 1
 ildouble: 1
 ldouble: 1
+Test "jn (2, 0x1p1023)":
+double: 1
+idouble: 1
+Test "jn (2, 0x1p127)":
+double: 1
+idouble: 1
+ildouble: 1
+ldouble: 1
 Test "jn (2, 2.4048255576957729)":
 double: 1
 float: 1
@@ -6844,6 +6852,14 @@ ifloat: 1
 Test "yn (10, 2.0)":
 float: 3
 ifloat: 3
+Test "yn (2, 0x1.ffff62p+99)":
+double: 1
+idouble: 1
+ildouble: 1
+ldouble: 1
+Test "yn (2, 0x1p127)":
+float: 2
+ifloat: 2
 Test "yn (3, 0.125)":
 ildouble: 1
 ldouble: 1
diff --git a/sysdeps/ieee754/flt-32/e_jnf.c b/sysdeps/ieee754/flt-32/e_jnf.c
index ad26d7e..5984d94 100644
--- a/sysdeps/ieee754/flt-32/e_jnf.c
+++ b/sysdeps/ieee754/flt-32/e_jnf.c
@@ -54,7 +54,7 @@ __ieee754_jnf(int n, float x)
 	    b = __ieee754_j1f(x);
 	    for(i=1;i<n;i++){
 		temp = b;
-		b = b*((float)(i+i)/x) - a; /* avoid underflow */
+		b = b*((double)(i+i)/x) - a; /* avoid underflow */
 		a = temp;
 	    }
 	} else {
@@ -196,7 +196,7 @@ __ieee754_ynf(int n, float x)
 	GET_FLOAT_WORD(ib,b);
 	for(i=1;i<n&&ib!=0xff800000;i++){
 	    temp = b;
-	    b = ((float)(i+i)/x)*b - a;
+	    b = ((double)(i+i)/x)*b - a;
 	    GET_FLOAT_WORD(ib,b);
 	    a = temp;
 	}
diff --git a/sysdeps/x86_64/fpu/libm-test-ulps b/sysdeps/x86_64/fpu/libm-test-ulps
index d02618a..477eedc 100644
--- a/sysdeps/x86_64/fpu/libm-test-ulps
+++ b/sysdeps/x86_64/fpu/libm-test-ulps
@@ -6403,6 +6403,11 @@ idouble: 2
 ifloat: 2
 ildouble: 1
 ldouble: 1
+Test "jn (2, 0x1p127)":
+double: 1
+idouble: 1
+ildouble: 1
+ldouble: 1
 Test "jn (2, 2.4048255576957729)":
 double: 2
 float: 1
@@ -7728,6 +7733,16 @@ double: 3
 float: 1
 idouble: 3
 ifloat: 1
+Test "yn (2, 0x1.ffff62p+99)":
+double: 1
+idouble: 1
+ildouble: 1
+ldouble: 1
+Test "yn (2, 0x1p127)":
+double: 1
+float: 3
+idouble: 1
+ifloat: 3
 Test "yn (3, 0.125)":
 double: 1
 idouble: 1
@@ -8428,9 +8443,9 @@ ldouble: 2
 
 Function: "yn":
 double: 3
-float: 2
+float: 3
 idouble: 3
-ifloat: 2
+ifloat: 3
 ildouble: 4
 ldouble: 4
 

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=e53103749c19199b0ec23e8a5b330dd2e288f5ac

commit e53103749c19199b0ec23e8a5b330dd2e288f5ac
Author: Thomas Schwinge <thomas@codesourcery.com>
Date:   Thu May 23 18:00:10 2013 +0200

    [BZ #15522] strtod ("nan(N)") returning a sNaN in some cases

diff --git a/ChangeLog b/ChangeLog
index 1ffcad4..13486b0 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,29 @@
+2013-08-29  Thomas Schwinge  <thomas@codesourcery.com>
+
+	[BZ #15522] strtod ("nan(N)") returning a sNaN in some cases
+
+	* stdlib/strtof_l.c (SET_MANTISSA): Rewrite.
+	* stdlib/strtod_l.c (SET_MANTISSA): Likewise.
+	* sysdeps/ieee754/ldbl-64-128/strtold_l.c (SET_MANTISSA):
+	Likewise.
+	* sysdeps/ieee754/ldbl-96/strtold_l.c (SET_MANTISSA): Likewise.
+	* sysdeps/ieee754/ldbl-128/strtold_l.c (SET_MANTISSA): Likewise.
+	* sysdeps/ieee754/ldbl-128ibm/strtold_l.c (SET_MANTISSA):
+	Likewise.
+	* sysdeps/ieee754/ldbl-128ibm/ieee754.h
+	(ibm_extended_long_double): Add ieee_nan member.
+	* stdlib/tst-strtod6.c (test): New function, renamed from do_test.
+	(do_test): New function.
+
+	* math/basic-test.c (TEST_CONVERT): New macro, renamed from
+	TEST_TRUNC.
+	(convert_dfsf_test, convert_tfsf_test, convert_tfdf_test): New
+	functions, renamed from truncdfsf_test, trunctfsf_test,
+	trunctfdf_test.
+	(convert_sfdf_test, convert_sftf_test, convert_dftf_test): New
+	functions.
+	(do_test): Run all these.
+
 2013-08-23  Joseph Myers  <joseph@codesourcery.com>
 
 	[BZ #15532]
diff --git a/NEWS b/NEWS
index c83a14e..18cf053 100644
--- a/NEWS
+++ b/NEWS
@@ -4,6 +4,16 @@ See the end for copying conditions.
 
 Please send GNU C library bug reports via <http://sourceware.org/bugzilla/>
 using `glibc' in the "product" field.
+<<<<<<< HEAD
+=======
+
+Version 2.19
+
+* The following bugs are resolved with this release:
+
+  14699, 15522, 15531, 15532, 15736, 15749, 15797, 15867, 15890, 15897,
+  15905.
+>>>>>>> 0007fc9... [BZ #15522] strtod ("nan(N)") returning a sNaN in some cases
 
 Version 2.18
 
@@ -20,9 +30,9 @@ Version 2.18
   15335, 15336, 15337, 15339, 15342, 15346, 15359, 15361, 15366, 15380,
   15381, 15394, 15395, 15405, 15406, 15409, 15416, 15418, 15419, 15423,
   15424, 15426, 15429, 15431, 15432, 15441, 15442, 15448, 15465, 15480,
-  15485, 15488, 15490, 15492, 15493, 15497, 15506, 15529, 15532, 15536,
-  15553, 15577, 15583, 15618, 15627, 15631, 15654, 15655, 15666, 15667,
-  15674, 15711, 15755, 15759, 15797.
+  15485, 15488, 15490, 15492, 15493, 15497, 15506, 15522, 15529, 15532,
+  15536, 15553, 15577, 15583, 15618, 15627, 15631, 15654, 15655, 15666,
+  15667, 15674, 15711, 15755, 15759, 15797.
 
 * CVE-2013-2207 Incorrectly granting access to another user's pseudo-terminal
   has been fixed by disabling the use of pt_chown (Bugzilla #15755).
diff --git a/stdlib/strtod_l.c b/stdlib/strtod_l.c
index 5b41e2b..8f60653 100644
--- a/stdlib/strtod_l.c
+++ b/stdlib/strtod_l.c
@@ -42,11 +42,10 @@ extern unsigned long long int ____strtoull_l_internal (const char *, char **,
 # define SET_MANTISSA(flt, mant) \
   do { union ieee754_double u;						      \
        u.d = (flt);							      \
-       if ((mant & 0xfffffffffffffULL) == 0)				      \
-	 mant = 0x8000000000000ULL;					      \
-       u.ieee.mantissa0 = ((mant) >> 32) & 0xfffff;			      \
-       u.ieee.mantissa1 = (mant) & 0xffffffff;				      \
-       (flt) = u.d;							      \
+       u.ieee_nan.mantissa0 = (mant) >> 32;				      \
+       u.ieee_nan.mantissa1 = (mant);					      \
+       if ((u.ieee.mantissa0 | u.ieee.mantissa1) != 0)			      \
+	 (flt) = u.d;							      \
   } while (0)
 #endif
 /* End of configuration part.  */
diff --git a/stdlib/strtof_l.c b/stdlib/strtof_l.c
index 6fb44bd..c4c1c1f 100644
--- a/stdlib/strtof_l.c
+++ b/stdlib/strtof_l.c
@@ -37,10 +37,9 @@ extern unsigned long long int ____strtoull_l_internal (const char *, char **,
 #define SET_MANTISSA(flt, mant) \
   do { union ieee754_float u;						      \
        u.f = (flt);							      \
-       if ((mant & 0x7fffff) == 0)					      \
-	 mant = 0x400000;						      \
-       u.ieee.mantissa = (mant) & 0x7fffff;				      \
-       (flt) = u.f;							      \
+       u.ieee_nan.mantissa = (mant);					      \
+       if (u.ieee.mantissa != 0)					      \
+	 (flt) = u.f;							      \
   } while (0)
 
 #include "strtod_l.c"
diff --git a/stdlib/tst-strtod6.c b/stdlib/tst-strtod6.c
index 1d87266..15e79fd 100644
--- a/stdlib/tst-strtod6.c
+++ b/stdlib/tst-strtod6.c
@@ -4,12 +4,13 @@
 #include <string.h>
 
 static int
-do_test (void)
+test (const char str[])
 {
-  static const char str[] = "NaN(blabla)something";
   char *endp;
   int result = 0;
 
+  puts (str);
+
   double d = strtod (str, &endp);
   if (!isnan (d))
     {
@@ -64,5 +65,24 @@ do_test (void)
   return result;
 }
 
+static int
+do_test (void)
+{
+  int result = 0;
+
+  result |= test ("NaN(blabla)something");
+  result |= test ("NaN(1234)something");
+  /* UINT32_MAX.  */
+  result |= test ("NaN(4294967295)something");
+  /* UINT64_MAX.  */
+  result |= test ("NaN(18446744073709551615)something");
+  /* The case of zero is special in that "something" has to be done to make the
+     mantissa different from zero, which would mean infinity instead of
+     NaN.  */
+  result |= test ("NaN(0)something");
+
+  return result;
+}
+
 #define TEST_FUNCTION do_test ()
 #include "../test-skeleton.c"
diff --git a/sysdeps/ieee754/ldbl-128/strtold_l.c b/sysdeps/ieee754/ldbl-128/strtold_l.c
index 8e0bc03..d3a1d1e 100644
--- a/sysdeps/ieee754/ldbl-128/strtold_l.c
+++ b/sysdeps/ieee754/ldbl-128/strtold_l.c
@@ -34,11 +34,13 @@
 #define SET_MANTISSA(flt, mant) \
   do { union ieee854_long_double u;					      \
        u.d = (flt);							      \
-       u.ieee.mantissa0 = 0x8000;					      \
-       u.ieee.mantissa1 = 0;						      \
-       u.ieee.mantissa2 = ((mant) >> 32);	      			      \
-       u.ieee.mantissa3 = (mant) & 0xffffffff;				      \
-       (flt) = u.d;							      \
+       u.ieee_nan.mantissa0 = 0;					      \
+       u.ieee_nan.mantissa1 = 0;					      \
+       u.ieee_nan.mantissa2 = (mant) >> 32;				      \
+       u.ieee_nan.mantissa3 = (mant);					      \
+       if ((u.ieee.mantissa0 | u.ieee.mantissa1				      \
+	    | u.ieee.mantissa2 | u.ieee.mantissa3) != 0)		      \
+	 (flt) = u.d;							      \
   } while (0)
 
 #include <strtod_l.c>
diff --git a/sysdeps/ieee754/ldbl-128ibm/ieee754.h b/sysdeps/ieee754/ldbl-128ibm/ieee754.h
index e5644f5..9e94f53 100644
--- a/sysdeps/ieee754/ldbl-128ibm/ieee754.h
+++ b/sysdeps/ieee754/ldbl-128ibm/ieee754.h
@@ -199,6 +199,25 @@ union ibm_extended_long_double
 	unsigned int mantissa2:20;
 	unsigned int mantissa3:32;
       } ieee;
+
+    /* This format makes it easier to see if a NaN is a signalling NaN.  */
+    struct
+      { /* Big endian.  There is no other.  */
+
+	unsigned int negative:1;
+	unsigned int exponent:11;
+	unsigned int quiet_nan:1;
+	/* Together Mantissa0-3 comprise the mantissa.  */
+	unsigned int mantissa0:19;
+	unsigned int mantissa1:32;
+
+	unsigned int negative2:1;
+	unsigned int exponent2:11;
+	/* There is an implied 1 here?  */
+	/* Together these comprise the mantissa.  */
+	unsigned int mantissa2:20;
+	unsigned int mantissa3:32;
+      } ieee_nan;
    };
 
 #define IBM_EXTENDED_LONG_DOUBLE_BIAS 0x3ff /* Added to exponent.  */
diff --git a/sysdeps/ieee754/ldbl-128ibm/strtold_l.c b/sysdeps/ieee754/ldbl-128ibm/strtold_l.c
index 93415f0..04e3288 100644
--- a/sysdeps/ieee754/ldbl-128ibm/strtold_l.c
+++ b/sysdeps/ieee754/ldbl-128ibm/strtold_l.c
@@ -44,11 +44,10 @@ libc_hidden_proto (STRTOF)
 # define SET_MANTISSA(flt, mant) \
   do { union ibm_extended_long_double u;				      \
        u.d = (flt);							      \
-       if ((mant & 0xfffffffffffffULL) == 0)				      \
-	 mant = 0x8000000000000ULL;					      \
-       u.ieee.mantissa0 = ((mant) >> 32) & 0xfffff;			      \
-       u.ieee.mantissa1 = (mant) & 0xffffffff;				      \
-       (flt) = u.d;							      \
+       u.ieee_nan.mantissa0 = (mant) >> 32;				      \
+       u.ieee_nan.mantissa1 = (mant);					      \
+       if ((u.ieee.mantissa0 | u.ieee.mantissa1) != 0)			      \
+	 (flt) = u.d;							      \
   } while (0)
 
 #include <strtod_l.c>
diff --git a/sysdeps/ieee754/ldbl-64-128/strtold_l.c b/sysdeps/ieee754/ldbl-64-128/strtold_l.c
index 8182b2b..e9b33f2 100644
--- a/sysdeps/ieee754/ldbl-64-128/strtold_l.c
+++ b/sysdeps/ieee754/ldbl-64-128/strtold_l.c
@@ -44,11 +44,13 @@ libc_hidden_proto (STRTOF)
 #define SET_MANTISSA(flt, mant) \
   do { union ieee854_long_double u;					      \
        u.d = (flt);							      \
-       u.ieee.mantissa0 = 0x8000;					      \
-       u.ieee.mantissa1 = 0;						      \
-       u.ieee.mantissa2 = ((mant) >> 32);	      			      \
-       u.ieee.mantissa3 = (mant) & 0xffffffff;				      \
-       (flt) = u.d;							      \
+       u.ieee_nan.mantissa0 = 0;					      \
+       u.ieee_nan.mantissa1 = 0;					      \
+       u.ieee_nan.mantissa2 = (mant) >> 32;				      \
+       u.ieee_nan.mantissa3 = (mant);					      \
+       if ((u.ieee.mantissa0 | u.ieee.mantissa1				      \
+	    | u.ieee.mantissa2 | u.ieee.mantissa3) != 0)		      \
+	 (flt) = u.d;							      \
   } while (0)
 
 #include <strtod_l.c>
diff --git a/sysdeps/ieee754/ldbl-96/strtold_l.c b/sysdeps/ieee754/ldbl-96/strtold_l.c
index ded84f3..dccf98c 100644
--- a/sysdeps/ieee754/ldbl-96/strtold_l.c
+++ b/sysdeps/ieee754/ldbl-96/strtold_l.c
@@ -34,11 +34,10 @@
 #define SET_MANTISSA(flt, mant) \
   do { union ieee854_long_double u;					      \
        u.d = (flt);							      \
-       if ((mant & 0x7fffffffffffffffULL) == 0)				      \
-	 mant = 0x4000000000000000ULL;					      \
-       u.ieee.mantissa0 = (((mant) >> 32) & 0x7fffffff) | 0x80000000;	      \
-       u.ieee.mantissa1 = (mant) & 0xffffffff;				      \
-       (flt) = u.d;							      \
+       u.ieee_nan.mantissa0 = (mant) >> 32;				      \
+       u.ieee_nan.mantissa1 = (mant);					      \
+       if ((u.ieee.mantissa0 | u.ieee.mantissa1) != 0)			      \
+	 (flt) = u.d;							      \
   } while (0)
 
 #include <stdlib/strtod_l.c>

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=85ce5db8d835281c8beff6e750c02c799dee3f6f

commit 85ce5db8d835281c8beff6e750c02c799dee3f6f
Author: Joseph Myers <joseph@codesourcery.com>
Date:   Fri Aug 23 19:45:38 2013 +0000

    Fix cexp (NaN + i0) (bug 15532).

diff --git a/ChangeLog b/ChangeLog
index 7b4d6e9..1ffcad4 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+2013-08-23  Joseph Myers  <joseph@codesourcery.com>
+
+	[BZ #15532]
+	* math/s_cexp.c (__cexp): Return NaN + i0 for NaN + i0 argument.
+	* math/s_cexpf.c (__cexpf): Likewise.
+	* math/s_cexpl.c (__cexpl): Likewise.
+	* math/libm-test.inc (cexp_test_data): Correct expected return
+	value for NaN + i0.  Add another test.
+
 2013-08-21  Joseph Myers  <joseph@codesourcery.com>
 
 	[BZ #15797]
diff --git a/NEWS b/NEWS
index 0d0a315..c83a14e 100644
--- a/NEWS
+++ b/NEWS
@@ -20,9 +20,9 @@ Version 2.18
   15335, 15336, 15337, 15339, 15342, 15346, 15359, 15361, 15366, 15380,
   15381, 15394, 15395, 15405, 15406, 15409, 15416, 15418, 15419, 15423,
   15424, 15426, 15429, 15431, 15432, 15441, 15442, 15448, 15465, 15480,
-  15485, 15488, 15490, 15492, 15493, 15497, 15506, 15529, 15536, 15553,
-  15577, 15583, 15618, 15627, 15631, 15654, 15655, 15666, 15667, 15674,
-  15711, 15755, 15759, 15797.
+  15485, 15488, 15490, 15492, 15493, 15497, 15506, 15529, 15532, 15536,
+  15553, 15577, 15583, 15618, 15627, 15631, 15654, 15655, 15666, 15667,
+  15674, 15711, 15755, 15759, 15797.
 
 * CVE-2013-2207 Incorrectly granting access to another user's pseudo-terminal
   has been fixed by disabling the use of pt_chown (Bugzilla #15755).
diff --git a/math/libm-test.inc b/math/libm-test.inc
index 8c1dcac..7408c6b 100644
--- a/math/libm-test.inc
+++ b/math/libm-test.inc
@@ -6193,7 +6193,8 @@ static const struct test_c_c_data cexp_test_data[] =
 
     TEST_c_c (cexp, plus_infty, qnan_value, plus_infty, qnan_value),
 
-    TEST_c_c (cexp, qnan_value, 0.0, qnan_value, qnan_value, INVALID_EXCEPTION_OK),
+    TEST_c_c (cexp, qnan_value, 0.0, qnan_value, 0.0),
+    TEST_c_c (cexp, qnan_value, minus_zero, qnan_value, minus_zero),
     TEST_c_c (cexp, qnan_value, 1.0, qnan_value, qnan_value, INVALID_EXCEPTION_OK),
 
     TEST_c_c (cexp, qnan_value, plus_infty, qnan_value, qnan_value, INVALID_EXCEPTION_OK),
diff --git a/math/s_cexp.c b/math/s_cexp.c
index 655e4e8..40e0e51 100644
--- a/math/s_cexp.c
+++ b/math/s_cexp.c
@@ -145,12 +145,18 @@ __cexp (__complex__ double x)
     }
   else
     {
-      /* If the real part is NaN the result is NaN + iNaN.  */
+      /* If the real part is NaN the result is NaN + iNaN unless the
+	 imaginary part is zero.  */
       __real__ retval = __nan ("");
-      __imag__ retval = __nan ("");
+      if (icls == FP_ZERO)
+	__imag__ retval = __imag__ x;
+      else
+	{
+	  __imag__ retval = __nan ("");
 
-      if (rcls != FP_NAN || icls != FP_NAN)
-	feraiseexcept (FE_INVALID);
+	  if (rcls != FP_NAN || icls != FP_NAN)
+	    feraiseexcept (FE_INVALID);
+	}
     }
 
   return retval;
diff --git a/math/s_cexpf.c b/math/s_cexpf.c
index fa942d3..7c42205 100644
--- a/math/s_cexpf.c
+++ b/math/s_cexpf.c
@@ -145,12 +145,18 @@ __cexpf (__complex__ float x)
     }
   else
     {
-      /* If the real part is NaN the result is NaN + iNaN.  */
+      /* If the real part is NaN the result is NaN + iNaN unless the
+	 imaginary part is zero.  */
       __real__ retval = __nanf ("");
-      __imag__ retval = __nanf ("");
+      if (icls == FP_ZERO)
+	__imag__ retval = __imag__ x;
+      else
+	{
+	  __imag__ retval = __nanf ("");
 
-      if (rcls != FP_NAN || icls != FP_NAN)
-	feraiseexcept (FE_INVALID);
+	  if (rcls != FP_NAN || icls != FP_NAN)
+	    feraiseexcept (FE_INVALID);
+	}
     }
 
   return retval;
diff --git a/math/s_cexpl.c b/math/s_cexpl.c
index d827bc3..0c35603 100644
--- a/math/s_cexpl.c
+++ b/math/s_cexpl.c
@@ -145,12 +145,18 @@ __cexpl (__complex__ long double x)
     }
   else
     {
-      /* If the real part is NaN the result is NaN + iNaN.  */
+      /* If the real part is NaN the result is NaN + iNaN unless the
+	 imaginary part is zero.  */
       __real__ retval = __nanl ("");
-      __imag__ retval = __nanl ("");
+      if (icls == FP_ZERO)
+	__imag__ retval = __imag__ x;
+      else
+	{
+	  __imag__ retval = __nanl ("");
 
-      if (rcls != FP_NAN || icls != FP_NAN)
-	feraiseexcept (FE_INVALID);
+	  if (rcls != FP_NAN || icls != FP_NAN)
+	    feraiseexcept (FE_INVALID);
+	}
     }
 
   return retval;

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=c3a4bddd656561cfffba2605e148e65d4ff07e21

commit c3a4bddd656561cfffba2605e148e65d4ff07e21
Author: Joseph Myers <joseph@codesourcery.com>
Date:   Wed Aug 21 19:56:48 2013 +0000

    Fix fdim handling of infinities (bug 15797).

diff --git a/ChangeLog b/ChangeLog
index 16e258c..7b4d6e9 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+2013-08-21  Joseph Myers  <joseph@codesourcery.com>
+
+	[BZ #15797]
+	* math/s_fdim.c (__fdim): Check for infinite arguments if result
+	is infinite, not alongside NaN test.
+	* math/s_fdimf.c (__fdimf): Likewise.
+	* math/s_fdiml.c (__fdiml): Likewise.
+	* math/libm-test.inc (fdim_test_data): Add more tests.  Test that
+	errno is unchanged.
+
 2013-07-23  Adhemerval Zanella  <azanella@linux.vnet.ibm.com>
 
 	[BZ #15867]
diff --git a/NEWS b/NEWS
index ab3f353..0d0a315 100644
--- a/NEWS
+++ b/NEWS
@@ -22,7 +22,7 @@ Version 2.18
   15424, 15426, 15429, 15431, 15432, 15441, 15442, 15448, 15465, 15480,
   15485, 15488, 15490, 15492, 15493, 15497, 15506, 15529, 15536, 15553,
   15577, 15583, 15618, 15627, 15631, 15654, 15655, 15666, 15667, 15674,
-  15711, 15755, 15759.
+  15711, 15755, 15759, 15797.
 
 * CVE-2013-2207 Incorrectly granting access to another user's pseudo-terminal
   has been fixed by disabling the use of pt_chown (Bugzilla #15755).
diff --git a/math/libm-test.inc b/math/libm-test.inc
index 3b382af..8c1dcac 100644
--- a/math/libm-test.inc
+++ b/math/libm-test.inc
@@ -8139,33 +8139,37 @@ fabs_test (void)
 
 static const struct test_ff_f_data fdim_test_data[] =
   {
-    TEST_ff_f (fdim, 0, 0, 0, NO_INEXACT_EXCEPTION),
-    TEST_ff_f (fdim, 9, 0, 9, NO_INEXACT_EXCEPTION),
-    TEST_ff_f (fdim, 0, 9, 0, NO_INEXACT_EXCEPTION),
-    TEST_ff_f (fdim, -9, 0, 0, NO_INEXACT_EXCEPTION),
-    TEST_ff_f (fdim, 0, -9, 9, NO_INEXACT_EXCEPTION),
-
-    TEST_ff_f (fdim, plus_infty, 9, plus_infty, NO_INEXACT_EXCEPTION),
-    TEST_ff_f (fdim, plus_infty, -9, plus_infty, NO_INEXACT_EXCEPTION),
-    TEST_ff_f (fdim, minus_infty, 9, 0, NO_INEXACT_EXCEPTION),
-    TEST_ff_f (fdim, minus_infty, -9, 0, NO_INEXACT_EXCEPTION),
-    TEST_ff_f (fdim, 9, minus_infty, plus_infty, NO_INEXACT_EXCEPTION),
-    TEST_ff_f (fdim, -9, minus_infty, plus_infty, NO_INEXACT_EXCEPTION),
-    TEST_ff_f (fdim, 9, plus_infty, 0, NO_INEXACT_EXCEPTION),
-    TEST_ff_f (fdim, -9, plus_infty, 0, NO_INEXACT_EXCEPTION),
-
-    TEST_ff_f (fdim, 0, qnan_value, qnan_value, NO_INEXACT_EXCEPTION),
-    TEST_ff_f (fdim, 9, qnan_value, qnan_value, NO_INEXACT_EXCEPTION),
-    TEST_ff_f (fdim, -9, qnan_value, qnan_value, NO_INEXACT_EXCEPTION),
-    TEST_ff_f (fdim, qnan_value, 9, qnan_value, NO_INEXACT_EXCEPTION),
-    TEST_ff_f (fdim, qnan_value, -9, qnan_value, NO_INEXACT_EXCEPTION),
-    TEST_ff_f (fdim, plus_infty, qnan_value, qnan_value, NO_INEXACT_EXCEPTION),
-    TEST_ff_f (fdim, minus_infty, qnan_value, qnan_value, NO_INEXACT_EXCEPTION),
-    TEST_ff_f (fdim, qnan_value, plus_infty, qnan_value, NO_INEXACT_EXCEPTION),
-    TEST_ff_f (fdim, qnan_value, minus_infty, qnan_value, NO_INEXACT_EXCEPTION),
-    TEST_ff_f (fdim, qnan_value, qnan_value, qnan_value, NO_INEXACT_EXCEPTION),
-
-    TEST_ff_f (fdim, plus_infty, plus_infty, 0, NO_INEXACT_EXCEPTION),
+    TEST_ff_f (fdim, 0, 0, 0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_ff_f (fdim, 9, 0, 9, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_ff_f (fdim, 0, 9, 0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_ff_f (fdim, -9, 0, 0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_ff_f (fdim, 0, -9, 9, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+
+    TEST_ff_f (fdim, plus_infty, 9, plus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_ff_f (fdim, plus_infty, -9, plus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_ff_f (fdim, minus_infty, 9, 0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_ff_f (fdim, minus_infty, -9, 0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_ff_f (fdim, 9, minus_infty, plus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_ff_f (fdim, -9, minus_infty, plus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_ff_f (fdim, 9, plus_infty, 0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_ff_f (fdim, -9, plus_infty, 0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+
+    TEST_ff_f (fdim, 0, qnan_value, qnan_value, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_ff_f (fdim, 9, qnan_value, qnan_value, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_ff_f (fdim, -9, qnan_value, qnan_value, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_ff_f (fdim, qnan_value, 0, qnan_value, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_ff_f (fdim, qnan_value, 9, qnan_value, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_ff_f (fdim, qnan_value, -9, qnan_value, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_ff_f (fdim, plus_infty, qnan_value, qnan_value, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_ff_f (fdim, minus_infty, qnan_value, qnan_value, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_ff_f (fdim, qnan_value, plus_infty, qnan_value, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_ff_f (fdim, qnan_value, minus_infty, qnan_value, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_ff_f (fdim, qnan_value, qnan_value, qnan_value, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+
+    TEST_ff_f (fdim, plus_infty, plus_infty, 0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_ff_f (fdim, plus_infty, minus_infty, plus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_ff_f (fdim, minus_infty, plus_infty, 0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
+    TEST_ff_f (fdim, minus_infty, minus_infty, 0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
   };
 
 static void
diff --git a/math/s_fdim.c b/math/s_fdim.c
index 2f97948..f8fd804 100644
--- a/math/s_fdim.c
+++ b/math/s_fdim.c
@@ -26,16 +26,16 @@ __fdim (double x, double y)
   int clsx = fpclassify (x);
   int clsy = fpclassify (y);
 
-  if (clsx == FP_NAN || clsy == FP_NAN
-      || (y < 0 && clsx == FP_INFINITE && clsy == FP_INFINITE))
-    /* Raise invalid flag.  */
+  if (clsx == FP_NAN || clsy == FP_NAN)
+    /* Raise invalid flag for signaling but not quiet NaN.  */
     return x - y;
 
   if (x <= y)
     return 0.0;
 
   double r = x - y;
-  if (fpclassify (r) == FP_INFINITE)
+  if (fpclassify (r) == FP_INFINITE
+      && clsx != FP_INFINITE && clsy != FP_INFINITE)
     __set_errno (ERANGE);
 
   return r;
diff --git a/math/s_fdimf.c b/math/s_fdimf.c
index 03810b5..86efe6e 100644
--- a/math/s_fdimf.c
+++ b/math/s_fdimf.c
@@ -26,16 +26,16 @@ __fdimf (float x, float y)
   int clsx = fpclassify (x);
   int clsy = fpclassify (y);
 
-  if (clsx == FP_NAN || clsy == FP_NAN
-      || (y < 0 && clsx == FP_INFINITE && clsy == FP_INFINITE))
-    /* Raise invalid flag.  */
+  if (clsx == FP_NAN || clsy == FP_NAN)
+    /* Raise invalid flag for signaling but not quiet NaN.  */
     return x - y;
 
   if (x <= y)
     return 0.0f;
 
   float r = x - y;
-  if (fpclassify (r) == FP_INFINITE)
+  if (fpclassify (r) == FP_INFINITE
+      && clsx != FP_INFINITE && clsy != FP_INFINITE)
     __set_errno (ERANGE);
 
   return r;
diff --git a/math/s_fdiml.c b/math/s_fdiml.c
index 5604532..030fcc2 100644
--- a/math/s_fdiml.c
+++ b/math/s_fdiml.c
@@ -26,16 +26,16 @@ __fdiml (long double x, long double y)
   int clsx = fpclassify (x);
   int clsy = fpclassify (y);
 
-  if (clsx == FP_NAN || clsy == FP_NAN
-      || (y < 0 && clsx == FP_INFINITE && clsy == FP_INFINITE))
-    /* Raise invalid flag.  */
+  if (clsx == FP_NAN || clsy == FP_NAN)
+    /* Raise invalid flag for signaling but not quiet NaN.  */
     return x - y;
 
   if (x <= y)
     return 0.0f;
 
   long double r = x - y;
-  if (fpclassify (r) == FP_INFINITE)
+  if (fpclassify (r) == FP_INFINITE
+      && clsx != FP_INFINITE && clsy != FP_INFINITE)
     __set_errno (ERANGE);
 
   return r;

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=1778fd0a17a74422a58d8eada3fa08b80f0a0c27

commit 1778fd0a17a74422a58d8eada3fa08b80f0a0c27
Author: Adhemerval Zanella <azanella@linux.vnet.ibm.com>
Date:   Tue Aug 20 15:01:59 2013 -0500

    PowerPC: fix backtrace to handle signal trampolines
    
    This patch fixes backtrace for PPC32 and PPC64 to correctly handle
    signal trampolines. The 'debug/tst-backtrace6.c' also check for
    SA_SIGINFO handling, where is triggers another vDSO symbols for PPC32.

diff --git a/ChangeLog b/ChangeLog
index bf25bd6..16e258c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,20 @@
+2013-07-23  Adhemerval Zanella  <azanella@linux.vnet.ibm.com>
+
+	[BZ #15867]
+	* sysdeps/powerpc/powerpc32/backtrace.c (__backtrace): Handle signal
+	trampoline stack frame information.
+	* sysdeps/powerpc/powerpc64/backtrace.c (__backtrace): Likewise.
+	* sysdeps/unix/sysv/linux/powerpc/bits/libc-vdso.h
+	(__vdso_sigtramp_rt64): New variable: PPC64 signal trampoline.
+	(__vdso_sigtramp32): New variable: PPC32 signal trampoline.
+	(__vdso_sigtramp_rt32): New variable: PPC32 signal trampoline.
+	* sysdeps/unix/sysv/linux/powerpc/init-first.c
+	(_libc_vdso_platform_setup): Initialize the signal trampolines.
+	* debug/tst-backtrace5.c (fn): Add an option set modify sigaction
+	sa_flags value.
+	* debug/tst-backtrace6.c: New file: check backtrace for signal frames,
+	interrupting a syscall and set with option SA_SIGINFO.
+
 2013-08-20  Joseph Myers  <joseph@codesourcery.com>
 
 	[BZ #15531]

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=8df86a8394d0ea121f2066efe618f2b1cc799be3

commit 8df86a8394d0ea121f2066efe618f2b1cc799be3
Author: Joseph Myers <joseph@codesourcery.com>
Date:   Tue Aug 20 19:41:15 2013 +0000

    Fix cproj handling of (finite, NaN) arguments (bug 15531).
    
    backport of c980f2f4fe0f5d301f706017a1f7e4e942193ec0

diff --git a/ChangeLog b/ChangeLog
index 9ad0719..bf25bd6 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,19 @@
+2013-08-20  Joseph Myers  <joseph@codesourcery.com>
+
+	[BZ #15531]
+	* math/s_cproj.c (__cproj): Only return an infinity if one part of
+	argument is infinite.
+	* math/s_cprojf.c (__cprojf): Likewise.
+	* math/s_cprojl.c (__cprojl): Likewise.
+	* sysdeps/ieee754/ldbl-128ibm/s_cprojl.c (__cprojl): Likewise.
+	* math/libm-test.inc (cproj_test_data): Add more tests.
+
+	* sysdeps/unix/sysv/linux/mmap64.c: Include <string.h>.
+
+	* sysdeps/unix/sysv/linux/mmap64.c (__mmap64)
+	[MMAP2_PAGE_SHIFT == -1]: Use __getpagesize to determine page
+	size.  Use __ffs to determine corresponding shift.
+
 2013-08-20  Andreas Arnez  <arnez@linux.vnet.ibm.com>
 
 	* elf/setup-vdso.h (setup_vdso): Fix missing string termination.
diff --git a/NEWS b/NEWS
index 4d168c5..ab3f353 100644
--- a/NEWS
+++ b/NEWS
@@ -16,13 +16,13 @@ Version 2.18
   14952, 14964, 14981, 14982, 14985, 14991, 14994, 14996, 15000, 15003,
   15006, 15007, 15014, 15020, 15022, 15023, 15036, 15054, 15055, 15062,
   15078, 15084, 15085, 15086, 15100, 15160, 15214, 15221, 15232, 15234,
-  15283, 15285, 15287, 15304, 15305, 15307, 15309, 15327, 15330, 15335,
-  15336, 15337, 15339, 15342, 15346, 15359, 15361, 15366, 15380, 15381,
-  15394, 15395, 15405, 15406, 15409, 15416, 15418, 15419, 15423, 15424,
-  15426, 15429, 15431, 15432, 15441, 15442, 15448, 15465, 15480, 15485,
-  15488, 15490, 15492, 15493, 15497, 15506, 15529, 15536, 15553, 15577,
-  15583, 15618, 15627, 15631, 15654, 15655, 15666, 15667, 15674, 15711,
-  15755, 15759.
+  15283, 15285, 15287, 15304, 15305, 15307, 15309, 15327, 15330, 15331,
+  15335, 15336, 15337, 15339, 15342, 15346, 15359, 15361, 15366, 15380,
+  15381, 15394, 15395, 15405, 15406, 15409, 15416, 15418, 15419, 15423,
+  15424, 15426, 15429, 15431, 15432, 15441, 15442, 15448, 15465, 15480,
+  15485, 15488, 15490, 15492, 15493, 15497, 15506, 15529, 15536, 15553,
+  15577, 15583, 15618, 15627, 15631, 15654, 15655, 15666, 15667, 15674,
+  15711, 15755, 15759.
 
 * CVE-2013-2207 Incorrectly granting access to another user's pseudo-terminal
   has been fixed by disabling the use of pt_chown (Bugzilla #15755).
diff --git a/math/libm-test.inc b/math/libm-test.inc
index 2324d4f..3b382af 100644
--- a/math/libm-test.inc
+++ b/math/libm-test.inc
@@ -7061,11 +7061,51 @@ static const struct test_c_c_data cproj_test_data[] =
 
     TEST_c_c (cproj, qnan_value, qnan_value, qnan_value, qnan_value, NO_INEXACT_EXCEPTION),
 
+    TEST_c_c (cproj, plus_zero, qnan_value, plus_zero, qnan_value, NO_INEXACT_EXCEPTION),
+    TEST_c_c (cproj, minus_zero, qnan_value, minus_zero, qnan_value, NO_INEXACT_EXCEPTION),
+    TEST_c_c (cproj, qnan_value, plus_zero, qnan_value, plus_zero, NO_INEXACT_EXCEPTION),
+    TEST_c_c (cproj, qnan_value, minus_zero, qnan_value, minus_zero, NO_INEXACT_EXCEPTION),
+
+    TEST_c_c (cproj, 1.0, qnan_value, 1.0, qnan_value, NO_INEXACT_EXCEPTION),
+    TEST_c_c (cproj, -1.0, qnan_value, -1.0, qnan_value, NO_INEXACT_EXCEPTION),
+    TEST_c_c (cproj, qnan_value, 1.0, qnan_value, 1.0, NO_INEXACT_EXCEPTION),
+    TEST_c_c (cproj, qnan_value, -1.0, qnan_value, -1.0, NO_INEXACT_EXCEPTION),
+
     TEST_c_c (cproj, plus_infty, plus_infty, plus_infty, 0.0, NO_INEXACT_EXCEPTION),
     TEST_c_c (cproj, plus_infty, minus_infty, plus_infty, minus_zero, NO_INEXACT_EXCEPTION),
     TEST_c_c (cproj, minus_infty, plus_infty, plus_infty, 0.0, NO_INEXACT_EXCEPTION),
     TEST_c_c (cproj, minus_infty, minus_infty, plus_infty, minus_zero, NO_INEXACT_EXCEPTION),
 
+    TEST_c_c (cproj, plus_infty, plus_zero, plus_infty, 0.0, NO_INEXACT_EXCEPTION),
+    TEST_c_c (cproj, plus_infty, minus_zero, plus_infty, minus_zero, NO_INEXACT_EXCEPTION),
+    TEST_c_c (cproj, minus_infty, plus_zero, plus_infty, 0.0, NO_INEXACT_EXCEPTION),
+    TEST_c_c (cproj, minus_infty, minus_zero, plus_infty, minus_zero, NO_INEXACT_EXCEPTION),
+
+    TEST_c_c (cproj, plus_zero, plus_infty, plus_infty, 0.0, NO_INEXACT_EXCEPTION),
+    TEST_c_c (cproj, plus_zero, minus_infty, plus_infty, minus_zero, NO_INEXACT_EXCEPTION),
+    TEST_c_c (cproj, minus_zero, plus_infty, plus_infty, 0.0, NO_INEXACT_EXCEPTION),
+    TEST_c_c (cproj, minus_zero, minus_infty, plus_infty, minus_zero, NO_INEXACT_EXCEPTION),
+
+    TEST_c_c (cproj, plus_infty, 1.0, plus_infty, 0.0, NO_INEXACT_EXCEPTION),
+    TEST_c_c (cproj, plus_infty, -1.0, plus_infty, minus_zero, NO_INEXACT_EXCEPTION),
+    TEST_c_c (cproj, minus_infty, 1.0, plus_infty, 0.0, NO_INEXACT_EXCEPTION),
+    TEST_c_c (cproj, minus_infty, -1.0, plus_infty, minus_zero, NO_INEXACT_EXCEPTION),
+
+    TEST_c_c (cproj, 1.0, plus_infty, plus_infty, 0.0, NO_INEXACT_EXCEPTION),
+    TEST_c_c (cproj, 1.0, minus_infty, plus_infty, minus_zero, NO_INEXACT_EXCEPTION),
+    TEST_c_c (cproj, -1.0, plus_infty, plus_infty, 0.0, NO_INEXACT_EXCEPTION),
+    TEST_c_c (cproj, -1.0, minus_infty, plus_infty, minus_zero, NO_INEXACT_EXCEPTION),
+
+    TEST_c_c (cproj, plus_infty, qnan_value, plus_infty, 0.0, NO_INEXACT_EXCEPTION),
+    TEST_c_c (cproj, plus_infty, -qnan_value, plus_infty, minus_zero, NO_INEXACT_EXCEPTION),
+    TEST_c_c (cproj, minus_infty, qnan_value, plus_infty, 0.0, NO_INEXACT_EXCEPTION),
+    TEST_c_c (cproj, minus_infty, -qnan_value, plus_infty, minus_zero, NO_INEXACT_EXCEPTION),
+
+    TEST_c_c (cproj, qnan_value, plus_infty, plus_infty, 0.0, NO_INEXACT_EXCEPTION),
+    TEST_c_c (cproj, qnan_value, minus_infty, plus_infty, minus_zero, NO_INEXACT_EXCEPTION),
+    TEST_c_c (cproj, -qnan_value, plus_infty, plus_infty, 0.0, NO_INEXACT_EXCEPTION),
+    TEST_c_c (cproj, -qnan_value, minus_infty, plus_infty, minus_zero, NO_INEXACT_EXCEPTION),
+
     TEST_c_c (cproj, 1.0, 0.0, 1.0, 0.0, NO_INEXACT_EXCEPTION),
     TEST_c_c (cproj, 2.0, 3.0, 2.0, 3.0, NO_INEXACT_EXCEPTION),
   };
diff --git a/math/s_cproj.c b/math/s_cproj.c
index c0be461..98f1a4c 100644
--- a/math/s_cproj.c
+++ b/math/s_cproj.c
@@ -24,9 +24,7 @@
 __complex__ double
 __cproj (__complex__ double x)
 {
-  if (isnan (__real__ x) && isnan (__imag__ x))
-    return x;
-  else if (!isfinite (__real__ x) || !isfinite (__imag__ x))
+  if (__isinf_ns (__real__ x) || __isinf_ns (__imag__ x))
     {
       __complex__ double res;
 
diff --git a/math/s_cprojf.c b/math/s_cprojf.c
index 188bbe3..e4dbc18 100644
--- a/math/s_cprojf.c
+++ b/math/s_cprojf.c
@@ -24,9 +24,7 @@
 __complex__ float
 __cprojf (__complex__ float x)
 {
-  if (isnan (__real__ x) && isnan (__imag__ x))
-    return x;
-  else if (!isfinite (__real__ x) || !isfinite (__imag__ x))
+  if (__isinf_nsf (__real__ x) || __isinf_nsf (__imag__ x))
     {
       __complex__ float res;
 
diff --git a/math/s_cprojl.c b/math/s_cprojl.c
index fbdf279..b564a83 100644
--- a/math/s_cprojl.c
+++ b/math/s_cprojl.c
@@ -24,9 +24,7 @@
 __complex__ long double
 __cprojl (__complex__ long double x)
 {
-  if (isnan (__real__ x) && isnan (__imag__ x))
-    return x;
-  else if (!isfinite (__real__ x) || !isfinite (__imag__ x))
+  if (__isinf_nsl (__real__ x) || __isinf_nsl (__imag__ x))
     {
       __complex__ long double res;
 
diff --git a/sysdeps/ieee754/ldbl-128ibm/s_cprojl.c b/sysdeps/ieee754/ldbl-128ibm/s_cprojl.c
index 3b4af54..a344e92 100644
--- a/sysdeps/ieee754/ldbl-128ibm/s_cprojl.c
+++ b/sysdeps/ieee754/ldbl-128ibm/s_cprojl.c
@@ -24,9 +24,7 @@
 __complex__ long double
 __cprojl (__complex__ long double x)
 {
-  if (isnan (__real__ x) && isnan (__imag__ x))
-    return x;
-  else if (!isfinite (__real__ x) || !isfinite (__imag__ x))
+  if (__isinf_nsl (__real__ x) || __isinf_nsl (__imag__ x))
     {
       __complex__ long double res;
 

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=f8a004f1fa412e3aae77faa30b4dfb654d721510

commit f8a004f1fa412e3aae77faa30b4dfb654d721510
Author: Andreas Arnez <arnez@linux.vnet.ibm.com>
Date:   Thu Oct 31 09:57:33 2013 -0500

    * elf/setup-vdso.h (setup_vdso): Fix missing string termination.
    
    backport of f315524e034cfc644157cb4af5ecc99f645dd067

diff --git a/ChangeLog b/ChangeLog
index 3a6ce47..9ad0719 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
+2013-08-20  Andreas Arnez  <arnez@linux.vnet.ibm.com>
+
+	* elf/setup-vdso.h (setup_vdso): Fix missing string termination.
+
 2013-08-16  Florian Weimer  <fweimer@redhat.com>
 
 	[BZ #14699]
diff --git a/elf/setup-vdso.h b/elf/setup-vdso.h
index a98dfec..056d885 100644
--- a/elf/setup-vdso.h
+++ b/elf/setup-vdso.h
@@ -89,7 +89,7 @@ setup_vdso (struct link_map *main_map __attribute__ ((unused)),
 	     addresses in the vsyscall DSO pages in writev() calls.  */
 	  const char *dsoname = ((char *) D_PTR (l, l_info[DT_STRTAB])
 				 + l->l_info[DT_SONAME]->d_un.d_val);
-	  size_t len = strlen (dsoname);
+	  size_t len = strlen (dsoname) + 1;
 	  char *copy = malloc (len);
 	  if (copy == NULL)
 	    _dl_fatal_printf ("out of memory\n");

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=f166b9c6e90d631115c59b4357357bc168d8e51a

commit f166b9c6e90d631115c59b4357357bc168d8e51a
Author: Florian Weimer <fweimer@redhat.com>
Date:   Thu Oct 31 09:55:52 2013 -0500

    CVE-2013-4237, BZ #14699: Buffer overflow in readdir_r
    
    * sysdeps/posix/dirstream.h (struct __dirstream): Add errcode
    member.
    * sysdeps/posix/opendir.c (__alloc_dir): Initialize errcode
    member.
    * sysdeps/posix/rewinddir.c (rewinddir): Reset errcode member.
    * sysdeps/posix/readdir_r.c (__READDIR_R): Enforce NAME_MAX limit.
    Return delayed error code.  Remove GETDENTS_64BIT_ALIGNED
    conditional.
    * sysdeps/unix/sysv/linux/wordsize-64/readdir_r.c: Do not define
    GETDENTS_64BIT_ALIGNED.
    * sysdeps/unix/sysv/linux/i386/readdir64_r.c: Likewise.
    * manual/filesys.texi (Reading/Closing Directory): Document
    ENAMETOOLONG return value of readdir_r.  Recommend readdir more
    strongly.
    * manual/conf.texi (Limits for Files): Add portability note to
    NAME_MAX, PATH_MAX.
    (Pathconf): Add portability note for _PC_NAME_MAX, _PC_PATH_MAX.
    
    backport of 91ce40854d0b7f865cf5024ef95a8026b76096f3

diff --git a/ChangeLog b/ChangeLog
index 3ef8981..3a6ce47 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,25 @@
+2013-08-16  Florian Weimer  <fweimer@redhat.com>
+
+	[BZ #14699]
+	CVE-2013-4237
+	* sysdeps/posix/dirstream.h (struct __dirstream): Add errcode
+	member.
+	* sysdeps/posix/opendir.c (__alloc_dir): Initialize errcode
+	member.
+	* sysdeps/posix/rewinddir.c (rewinddir): Reset errcode member.
+	* sysdeps/posix/readdir_r.c (__READDIR_R): Enforce NAME_MAX limit.
+	Return delayed error code.  Remove GETDENTS_64BIT_ALIGNED
+	conditional.
+	* sysdeps/unix/sysv/linux/wordsize-64/readdir_r.c: Do not define
+	GETDENTS_64BIT_ALIGNED.
+	* sysdeps/unix/sysv/linux/i386/readdir64_r.c: Likewise.
+	* manual/filesys.texi (Reading/Closing Directory): Document
+	ENAMETOOLONG return value of readdir_r.  Recommend readdir more
+	strongly.
+	* manual/conf.texi (Limits for Files): Add portability note to
+	NAME_MAX, PATH_MAX.
+	(Pathconf): Add portability note for _PC_NAME_MAX, _PC_PATH_MAX.
+
 2013-07-23  Adhemerval Zanella  <azanella@linux.vnet.ibm.com>
 
 	* sysdeps/powerpc/powerpc32/backtrace.c (__backtrace): Handle signal
diff --git a/NEWS b/NEWS
index b023c30..4d168c5 100644
--- a/NEWS
+++ b/NEWS
@@ -4,7 +4,7 @@ See the end for copying conditions.
 
 Please send GNU C library bug reports via <http://sourceware.org/bugzilla/>
 using `glibc' in the "product" field.
-
+
 Version 2.18
 
 * The following bugs are resolved with this release:
@@ -12,17 +12,17 @@ Version 2.18
   2546, 2560, 5159, 6809, 7006, 10060, 10062, 10283, 10357, 10686, 11120,
   11561, 12310, 12387, 12492, 12515, 12723, 13550, 13889, 13951, 13988,
   14142, 14176, 14200, 14256, 14280, 14293, 14317, 14327, 14478, 14496,
-  14582, 14686, 14812, 14888, 14894, 14907, 14908, 14909, 14920, 14952,
-  14964, 14981, 14982, 14985, 14991, 14994, 14996, 15000, 15003, 15006,
-  15007, 15014, 15020, 15022, 15023, 15036, 15054, 15055, 15062, 15078,
-  15084, 15085, 15086, 15100, 15160, 15214, 15221, 15232, 15234, 15283,
-  15285, 15287, 15304, 15305, 15307, 15309, 15327, 15330, 15335, 15336,
-  15337, 15339, 15342, 15346, 15359, 15361, 15366, 15380, 15381, 15394,
-  15395, 15405, 15406, 15409, 15416, 15418, 15419, 15423, 15424, 15426,
-  15429, 15431, 15432, 15441, 15442, 15448, 15465, 15480, 15485, 15488,
-  15490, 15492, 15493, 15497, 15506, 15529, 15536, 15553, 15577, 15583,
-  15618, 15627, 15631, 15654, 15655, 15666, 15667, 15674, 15711, 15755,
-  15759.
+  14582, 14686, 14699, 14812, 14888, 14894, 14907, 14908, 14909, 14920,
+  14952, 14964, 14981, 14982, 14985, 14991, 14994, 14996, 15000, 15003,
+  15006, 15007, 15014, 15020, 15022, 15023, 15036, 15054, 15055, 15062,
+  15078, 15084, 15085, 15086, 15100, 15160, 15214, 15221, 15232, 15234,
+  15283, 15285, 15287, 15304, 15305, 15307, 15309, 15327, 15330, 15335,
+  15336, 15337, 15339, 15342, 15346, 15359, 15361, 15366, 15380, 15381,
+  15394, 15395, 15405, 15406, 15409, 15416, 15418, 15419, 15423, 15424,
+  15426, 15429, 15431, 15432, 15441, 15442, 15448, 15465, 15480, 15485,
+  15488, 15490, 15492, 15493, 15497, 15506, 15529, 15536, 15553, 15577,
+  15583, 15618, 15627, 15631, 15654, 15655, 15666, 15667, 15674, 15711,
+  15755, 15759.
 
 * CVE-2013-2207 Incorrectly granting access to another user's pseudo-terminal
   has been fixed by disabling the use of pt_chown (Bugzilla #15755).
@@ -37,6 +37,10 @@ Version 2.18
 * CVE-2013-1914 Stack overflow in getaddrinfo with many results has been
   fixed (Bugzilla #15330).
 
+* CVE-2013-4237 The readdir_r function could write more than NAME_MAX bytes
+  to the d_name member of struct dirent, or omit the terminating NUL
+  character.  (Bugzilla #14699).
+
 * Add support for calling C++11 thread_local object destructors on thread
   and program exit.  This needs compiler support for offloading C++11
   destructor calls to glibc.
diff --git a/manual/conf.texi b/manual/conf.texi
index 7eb8b36..c720063 100644
--- a/manual/conf.texi
+++ b/manual/conf.texi
@@ -1149,6 +1149,9 @@ typed ahead as input.  @xref{I/O Queues}.
 @deftypevr Macro int NAME_MAX
 The uniform system limit (if any) for the length of a file name component, not
 including the terminating null character.
+
+@strong{Portability Note:} On some systems, @theglibc{} defines
+@code{NAME_MAX}, but does not actually enforce this limit.
 @end deftypevr
 
 @comment limits.h
@@ -1157,6 +1160,9 @@ including the terminating null character.
 The uniform system limit (if any) for the length of an entire file name (that
 is, the argument given to system calls such as @code{open}), including the
 terminating null character.
+
+@strong{Portability Note:} @Theglibc{} does not enforce this limit
+even if @code{PATH_MAX} is defined.
 @end deftypevr
 
 @cindex limits, pipe buffer size
@@ -1476,6 +1482,9 @@ Inquire about the value of @code{POSIX_REC_MIN_XFER_SIZE}.
 Inquire about the value of @code{POSIX_REC_XFER_ALIGN}.
 @end table
 
+@strong{Portability Note:} On some systems, @theglibc{} does not
+enforce @code{_PC_NAME_MAX} or @code{_PC_PATH_MAX} limits.
+
 @node Utility Limits
 @section Utility Program Capacity Limits
 
diff --git a/manual/filesys.texi b/manual/filesys.texi
index 1df9cf2..814c210 100644
--- a/manual/filesys.texi
+++ b/manual/filesys.texi
@@ -444,9 +444,9 @@ symbols are declared in the header file @file{dirent.h}.
 @comment POSIX.1
 @deftypefun {struct dirent *} readdir (DIR *@var{dirstream})
 This function reads the next entry from the directory.  It normally
-returns a pointer to a structure containing information about the file.
-This structure is statically allocated and can be rewritten by a
-subsequent call.
+returns a pointer to a structure containing information about the
+file.  This structure is associated with the @var{dirstream} handle
+and can be rewritten by a subsequent call.
 
 @strong{Portability Note:} On some systems @code{readdir} may not
 return entries for @file{.} and @file{..}, even though these are always
@@ -461,19 +461,61 @@ conditions are defined for this function:
 The @var{dirstream} argument is not valid.
 @end table
 
-@code{readdir} is not thread safe.  Multiple threads using
-@code{readdir} on the same @var{dirstream} may overwrite the return
-value.  Use @code{readdir_r} when this is critical.
+To distinguish between an end-of-directory condition or an error, you
+must set @code{errno} to zero before calling @code{readdir}.  To avoid
+entering an infinite loop, you should stop reading from the directory
+after the first error.
+
+In POSIX.1-2008, @code{readdir} is not thread-safe.  In @theglibc{}
+implementation, it is safe to call @code{readdir} concurrently on
+different @var{dirstream}s, but multiple threads accessing the same
+@var{dirstream} result in undefined behavior.  @code{readdir_r} is a
+fully thread-safe alternative, but suffers from poor portability (see
+below).  It is recommended that you use @code{readdir}, with external
+locking if multiple threads access the same @var{dirstream}.
 @end deftypefun
 
 @comment dirent.h
 @comment GNU
 @deftypefun int readdir_r (DIR *@var{dirstream}, struct dirent *@var{entry}, struct dirent **@var{result})
-This function is the reentrant version of @code{readdir}.  Like
-@code{readdir} it returns the next entry from the directory.  But to
-prevent conflicts between simultaneously running threads the result is
-not stored in statically allocated memory.  Instead the argument
-@var{entry} points to a place to store the result.
+This function is a version of @code{readdir} which performs internal
+locking.  Like @code{readdir} it returns the next entry from the
+directory.  To prevent conflicts between simultaneously running
+threads the result is stored inside the @var{entry} object.
+
+@strong{Portability Note:} It is recommended to use @code{readdir}
+instead of @code{readdir_r} for the following reasons:
+
+@itemize @bullet
+@item
+On systems which do not define @code{NAME_MAX}, it may not be possible
+to use @code{readdir_r} safely because the caller does not specify the
+length of the buffer for the directory entry.
+
+@item
+On some systems, @code{readdir_r} cannot read directory entries with
+very long names.  If such a name is encountered, @theglibc{}
+implementation of @code{readdir_r} returns with an error code of
+@code{ENAMETOOLONG} after the final directory entry has been read.  On
+other systems, @code{readdir_r} may return successfully, but the
+@code{d_name} member may not be NUL-terminated or may be truncated.
+
+@item
+POSIX-1.2008 does not guarantee that @code{readdir} is thread-safe,
+even when access to the same @var{dirstream} is serialized.  But in
+current implementations (including @theglibc{}), it is safe to call
+@code{readdir} concurrently on different @var{dirstream}s, so there is
+no need to use @code{readdir_r} in most multi-threaded programs.  In
+the rare case that multiple threads need to read from the same
+@var{dirstream}, it is still better to use @code{readdir} and external
+synchronization.
+
+@item
+It is expected that future versions of POSIX will obsolete
+@code{readdir_r} and mandate the level of thread safety for
+@code{readdir} which is provided by @theglibc{} and other
+implementations today.
+@end itemize
 
 Normally @code{readdir_r} returns zero and sets @code{*@var{result}}
 to @var{entry}.  If there are no more entries in the directory or an
@@ -481,15 +523,6 @@ error is detected, @code{readdir_r} sets @code{*@var{result}} to a
 null pointer and returns a nonzero error code, also stored in
 @code{errno}, as described for @code{readdir}.
 
-@strong{Portability Note:} On some systems @code{readdir_r} may not
-return a NUL terminated string for the file name, even when there is no
-@code{d_reclen} field in @code{struct dirent} and the file
-name is the maximum allowed size.  Modern systems all have the
-@code{d_reclen} field, and on old systems multi-threading is not
-critical.  In any case there is no such problem with the @code{readdir}
-function, so that even on systems without the @code{d_reclen} member one
-could use multiple threads by using external locking.
-
 It is also important to look at the definition of the @code{struct
 dirent} type.  Simply passing a pointer to an object of this type for
 the second parameter of @code{readdir_r} might not be enough.  Some
diff --git a/sysdeps/posix/dirstream.h b/sysdeps/posix/dirstream.h
index a7a074d..8e8570d 100644
--- a/sysdeps/posix/dirstream.h
+++ b/sysdeps/posix/dirstream.h
@@ -39,6 +39,8 @@ struct __dirstream
 
     off_t filepos;		/* Position of next entry to read.  */
 
+    int errcode;		/* Delayed error code.  */
+
     /* Directory block.  */
     char data[0] __attribute__ ((aligned (__alignof__ (void*))));
   };
diff --git a/sysdeps/posix/opendir.c b/sysdeps/posix/opendir.c
index ddfc3a7..fc05b0f 100644
--- a/sysdeps/posix/opendir.c
+++ b/sysdeps/posix/opendir.c
@@ -231,6 +231,7 @@ __alloc_dir (int fd, bool close_fd, int flags, const struct stat64 *statp)
   dirp->size = 0;
   dirp->offset = 0;
   dirp->filepos = 0;
+  dirp->errcode = 0;
 
   return dirp;
 }
diff --git a/sysdeps/posix/readdir_r.c b/sysdeps/posix/readdir_r.c
index b5a8e2e..8ed5c3f 100644
--- a/sysdeps/posix/readdir_r.c
+++ b/sysdeps/posix/readdir_r.c
@@ -40,6 +40,7 @@ __READDIR_R (DIR *dirp, DIRENT_TYPE *entry, DIRENT_TYPE **result)
   DIRENT_TYPE *dp;
   size_t reclen;
   const int saved_errno = errno;
+  int ret;
 
   __libc_lock_lock (dirp->lock);
 
@@ -70,10 +71,10 @@ __READDIR_R (DIR *dirp, DIRENT_TYPE *entry, DIRENT_TYPE **result)
 		  bytes = 0;
 		  __set_errno (saved_errno);
 		}
+	      if (bytes < 0)
+		dirp->errcode = errno;
 
 	      dp = NULL;
-	      /* Reclen != 0 signals that an error occurred.  */
-	      reclen = bytes != 0;
 	      break;
 	    }
 	  dirp->size = (size_t) bytes;
@@ -106,29 +107,46 @@ __READDIR_R (DIR *dirp, DIRENT_TYPE *entry, DIRENT_TYPE **result)
       dirp->filepos += reclen;
 #endif
 
-      /* Skip deleted files.  */
+#ifdef NAME_MAX
+      if (reclen > offsetof (DIRENT_TYPE, d_name) + NAME_MAX + 1)
+	{
+	  /* The record is very long.  It could still fit into the
+	     caller-supplied buffer if we can skip padding at the
+	     end.  */
+	  size_t namelen = _D_EXACT_NAMLEN (dp);
+	  if (namelen <= NAME_MAX)
+	    reclen = offsetof (DIRENT_TYPE, d_name) + namelen + 1;
+	  else
+	    {
+	      /* The name is too long.  Ignore this file.  */
+	      dirp->errcode = ENAMETOOLONG;
+	      dp->d_ino = 0;
+	      continue;
+	    }
+	}
+#endif
+
+      /* Skip deleted and ignored files.  */
     }
   while (dp->d_ino == 0);
 
   if (dp != NULL)
     {
-#ifdef GETDENTS_64BIT_ALIGNED
-      /* The d_reclen value might include padding which is not part of
-	 the DIRENT_TYPE data structure.  */
-      reclen = MIN (reclen,
-		    offsetof (DIRENT_TYPE, d_name) + sizeof (dp->d_name));
-#endif
       *result = memcpy (entry, dp, reclen);
-#ifdef GETDENTS_64BIT_ALIGNED
+#ifdef _DIRENT_HAVE_D_RECLEN
       entry->d_reclen = reclen;
 #endif
+      ret = 0;
     }
   else
-    *result = NULL;
+    {
+      *result = NULL;
+      ret = dirp->errcode;
+    }
 
   __libc_lock_unlock (dirp->lock);
 
-  return dp != NULL ? 0 : reclen ? errno : 0;
+  return ret;
 }
 
 #ifdef __READDIR_R_ALIAS
diff --git a/sysdeps/posix/rewinddir.c b/sysdeps/posix/rewinddir.c
index 2935a8e..d4991ad 100644
--- a/sysdeps/posix/rewinddir.c
+++ b/sysdeps/posix/rewinddir.c
@@ -33,6 +33,7 @@ rewinddir (dirp)
   dirp->filepos = 0;
   dirp->offset = 0;
   dirp->size = 0;
+  dirp->errcode = 0;
 #ifndef NOT_IN_libc
   __libc_lock_unlock (dirp->lock);
 #endif
diff --git a/sysdeps/unix/sysv/linux/i386/readdir64_r.c b/sysdeps/unix/sysv/linux/i386/readdir64_r.c
index 8ebbcfd..a7d114e 100644
--- a/sysdeps/unix/sysv/linux/i386/readdir64_r.c
+++ b/sysdeps/unix/sysv/linux/i386/readdir64_r.c
@@ -18,7 +18,6 @@
 #define __READDIR_R __readdir64_r
 #define __GETDENTS __getdents64
 #define DIRENT_TYPE struct dirent64
-#define GETDENTS_64BIT_ALIGNED 1
 
 #include <sysdeps/posix/readdir_r.c>
 
diff --git a/sysdeps/unix/sysv/linux/wordsize-64/readdir_r.c b/sysdeps/unix/sysv/linux/wordsize-64/readdir_r.c
index 5ed8e95..290f2c8 100644
--- a/sysdeps/unix/sysv/linux/wordsize-64/readdir_r.c
+++ b/sysdeps/unix/sysv/linux/wordsize-64/readdir_r.c
@@ -1,5 +1,4 @@
 #define readdir64_r __no_readdir64_r_decl
-#define GETDENTS_64BIT_ALIGNED 1
 #include <sysdeps/posix/readdir_r.c>
 #undef readdir64_r
 weak_alias (__readdir_r, readdir64_r)

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=760b348db29b446efc760b4bc3627379cc61b0d8

commit 760b348db29b446efc760b4bc3627379cc61b0d8
Merge: 84dd394 eefa3be
Author: Tulio Magno Quites Machado Filho <tuliom@linux.vnet.ibm.com>
Date:   Tue Aug 20 15:26:27 2013 -0300

    Merge branch 'release/2.18/master' into ibm/2.18/master


http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=84dd3946e0e0aee66635ba4373943d113fd25ca1

commit 84dd3946e0e0aee66635ba4373943d113fd25ca1
Author: Adhemerval Zanella <azanella@linux.vnet.ibm.com>
Date:   Thu Jul 25 10:53:11 2013 -0300

    PowerPC: use libgcc _Unwind functions to get backtrace
    
    This patch changes the way backtraces are obtained on PowerPC by
    relaying on libgcc _Unwind function instead of just backchain parse.
    It fixes debug/tst-backtrace5 for PPC32 and PPC64.

diff --git a/ChangeLog b/ChangeLog
index 8d937a9..3ef8981 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,19 @@
+2013-07-23  Adhemerval Zanella  <azanella@linux.vnet.ibm.com>
+
+	* sysdeps/powerpc/powerpc32/backtrace.c (__backtrace): Handle signal
+	trampoline stack frame information.
+	* sysdeps/powerpc/powerpc64/backtrace.c (__backtrace): Likewise.
+	* sysdeps/unix/sysv/linux/powerpc/bits/libc-vdso.h
+	(__vdso_sigtramp_rt64): New variable: PPC64 signal trampoline.
+	(__vdso_sigtramp32): New variable: PPC32 signal trampoline.
+	(__vdso_sigtramp_rt32): New variable: PPC32 signal trampoline.
+	* sysdeps/unix/sysv/linux/powerpc/init-first.c
+	(_libc_vdso_platform_setup): Initialize the signal trampolines.
+	* debug/tst-backtrace5.c (fn): Add an option set modify sigaction
+	sa_flags value.
+	* debug/tst-backtrace6.c: New file: check backtrace for signal frames,
+	interrupting a syscall and set with option SA_SIGINFO.
+
 2013-08-03  David S. Miller  <davem@davemloft.net>
 
 	* po/ko.po: Update Korean translation from translation project.
diff --git a/debug/Makefile b/debug/Makefile
index 779741f..13ee5c8 100644
--- a/debug/Makefile
+++ b/debug/Makefile
@@ -130,16 +130,18 @@ CFLAGS-tst-backtrace2.c += -funwind-tables
 CFLAGS-tst-backtrace3.c += -funwind-tables
 CFLAGS-tst-backtrace4.c += -funwind-tables
 CFLAGS-tst-backtrace5.c += -funwind-tables
+CFLAGS-tst-backtrace6.c += -funwind-tables
 LDFLAGS-tst-backtrace2 = -rdynamic
 LDFLAGS-tst-backtrace3 = -rdynamic
 LDFLAGS-tst-backtrace4 = -rdynamic
 LDFLAGS-tst-backtrace5 = -rdynamic
+LDFLAGS-tst-backtrace6 = -rdynamic
 
 tests = backtrace-tst tst-longjmp_chk tst-chk1 tst-chk2 tst-chk3 \
 	tst-lfschk1 tst-lfschk2 tst-lfschk3 test-strcpy_chk test-stpcpy_chk \
 	tst-chk4 tst-chk5 tst-chk6 tst-lfschk4 tst-lfschk5 tst-lfschk6 \
 	tst-longjmp_chk2 tst-backtrace2 tst-backtrace3 tst-backtrace4 \
-	tst-backtrace5
+	tst-backtrace5 tst-backtrace6
 
 tests-ifunc := $(stpcpy_chk strcpy_chk:%=test-%-ifunc)
 tests += $(tests-ifunc)
diff --git a/debug/tst-backtrace5.c b/debug/tst-backtrace5.c
index ca47437..51180c1 100644
--- a/debug/tst-backtrace5.c
+++ b/debug/tst-backtrace5.c
@@ -28,6 +28,10 @@
 
 #include "tst-backtrace.h"
 
+#ifndef SIGACTION_FLAGS
+# define SIGACTION_FLAGS 0
+#endif
+
 static int do_test (void);
 #define TEST_FUNCTION do_test ()
 #include "../test-skeleton.c"
@@ -91,7 +95,7 @@ handle_signal (int signum)
 }
 
 NO_INLINE int
-fn (int c)
+fn (int c, int flags)
 {
   pid_t parent_pid, child_pid;
   int pipefd[2];
@@ -100,12 +104,13 @@ fn (int c)
 
   if (c > 0)
     {
-      fn (c - 1);
+      fn (c - 1, flags);
       return x;
     }
 
   memset (&act, 0, sizeof (act));
   act.sa_handler = handle_signal;
+  act.sa_flags = flags;
   sigemptyset (&act.sa_mask);
   sigaction (SIGUSR1, &act, NULL);
   parent_pid = getpid ();
@@ -131,6 +136,6 @@ fn (int c)
 NO_INLINE static int
 do_test (void)
 {
-  fn (2);
+  fn (2, SIGACTION_FLAGS);
   return ret;
 }
diff --git a/debug/tst-backtrace6.c b/debug/tst-backtrace6.c
new file mode 100644
index 0000000..cd8dbcd
--- /dev/null
+++ b/debug/tst-backtrace6.c
@@ -0,0 +1,21 @@
+/* Test backtrace and backtrace_symbols for signal frames, where a
+   system call was interrupted by a signal.
+   Copyright (C) 2013 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/>.  */
+
+#define SIGACTION_FLAGS SA_SIGINFO
+#include <debug/tst-backtrace5.c>
diff --git a/sysdeps/powerpc/powerpc32/backtrace.c b/sysdeps/powerpc/powerpc32/backtrace.c
index b4b11dd..8d413e6 100644
--- a/sysdeps/powerpc/powerpc32/backtrace.c
+++ b/sysdeps/powerpc/powerpc32/backtrace.c
@@ -18,6 +18,9 @@
 
 #include <execinfo.h>
 #include <stddef.h>
+#include <string.h>
+#include <signal.h>
+#include <bits/libc-vdso.h>
 
 /* This is the stack layout we see with every stack frame.
    Note that every routine is required by the ABI to lay out the stack
@@ -35,6 +38,46 @@ struct layout
   void *return_address;
 };
 
+#define SIGNAL_FRAMESIZE 64
+
+/* Since the signal handler is just like any other function it needs to
+   save/restore its LR and it will save it into callers stack frame.
+   Since a signal handler doesn't have a caller, the kernel creates a
+   dummy frame to make it look like it has a caller.  */
+struct signal_frame_32 {
+  char               dummy[SIGNAL_FRAMESIZE];
+  struct sigcontext  sctx;
+  mcontext_t         mctx;
+  /* We don't care about the rest, since IP value is at 'mctx' field.  */
+};
+
+static inline int
+is_sigtramp_address (unsigned int nip)
+{
+#ifdef SHARED
+  if (nip == (unsigned int)__vdso_sigtramp32)
+    return 1;
+#endif
+  return 0;
+}
+
+struct rt_signal_frame_32 {
+  char               dummy[SIGNAL_FRAMESIZE + 16];
+  siginfo_t          info;
+  struct ucontext    uc;
+  /* We don't care about the rest, since IP value is at 'uc' field.  */
+};
+
+static inline int
+is_sigtramp_address_rt (unsigned int nip)
+{
+#ifdef SHARED
+  if (nip == (unsigned int)__vdso_sigtramp_rt32)
+    return 1;
+#endif
+  return 0;
+}
+
 int
 __backtrace (void **array, int size)
 {
@@ -50,7 +93,28 @@ __backtrace (void **array, int size)
   for (				count = 0;
        current != NULL && 	count < size;
        current = current->next, count++)
-    array[count] = current->return_address;
+    {
+      gregset_t *gregset = NULL;
+
+      array[count] = current->return_address;
+
+      /* Check if the symbol is the signal trampoline and get the interrupted
+       * symbol address from the trampoline saved area.  */
+      if (is_sigtramp_address ((unsigned int)current->return_address))
+	{
+	  struct signal_frame_32 *sigframe =
+	    (struct signal_frame_32*) current;
+          gregset = &sigframe->mctx.gregs;
+        }
+      else if (is_sigtramp_address_rt ((unsigned int)current->return_address))
+	{
+	  struct rt_signal_frame_32 *sigframe =
+            (struct rt_signal_frame_32*) current;
+          gregset = &sigframe->uc.uc_mcontext.uc_regs->gregs;
+        }
+      if (gregset)
+	array[++count] = (void*)((*gregset)[PT_NIP]);
+    }
 
   /* It's possible the second-last stack frame can't return
      (that is, it's __libc_start_main), in which case
diff --git a/sysdeps/powerpc/powerpc64/backtrace.c b/sysdeps/powerpc/powerpc64/backtrace.c
index 2d3e051..9b9a9f1 100644
--- a/sysdeps/powerpc/powerpc64/backtrace.c
+++ b/sysdeps/powerpc/powerpc64/backtrace.c
@@ -18,6 +18,9 @@
 
 #include <execinfo.h>
 #include <stddef.h>
+#include <string.h>
+#include <signal.h>
+#include <bits/libc-vdso.h>
 
 /* This is the stack layout we see with every stack frame.
    Note that every routine is required by the ABI to lay out the stack
@@ -38,6 +41,27 @@ struct layout
   void *return_address;
 };
 
+/* Since the signal handler is just like any other function it needs to
+   save/restore its LR and it will save it into callers stack frame.
+   Since a signal handler doesn't have a caller, the kernel creates a
+   dummy frame to make it look like it has a caller.  */
+struct signal_frame_64 {
+#define SIGNAL_FRAMESIZE 128
+  char            dummy[SIGNAL_FRAMESIZE];
+  struct ucontext uc;
+  /* We don't care about the rest, since the IP value is at 'uc' field.  */
+};
+
+static inline int
+is_sigtramp_address (unsigned long nip)
+{
+#ifdef SHARED
+  if (nip == (unsigned long)__vdso_sigtramp_rt64)
+    return 1;
+#endif
+  return 0;
+}
+
 int
 __backtrace (void **array, int size)
 {
@@ -53,7 +77,17 @@ __backtrace (void **array, int size)
   for (				count = 0;
        current != NULL && 	count < size;
        current = current->next, count++)
-    array[count] = current->return_address;
+    {
+      array[count] = current->return_address;
+
+      /* Check if the symbol is the signal trampoline and get the interrupted
+       * symbol address from the trampoline saved area.  */
+      if (is_sigtramp_address ((unsigned long)current->return_address))
+        {
+	  struct signal_frame_64 *sigframe = (struct signal_frame_64*) current;
+          array[++count] = (void*)sigframe->uc.uc_mcontext.gp_regs[PT_NIP];
+	}
+    }
 
   /* It's possible the second-last stack frame can't return
      (that is, it's __libc_start_main), in which case
diff --git a/sysdeps/unix/sysv/linux/powerpc/bits/libc-vdso.h b/sysdeps/unix/sysv/linux/powerpc/bits/libc-vdso.h
index 8b195db..ba54de4 100644
--- a/sysdeps/unix/sysv/linux/powerpc/bits/libc-vdso.h
+++ b/sysdeps/unix/sysv/linux/powerpc/bits/libc-vdso.h
@@ -34,6 +34,13 @@ extern void *__vdso_getcpu;
 
 extern void *__vdso_time;
 
+#if defined(__PPC64__) || defined(__powerpc64__)
+extern void *__vdso_sigtramp_rt64;
+#else
+extern void *__vdso_sigtramp32;
+extern void *__vdso_sigtramp_rt32;
+#endif
+
 /* This macro is needed for PPC64 to return a skeleton OPD entry of a vDSO
    symbol.  This works because _dl_vdso_vsym always return the function
    address, and no vDSO symbols use the TOC or chain pointers from the OPD
diff --git a/sysdeps/unix/sysv/linux/powerpc/init-first.c b/sysdeps/unix/sysv/linux/powerpc/init-first.c
index f6f05f0..061715f 100644
--- a/sysdeps/unix/sysv/linux/powerpc/init-first.c
+++ b/sysdeps/unix/sysv/linux/powerpc/init-first.c
@@ -29,6 +29,12 @@ void *__vdso_clock_getres;
 void *__vdso_get_tbfreq;
 void *__vdso_getcpu;
 void *__vdso_time;
+#if defined(__PPC64__) || defined(__powerpc64__)
+void *__vdso_sigtramp_rt64;
+#else
+void *__vdso_sigtramp32;
+void *__vdso_sigtramp_rt32;
+#endif
 
 static inline void
 _libc_vdso_platform_setup (void)
@@ -46,6 +52,16 @@ _libc_vdso_platform_setup (void)
   __vdso_getcpu = _dl_vdso_vsym ("__kernel_getcpu", &linux2615);
 
   __vdso_time = _dl_vdso_vsym ("__kernel_time", &linux2615);
+
+  /* PPC64 uses only one signal trampoline symbol, while PPC32 will use
+     two depending if SA_SIGINFO is used (__kernel_sigtramp_rt32) or not
+     (__kernel_sigtramp32).  */
+#if defined(__PPC64__) || defined(__powerpc64__)
+  __vdso_sigtramp_rt64 = _dl_vdso_vsym ("__kernel_sigtramp_rt64", &linux2615);
+#else
+  __vdso_sigtramp32 = _dl_vdso_vsym ("__kernel_sigtramp32", &linux2615);
+  __vdso_sigtramp_rt32 = _dl_vdso_vsym ("__kernel_sigtramp_rt32", &linux2615);
+#endif
 }
 
 # define VDSO_SETUP _libc_vdso_platform_setup

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=733a36d81544dad38726489b43523cc0ac95095d

commit 733a36d81544dad38726489b43523cc0ac95095d
Merge: 2d16beb 85891ac
Author: Tulio Magno Quites Machado Filho <tuliom@linux.vnet.ibm.com>
Date:   Tue Aug 6 14:13:45 2013 -0300

    Merge branch 'master' into ibm/2.18/master

diff --cc ChangeLog
index cbb6a56,fa588c9..8d937a9
--- a/ChangeLog
+++ b/ChangeLog
@@@ -1,11 -1,13 +1,21 @@@
+ 2013-08-03  David S. Miller  <davem@davemloft.net>
+ 
+ 	* po/ko.po: Update Korean translation from translation project.
+ 
+ 2013-08-01  David S. Miller  <davem@davemloft.net>
+ 
+ 	* manual/contrib.texi: Update entry for Siddhesh Poyarekar.  Add
+ 	entries for Will Newton, Andi Kleen, David Holsgrove, and Ondrej
+ 	Bilka.
+ 
 +2012-07-06  Ryan S. Arnold  <rsa@linux.vnet.ibm.com>
 +
 +	* elf/get-dynamic-info.h (elf_get_dynamic_info): Remove assert()
 +	around DT_RUNPATH and DT_RPATH which prevents running a dynamic
 +	linker with an embedded RPATH flag, which is what a compiler
 +	modified to embed a non-default INTERP section would do.
 +
 +
  2013-07-30  David S. Miller  <davem@davemloft.net>
  
  	* po/fr.po: Update French translation from translation project.

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=2d16bebbeabd3ab312998c969e21d092ff348485

commit 2d16bebbeabd3ab312998c969e21d092ff348485
Author: Ryan S. Arnold <rsa@linux.vnet.ibm.com>
Date:   Thu Aug 1 13:11:18 2013 -0300

    Remove assert() if DT_RUNPATH and DT_RPATH flags are found in ld.so.

diff --git a/ChangeLog b/ChangeLog
index 6aecb1b..cbb6a56 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+2012-07-06  Ryan S. Arnold  <rsa@linux.vnet.ibm.com>
+
+	* elf/get-dynamic-info.h (elf_get_dynamic_info): Remove assert()
+	around DT_RUNPATH and DT_RPATH which prevents running a dynamic
+	linker with an embedded RPATH flag, which is what a compiler
+	modified to embed a non-default INTERP section would do.
+
+
 2013-07-30  David S. Miller  <davem@davemloft.net>
 
 	* po/fr.po: Update French translation from translation project.
diff --git a/elf/get-dynamic-info.h b/elf/get-dynamic-info.h
index 3cc1073..57cf964 100644
--- a/elf/get-dynamic-info.h
+++ b/elf/get-dynamic-info.h
@@ -130,8 +130,8 @@ elf_get_dynamic_info (struct link_map *l, ElfW(Dyn) *temp)
   assert (info[DT_FLAGS] == NULL
 	  || (info[DT_FLAGS]->d_un.d_val & ~DF_BIND_NOW) == 0);
   /* Flags must not be set for ld.so.  */
-  assert (info[DT_RUNPATH] == NULL);
-  assert (info[DT_RPATH] == NULL);
+  info[DT_RUNPATH] = NULL;
+  info[DT_RPATH] = NULL;
 #else
   if (info[DT_FLAGS] != NULL)
     {

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=975208ca8a02f332572edde22d3e4da6c100bdbc

commit 975208ca8a02f332572edde22d3e4da6c100bdbc
Author: Tulio Magno Quites Machado Filho <tuliom@linux.vnet.ibm.com>
Date:   Thu Aug 1 12:54:00 2013 -0300

    Partially revert commit 2663b74f8103a2a8a46b4896439b7a452480fc7c
    
    This change is necessary in order to avoid the issue documented at
    http://sourceware.org/ml/libc-alpha/2013-05/msg00350.html.

diff --git a/localedata/locales/bo_CN b/localedata/locales/bo_CN
index aa8ff07..cd61856 100644
--- a/localedata/locales/bo_CN
+++ b/localedata/locales/bo_CN
@@ -144,8 +144,7 @@ END LC_MEASUREMENT
 
 LC_NAME
 % FIXME
-
-name_fmt  ""
+name_fmt	"FIXME"
 % name_gen	"FIXME"
 % name_miss	"FIXME"
 % name_mr	"FIXME"
diff --git a/localedata/locales/bo_IN b/localedata/locales/bo_IN
index 9e9c4ff..c90db17 100644
--- a/localedata/locales/bo_IN
+++ b/localedata/locales/bo_IN
@@ -70,7 +70,7 @@ END LC_MEASUREMENT
 
 LC_NAME
 % FIXME
-name_fmt	""
+name_fmt	"FIXME"
 % name_gen	"FIXME"
 % name_miss	"FIXME"
 % name_mr	"FIXME"

-----------------------------------------------------------------------


hooks/post-receive
-- 
GNU C Library master sources


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]