import glibc-2.17-292.el7.src.rpm
Signed-off-by: zhangbinchen <zhangbinchen@openanolis.org>
This commit is contained in:
commit
ff0128648f
929 changed files with 436800 additions and 0 deletions
642
glibc-ppc64le-29.patch
Normal file
642
glibc-ppc64le-29.patch
Normal file
|
@ -0,0 +1,642 @@
|
|||
# commit 664318c3eb07032e2bfcf47cb2aa3c89280c19e7
|
||||
# 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.
|
||||
#
|
||||
Index: glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power7/strchr.S
|
||||
===================================================================
|
||||
--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power7/strchr.S.orig
|
||||
+++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power7/strchr.S
|
||||
@@ -37,8 +37,8 @@ ENTRY (BP_SYM(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. */
|
||||
@@ -48,11 +48,17 @@ ENTRY (BP_SYM(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. */
|
||||
@@ -67,7 +73,7 @@ ENTRY (BP_SYM(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
|
||||
@@ -102,22 +108,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
|
||||
@@ -135,10 +150,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)
|
||||
@@ -193,7 +212,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
|
||||
Index: glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power7/strchrnul.S
|
||||
===================================================================
|
||||
--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power7/strchrnul.S.orig
|
||||
+++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power7/strchrnul.S
|
||||
@@ -29,8 +29,8 @@ ENTRY (BP_SYM(__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. */
|
||||
@@ -45,10 +45,17 @@ ENTRY (BP_SYM(__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. */
|
||||
@@ -56,7 +63,7 @@ ENTRY (BP_SYM(__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)
|
||||
@@ -78,7 +85,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
|
||||
@@ -97,9 +104,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
|
||||
|
||||
@@ -107,7 +114,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
|
||||
Index: glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/strchr.S
|
||||
===================================================================
|
||||
--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/strchr.S.orig
|
||||
+++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/strchr.S
|
||||
@@ -44,6 +44,8 @@ ENTRY (BP_SYM (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
|
||||
|
||||
CHECK_BOUNDS_LOW (rSTR, rTMP1, rTMP2)
|
||||
STORE_RETURN_BOUNDS (rTMP1, rTMP2)
|
||||
@@ -59,53 +61,74 @@ ENTRY (BP_SYM (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
|
||||
STORE_RETURN_VALUE (rSTR)
|
||||
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
|
||||
CHECK_BOUNDS_HIGH_RTN (rSTR, rTMP2, twlge)
|
||||
@@ -113,13 +136,21 @@ L(missed):
|
||||
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
|
||||
CHECK_BOUNDS_HIGH_RTN (rSTR, rTMP2, twlge)
|
||||
STORE_RETURN_VALUE (rSTR)
|
||||
Index: glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/power7/strchr.S
|
||||
===================================================================
|
||||
--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/power7/strchr.S.orig
|
||||
+++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/power7/strchr.S
|
||||
@@ -37,8 +37,8 @@ ENTRY (BP_SYM(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
|
||||
@@ -49,11 +49,17 @@ ENTRY (BP_SYM(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. */
|
||||
@@ -110,15 +116,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
|
||||
@@ -137,9 +152,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)
|
||||
@@ -194,7 +213,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
|
||||
Index: glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/power7/strchrnul.S
|
||||
===================================================================
|
||||
--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/power7/strchrnul.S.orig
|
||||
+++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/power7/strchrnul.S
|
||||
@@ -29,8 +29,8 @@ ENTRY (BP_SYM(__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. */
|
||||
@@ -46,10 +46,17 @@ ENTRY (BP_SYM(__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. */
|
||||
@@ -99,7 +106,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
|
||||
@@ -108,7 +115,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
|
||||
Index: glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/strchr.S
|
||||
===================================================================
|
||||
--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/strchr.S.orig
|
||||
+++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/strchr.S
|
||||
@@ -50,14 +50,16 @@ ENTRY (BP_SYM (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
|
||||
|
||||
CHECK_BOUNDS_LOW (rSTR, rTMP1, rTMP2)
|
||||
STORE_RETURN_BOUNDS (rTMP1, rTMP2)
|
||||
|
||||
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
|
||||
@@ -70,53 +72,74 @@ ENTRY (BP_SYM (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
|
||||
STORE_RETURN_VALUE (rSTR)
|
||||
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
|
||||
CHECK_BOUNDS_HIGH_RTN (rSTR, rTMP2, tdlge)
|
||||
@@ -124,13 +147,21 @@ L(missed):
|
||||
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
|
||||
CHECK_BOUNDS_HIGH_RTN (rSTR, rTMP2, tdlge)
|
||||
STORE_RETURN_VALUE (rSTR)
|
Loading…
Add table
Add a link
Reference in a new issue