diff options
Diffstat (limited to 'packages/glibc/2.17/0048-glibc-ppc64le-26.patch')
-rw-r--r-- | packages/glibc/2.17/0048-glibc-ppc64le-26.patch | 379 |
1 files changed, 379 insertions, 0 deletions
diff --git a/packages/glibc/2.17/0048-glibc-ppc64le-26.patch b/packages/glibc/2.17/0048-glibc-ppc64le-26.patch new file mode 100644 index 0000000..93fd255 --- /dev/null +++ b/packages/glibc/2.17/0048-glibc-ppc64le-26.patch @@ -0,0 +1,379 @@ +# commit 33ee81de05e83ce12f32a491270bb4c1611399c7 +# 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 -urN glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power7/strnlen.S glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power7/strnlen.S +--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power7/strnlen.S 2014-05-28 12:40:17.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power7/strnlen.S 2014-05-28 12:44:52.000000000 -0500 +@@ -30,51 +30,47 @@ + 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): +@@ -90,15 +86,18 @@ + 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 +@@ -123,49 +122,56 @@ + 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 (BP_SYM (__strnlen)) + weak_alias (BP_SYM (__strnlen), BP_SYM(strnlen)) + libc_hidden_builtin_def (strnlen) +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/power7/strnlen.S glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/power7/strnlen.S +--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/power7/strnlen.S 2014-05-28 12:40:17.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/power7/strnlen.S 2014-05-28 13:24:41.000000000 -0500 +@@ -26,33 +26,29 @@ + ENTRY (BP_SYM (__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. */ +@@ -65,17 +61,18 @@ + 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): +@@ -91,15 +88,18 @@ + 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 +@@ -121,52 +121,59 @@ + /* 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 (BP_SYM (__strnlen)) + weak_alias (BP_SYM (__strnlen), BP_SYM(strnlen)) + libc_hidden_builtin_def (strnlen) |