ce426f
    Backport of
ce426f
    commit 8bedcb5f03c62bf6001396dafdd82fbd4da7c2db
ce426f
    Author: Adhemerval Zanella <azanella@linux.vnet.ibm.com>
ce426f
    Date:   Wed Jan 7 07:18:30 2015 -0500
ce426f
    
ce426f
        powerpc: Optimized strcmp for POWER8/PPC64
ce426f
    
ce426f
        This patch adds an optimized POWER8 strcmp using unaligned accesses.
ce426f
        The algorithm first check the initial 16 bytes, then align the first
ce426f
        function source and uses unaligned loads on second argument only.
ce426f
        Aditional checks for page boundaries are done for unaligned cases
ce426f
    
ce426f
        ChangeLog:
ce426f
    	2015-01-13  Adhemerval Zanella  <azanella@linux.vnet.ibm.com>
ce426f
    
ce426f
     	* sysdeps/powerpc/powerpc64/multiarch/Makefile [sysdep_routines]:
ce426f
    	Add strcmp-power8 object.
ce426f
    	* sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c
ce426f
    	(__libc_ifunc_impl_list): Add __strcmp_power8 implementation.
ce426f
    	* sysdeps/powerpc/powerpc64/multiarch/strcmp-power8.S: New file.
ce426f
    	* sysdeps/powerpc/powerpc64/multiarch/strcmp.c (strcmp): Add
ce426f
    	__strcmp_power8 implementation.
ce426f
    	* sysdeps/powerpc/powerpc64/power8/strcmp.S: New file.
ce426f
    	* NEWS: Update.
ce426f
    
ce426f
    and its dependency:
ce426f
    commit e23d3d2690bf63207b1a47e83a94693daebbbfe5
ce426f
    Author: Vidya Ranganathan <vidya@linux.vnet.ibm.com>
ce426f
    Date:   Fri Jun 6 07:56:07 2014 -0500
ce426f
    
ce426f
        PowerPC: Optimized strcmp for PPC64/POWER7
ce426f
    
ce426f
        Optimization is achieved on 8 byte aligned strings with double word
ce426f
        comparison using cmpb instruction. On unaligned strings loop unrolling
ce426f
        is applied for Power7 gain.
ce426f
    
ce426f
        ChangeLog:
ce426f
        2014-06-11  Vidya Ranganathan  <vidya@linux.vnet.ibm.com>
ce426f
    
ce426f
           * sysdeps/powerpc/powerpc64/power7/strcmp.S: New file: Optimization.
ce426f
           * sysdeps/powerpc/powerpc64/multiarch/strcmp.c: New file:
ce426f
           multiarch strcmp for PPC64.
ce426f
           * sysdeps/powerpc/powerpc64/multiarch/strcmp-ppc64.S: New file.
ce426f
           * sysdeps/powerpc/powerpc64/multiarch/strcmp-power7.S: New file.
ce426f
           * sysdeps/powerpc/powerpc64/multiarch/Makefile: Add strcmp
ce426f
           multiarch optimizations.
ce426f
           * sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c:
ce426f
           (__libc_ifunc_impl_list): Likewise.
ce426f
ce426f
diff --git a/sysdeps/powerpc/powerpc64/multiarch/Makefile b/sysdeps/powerpc/powerpc64/multiarch/Makefile
ce426f
index ef39917..27c8b65 100644
ce426f
--- a/sysdeps/powerpc/powerpc64/multiarch/Makefile
ce426f
+++ b/sysdeps/powerpc/powerpc64/multiarch/Makefile
ce426f
@@ -7,9 +7,10 @@ sysdep_routines += memcpy-power7 memcpy-a2 memcpy-power6 memcpy-cell \
ce426f
                   memrchr-power7 memrchr-ppc64 rawmemchr-power7 \
ce426f
                   stpcpy-power8 stpcpy-power7 stpcpy-ppc64 \
ce426f
                   strcat-power8 strcat-power7 strcat-ppc64 \
ce426f
+                  strcmp-power8 strcmp-power7 strcmp-ppc64 \
ce426f
                   strcpy-power8 strcpy-power7 strcpy-ppc64 \
ce426f
                   stpncpy-power8 stpncpy-power7 stpncpy-ppc64 \
ce426f
-                  strncpy-power8 strncpy-power7 strncpy-ppc64 
ce426f
+                  strncpy-power8 strncpy-power7 strncpy-ppc64 \
ce426f
                   strncat-power7 \
ce426f
                   rawmemchr-ppc64 strlen-power7 strlen-ppc64 strnlen-power7 \
ce426f
                   strnlen-ppc64 strcasecmp-power7 strcasecmp_l-power7 \
ce426f
diff --git a/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c b/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c
ce426f
index 23bf5dc..2b38c71 100644
ce426f
--- a/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c
ce426f
+++ b/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c
ce426f
@@ -277,5 +277,15 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
ce426f
 	      IFUNC_IMPL_ADD (array, i, stpncpy, 1,
ce426f
 			     __stpncpy_ppc))
ce426f
 
ce426f
+  /* Support sysdeps/powerpc/powerpc64/multiarch/strcmp.c.  */
ce426f
+  IFUNC_IMPL (i, name, strcmp,
ce426f
+	      IFUNC_IMPL_ADD (array, i, strcmp,
ce426f
+			      hwcap2 & PPC_FEATURE2_ARCH_2_07,
ce426f
+			      __strcmp_power8)
ce426f
+	      IFUNC_IMPL_ADD (array, i, strcmp,
ce426f
+			      hwcap & PPC_FEATURE_HAS_VSX,
ce426f
+			      __strcmp_power7)
ce426f
+	      IFUNC_IMPL_ADD (array, i, strcmp, 1,
ce426f
+			     __strcmp_ppc))
ce426f
   return i;
ce426f
 }
ce426f
diff --git a/sysdeps/powerpc/powerpc64/multiarch/strcmp-power7.S b/sysdeps/powerpc/powerpc64/multiarch/strcmp-power7.S
ce426f
new file mode 100644
ce426f
index 0000000..790ce8d
ce426f
--- /dev/null
ce426f
+++ b/sysdeps/powerpc/powerpc64/multiarch/strcmp-power7.S
ce426f
@@ -0,0 +1,40 @@
ce426f
+/* Optimized strcmp implementation for POWER7.
ce426f
+   Copyright (C) 2014 Free Software Foundation, Inc.
ce426f
+   This file is part of the GNU C Library.
ce426f
+
ce426f
+   The GNU C Library is free software; you can redistribute it and/or
ce426f
+   modify it under the terms of the GNU Lesser General Public
ce426f
+   License as published by the Free Software Foundation; either
ce426f
+   version 2.1 of the License, or (at your option) any later version.
ce426f
+
ce426f
+   The GNU C Library is distributed in the hope that it will be useful,
ce426f
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
ce426f
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
ce426f
+   Lesser General Public License for more details.
ce426f
+
ce426f
+   You should have received a copy of the GNU Lesser General Public
ce426f
+   License along with the GNU C Library; if not, see
ce426f
+   <http://www.gnu.org/licenses/>.  */
ce426f
+
ce426f
+#include <sysdep.h>
ce426f
+
ce426f
+#undef EALIGN
ce426f
+#define EALIGN(name, alignt, words)				\
ce426f
+  .section ".text";						\
ce426f
+  ENTRY_2(__strcmp_power7)					\
ce426f
+  .align ALIGNARG(alignt);					\
ce426f
+  EALIGN_W_##words;						\
ce426f
+  BODY_LABEL(__strcmp_power7):					\
ce426f
+  cfi_startproc;						\
ce426f
+  LOCALENTRY(__strcmp_power7)
ce426f
+
ce426f
+#undef END
ce426f
+#define END(name)						\
ce426f
+  cfi_endproc;							\
ce426f
+  TRACEBACK(__strcmp_power7)					\
ce426f
+  END_2(__strcmp_power7)
ce426f
+
ce426f
+#undef libc_hidden_builtin_def
ce426f
+#define libc_hidden_builtin_def(name)
ce426f
+
ce426f
+#include <sysdeps/powerpc/powerpc64/power7/strcmp.S>
ce426f
diff --git a/sysdeps/powerpc/powerpc64/multiarch/strcmp-power8.S b/sysdeps/powerpc/powerpc64/multiarch/strcmp-power8.S
ce426f
new file mode 100644
ce426f
index 0000000..dc4bfac
ce426f
--- /dev/null
ce426f
+++ b/sysdeps/powerpc/powerpc64/multiarch/strcmp-power8.S
ce426f
@@ -0,0 +1,40 @@
ce426f
+/* Optimized strcmp implementation for POWER8/PPC64.
ce426f
+   Copyright (C) 2015 Free Software Foundation, Inc.
ce426f
+   This file is part of the GNU C Library.
ce426f
+
ce426f
+   The GNU C Library is free software; you can redistribute it and/or
ce426f
+   modify it under the terms of the GNU Lesser General Public
ce426f
+   License as published by the Free Software Foundation; either
ce426f
+   version 2.1 of the License, or (at your option) any later version.
ce426f
+
ce426f
+   The GNU C Library is distributed in the hope that it will be useful,
ce426f
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
ce426f
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
ce426f
+   Lesser General Public License for more details.
ce426f
+
ce426f
+   You should have received a copy of the GNU Lesser General Public
ce426f
+   License along with the GNU C Library; if not, see
ce426f
+   <http://www.gnu.org/licenses/>.  */
ce426f
+
ce426f
+#include <sysdep.h>
ce426f
+
ce426f
+#undef EALIGN
ce426f
+#define EALIGN(name, alignt, words)				\
ce426f
+  .section ".text";						\
ce426f
+  ENTRY_2(__strcmp_power8)					\
ce426f
+  .align ALIGNARG(alignt);					\
ce426f
+  EALIGN_W_##words;						\
ce426f
+  BODY_LABEL(__strcmp_power8):					\
ce426f
+  cfi_startproc;						\
ce426f
+  LOCALENTRY(__strcmp_power8)
ce426f
+
ce426f
+#undef END
ce426f
+#define END(name)						\
ce426f
+  cfi_endproc;							\
ce426f
+  TRACEBACK(__strcmp_power8)					\
ce426f
+  END_2(__strcmp_power8)
ce426f
+
ce426f
+#undef libc_hidden_builtin_def
ce426f
+#define libc_hidden_builtin_def(name)
ce426f
+
ce426f
+#include <sysdeps/powerpc/powerpc64/power8/strcmp.S>
ce426f
diff --git a/sysdeps/powerpc/powerpc64/multiarch/strcmp-ppc64.S b/sysdeps/powerpc/powerpc64/multiarch/strcmp-ppc64.S
ce426f
new file mode 100644
ce426f
index 0000000..93d1277
ce426f
--- /dev/null
ce426f
+++ b/sysdeps/powerpc/powerpc64/multiarch/strcmp-ppc64.S
ce426f
@@ -0,0 +1,43 @@
ce426f
+/* Default strcmp implementation for PowerPC64.
ce426f
+   Copyright (C) 2014 Free Software Foundation, Inc.
ce426f
+   This file is part of the GNU C Library.
ce426f
+
ce426f
+   The GNU C Library is free software; you can redistribute it and/or
ce426f
+   modify it under the terms of the GNU Lesser General Public
ce426f
+   License as published by the Free Software Foundation; either
ce426f
+   version 2.1 of the License, or (at your option) any later version.
ce426f
+
ce426f
+   The GNU C Library is distributed in the hope that it will be useful,
ce426f
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
ce426f
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
ce426f
+   Lesser General Public License for more details.
ce426f
+
ce426f
+   You should have received a copy of the GNU Lesser General Public
ce426f
+   License along with the GNU C Library; if not, see
ce426f
+   <http://www.gnu.org/licenses/>.  */
ce426f
+
ce426f
+#include <sysdep.h>
ce426f
+
ce426f
+#if defined SHARED && !defined NOT_IN_libc
ce426f
+# undef EALIGN
ce426f
+# define EALIGN(name, alignt, words)				\
ce426f
+  .section ".text";						\
ce426f
+  ENTRY_2(__strcmp_ppc)						\
ce426f
+  .align ALIGNARG(alignt);					\
ce426f
+  EALIGN_W_##words;						\
ce426f
+  BODY_LABEL(__strcmp_ppc):					\
ce426f
+  cfi_startproc;						\
ce426f
+  LOCALENTRY(__strcmp_ppc)
ce426f
+
ce426f
+# undef END
ce426f
+# define END(name)						\
ce426f
+  cfi_endproc;							\
ce426f
+  TRACEBACK(__strcmp_ppc)					\
ce426f
+  END_2(__strcmp_ppc)
ce426f
+
ce426f
+# undef libc_hidden_builtin_def
ce426f
+# define libc_hidden_builtin_def(name)				\
ce426f
+    .globl __GI_strcmp; __GI_strcmp = __strcmp_ppc
ce426f
+#endif
ce426f
+
ce426f
+#include <sysdeps/powerpc/powerpc64/strcmp.S>
ce426f
diff --git a/sysdeps/powerpc/powerpc64/multiarch/strcmp.c b/sysdeps/powerpc/powerpc64/multiarch/strcmp.c
ce426f
new file mode 100644
ce426f
index 0000000..c711969
ce426f
--- /dev/null
ce426f
+++ b/sysdeps/powerpc/powerpc64/multiarch/strcmp.c
ce426f
@@ -0,0 +1,34 @@
ce426f
+/* Multiple versions of strcmp. PowerPC64 version.
ce426f
+   Copyright (C) 2014 Free Software Foundation, Inc.
ce426f
+   This file is part of the GNU C Library.
ce426f
+
ce426f
+   The GNU C Library is free software; you can redistribute it and/or
ce426f
+   modify it under the terms of the GNU Lesser General Public
ce426f
+   License as published by the Free Software Foundation; either
ce426f
+   version 2.1 of the License, or (at your option) any later version.
ce426f
+
ce426f
+   The GNU C Library is distributed in the hope that it will be useful,
ce426f
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
ce426f
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
ce426f
+   Lesser General Public License for more details.
ce426f
+
ce426f
+   You should have received a copy of the GNU Lesser General Public
ce426f
+   License along with the GNU C Library; if not, see
ce426f
+   <http://www.gnu.org/licenses/>.  */
ce426f
+
ce426f
+#if defined SHARED && !defined NOT_IN_libc
ce426f
+# include <string.h>
ce426f
+# include <shlib-compat.h>
ce426f
+# include "init-arch.h"
ce426f
+
ce426f
+extern __typeof (strcmp) __strcmp_ppc attribute_hidden;
ce426f
+extern __typeof (strcmp) __strcmp_power7 attribute_hidden;
ce426f
+extern __typeof (strcmp) __strcmp_power8 attribute_hidden;
ce426f
+
ce426f
+libc_ifunc (strcmp,
ce426f
+            (hwcap2 & PPC_FEATURE2_ARCH_2_07)
ce426f
+              ? __strcmp_power8 :
ce426f
+              (hwcap & PPC_FEATURE_HAS_VSX)
ce426f
+              ? __strcmp_power7
ce426f
+            : __strcmp_ppc);
ce426f
+#endif
ce426f
diff --git a/sysdeps/powerpc/powerpc64/power7/strcmp.S b/sysdeps/powerpc/powerpc64/power7/strcmp.S
ce426f
new file mode 100644
ce426f
index 0000000..f16a9d8
ce426f
--- /dev/null
ce426f
+++ b/sysdeps/powerpc/powerpc64/power7/strcmp.S
ce426f
@@ -0,0 +1,195 @@
ce426f
+/* Optimized strcmp implementation for Power7 using 'cmpb' instruction
ce426f
+   Copyright (C) 2014 Free Software Foundation, Inc.
ce426f
+   This file is part of the GNU C Library.
ce426f
+
ce426f
+   The GNU C Library is free software; you can redistribute it and/or
ce426f
+   modify it under the terms of the GNU Lesser General Public
ce426f
+   License as published by the Free Software Foundation; either
ce426f
+   version 2.1 of the License, or (at your option) any later version.
ce426f
+
ce426f
+   The GNU C Library is distributed in the hope that it will be useful,
ce426f
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
ce426f
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
ce426f
+   Lesser General Public License for more details.
ce426f
+
ce426f
+   You should have received a copy of the GNU Lesser General Public
ce426f
+   License along with the GNU C Library; if not, see
ce426f
+   <http://www.gnu.org/licenses/>.  */
ce426f
+
ce426f
+/* The optimization is achieved here through cmpb instruction.
ce426f
+   8byte aligned strings are processed with double word comparision
ce426f
+   and unaligned strings are handled effectively with loop unrolling
ce426f
+   technique  */
ce426f
+
ce426f
+#include <sysdep.h>
ce426f
+
ce426f
+/* int [r3] strcmp (const char *s1 [r3], const char *s2 [r4])  */
ce426f
+
ce426f
+EALIGN (strcmp, 4, 0)
ce426f
+	CALL_MCOUNT 2
ce426f
+
ce426f
+	or r9, r3, r4
ce426f
+	rldicl. r10, r9, 0, 61	/* are s1 and s2 8 byte aligned..?  */
ce426f
+	bne cr0, L(process_unaligned_bytes)
ce426f
+
ce426f
+/* process input parameters on double word aligned boundary  */
ce426f
+	ld r9, 0(r4)		/* load s2 at offset=0  */
ce426f
+	li r10, 0		/* load mask=0  */
ce426f
+	cmpb r10, r9, r10	/* compare bytes at s2 with mask  */
ce426f
+	cmpdi cr7, r10, 0	/* is NULL found ..? is end of string HIT  */
ce426f
+	bne cr7, L(process_unaligned_bytes)	/* process byte by byte  */
ce426f
+
ce426f
+	ld r10, 0(r3)		/* load s1 at offset=0  */
ce426f
+	li r8, 0		/* load mask=0  */
ce426f
+	cmpb r8, r10, r8	/* compare bytes at s1 with mask  */
ce426f
+	cmpdi cr7, r8, 0	/* is NULL found ..? is end of string HIT  */
ce426f
+	bne cr7, L(process_unaligned_bytes)	/* process byte by byte  */
ce426f
+
ce426f
+/*s1 and s2 does not contain NULL now , so compare all 8 bytes in a GO  */
ce426f
+	cmpb r9, r10, r9	/* compare s1 and s2  */
ce426f
+	cmpdi cr7, r9, -1	/* compare result with 0xFFFFFFFFFFFFFFFF  */
ce426f
+	bne cr7, L(process_unaligned_bytes)	/* s1,s2 mismatch found  */
ce426f
+
ce426f
+	addi r5, r3, 8		/* save next offset of s2  */
ce426f
+	addi r11, r4, 8		/* save next offset of s1  */
ce426f
+	ld r8, 8(r4)		/* load s2 at offset=8  */
ce426f
+	li r9, 0		/* load mask=0  */
ce426f
+	cmpb r9, r8, r9		/* compare bytes at s2 with mask  */
ce426f
+	cmpdi cr7, r9, 0	/* NULL found ..?  */
ce426f
+	bne cr7, L(processBytes)/* update input and process bytes one by one  */
ce426f
+
ce426f
+	mr r9, r4		/* save s2  */
ce426f
+	li r10, 0		/* load mask=0  */
ce426f
+
ce426f
+	ld r7, 8(r3)		/* load s1 at offset=8  */
ce426f
+	cmpb r6, r7, r10	/* compare bytes at s1 with mask  */
ce426f
+	cmpdi cr7, r6, 0	/* is NULL found  */
ce426f
+	bne cr7, L(processBytes)/* mismatch, so process one by one  */
ce426f
+
ce426f
+L(unrollDword):
ce426f
+	cmpb r8, r7, r8		/* compare s1 and s2  */
ce426f
+	cmpdi cr7, r8, -1	/* compare result with 0xFFFFFFFFFFFFFFFF  */
ce426f
+	bne cr7, L(processBytes)/* mismatch with s1 and s2  */
ce426f
+
ce426f
+	addi r5, r3, 16		/* save offset=16 of s1  */
ce426f
+	addi r4, r9, 16		/* save offset=16 of s2  */
ce426f
+	ld r8, 16(r9)		/* load s2 at offset=16  */
ce426f
+	cmpb r7, r8, r10	/* compare bytes at s2 with mask  */
ce426f
+	cmpdi cr7, r7, 0	/* NULL found  ..?  */
ce426f
+	bne cr7, L(update2processBytes)
ce426f
+
ce426f
+	ld r7, 16(r3)		/* load s1 at offset=16  */
ce426f
+	cmpb r6, r7, r10	/* check s1 for end of string  */
ce426f
+	cmpdi cr7, r6, 0	/* end of s1 ?,then handle byte by byte  */
ce426f
+	bne 7,L(update2processBytes)
ce426f
+
ce426f
+	cmpb r8, r7, r8		/* compare s1 and s2 double words  */
ce426f
+	cmpdi cr7, r8, -1	/* compare results with 0xFFFFFFFFFFFFFFFF  */
ce426f
+	bne cr7,L(update2processBytes)
ce426f
+
ce426f
+	addi r5, r3, 24		/* update s1 to offset=24  */
ce426f
+	addi r4, r9, 24		/* update s2 to offset=24  */
ce426f
+
ce426f
+	ld r8, 24(r9)		/* load s2  */
ce426f
+	cmpb r7, r8, r10	/* compare s2 for NULL  */
ce426f
+	cmpdi cr7, r7, 0	/* verify if s2 is ending now  */
ce426f
+	bne cr7,L(update2processBytes)
ce426f
+
ce426f
+	ld r7, 24(r3)		/* load s1 at offset=24  */
ce426f
+	cmpb r6, r7, r10	/* verify for NULL  */
ce426f
+	cmpdi cr7, r6, 0	/* is NULL found  */
ce426f
+	bne cr7, L(update2processBytes)
ce426f
+
ce426f
+	cmpb r8, r7, r8		/* compare s1 and s2  */
ce426f
+	cmpdi cr7, r8, -1	/* are s1 and s2 same ..?  */
ce426f
+	bne cr7, L(update2processBytes)
ce426f
+
ce426f
+	addi r7, r9, 32		/* update s2 to next double word  */
ce426f
+	addi r3, r3, 32		/* update s1 to next double word  */
ce426f
+
ce426f
+	ld r8, 32(r9)		/* load s2  */
ce426f
+	mr r4, r7		/* save s2  */
ce426f
+	cmpb r6, r8, r10	/* compare s2 with NULL  */
ce426f
+	cmpdi cr7, r6, 0	/* end of s2 ..? */
ce426f
+	bne cr7, L(process_unaligned_bytes)
ce426f
+
ce426f
+	ld r6, 0(r3)		/* load and compare s1 for NULL  */
ce426f
+	cmpb r5, r6, r10
ce426f
+	cmpdi cr7, r5, 0
ce426f
+	bne cr7, L(process_unaligned_bytes)
ce426f
+
ce426f
+	cmpb r8, r6, r8		/* compare s1 and s2  */
ce426f
+	cmpdi cr7, r8, -1
ce426f
+	bne cr7, L(process_unaligned_bytes)
ce426f
+
ce426f
+	addi r5, r3, 8		/* increment s1 and d2 here  */
ce426f
+	addi r11, r9, 40
ce426f
+
ce426f
+	ld r8, 40(r9)		/* process s2 now  */
ce426f
+	cmpb r9, r8, r10
ce426f
+	cmpdi cr7, r9, 0
ce426f
+	bne cr7, L(processBytes)
ce426f
+
ce426f
+	mr r9, r7
ce426f
+	ld r7, 8(r3)		/* process s1 now  */
ce426f
+	cmpb r6, r7, r10
ce426f
+	cmpdi cr7, r6, 0
ce426f
+	beq cr7, L(unrollDword)	/* unroll to compare s1 and s2  */
ce426f
+
ce426f
+L(processBytes):
ce426f
+	mr r4, r11		/* update input params  */
ce426f
+	mr r3, r5
ce426f
+
ce426f
+	.p2align 4
ce426f
+L(process_unaligned_bytes):
ce426f
+	lbz r9, 0(r3)		/* load byte from s1  */
ce426f
+	lbz r10, 0(r4)		/* load byte from s2  */
ce426f
+	cmpdi cr7, r9, 0	/* compare *s1 with NULL  */
ce426f
+	beq cr7, L(diffOfNULL)	/* if *s1 is NULL , return *s1 - *s2  */
ce426f
+	cmplw cr7, r9, r10	/* compare *s1 and *s2  */
ce426f
+	bne cr7, L(ComputeDiff)	/* branch to compute difference and return  */
ce426f
+
ce426f
+	lbz r9, 1(r3)		/* load next byte from s1  */
ce426f
+	lbz r10, 1(r4)		/* load next byte from s2  */
ce426f
+	cmpdi cr7, r9, 0	/* compare *s1 with NULL  */
ce426f
+	beq cr7, L(diffOfNULL)	/* if *s1 is NULL , return *s1 - *s2  */
ce426f
+	cmplw cr7, r9, r10	/* compare *s1 and *s2  */
ce426f
+	bne cr7, L(ComputeDiff)	/* branch to compute difference and return  */
ce426f
+
ce426f
+	lbz r9, 2(r3)		/* unroll 3rd byte here  */
ce426f
+	lbz r10, 2(r4)
ce426f
+	cmpdi cr7, r9, 0
ce426f
+	beq cr7, L(diffOfNULL)
ce426f
+	cmplw cr7, r9, r10
ce426f
+	bne 7, L(ComputeDiff)
ce426f
+
ce426f
+	lbz r9, 3(r3)		/* unroll 4th byte now  */
ce426f
+	lbz r10, 3(r4)
ce426f
+	addi r3, r3, 4		/* increment s1 by unroll factor  */
ce426f
+	cmpdi cr7, r9, 0
ce426f
+	cmplw cr6, 9, r10
ce426f
+	beq cr7, L(diffOfNULL)
ce426f
+	addi r4, r4, 4		/* increment s2 by unroll factor  */
ce426f
+	beq cr6, L(process_unaligned_bytes)	/* unroll byte processing  */
ce426f
+
ce426f
+	.p2align 4
ce426f
+L(ComputeDiff):
ce426f
+	extsw r9, r9
ce426f
+	subf r10, r10, r9	/* compute s1 - s2  */
ce426f
+	extsw r3, r10
ce426f
+	blr			/* return  */
ce426f
+
ce426f
+	.p2align 4
ce426f
+L(diffOfNULL):
ce426f
+	li r9, 0
ce426f
+	subf r10, r10, r9	/* compute s1 - s2  */
ce426f
+	extsw r3, r10		/* sign extend result  */
ce426f
+	blr			/* return  */
ce426f
+
ce426f
+	.p2align 4
ce426f
+L(update2processBytes):
ce426f
+	mr r3, r5		/* update and proceed  */
ce426f
+	b L(process_unaligned_bytes)
ce426f
+
ce426f
+END (strcmp)
ce426f
+libc_hidden_builtin_def (strcmp)
ce426f
diff --git a/sysdeps/powerpc/powerpc64/power8/strcmp.S b/sysdeps/powerpc/powerpc64/power8/strcmp.S
ce426f
new file mode 100644
ce426f
index 0000000..223d891
ce426f
--- /dev/null
ce426f
+++ b/sysdeps/powerpc/powerpc64/power8/strcmp.S
ce426f
@@ -0,0 +1,257 @@
ce426f
+/* Optimized strcmp implementation for PowerPC64/POWER8.
ce426f
+   Copyright (C) 2015 Free Software Foundation, Inc.
ce426f
+   This file is part of the GNU C Library.
ce426f
+
ce426f
+   The GNU C Library is free software; you can redistribute it and/or
ce426f
+   modify it under the terms of the GNU Lesser General Public
ce426f
+   License as published by the Free Software Foundation; either
ce426f
+   version 2.1 of the License, or (at your option) any later version.
ce426f
+
ce426f
+   The GNU C Library is distributed in the hope that it will be useful,
ce426f
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
ce426f
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
ce426f
+   Lesser General Public License for more details.
ce426f
+
ce426f
+   You should have received a copy of the GNU Lesser General Public
ce426f
+   License along with the GNU C Library; if not, see
ce426f
+   <http://www.gnu.org/licenses/>.  */
ce426f
+
ce426f
+#include <sysdep.h>
ce426f
+
ce426f
+/* Implements the function
ce426f
+
ce426f
+   size_t [r3] strcmp (const char *s1 [r3], const char *s2 [r4])
ce426f
+
ce426f
+   The implementation uses unaligned doubleword access to avoid specialized
ce426f
+   code paths depending of data alignment.  Although recent powerpc64 uses
ce426f
+   64K as default, the page cross handling assumes minimum page size of
ce426f
+   4k.  */
ce426f
+
ce426f
+EALIGN (strcmp, 4, 0)
ce426f
+	li	r0,0
ce426f
+
ce426f
+	/* Check if [s1]+32 or [s2]+32 will cross a 4K page boundary using
ce426f
+	   the code:
ce426f
+
ce426f
+	    (((size_t) s1) % PAGE_SIZE > (PAGE_SIZE - ITER_SIZE))
ce426f
+
ce426f
+	   with PAGE_SIZE being 4096 and ITER_SIZE begin 32.  */
ce426f
+
ce426f
+	rldicl	r7,r3,0,52
ce426f
+	rldicl	r9,r4,0,52
ce426f
+	cmpldi	cr7,r7,4096-32
ce426f
+	bgt	cr7,L(pagecross_check)
ce426f
+	cmpldi	cr5,r9,4096-32
ce426f
+	bgt	cr5,L(pagecross_check)
ce426f
+
ce426f
+	/* For short string up to 32 bytes, load both s1 and s2 using
ce426f
+	   unaligned dwords and compare.  */
ce426f
+	ld	r8,0(r3)
ce426f
+	ld	r10,0(r4)
ce426f
+	cmpb	r12,r8,r0
ce426f
+	cmpb	r11,r8,r10
ce426f
+	orc.	r9,r12,r11
ce426f
+	bne	cr0,L(different_nocmpb)
ce426f
+
ce426f
+	ld	r8,8(r3)
ce426f
+	ld	r10,8(r4)
ce426f
+	cmpb	r12,r8,r0
ce426f
+	cmpb	r11,r8,r10
ce426f
+	orc.	r9,r12,r11
ce426f
+	bne	cr0,L(different_nocmpb)
ce426f
+
ce426f
+	ld	r8,16(r3)
ce426f
+	ld	r10,16(r4)
ce426f
+	cmpb	r12,r8,r0
ce426f
+	cmpb	r11,r8,r10
ce426f
+	orc.	r9,r12,r11
ce426f
+	bne	cr0,L(different_nocmpb)
ce426f
+
ce426f
+	ld	r8,24(r3)
ce426f
+	ld	r10,24(r4)
ce426f
+	cmpb	r12,r8,r0
ce426f
+	cmpb	r11,r8,r10
ce426f
+	orc.	r9,r12,r11
ce426f
+	bne	cr0,L(different_nocmpb)
ce426f
+
ce426f
+	addi	r7,r3,32
ce426f
+	addi	r4,r4,32
ce426f
+
ce426f
+L(align_8b):
ce426f
+	/* Now it has checked for first 32 bytes, align source1 to doubleword
ce426f
+	   and adjust source2 address.  */
ce426f
+	rldicl	r9,r7,0,61	/* source1 alignment to doubleword  */
ce426f
+	subf	r4,r9,r4	/* Adjust source2 address based on source1
ce426f
+				   alignment.  */
ce426f
+	rldicr	r7,r7,0,60	/* Align source1 to doubleword.  */
ce426f
+
ce426f
+	/* At this point, source1 alignment is 0 and source2 alignment is
ce426f
+	   between 0 and 7.  Check is source2 alignment is 0, meaning both
ce426f
+	   sources have the same alignment.  */
ce426f
+	andi.	r9,r4,0x7
ce426f
+	bne	cr0,L(loop_diff_align)
ce426f
+
ce426f
+	/* If both source1 and source2 are doubleword aligned, there is no
ce426f
+	   need for page boundary cross checks.  */
ce426f
+
ce426f
+	ld	r8,0(r7)
ce426f
+	ld	r10,0(r4)
ce426f
+	cmpb	r12,r8,r0
ce426f
+	cmpb	r11,r8,r10
ce426f
+	orc.	r9,r12,r11
ce426f
+	bne	cr0,L(different_nocmpb)
ce426f
+
ce426f
+	.align 4
ce426f
+L(loop_equal_align):
ce426f
+	ld	r8,8(r7)
ce426f
+	ld	r10,8(r4)
ce426f
+	cmpb	r12,r8,r0
ce426f
+	cmpb	r11,r8,r10
ce426f
+	orc.	r9,r12,r11
ce426f
+	bne	cr0,L(different_nocmpb)
ce426f
+
ce426f
+	ld	r8,16(r7)
ce426f
+	ld	r10,16(r4)
ce426f
+	cmpb	r12,r8,r0
ce426f
+	cmpb	r11,r8,r10
ce426f
+	orc.	r9,r12,r11
ce426f
+	bne	cr0,L(different_nocmpb)
ce426f
+
ce426f
+	ldu	r8,24(r7)
ce426f
+	ldu	r10,24(r4)
ce426f
+	cmpb	r12,r8,r0
ce426f
+	cmpb	r11,r8,r10
ce426f
+	orc.	r9,r12,r11
ce426f
+	bne	cr0,L(different_nocmpb)
ce426f
+
ce426f
+	b	L(loop_equal_align)
ce426f
+
ce426f
+	/* A zero byte was found in r8 (s1 dword), r9 contains the cmpb
ce426f
+	   result and r10 the dword from s2.  To code isolate the byte
ce426f
+	   up to end (including the '\0'), masking with 0xFF the remaining
ce426f
+	   ones:
ce426f
+
ce426f
+           #if __LITTLE_ENDIAN__
ce426f
+	     (__builtin_ffsl (x) - 1) = counting trailing zero bits
ce426f
+	     r9 = (__builtin_ffsl (r9) - 1) + 8;
ce426f
+	     r9 = -1UL << r9
ce426f
+	   #else
ce426f
+	     r9  = __builtin_clzl (r9) + 8;
ce426f
+	     r9  = -1UL >> r9
ce426f
+	   #endif
ce426f
+	     r8  = r8  | r9
ce426f
+	     r10 = r10 | r9  */
ce426f
+
ce426f
+#ifdef __LITTLE_ENDIAN__
ce426f
+	nor 	r9,r9,r9
ce426f
+L(different_nocmpb):
ce426f
+	neg	r3,r9
ce426f
+	and	r9,r9,r3
ce426f
+	cntlzd	r9,r9
ce426f
+	subfic	r9,r9,63
ce426f
+#else
ce426f
+	not	r9,r9
ce426f
+L(different_nocmpb):
ce426f
+	cntlzd	r9,r9
ce426f
+	subfic	r9,r9,56
ce426f
+#endif
ce426f
+	srd	r3,r8,r9
ce426f
+	srd	r10,r10,r9
ce426f
+	rldicl	r10,r10,0,56
ce426f
+	rldicl	r3,r3,0,56
ce426f
+	subf	r3,r10,r3
ce426f
+	extsw	r3,r3
ce426f
+	blr
ce426f
+
ce426f
+	.align	4
ce426f
+L(pagecross_check):
ce426f
+	subfic	r9,r9,4096
ce426f
+	subfic	r7,r7,4096
ce426f
+	cmpld	cr7,r7,r9
ce426f
+	bge	cr7,L(pagecross)
ce426f
+	mr	r7,r9
ce426f
+
ce426f
+	/* If unaligned 16 bytes reads across a 4K page boundary, it uses
ce426f
+	   a simple byte a byte comparison until the page alignment for s1
ce426f
+	   is reached.  */
ce426f
+L(pagecross):
ce426f
+	add	r7,r3,r7
ce426f
+	subf	r9,r3,r7
ce426f
+	mtctr	r9
ce426f
+
ce426f
+	.align	4
ce426f
+L(pagecross_loop):
ce426f
+	/* Loads a byte from s1 and s2, compare if *s1 is equal to *s2
ce426f
+	   and if *s1 is '\0'.  */
ce426f
+	lbz	r9,0(r3)
ce426f
+	lbz	r10,0(r4)
ce426f
+	addi	r3,r3,1
ce426f
+	addi	r4,r4,1
ce426f
+	cmplw	cr7,r9,r10
ce426f
+	cmpdi	cr5,r9,r0
ce426f
+	bne	cr7,L(pagecross_ne)
ce426f
+	beq	cr5,L(pagecross_nullfound)
ce426f
+	bdnz	L(pagecross_loop)
ce426f
+	b	L(align_8b)
ce426f
+
ce426f
+	.align	4
ce426f
+	/* The unaligned read of source2 will cross a 4K page boundary,
ce426f
+	   and the different byte or NULL maybe be in the remaining page
ce426f
+	   bytes. Since it can not use the unaligned load, the algorithm
ce426f
+	   reads and compares 8 bytes to keep source1 doubleword aligned.  */
ce426f
+L(check_source2_byte):
ce426f
+	li	r9,8
ce426f
+	mtctr	r9
ce426f
+
ce426f
+	.align	4
ce426f
+L(check_source2_byte_loop):
ce426f
+	lbz	r9,0(r7)
ce426f
+	lbz	r10,0(r4)
ce426f
+	addi	r7,r7,1
ce426f
+	addi	r4,r4,1
ce426f
+	cmplw	cr7,r9,10
ce426f
+	cmpdi	r5,r9,0
ce426f
+	bne	cr7,L(pagecross_ne)
ce426f
+	beq	cr5,L(pagecross_nullfound)
ce426f
+	bdnz	L(check_source2_byte_loop)
ce426f
+
ce426f
+	/* If source2 is unaligned to doubleword, the code needs to check
ce426f
+	   on each interation if the unaligned doubleword access will cross
ce426f
+	   a 4k page boundary.  */
ce426f
+	.align	5
ce426f
+L(loop_unaligned):
ce426f
+	ld	r8,0(r7)
ce426f
+	ld	r10,0(r4)
ce426f
+	cmpb	r12,r8,r0
ce426f
+	cmpb	r11,r8,r10
ce426f
+	orc.	r9,r12,r11
ce426f
+	bne	cr0,L(different_nocmpb)
ce426f
+	addi	r7,r7,8
ce426f
+	addi	r4,r4,8
ce426f
+
ce426f
+L(loop_diff_align):
ce426f
+	/* Check if [src2]+8 cross a 4k page boundary:
ce426f
+
ce426f
+	     srcin2 % PAGE_SIZE > (PAGE_SIZE - 8)
ce426f
+
ce426f
+	     with PAGE_SIZE being 4096.  */
ce426f
+	rldicl	r9,r4,0,52
ce426f
+	cmpldi	cr7,r9,4088
ce426f
+	ble	cr7,L(loop_unaligned)
ce426f
+	b	L(check_source2_byte)
ce426f
+
ce426f
+	.align	4
ce426f
+L(pagecross_ne):
ce426f
+	extsw	r3,r9
ce426f
+	mr	r9,r10
ce426f
+L(pagecross_retdiff):
ce426f
+	subf	r9,r9,r3
ce426f
+	extsw	r3,r9
ce426f
+	blr
ce426f
+
ce426f
+	.align	4
ce426f
+L(pagecross_nullfound):
ce426f
+	li	r3,0
ce426f
+	b	L(pagecross_retdiff)
ce426f
+END (strcmp)
ce426f
+libc_hidden_builtin_def (strcmp)