|
|
5de29b |
# commit 466b03933234017473c12dd1d92bda5e7fe49df7
|
|
|
5de29b |
# Author: Alan Modra <amodra@gmail.com>
|
|
|
5de29b |
# Date: Sat Aug 17 18:48:36 2013 +0930
|
|
|
5de29b |
#
|
|
|
5de29b |
# PowerPC LE memchr and memrchr
|
|
|
5de29b |
# http://sourceware.org/ml/libc-alpha/2013-08/msg00105.html
|
|
|
5de29b |
#
|
|
|
5de29b |
# Like strnlen, memchr and memrchr had a number of defects fixed by this
|
|
|
5de29b |
# patch as well as adding little-endian support. The first one I
|
|
|
5de29b |
# noticed was that the entry to the main loop needlessly checked for
|
|
|
5de29b |
# "are we done yet?" when we know the size is large enough that we can't
|
|
|
5de29b |
# be done. The second defect I noticed was that the main loop count was
|
|
|
5de29b |
# wrong, which in turn meant that the small loop needed to handle an
|
|
|
5de29b |
# extra word. Thirdly, there is nothing to say that the string can't
|
|
|
5de29b |
# wrap around zero, except of course that we'd normally hit a segfault
|
|
|
5de29b |
# on trying to read from address zero. Fixing that simplified a number
|
|
|
5de29b |
# of places:
|
|
|
5de29b |
#
|
|
|
5de29b |
# - /* Are we done already? */
|
|
|
5de29b |
# - addi r9,r8,8
|
|
|
5de29b |
# - cmpld r9,r7
|
|
|
5de29b |
# - bge L(null)
|
|
|
5de29b |
#
|
|
|
5de29b |
# becomes
|
|
|
5de29b |
#
|
|
|
5de29b |
# + cmpld r8,r7
|
|
|
5de29b |
# + beqlr
|
|
|
5de29b |
#
|
|
|
5de29b |
# However, the exit gets an extra test because I test for being on the
|
|
|
5de29b |
# last word then if so whether the byte offset is less than the end.
|
|
|
5de29b |
# Overall, the change is a win.
|
|
|
5de29b |
#
|
|
|
5de29b |
# Lastly, memrchr used the wrong cache hint.
|
|
|
5de29b |
#
|
|
|
5de29b |
# * sysdeps/powerpc/powerpc64/power7/memchr.S: Replace rlwimi with
|
|
|
5de29b |
# insrdi. Make better use of reg selection to speed exit slightly.
|
|
|
5de29b |
# Schedule entry path a little better. Remove useless "are we done"
|
|
|
5de29b |
# checks on entry to main loop. Handle wrapping around zero address.
|
|
|
5de29b |
# Correct main loop count. Handle single left-over word from main
|
|
|
5de29b |
# loop inline rather than by using loop_small. Remove extra word
|
|
|
5de29b |
# case in loop_small caused by wrong loop count. Add little-endian
|
|
|
5de29b |
# support.
|
|
|
5de29b |
# * sysdeps/powerpc/powerpc32/power7/memchr.S: Likewise.
|
|
|
5de29b |
# * sysdeps/powerpc/powerpc64/power7/memrchr.S: Likewise. Use proper
|
|
|
5de29b |
# cache hint.
|
|
|
5de29b |
# * sysdeps/powerpc/powerpc32/power7/memrchr.S: Likewise.
|
|
|
5de29b |
# * sysdeps/powerpc/powerpc64/power7/rawmemchr.S: Add little-endian
|
|
|
5de29b |
# support. Avoid rlwimi.
|
|
|
5de29b |
# * sysdeps/powerpc/powerpc32/power7/rawmemchr.S: Likewise.
|
|
|
5de29b |
#
|
|
|
12745e |
diff -urN glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power7/memchr.S glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power7/memchr.S
|
|
|
12745e |
--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power7/memchr.S 2014-05-29 13:09:17.000000000 -0500
|
|
|
12745e |
+++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power7/memchr.S 2014-05-29 13:13:37.000000000 -0500
|
|
|
5de29b |
@@ -1,5 +1,5 @@
|
|
|
5de29b |
/* Optimized memchr implementation for PowerPC32/POWER7 using cmpb insn.
|
|
|
5de29b |
- Copyright (C) 2010-2012 Free Software Foundation, Inc.
|
|
|
5de29b |
+ Copyright (C) 2010-2014 Free Software Foundation, Inc.
|
|
|
5de29b |
Contributed by Luis Machado <luisgpm@br.ibm.com>.
|
|
|
5de29b |
This file is part of the GNU C Library.
|
|
|
5de29b |
|
|
|
5de29b |
@@ -18,116 +18,118 @@
|
|
|
5de29b |
<http://www.gnu.org/licenses/>. */
|
|
|
5de29b |
|
|
|
5de29b |
#include <sysdep.h>
|
|
|
5de29b |
-#include <bp-sym.h>
|
|
|
5de29b |
-#include <bp-asm.h>
|
|
|
5de29b |
|
|
|
5de29b |
/* int [r3] memchr (char *s [r3], int byte [r4], int size [r5]) */
|
|
|
5de29b |
.machine power7
|
|
|
5de29b |
-ENTRY (BP_SYM (__memchr))
|
|
|
5de29b |
+ENTRY (__memchr)
|
|
|
5de29b |
CALL_MCOUNT
|
|
|
5de29b |
dcbt 0,r3
|
|
|
5de29b |
clrrwi r8,r3,2
|
|
|
5de29b |
- rlwimi r4,r4,8,16,23
|
|
|
5de29b |
- rlwimi r4,r4,16,0,15
|
|
|
5de29b |
+ insrwi r4,r4,8,16 /* Replicate byte to word. */
|
|
|
5de29b |
add r7,r3,r5 /* Calculate the last acceptable address. */
|
|
|
5de29b |
+ insrwi r4,r4,16,0
|
|
|
5de29b |
cmplwi r5,16
|
|
|
5de29b |
+ li r9, -1
|
|
|
5de29b |
+ rlwinm r6,r3,3,27,28 /* Calculate padding. */
|
|
|
5de29b |
+ addi r7,r7,-1
|
|
|
5de29b |
+#ifdef __LITTLE_ENDIAN__
|
|
|
5de29b |
+ slw r9,r9,r6
|
|
|
5de29b |
+#else
|
|
|
5de29b |
+ srw r9,r9,r6
|
|
|
5de29b |
+#endif
|
|
|
5de29b |
ble L(small_range)
|
|
|
5de29b |
|
|
|
5de29b |
- cmplw cr7,r3,r7 /* Compare the starting address (r3) with the
|
|
|
5de29b |
- ending address (r7). If (r3 >= r7), the size
|
|
|
5de29b |
- passed in is zero or negative. */
|
|
|
5de29b |
- ble cr7,L(proceed)
|
|
|
5de29b |
-
|
|
|
5de29b |
- li r7,-1 /* Artificially set our ending address (r7)
|
|
|
5de29b |
- such that we will exit early. */
|
|
|
5de29b |
-L(proceed):
|
|
|
5de29b |
- rlwinm r6,r3,3,27,28 /* Calculate padding. */
|
|
|
5de29b |
- cmpli cr6,r6,0 /* cr6 == Do we have padding? */
|
|
|
5de29b |
lwz r12,0(r8) /* Load word from memory. */
|
|
|
5de29b |
- cmpb r10,r12,r4 /* Check for BYTE's in WORD1. */
|
|
|
5de29b |
- beq cr6,L(proceed_no_padding)
|
|
|
5de29b |
- slw r10,r10,r6
|
|
|
5de29b |
- srw r10,r10,r6
|
|
|
5de29b |
-L(proceed_no_padding):
|
|
|
5de29b |
- cmplwi cr7,r10,0 /* If r10 == 0, no BYTEs have been found. */
|
|
|
5de29b |
+ cmpb r3,r12,r4 /* Check for BYTEs in WORD1. */
|
|
|
5de29b |
+ and r3,r3,r9
|
|
|
5de29b |
+ clrlwi r5,r7,30 /* Byte count - 1 in last word. */
|
|
|
5de29b |
+ clrrwi r7,r7,2 /* Address of last word. */
|
|
|
5de29b |
+ cmplwi cr7,r3,0 /* If r3 == 0, no BYTEs have been found. */
|
|
|
5de29b |
bne cr7,L(done)
|
|
|
5de29b |
|
|
|
5de29b |
- /* Are we done already? */
|
|
|
5de29b |
- addi r9,r8,4
|
|
|
5de29b |
- cmplw cr6,r9,r7
|
|
|
5de29b |
- bge cr6,L(null)
|
|
|
5de29b |
-
|
|
|
5de29b |
mtcrf 0x01,r8
|
|
|
5de29b |
/* Are we now aligned to a doubleword boundary? If so, skip to
|
|
|
5de29b |
the main loop. Otherwise, go through the alignment code. */
|
|
|
5de29b |
-
|
|
|
5de29b |
bt 29,L(loop_setup)
|
|
|
5de29b |
|
|
|
5de29b |
/* Handle WORD2 of pair. */
|
|
|
5de29b |
lwzu r12,4(r8)
|
|
|
5de29b |
- cmpb r10,r12,r4
|
|
|
5de29b |
- cmplwi cr7,r10,0
|
|
|
5de29b |
+ cmpb r3,r12,r4
|
|
|
5de29b |
+ cmplwi cr7,r3,0
|
|
|
5de29b |
bne cr7,L(done)
|
|
|
5de29b |
|
|
|
5de29b |
- /* Are we done already? */
|
|
|
5de29b |
- addi r9,r8,4
|
|
|
5de29b |
- cmplw cr6,r9,r7
|
|
|
5de29b |
- bge cr6,L(null)
|
|
|
5de29b |
-
|
|
|
5de29b |
L(loop_setup):
|
|
|
5de29b |
- sub r5,r7,r9
|
|
|
5de29b |
- srwi r6,r5,3 /* Number of loop iterations. */
|
|
|
5de29b |
+ /* The last word we want to read in the loop below is the one
|
|
|
5de29b |
+ containing the last byte of the string, ie. the word at
|
|
|
5de29b |
+ (s + size - 1) & ~3, or r7. The first word read is at
|
|
|
5de29b |
+ r8 + 4, we read 2 * cnt words, so the last word read will
|
|
|
5de29b |
+ be at r8 + 4 + 8 * cnt - 4. Solving for cnt gives
|
|
|
5de29b |
+ cnt = (r7 - r8) / 8 */
|
|
|
5de29b |
+ sub r6,r7,r8
|
|
|
5de29b |
+ srwi r6,r6,3 /* Number of loop iterations. */
|
|
|
5de29b |
mtctr r6 /* Setup the counter. */
|
|
|
5de29b |
- b L(loop)
|
|
|
5de29b |
- /* Main loop to look for BYTE backwards in the string. Since
|
|
|
5de29b |
- it's a small loop (< 8 instructions), align it to 32-bytes. */
|
|
|
5de29b |
- .p2align 5
|
|
|
5de29b |
+
|
|
|
5de29b |
+ /* Main loop to look for BYTE in the string. Since
|
|
|
5de29b |
+ it's a small loop (8 instructions), align it to 32-bytes. */
|
|
|
5de29b |
+ .align 5
|
|
|
5de29b |
L(loop):
|
|
|
5de29b |
/* Load two words, compare and merge in a
|
|
|
5de29b |
single register for speed. This is an attempt
|
|
|
5de29b |
to speed up the byte-checking process for bigger strings. */
|
|
|
5de29b |
lwz r12,4(r8)
|
|
|
5de29b |
lwzu r11,8(r8)
|
|
|
5de29b |
- cmpb r10,r12,r4
|
|
|
5de29b |
+ cmpb r3,r12,r4
|
|
|
5de29b |
cmpb r9,r11,r4
|
|
|
5de29b |
- or r5,r9,r10 /* Merge everything in one word. */
|
|
|
5de29b |
- cmplwi cr7,r5,0
|
|
|
5de29b |
+ or r6,r9,r3 /* Merge everything in one word. */
|
|
|
5de29b |
+ cmplwi cr7,r6,0
|
|
|
5de29b |
bne cr7,L(found)
|
|
|
5de29b |
bdnz L(loop)
|
|
|
5de29b |
|
|
|
5de29b |
- /* We're here because the counter reached 0, and that means we
|
|
|
5de29b |
- didn't have any matches for BYTE in the whole range. */
|
|
|
5de29b |
- subi r11,r7,4
|
|
|
5de29b |
- cmplw cr6,r8,r11
|
|
|
5de29b |
- blt cr6,L(loop_small)
|
|
|
5de29b |
- b L(null)
|
|
|
5de29b |
+ /* We may have one more dword to read. */
|
|
|
5de29b |
+ cmplw r8,r7
|
|
|
5de29b |
+ beqlr
|
|
|
5de29b |
|
|
|
5de29b |
+ lwzu r12,4(r8)
|
|
|
5de29b |
+ cmpb r3,r12,r4
|
|
|
5de29b |
+ cmplwi cr6,r3,0
|
|
|
5de29b |
+ bne cr6,L(done)
|
|
|
5de29b |
+ blr
|
|
|
5de29b |
+
|
|
|
5de29b |
+ .align 4
|
|
|
5de29b |
+L(found):
|
|
|
5de29b |
/* OK, one (or both) of the words contains BYTE. Check
|
|
|
5de29b |
the first word and decrement the address in case the first
|
|
|
5de29b |
word really contains BYTE. */
|
|
|
5de29b |
- .align 4
|
|
|
5de29b |
-L(found):
|
|
|
5de29b |
- cmplwi cr6,r10,0
|
|
|
5de29b |
+ cmplwi cr6,r3,0
|
|
|
5de29b |
addi r8,r8,-4
|
|
|
5de29b |
bne cr6,L(done)
|
|
|
5de29b |
|
|
|
5de29b |
/* BYTE must be in the second word. Adjust the address
|
|
|
5de29b |
- again and move the result of cmpb to r10 so we can calculate the
|
|
|
5de29b |
+ again and move the result of cmpb to r3 so we can calculate the
|
|
|
5de29b |
pointer. */
|
|
|
5de29b |
|
|
|
5de29b |
- mr r10,r9
|
|
|
5de29b |
+ mr r3,r9
|
|
|
5de29b |
addi r8,r8,4
|
|
|
5de29b |
|
|
|
5de29b |
- /* r10 has the output of the cmpb instruction, that is, it contains
|
|
|
5de29b |
+ /* r3 has the output of the cmpb instruction, that is, it contains
|
|
|
5de29b |
0xff in the same position as BYTE in the original
|
|
|
5de29b |
word from the string. Use that to calculate the pointer.
|
|
|
5de29b |
We need to make sure BYTE is *before* the end of the range. */
|
|
|
5de29b |
L(done):
|
|
|
5de29b |
- cntlzw r0,r10 /* Count leading zeroes before the match. */
|
|
|
5de29b |
- srwi r0,r0,3 /* Convert leading zeroes to bytes. */
|
|
|
5de29b |
+#ifdef __LITTLE_ENDIAN__
|
|
|
5de29b |
+ addi r0,r3,-1
|
|
|
5de29b |
+ andc r0,r0,r3
|
|
|
5de29b |
+ popcntw r0,r0 /* Count trailing zeros. */
|
|
|
5de29b |
+#else
|
|
|
5de29b |
+ cntlzw r0,r3 /* Count leading zeros before the match. */
|
|
|
5de29b |
+#endif
|
|
|
5de29b |
+ cmplw r8,r7 /* Are we on the last word? */
|
|
|
5de29b |
+ srwi r0,r0,3 /* Convert leading/trailing zeros to bytes. */
|
|
|
5de29b |
add r3,r8,r0
|
|
|
5de29b |
- cmplw r3,r7
|
|
|
5de29b |
- bge L(null)
|
|
|
5de29b |
+ cmplw cr7,r0,r5 /* If on the last dword, check byte offset. */
|
|
|
5de29b |
+ bnelr
|
|
|
5de29b |
+ blelr cr7
|
|
|
5de29b |
+ li r3,0
|
|
|
5de29b |
blr
|
|
|
5de29b |
|
|
|
5de29b |
.align 4
|
|
|
5de29b |
@@ -139,69 +141,44 @@
|
|
|
5de29b |
.align 4
|
|
|
5de29b |
L(small_range):
|
|
|
5de29b |
cmplwi r5,0
|
|
|
5de29b |
- rlwinm r6,r3,3,27,28 /* Calculate padding. */
|
|
|
5de29b |
- beq L(null) /* This branch is for the cmplwi r5,0 above */
|
|
|
5de29b |
+ beq L(null)
|
|
|
5de29b |
lwz r12,0(r8) /* Load word from memory. */
|
|
|
5de29b |
- cmplwi cr6,r6,0 /* cr6 == Do we have padding? */
|
|
|
5de29b |
- cmpb r10,r12,r4 /* Check for BYTE in DWORD1. */
|
|
|
5de29b |
- beq cr6,L(small_no_padding)
|
|
|
5de29b |
- slw r10,r10,r6
|
|
|
5de29b |
- srw r10,r10,r6
|
|
|
5de29b |
-L(small_no_padding):
|
|
|
5de29b |
- cmplwi cr7,r10,0
|
|
|
5de29b |
+ cmpb r3,r12,r4 /* Check for BYTE in DWORD1. */
|
|
|
5de29b |
+ and r3,r3,r9
|
|
|
5de29b |
+ cmplwi cr7,r3,0
|
|
|
5de29b |
+ clrlwi r5,r7,30 /* Byte count - 1 in last word. */
|
|
|
5de29b |
+ clrrwi r7,r7,2 /* Address of last word. */
|
|
|
5de29b |
+ cmplw r8,r7 /* Are we done already? */
|
|
|
5de29b |
bne cr7,L(done)
|
|
|
5de29b |
+ beqlr
|
|
|
5de29b |
|
|
|
5de29b |
- /* Are we done already? */
|
|
|
5de29b |
- addi r9,r8,4
|
|
|
5de29b |
- cmplw r9,r7
|
|
|
5de29b |
- bge L(null)
|
|
|
5de29b |
-
|
|
|
5de29b |
-L(loop_small): /* loop_small has been unrolled. */
|
|
|
5de29b |
lwzu r12,4(r8)
|
|
|
5de29b |
- cmpb r10,r12,r4
|
|
|
5de29b |
- addi r9,r8,4
|
|
|
5de29b |
- cmplwi cr6,r10,0
|
|
|
5de29b |
- cmplw r9,r7
|
|
|
5de29b |
+ cmpb r3,r12,r4
|
|
|
5de29b |
+ cmplwi cr6,r3,0
|
|
|
5de29b |
+ cmplw r8,r7
|
|
|
5de29b |
bne cr6,L(done)
|
|
|
5de29b |
- bge L(null)
|
|
|
5de29b |
+ beqlr
|
|
|
5de29b |
|
|
|
5de29b |
lwzu r12,4(r8)
|
|
|
5de29b |
- cmpb r10,r12,r4
|
|
|
5de29b |
- addi r9,r8,4
|
|
|
5de29b |
- cmplwi cr6,r10,0
|
|
|
5de29b |
- cmplw r9,r7
|
|
|
5de29b |
+ cmpb r3,r12,r4
|
|
|
5de29b |
+ cmplwi cr6,r3,0
|
|
|
5de29b |
+ cmplw r8,r7
|
|
|
5de29b |
bne cr6,L(done)
|
|
|
5de29b |
- bge L(null)
|
|
|
5de29b |
+ beqlr
|
|
|
5de29b |
|
|
|
5de29b |
lwzu r12,4(r8)
|
|
|
5de29b |
- cmpb r10,r12,r4
|
|
|
5de29b |
- addi r9,r8,4
|
|
|
5de29b |
- cmplwi cr6,r10,0
|
|
|
5de29b |
- cmplw r9,r7
|
|
|
5de29b |
+ cmpb r3,r12,r4
|
|
|
5de29b |
+ cmplwi cr6,r3,0
|
|
|
5de29b |
+ cmplw r8,r7
|
|
|
5de29b |
bne cr6,L(done)
|
|
|
5de29b |
- bge L(null)
|
|
|
5de29b |
+ beqlr
|
|
|
5de29b |
|
|
|
5de29b |
lwzu r12,4(r8)
|
|
|
5de29b |
- cmpb r10,r12,r4
|
|
|
5de29b |
- addi r9,r8,4
|
|
|
5de29b |
- cmplwi cr6,r10,0
|
|
|
5de29b |
- cmplw r9,r7
|
|
|
5de29b |
+ cmpb r3,r12,r4
|
|
|
5de29b |
+ cmplwi cr6,r3,0
|
|
|
5de29b |
bne cr6,L(done)
|
|
|
5de29b |
- bge L(null)
|
|
|
5de29b |
-
|
|
|
5de29b |
- /* For most cases we will never get here. Under some combinations of
|
|
|
5de29b |
- padding + length there is a leftover word that still needs to be
|
|
|
5de29b |
- checked. */
|
|
|
5de29b |
- lwzu r12,4(r8)
|
|
|
5de29b |
- cmpb r10,r12,r4
|
|
|
5de29b |
- addi r9,r8,4
|
|
|
5de29b |
- cmplwi cr6,r10,0
|
|
|
5de29b |
- bne cr6,L(done)
|
|
|
5de29b |
-
|
|
|
5de29b |
- /* save a branch and exit directly */
|
|
|
5de29b |
- li r3,0
|
|
|
5de29b |
blr
|
|
|
5de29b |
|
|
|
5de29b |
-END (BP_SYM (__memchr))
|
|
|
5de29b |
-weak_alias (BP_SYM (__memchr), BP_SYM(memchr))
|
|
|
5de29b |
+END (__memchr)
|
|
|
5de29b |
+weak_alias (__memchr, memchr)
|
|
|
5de29b |
libc_hidden_builtin_def (memchr)
|
|
|
12745e |
diff -urN glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power7/memrchr.S glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power7/memrchr.S
|
|
|
12745e |
--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power7/memrchr.S 2014-05-29 13:09:17.000000000 -0500
|
|
|
12745e |
+++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power7/memrchr.S 2014-05-29 13:13:47.000000000 -0500
|
|
|
5de29b |
@@ -1,5 +1,5 @@
|
|
|
5de29b |
/* Optimized memrchr implementation for PowerPC32/POWER7 using cmpb insn.
|
|
|
5de29b |
- Copyright (C) 2010 Free Software Foundation, Inc.
|
|
|
5de29b |
+ Copyright (C) 2010-2014 Free Software Foundation, Inc.
|
|
|
5de29b |
Contributed by Luis Machado <luisgpm@br.ibm.com>.
|
|
|
5de29b |
This file is part of the GNU C Library.
|
|
|
5de29b |
|
|
|
5de29b |
@@ -18,124 +18,136 @@
|
|
|
5de29b |
<http://www.gnu.org/licenses/>. */
|
|
|
5de29b |
|
|
|
5de29b |
#include <sysdep.h>
|
|
|
5de29b |
-#include <bp-sym.h>
|
|
|
5de29b |
-#include <bp-asm.h>
|
|
|
5de29b |
|
|
|
5de29b |
/* int [r3] memrchr (char *s [r3], int byte [r4], int size [r5]) */
|
|
|
5de29b |
.machine power7
|
|
|
5de29b |
-ENTRY (BP_SYM (__memrchr))
|
|
|
5de29b |
+ENTRY (__memrchr)
|
|
|
5de29b |
CALL_MCOUNT
|
|
|
5de29b |
- dcbt 0,r3
|
|
|
5de29b |
- mr r7,r3
|
|
|
5de29b |
- add r3,r7,r5 /* Calculate the last acceptable address. */
|
|
|
5de29b |
- cmplw cr7,r3,r7 /* Is the address equal or less than r3? */
|
|
|
5de29b |
+ add r7,r3,r5 /* Calculate the last acceptable address. */
|
|
|
5de29b |
+ neg r0,r7
|
|
|
5de29b |
+ addi r7,r7,-1
|
|
|
5de29b |
+ mr r10,r3
|
|
|
5de29b |
+ clrrwi r6,r7,7
|
|
|
5de29b |
+ li r9,3<<5
|
|
|
5de29b |
+ dcbt r9,r6,16 /* Stream hint, decreasing addresses. */
|
|
|
5de29b |
|
|
|
5de29b |
/* Replicate BYTE to word. */
|
|
|
5de29b |
- rlwimi r4,r4,8,16,23
|
|
|
5de29b |
- rlwimi r4,r4,16,0,15
|
|
|
5de29b |
- bge cr7,L(proceed)
|
|
|
5de29b |
-
|
|
|
5de29b |
- li r3,-1 /* Make r11 the biggest if r4 <= 0. */
|
|
|
5de29b |
-L(proceed):
|
|
|
5de29b |
+ insrwi r4,r4,8,16
|
|
|
5de29b |
+ insrwi r4,r4,16,0
|
|
|
5de29b |
li r6,-4
|
|
|
5de29b |
- addi r9,r3,-1
|
|
|
5de29b |
- clrrwi r8,r9,2
|
|
|
5de29b |
- addi r8,r8,4
|
|
|
5de29b |
- neg r0,r3
|
|
|
5de29b |
+ li r9,-1
|
|
|
5de29b |
rlwinm r0,r0,3,27,28 /* Calculate padding. */
|
|
|
5de29b |
-
|
|
|
5de29b |
+ clrrwi r8,r7,2
|
|
|
5de29b |
+ srw r9,r9,r0
|
|
|
5de29b |
cmplwi r5,16
|
|
|
5de29b |
+ clrrwi r0,r10,2
|
|
|
5de29b |
ble L(small_range)
|
|
|
5de29b |
|
|
|
5de29b |
- lwbrx r12,r8,r6 /* Load reversed word from memory. */
|
|
|
5de29b |
- cmpb r10,r12,r4 /* Check for BYTE in WORD1. */
|
|
|
5de29b |
- slw r10,r10,r0
|
|
|
5de29b |
- srw r10,r10,r0
|
|
|
5de29b |
- cmplwi cr7,r10,0 /* If r10 == 0, no BYTE's have been found. */
|
|
|
5de29b |
+#ifdef __LITTLE_ENDIAN__
|
|
|
5de29b |
+ lwzx r12,0,r8
|
|
|
5de29b |
+#else
|
|
|
5de29b |
+ lwbrx r12,0,r8 /* Load reversed word from memory. */
|
|
|
5de29b |
+#endif
|
|
|
5de29b |
+ cmpb r3,r12,r4 /* Check for BYTE in WORD1. */
|
|
|
5de29b |
+ and r3,r3,r9
|
|
|
5de29b |
+ cmplwi cr7,r3,0 /* If r3 == 0, no BYTEs have been found. */
|
|
|
5de29b |
bne cr7,L(done)
|
|
|
5de29b |
|
|
|
5de29b |
- /* Are we done already? */
|
|
|
5de29b |
- addi r9,r8,-4
|
|
|
5de29b |
- cmplw cr6,r9,r7
|
|
|
5de29b |
- ble cr6,L(null)
|
|
|
5de29b |
-
|
|
|
5de29b |
mtcrf 0x01,r8
|
|
|
5de29b |
/* Are we now aligned to a doubleword boundary? If so, skip to
|
|
|
5de29b |
the main loop. Otherwise, go through the alignment code. */
|
|
|
5de29b |
- mr r8,r9
|
|
|
5de29b |
- bt 29,L(loop_setup)
|
|
|
5de29b |
+ bf 29,L(loop_setup)
|
|
|
5de29b |
|
|
|
5de29b |
/* Handle WORD2 of pair. */
|
|
|
5de29b |
+#ifdef __LITTLE_ENDIAN__
|
|
|
5de29b |
+ lwzx r12,r8,r6
|
|
|
5de29b |
+#else
|
|
|
5de29b |
lwbrx r12,r8,r6
|
|
|
5de29b |
- cmpb r10,r12,r4
|
|
|
5de29b |
- cmplwi cr7,r10,0
|
|
|
5de29b |
- bne cr7,L(done)
|
|
|
5de29b |
-
|
|
|
5de29b |
- /* Are we done already? */
|
|
|
5de29b |
+#endif
|
|
|
5de29b |
addi r8,r8,-4
|
|
|
5de29b |
- cmplw cr6,r8,r7
|
|
|
5de29b |
- ble cr6,L(null)
|
|
|
5de29b |
+ cmpb r3,r12,r4
|
|
|
5de29b |
+ cmplwi cr7,r3,0
|
|
|
5de29b |
+ bne cr7,L(done)
|
|
|
5de29b |
|
|
|
5de29b |
L(loop_setup):
|
|
|
5de29b |
- li r0,-8
|
|
|
5de29b |
- sub r5,r8,r7
|
|
|
5de29b |
- srwi r9,r5,3 /* Number of loop iterations. */
|
|
|
5de29b |
+ /* The last word we want to read in the loop below is the one
|
|
|
5de29b |
+ containing the first byte of the string, ie. the word at
|
|
|
5de29b |
+ s & ~3, or r0. The first word read is at r8 - 4, we
|
|
|
5de29b |
+ read 2 * cnt words, so the last word read will be at
|
|
|
5de29b |
+ r8 - 4 - 8 * cnt + 4. Solving for cnt gives
|
|
|
5de29b |
+ cnt = (r8 - r0) / 8 */
|
|
|
5de29b |
+ sub r5,r8,r0
|
|
|
5de29b |
+ addi r8,r8,-4
|
|
|
5de29b |
+ srwi r9,r5,3 /* Number of loop iterations. */
|
|
|
5de29b |
mtctr r9 /* Setup the counter. */
|
|
|
5de29b |
- b L(loop)
|
|
|
5de29b |
- /* Main loop to look for BYTE backwards in the string. Since it's a
|
|
|
5de29b |
- small loop (< 8 instructions), align it to 32-bytes. */
|
|
|
5de29b |
- .p2align 5
|
|
|
5de29b |
+
|
|
|
5de29b |
+ /* Main loop to look for BYTE backwards in the string.
|
|
|
5de29b |
+ FIXME: Investigate whether 32 byte align helps with this
|
|
|
5de29b |
+ 9 instruction loop. */
|
|
|
5de29b |
+ .align 5
|
|
|
5de29b |
L(loop):
|
|
|
5de29b |
/* Load two words, compare and merge in a
|
|
|
5de29b |
single register for speed. This is an attempt
|
|
|
5de29b |
to speed up the byte-checking process for bigger strings. */
|
|
|
5de29b |
|
|
|
5de29b |
- lwbrx r12,r8,r6
|
|
|
5de29b |
- lwbrx r11,r8,r0
|
|
|
5de29b |
- addi r8,r8,-4
|
|
|
5de29b |
- cmpb r10,r12,r4
|
|
|
5de29b |
+#ifdef __LITTLE_ENDIAN__
|
|
|
5de29b |
+ lwzx r12,0,r8
|
|
|
5de29b |
+ lwzx r11,r8,r6
|
|
|
5de29b |
+#else
|
|
|
5de29b |
+ lwbrx r12,0,r8
|
|
|
5de29b |
+ lwbrx r11,r8,r6
|
|
|
5de29b |
+#endif
|
|
|
5de29b |
+ cmpb r3,r12,r4
|
|
|
5de29b |
cmpb r9,r11,r4
|
|
|
5de29b |
- or r5,r9,r10 /* Merge everything in one word. */
|
|
|
5de29b |
+ or r5,r9,r3 /* Merge everything in one word. */
|
|
|
5de29b |
cmplwi cr7,r5,0
|
|
|
5de29b |
bne cr7,L(found)
|
|
|
5de29b |
- addi r8,r8,-4
|
|
|
5de29b |
+ addi r8,r8,-8
|
|
|
5de29b |
bdnz L(loop)
|
|
|
5de29b |
- /* We're here because the counter reached 0, and that means we
|
|
|
5de29b |
- didn't have any matches for BYTE in the whole range. Just return
|
|
|
5de29b |
- the original range. */
|
|
|
5de29b |
- addi r9,r8,4
|
|
|
5de29b |
- cmplw cr6,r9,r7
|
|
|
5de29b |
- bgt cr6,L(loop_small)
|
|
|
5de29b |
- b L(null)
|
|
|
5de29b |
|
|
|
5de29b |
- /* OK, one (or both) of the words contains BYTE. Check
|
|
|
5de29b |
- the first word and decrement the address in case the first
|
|
|
5de29b |
- word really contains BYTE. */
|
|
|
5de29b |
+ /* We may have one more word to read. */
|
|
|
5de29b |
+ cmplw r8,r0
|
|
|
5de29b |
+ bnelr
|
|
|
5de29b |
+
|
|
|
5de29b |
+#ifdef __LITTLE_ENDIAN__
|
|
|
5de29b |
+ lwzx r12,0,r8
|
|
|
5de29b |
+#else
|
|
|
5de29b |
+ lwbrx r12,0,r8
|
|
|
5de29b |
+#endif
|
|
|
5de29b |
+ cmpb r3,r12,r4
|
|
|
5de29b |
+ cmplwi cr7,r3,0
|
|
|
5de29b |
+ bne cr7,L(done)
|
|
|
5de29b |
+ blr
|
|
|
5de29b |
+
|
|
|
5de29b |
.align 4
|
|
|
5de29b |
L(found):
|
|
|
5de29b |
- cmplwi cr6,r10,0
|
|
|
5de29b |
- addi r8,r8,4
|
|
|
5de29b |
+ /* OK, one (or both) of the words contains BYTE. Check
|
|
|
5de29b |
+ the first word. */
|
|
|
5de29b |
+ cmplwi cr6,r3,0
|
|
|
5de29b |
bne cr6,L(done)
|
|
|
5de29b |
|
|
|
5de29b |
/* BYTE must be in the second word. Adjust the address
|
|
|
5de29b |
- again and move the result of cmpb to r10 so we can calculate the
|
|
|
5de29b |
+ again and move the result of cmpb to r3 so we can calculate the
|
|
|
5de29b |
pointer. */
|
|
|
5de29b |
|
|
|
5de29b |
- mr r10,r9
|
|
|
5de29b |
+ mr r3,r9
|
|
|
5de29b |
addi r8,r8,-4
|
|
|
5de29b |
|
|
|
5de29b |
- /* r10 has the output of the cmpb instruction, that is, it contains
|
|
|
5de29b |
+ /* r3 has the output of the cmpb instruction, that is, it contains
|
|
|
5de29b |
0xff in the same position as BYTE in the original
|
|
|
5de29b |
word from the string. Use that to calculate the pointer.
|
|
|
5de29b |
We need to make sure BYTE is *before* the end of the
|
|
|
5de29b |
range. */
|
|
|
5de29b |
L(done):
|
|
|
5de29b |
- cntlzw r0,r10 /* Count leading zeroes before the match. */
|
|
|
5de29b |
- srwi r6,r0,3 /* Convert leading zeroes to bytes. */
|
|
|
5de29b |
- addi r0,r6,1
|
|
|
5de29b |
+ cntlzw r9,r3 /* Count leading zeros before the match. */
|
|
|
5de29b |
+ cmplw r8,r0 /* Are we on the last word? */
|
|
|
5de29b |
+ srwi r6,r9,3 /* Convert leading zeros to bytes. */
|
|
|
5de29b |
+ addi r0,r6,-3
|
|
|
5de29b |
sub r3,r8,r0
|
|
|
5de29b |
- cmplw r3,r7
|
|
|
5de29b |
- blt L(null)
|
|
|
5de29b |
+ cmplw cr7,r3,r10
|
|
|
5de29b |
+ bnelr
|
|
|
5de29b |
+ bgelr cr7
|
|
|
5de29b |
+ li r3,0
|
|
|
5de29b |
blr
|
|
|
5de29b |
|
|
|
5de29b |
.align 4
|
|
|
5de29b |
@@ -149,29 +161,36 @@
|
|
|
5de29b |
cmplwi r5,0
|
|
|
5de29b |
beq L(null)
|
|
|
5de29b |
|
|
|
5de29b |
- lwbrx r12,r8,r6 /* Load reversed word from memory. */
|
|
|
5de29b |
- cmpb r10,r12,r4 /* Check for null bytes in WORD1. */
|
|
|
5de29b |
- slw r10,r10,r0
|
|
|
5de29b |
- srw r10,r10,r0
|
|
|
5de29b |
- cmplwi cr7,r10,0
|
|
|
5de29b |
+#ifdef __LITTLE_ENDIAN__
|
|
|
5de29b |
+ lwzx r12,0,r8
|
|
|
5de29b |
+#else
|
|
|
5de29b |
+ lwbrx r12,0,r8 /* Load reversed word from memory. */
|
|
|
5de29b |
+#endif
|
|
|
5de29b |
+ cmpb r3,r12,r4 /* Check for BYTE in WORD1. */
|
|
|
5de29b |
+ and r3,r3,r9
|
|
|
5de29b |
+ cmplwi cr7,r3,0
|
|
|
5de29b |
bne cr7,L(done)
|
|
|
5de29b |
|
|
|
5de29b |
+ /* Are we done already? */
|
|
|
5de29b |
+ cmplw r8,r0
|
|
|
5de29b |
addi r8,r8,-4
|
|
|
5de29b |
- cmplw r8,r7
|
|
|
5de29b |
- ble L(null)
|
|
|
5de29b |
- b L(loop_small)
|
|
|
5de29b |
+ beqlr
|
|
|
5de29b |
|
|
|
5de29b |
- .p2align 5
|
|
|
5de29b |
+ .align 5
|
|
|
5de29b |
L(loop_small):
|
|
|
5de29b |
- lwbrx r12,r8,r6
|
|
|
5de29b |
- cmpb r10,r12,r4
|
|
|
5de29b |
- cmplwi cr6,r10,0
|
|
|
5de29b |
- bne cr6,L(done)
|
|
|
5de29b |
+#ifdef __LITTLE_ENDIAN__
|
|
|
5de29b |
+ lwzx r12,0,r8
|
|
|
5de29b |
+#else
|
|
|
5de29b |
+ lwbrx r12,0,r8
|
|
|
5de29b |
+#endif
|
|
|
5de29b |
+ cmpb r3,r12,r4
|
|
|
5de29b |
+ cmplw r8,r0
|
|
|
5de29b |
+ cmplwi cr7,r3,0
|
|
|
5de29b |
+ bne cr7,L(done)
|
|
|
5de29b |
addi r8,r8,-4
|
|
|
5de29b |
- cmplw r8,r7
|
|
|
5de29b |
- ble L(null)
|
|
|
5de29b |
- b L(loop_small)
|
|
|
5de29b |
+ bne L(loop_small)
|
|
|
5de29b |
+ blr
|
|
|
5de29b |
|
|
|
5de29b |
-END (BP_SYM (__memrchr))
|
|
|
5de29b |
-weak_alias (BP_SYM (__memrchr), BP_SYM(memrchr))
|
|
|
5de29b |
+END (__memrchr)
|
|
|
5de29b |
+weak_alias (__memrchr, memrchr)
|
|
|
5de29b |
libc_hidden_builtin_def (memrchr)
|
|
|
12745e |
diff -urN glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power7/rawmemchr.S glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power7/rawmemchr.S
|
|
|
12745e |
--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power7/rawmemchr.S 2014-05-29 13:09:17.000000000 -0500
|
|
|
12745e |
+++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc32/power7/rawmemchr.S 2014-05-29 13:09:19.000000000 -0500
|
|
|
5de29b |
@@ -29,16 +29,21 @@
|
|
|
5de29b |
clrrwi r8,r3,2 /* Align the address to word boundary. */
|
|
|
5de29b |
|
|
|
5de29b |
/* Replicate byte to word. */
|
|
|
5de29b |
- rlwimi r4,r4,8,16,23
|
|
|
5de29b |
- rlwimi r4,r4,16,0,15
|
|
|
5de29b |
+ rldimi r4,r4,8,48
|
|
|
5de29b |
+ rldimi r4,r4,16,32
|
|
|
5de29b |
|
|
|
5de29b |
/* Now r4 has a word of c bytes. */
|
|
|
5de29b |
|
|
|
5de29b |
rlwinm r6,r3,3,27,28 /* Calculate padding. */
|
|
|
5de29b |
lwz r12,0(r8) /* Load word from memory. */
|
|
|
5de29b |
cmpb r5,r12,r4 /* Compare each byte against c byte. */
|
|
|
5de29b |
+#ifdef __LITTLE_ENDIAN__
|
|
|
5de29b |
+ srw r5,r5,r6
|
|
|
5de29b |
+ slw r5,r5,r6
|
|
|
5de29b |
+#else
|
|
|
5de29b |
slw r5,r5,r6 /* Move left to discard ignored bits. */
|
|
|
5de29b |
srw r5,r5,r6 /* Bring the bits back as zeros. */
|
|
|
5de29b |
+#endif
|
|
|
5de29b |
cmpwi cr7,r5,0 /* If r5 == 0, no c bytes have been found. */
|
|
|
5de29b |
bne cr7,L(done)
|
|
|
5de29b |
|
|
|
5de29b |
@@ -92,8 +97,14 @@
|
|
|
5de29b |
word from the string. Use that fact to find out what is
|
|
|
5de29b |
the position of the byte inside the string. */
|
|
|
5de29b |
L(done):
|
|
|
5de29b |
+#ifdef __LITTLE_ENDIAN__
|
|
|
5de29b |
+ addi r0,r5,-1
|
|
|
5de29b |
+ andc r0,r0,r5
|
|
|
5de29b |
+ popcntw r0,r0
|
|
|
5de29b |
+#else
|
|
|
5de29b |
cntlzw r0,r5 /* Count leading zeros before the match. */
|
|
|
5de29b |
- srwi r0,r0,3 /* Convert leading zeroes to bytes. */
|
|
|
5de29b |
+#endif
|
|
|
5de29b |
+ srwi r0,r0,3 /* Convert leading zeros to bytes. */
|
|
|
5de29b |
add r3,r8,r0 /* Return address of the matching char. */
|
|
|
5de29b |
blr
|
|
|
5de29b |
END (BP_SYM (__rawmemchr))
|
|
|
12745e |
diff -urN glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/power7/memchr.S glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/power7/memchr.S
|
|
|
12745e |
--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/power7/memchr.S 2014-05-29 13:09:17.000000000 -0500
|
|
|
12745e |
+++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/power7/memchr.S 2014-05-29 13:13:57.000000000 -0500
|
|
|
5de29b |
@@ -1,5 +1,5 @@
|
|
|
5de29b |
/* Optimized memchr implementation for PowerPC64/POWER7 using cmpb insn.
|
|
|
5de29b |
- Copyright (C) 2010-2012 Free Software Foundation, Inc.
|
|
|
5de29b |
+ Copyright (C) 2010-2014 Free Software Foundation, Inc.
|
|
|
5de29b |
Contributed by Luis Machado <luisgpm@br.ibm.com>.
|
|
|
5de29b |
This file is part of the GNU C Library.
|
|
|
5de29b |
|
|
|
5de29b |
@@ -18,118 +18,119 @@
|
|
|
5de29b |
<http://www.gnu.org/licenses/>. */
|
|
|
5de29b |
|
|
|
5de29b |
#include <sysdep.h>
|
|
|
5de29b |
-#include <bp-sym.h>
|
|
|
5de29b |
-#include <bp-asm.h>
|
|
|
5de29b |
|
|
|
5de29b |
/* int [r3] memchr (char *s [r3], int byte [r4], int size [r5]) */
|
|
|
5de29b |
.machine power7
|
|
|
5de29b |
-ENTRY (BP_SYM (__memchr))
|
|
|
5de29b |
- CALL_MCOUNT 2
|
|
|
5de29b |
+ENTRY (__memchr)
|
|
|
5de29b |
+ CALL_MCOUNT 3
|
|
|
5de29b |
dcbt 0,r3
|
|
|
5de29b |
clrrdi r8,r3,3
|
|
|
5de29b |
- rlwimi r4,r4,8,16,23
|
|
|
5de29b |
- rlwimi r4,r4,16,0,15
|
|
|
5de29b |
+ insrdi r4,r4,8,48
|
|
|
5de29b |
add r7,r3,r5 /* Calculate the last acceptable address. */
|
|
|
5de29b |
+ insrdi r4,r4,16,32
|
|
|
5de29b |
cmpldi r5,32
|
|
|
5de29b |
+ li r9, -1
|
|
|
5de29b |
+ rlwinm r6,r3,3,26,28 /* Calculate padding. */
|
|
|
5de29b |
insrdi r4,r4,32,0
|
|
|
5de29b |
+ addi r7,r7,-1
|
|
|
5de29b |
+#ifdef __LITTLE_ENDIAN__
|
|
|
5de29b |
+ sld r9,r9,r6
|
|
|
5de29b |
+#else
|
|
|
5de29b |
+ srd r9,r9,r6
|
|
|
5de29b |
+#endif
|
|
|
5de29b |
ble L(small_range)
|
|
|
5de29b |
|
|
|
5de29b |
- cmpld cr7,r3,r7 /* Compare the starting address (r3) with the
|
|
|
5de29b |
- ending address (r7). If (r3 >= r7),
|
|
|
5de29b |
- the size passed in was zero or negative. */
|
|
|
5de29b |
- ble cr7,L(proceed)
|
|
|
5de29b |
-
|
|
|
5de29b |
- li r7,-1 /* Artificially set our ending address (r7)
|
|
|
5de29b |
- such that we will exit early. */
|
|
|
5de29b |
-
|
|
|
5de29b |
-L(proceed):
|
|
|
5de29b |
- rlwinm r6,r3,3,26,28 /* Calculate padding. */
|
|
|
5de29b |
- cmpldi cr6,r6,0 /* cr6 == Do we have padding? */
|
|
|
5de29b |
ld r12,0(r8) /* Load doubleword from memory. */
|
|
|
5de29b |
- cmpb r10,r12,r4 /* Check for BYTEs in DWORD1. */
|
|
|
5de29b |
- beq cr6,L(proceed_no_padding)
|
|
|
5de29b |
- sld r10,r10,r6
|
|
|
5de29b |
- srd r10,r10,r6
|
|
|
5de29b |
-L(proceed_no_padding):
|
|
|
5de29b |
- cmpldi cr7,r10,0 /* Does r10 indicate we got a hit? */
|
|
|
5de29b |
+ cmpb r3,r12,r4 /* Check for BYTEs in DWORD1. */
|
|
|
5de29b |
+ and r3,r3,r9
|
|
|
5de29b |
+ clrldi r5,r7,61 /* Byte count - 1 in last dword. */
|
|
|
5de29b |
+ clrrdi r7,r7,3 /* Address of last doubleword. */
|
|
|
5de29b |
+ cmpldi cr7,r3,0 /* Does r3 indicate we got a hit? */
|
|
|
5de29b |
bne cr7,L(done)
|
|
|
5de29b |
|
|
|
5de29b |
- /* See if we are at the last acceptable address yet. */
|
|
|
5de29b |
- addi r9,r8,8
|
|
|
5de29b |
- cmpld cr6,r9,r7
|
|
|
5de29b |
- bge cr6,L(null)
|
|
|
5de29b |
-
|
|
|
5de29b |
mtcrf 0x01,r8
|
|
|
5de29b |
/* Are we now aligned to a quadword boundary? If so, skip to
|
|
|
5de29b |
the main loop. Otherwise, go through the alignment code. */
|
|
|
5de29b |
-
|
|
|
5de29b |
bt 28,L(loop_setup)
|
|
|
5de29b |
|
|
|
5de29b |
/* Handle DWORD2 of pair. */
|
|
|
5de29b |
ldu r12,8(r8)
|
|
|
5de29b |
- cmpb r10,r12,r4
|
|
|
5de29b |
- cmpldi cr7,r10,0
|
|
|
5de29b |
+ cmpb r3,r12,r4
|
|
|
5de29b |
+ cmpldi cr7,r3,0
|
|
|
5de29b |
bne cr7,L(done)
|
|
|
5de29b |
|
|
|
5de29b |
- /* Are we done already? */
|
|
|
5de29b |
- addi r9,r8,8
|
|
|
5de29b |
- cmpld cr6,r9,r7
|
|
|
5de29b |
- bge cr6,L(null)
|
|
|
5de29b |
-
|
|
|
5de29b |
L(loop_setup):
|
|
|
5de29b |
- sub r5,r7,r9
|
|
|
5de29b |
- srdi r6,r5,4 /* Number of loop iterations. */
|
|
|
5de29b |
+ /* The last dword we want to read in the loop below is the one
|
|
|
5de29b |
+ containing the last byte of the string, ie. the dword at
|
|
|
5de29b |
+ (s + size - 1) & ~7, or r7. The first dword read is at
|
|
|
5de29b |
+ r8 + 8, we read 2 * cnt dwords, so the last dword read will
|
|
|
5de29b |
+ be at r8 + 8 + 16 * cnt - 8. Solving for cnt gives
|
|
|
5de29b |
+ cnt = (r7 - r8) / 16 */
|
|
|
5de29b |
+ sub r6,r7,r8
|
|
|
5de29b |
+ srdi r6,r6,4 /* Number of loop iterations. */
|
|
|
5de29b |
mtctr r6 /* Setup the counter. */
|
|
|
5de29b |
- b L(loop)
|
|
|
5de29b |
- /* Main loop to look for BYTE backwards in the string. Since
|
|
|
5de29b |
- it's a small loop (< 8 instructions), align it to 32-bytes. */
|
|
|
5de29b |
- .p2align 5
|
|
|
5de29b |
+
|
|
|
5de29b |
+ /* Main loop to look for BYTE in the string. Since
|
|
|
5de29b |
+ it's a small loop (8 instructions), align it to 32-bytes. */
|
|
|
5de29b |
+ .align 5
|
|
|
5de29b |
L(loop):
|
|
|
5de29b |
/* Load two doublewords, compare and merge in a
|
|
|
5de29b |
single register for speed. This is an attempt
|
|
|
5de29b |
to speed up the byte-checking process for bigger strings. */
|
|
|
5de29b |
ld r12,8(r8)
|
|
|
5de29b |
ldu r11,16(r8)
|
|
|
5de29b |
- cmpb r10,r12,r4
|
|
|
5de29b |
+ cmpb r3,r12,r4
|
|
|
5de29b |
cmpb r9,r11,r4
|
|
|
5de29b |
- or r5,r9,r10 /* Merge everything in one doubleword. */
|
|
|
5de29b |
- cmpldi cr7,r5,0
|
|
|
5de29b |
+ or r6,r9,r3 /* Merge everything in one doubleword. */
|
|
|
5de29b |
+ cmpldi cr7,r6,0
|
|
|
5de29b |
bne cr7,L(found)
|
|
|
5de29b |
bdnz L(loop)
|
|
|
5de29b |
|
|
|
5de29b |
- /* We're here because the counter reached 0, and that means we
|
|
|
5de29b |
- didn't have any matches for BYTE in the whole range. */
|
|
|
5de29b |
- subi r11,r7,8
|
|
|
5de29b |
- cmpld cr6,r8,r11
|
|
|
5de29b |
- blt cr6,L(loop_small)
|
|
|
5de29b |
- b L(null)
|
|
|
5de29b |
+ /* We may have one more dword to read. */
|
|
|
5de29b |
+ cmpld r8,r7
|
|
|
5de29b |
+ beqlr
|
|
|
5de29b |
|
|
|
5de29b |
+ ldu r12,8(r8)
|
|
|
5de29b |
+ cmpb r3,r12,r4
|
|
|
5de29b |
+ cmpldi cr6,r3,0
|
|
|
5de29b |
+ bne cr6,L(done)
|
|
|
5de29b |
+ blr
|
|
|
5de29b |
+
|
|
|
5de29b |
+ .align 4
|
|
|
5de29b |
+L(found):
|
|
|
5de29b |
/* OK, one (or both) of the doublewords contains BYTE. Check
|
|
|
5de29b |
the first doubleword and decrement the address in case the first
|
|
|
5de29b |
doubleword really contains BYTE. */
|
|
|
5de29b |
- .align 4
|
|
|
5de29b |
-L(found):
|
|
|
5de29b |
- cmpldi cr6,r10,0
|
|
|
5de29b |
+ cmpldi cr6,r3,0
|
|
|
5de29b |
addi r8,r8,-8
|
|
|
5de29b |
bne cr6,L(done)
|
|
|
5de29b |
|
|
|
5de29b |
/* BYTE must be in the second doubleword. Adjust the address
|
|
|
5de29b |
- again and move the result of cmpb to r10 so we can calculate the
|
|
|
5de29b |
+ again and move the result of cmpb to r3 so we can calculate the
|
|
|
5de29b |
pointer. */
|
|
|
5de29b |
|
|
|
5de29b |
- mr r10,r9
|
|
|
5de29b |
+ mr r3,r9
|
|
|
5de29b |
addi r8,r8,8
|
|
|
5de29b |
|
|
|
5de29b |
- /* r10 has the output of the cmpb instruction, that is, it contains
|
|
|
5de29b |
+ /* r3 has the output of the cmpb instruction, that is, it contains
|
|
|
5de29b |
0xff in the same position as BYTE in the original
|
|
|
5de29b |
doubleword from the string. Use that to calculate the pointer.
|
|
|
5de29b |
We need to make sure BYTE is *before* the end of the range. */
|
|
|
5de29b |
L(done):
|
|
|
5de29b |
- cntlzd r0,r10 /* Count leading zeroes before the match. */
|
|
|
5de29b |
- srdi r0,r0,3 /* Convert leading zeroes to bytes. */
|
|
|
5de29b |
+#ifdef __LITTLE_ENDIAN__
|
|
|
5de29b |
+ addi r0,r3,-1
|
|
|
5de29b |
+ andc r0,r0,r3
|
|
|
5de29b |
+ popcntd r0,r0 /* Count trailing zeros. */
|
|
|
5de29b |
+#else
|
|
|
5de29b |
+ cntlzd r0,r3 /* Count leading zeros before the match. */
|
|
|
5de29b |
+#endif
|
|
|
5de29b |
+ cmpld r8,r7 /* Are we on the last dword? */
|
|
|
5de29b |
+ srdi r0,r0,3 /* Convert leading/trailing zeros to bytes. */
|
|
|
5de29b |
add r3,r8,r0
|
|
|
5de29b |
- cmpld r3,r7
|
|
|
5de29b |
- bge L(null)
|
|
|
5de29b |
+ cmpld cr7,r0,r5 /* If on the last dword, check byte offset. */
|
|
|
5de29b |
+ bnelr
|
|
|
5de29b |
+ blelr cr7
|
|
|
5de29b |
+ li r3,0
|
|
|
5de29b |
blr
|
|
|
5de29b |
|
|
|
5de29b |
.align 4
|
|
|
5de29b |
@@ -141,67 +142,44 @@
|
|
|
5de29b |
.align 4
|
|
|
5de29b |
L(small_range):
|
|
|
5de29b |
cmpldi r5,0
|
|
|
5de29b |
- rlwinm r6,r3,3,26,28 /* Calculate padding. */
|
|
|
5de29b |
- beq L(null) /* This branch is for the cmpldi r5,0 above. */
|
|
|
5de29b |
+ beq L(null)
|
|
|
5de29b |
ld r12,0(r8) /* Load word from memory. */
|
|
|
5de29b |
- cmpldi cr6,r6,0 /* cr6 == Do we have padding? */
|
|
|
5de29b |
- cmpb r10,r12,r4 /* Check for BYTE in DWORD1. */
|
|
|
5de29b |
- /* If no padding, skip the shifts. */
|
|
|
5de29b |
- beq cr6,L(small_no_padding)
|
|
|
5de29b |
- sld r10,r10,r6
|
|
|
5de29b |
- srd r10,r10,r6
|
|
|
5de29b |
-L(small_no_padding):
|
|
|
5de29b |
- cmpldi cr7,r10,0
|
|
|
5de29b |
+ cmpb r3,r12,r4 /* Check for BYTE in DWORD1. */
|
|
|
5de29b |
+ and r3,r3,r9
|
|
|
5de29b |
+ cmpldi cr7,r3,0
|
|
|
5de29b |
+ clrldi r5,r7,61 /* Byte count - 1 in last dword. */
|
|
|
5de29b |
+ clrrdi r7,r7,3 /* Address of last doubleword. */
|
|
|
5de29b |
+ cmpld r8,r7 /* Are we done already? */
|
|
|
5de29b |
bne cr7,L(done)
|
|
|
5de29b |
-
|
|
|
5de29b |
- /* Are we done already? */
|
|
|
5de29b |
- addi r9,r8,8
|
|
|
5de29b |
- cmpld r9,r7
|
|
|
5de29b |
- bge L(null)
|
|
|
5de29b |
- /* If we're not done, drop through into loop_small. */
|
|
|
5de29b |
-
|
|
|
5de29b |
-L(loop_small): /* loop_small has been unrolled. */
|
|
|
5de29b |
- ldu r12,8(r8)
|
|
|
5de29b |
- cmpb r10,r12,r4
|
|
|
5de29b |
- addi r9,r8,8
|
|
|
5de29b |
- cmpldi cr6,r10,0
|
|
|
5de29b |
- cmpld r9,r7
|
|
|
5de29b |
- bne cr6,L(done) /* Found something. */
|
|
|
5de29b |
- bge L(null) /* Hit end of string (length). */
|
|
|
5de29b |
+ beqlr
|
|
|
5de29b |
|
|
|
5de29b |
ldu r12,8(r8)
|
|
|
5de29b |
- cmpb r10,r12,r4
|
|
|
5de29b |
- addi r9,r8,8
|
|
|
5de29b |
- cmpldi cr6,r10,0
|
|
|
5de29b |
- cmpld r9,r7
|
|
|
5de29b |
+ cmpb r3,r12,r4
|
|
|
5de29b |
+ cmpldi cr6,r3,0
|
|
|
5de29b |
+ cmpld r8,r7
|
|
|
5de29b |
bne cr6,L(done) /* Found something. */
|
|
|
5de29b |
- bge L(null)
|
|
|
5de29b |
+ beqlr /* Hit end of string (length). */
|
|
|
5de29b |
|
|
|
5de29b |
ldu r12,8(r8)
|
|
|
5de29b |
- subi r11,r7,8
|
|
|
5de29b |
- cmpb r10,r12,r4
|
|
|
5de29b |
- cmpldi cr6,r10,0
|
|
|
5de29b |
- ori r2,r2,0 /* Force a dispatch group. */
|
|
|
5de29b |
+ cmpb r3,r12,r4
|
|
|
5de29b |
+ cmpldi cr6,r3,0
|
|
|
5de29b |
+ cmpld r8,r7
|
|
|
5de29b |
bne cr6,L(done)
|
|
|
5de29b |
+ beqlr
|
|
|
5de29b |
|
|
|
5de29b |
- cmpld r8,r11 /* At end of range? */
|
|
|
5de29b |
- bge L(null)
|
|
|
5de29b |
-
|
|
|
5de29b |
- /* For most cases we will never get here. Under some combinations of
|
|
|
5de29b |
- padding + length there is a leftover double that still needs to be
|
|
|
5de29b |
- checked. */
|
|
|
5de29b |
- ldu r12,8(r8)
|
|
|
5de29b |
- cmpb r10,r12,r4
|
|
|
5de29b |
- addi r9,r8,8
|
|
|
5de29b |
- cmpldi cr6,r10,0
|
|
|
5de29b |
- cmpld r9,r7
|
|
|
5de29b |
- bne cr6,L(done) /* Found something. */
|
|
|
5de29b |
+ ldu r12,8(r8)
|
|
|
5de29b |
+ cmpb r3,r12,r4
|
|
|
5de29b |
+ cmpldi cr6,r3,0
|
|
|
5de29b |
+ cmpld r8,r7
|
|
|
5de29b |
+ bne cr6,L(done)
|
|
|
5de29b |
+ beqlr
|
|
|
5de29b |
|
|
|
5de29b |
- /* Save a branch and exit directly. */
|
|
|
5de29b |
- li r3,0
|
|
|
5de29b |
+ ldu r12,8(r8)
|
|
|
5de29b |
+ cmpb r3,r12,r4
|
|
|
5de29b |
+ cmpldi cr6,r3,0
|
|
|
5de29b |
+ bne cr6,L(done)
|
|
|
5de29b |
blr
|
|
|
5de29b |
|
|
|
5de29b |
-
|
|
|
5de29b |
-END (BP_SYM (__memchr))
|
|
|
5de29b |
-weak_alias (BP_SYM (__memchr), BP_SYM(memchr))
|
|
|
5de29b |
+END (__memchr)
|
|
|
5de29b |
+weak_alias (__memchr, memchr)
|
|
|
5de29b |
libc_hidden_builtin_def (memchr)
|
|
|
12745e |
diff -urN glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/power7/memrchr.S glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/power7/memrchr.S
|
|
|
12745e |
--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/power7/memrchr.S 2014-05-29 13:09:17.000000000 -0500
|
|
|
12745e |
+++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/power7/memrchr.S 2014-05-29 13:14:06.000000000 -0500
|
|
|
5de29b |
@@ -1,5 +1,5 @@
|
|
|
5de29b |
/* Optimized memrchr implementation for PowerPC64/POWER7 using cmpb insn.
|
|
|
5de29b |
- Copyright (C) 2010 Free Software Foundation, Inc.
|
|
|
5de29b |
+ Copyright (C) 2010-2014 Free Software Foundation, Inc.
|
|
|
5de29b |
Contributed by Luis Machado <luisgpm@br.ibm.com>.
|
|
|
5de29b |
This file is part of the GNU C Library.
|
|
|
5de29b |
|
|
|
5de29b |
@@ -18,125 +18,137 @@
|
|
|
5de29b |
<http://www.gnu.org/licenses/>. */
|
|
|
5de29b |
|
|
|
5de29b |
#include <sysdep.h>
|
|
|
5de29b |
-#include <bp-sym.h>
|
|
|
5de29b |
-#include <bp-asm.h>
|
|
|
5de29b |
|
|
|
5de29b |
/* int [r3] memrchr (char *s [r3], int byte [r4], int size [r5]) */
|
|
|
5de29b |
.machine power7
|
|
|
5de29b |
-ENTRY (BP_SYM (__memrchr))
|
|
|
5de29b |
- CALL_MCOUNT
|
|
|
5de29b |
- dcbt 0,r3
|
|
|
5de29b |
- mr r7,r3
|
|
|
5de29b |
- add r3,r7,r5 /* Calculate the last acceptable address. */
|
|
|
5de29b |
- cmpld cr7,r3,r7 /* Is the address equal or less than r3? */
|
|
|
5de29b |
+ENTRY (__memrchr)
|
|
|
5de29b |
+ CALL_MCOUNT 3
|
|
|
5de29b |
+ add r7,r3,r5 /* Calculate the last acceptable address. */
|
|
|
5de29b |
+ neg r0,r7
|
|
|
5de29b |
+ addi r7,r7,-1
|
|
|
5de29b |
+ mr r10,r3
|
|
|
5de29b |
+ clrrdi r6,r7,7
|
|
|
5de29b |
+ li r9,3<<5
|
|
|
5de29b |
+ dcbt r9,r6,8 /* Stream hint, decreasing addresses. */
|
|
|
5de29b |
|
|
|
5de29b |
/* Replicate BYTE to doubleword. */
|
|
|
5de29b |
- rlwimi r4,r4,8,16,23
|
|
|
5de29b |
- rlwimi r4,r4,16,0,15
|
|
|
5de29b |
+ insrdi r4,r4,8,48
|
|
|
5de29b |
+ insrdi r4,r4,16,32
|
|
|
5de29b |
insrdi r4,r4,32,0
|
|
|
5de29b |
- bge cr7,L(proceed)
|
|
|
5de29b |
-
|
|
|
5de29b |
- li r3,-1 /* Make r11 the biggest if r4 <= 0. */
|
|
|
5de29b |
-L(proceed):
|
|
|
5de29b |
li r6,-8
|
|
|
5de29b |
- addi r9,r3,-1
|
|
|
5de29b |
- clrrdi r8,r9,3
|
|
|
5de29b |
- addi r8,r8,8
|
|
|
5de29b |
- neg r0,r3
|
|
|
5de29b |
+ li r9,-1
|
|
|
5de29b |
rlwinm r0,r0,3,26,28 /* Calculate padding. */
|
|
|
5de29b |
-
|
|
|
5de29b |
+ clrrdi r8,r7,3
|
|
|
5de29b |
+ srd r9,r9,r0
|
|
|
5de29b |
cmpldi r5,32
|
|
|
5de29b |
+ clrrdi r0,r10,3
|
|
|
5de29b |
ble L(small_range)
|
|
|
5de29b |
|
|
|
5de29b |
- ldbrx r12,r8,r6 /* Load reversed doubleword from memory. */
|
|
|
5de29b |
- cmpb r10,r12,r4 /* Check for BYTE in DWORD1. */
|
|
|
5de29b |
- sld r10,r10,r0
|
|
|
5de29b |
- srd r10,r10,r0
|
|
|
5de29b |
- cmpldi cr7,r10,0 /* If r10 == 0, no BYTE's have been found. */
|
|
|
5de29b |
+#ifdef __LITTLE_ENDIAN__
|
|
|
5de29b |
+ ldx r12,0,r8
|
|
|
5de29b |
+#else
|
|
|
5de29b |
+ ldbrx r12,0,r8 /* Load reversed doubleword from memory. */
|
|
|
5de29b |
+#endif
|
|
|
5de29b |
+ cmpb r3,r12,r4 /* Check for BYTE in DWORD1. */
|
|
|
5de29b |
+ and r3,r3,r9
|
|
|
5de29b |
+ cmpldi cr7,r3,0 /* If r3 == 0, no BYTEs have been found. */
|
|
|
5de29b |
bne cr7,L(done)
|
|
|
5de29b |
|
|
|
5de29b |
- /* Are we done already? */
|
|
|
5de29b |
- addi r9,r8,-8
|
|
|
5de29b |
- cmpld cr6,r9,r7
|
|
|
5de29b |
- ble cr6,L(null)
|
|
|
5de29b |
-
|
|
|
5de29b |
mtcrf 0x01,r8
|
|
|
5de29b |
- /* Are we now aligned to a doubleword boundary? If so, skip to
|
|
|
5de29b |
+ /* Are we now aligned to a quadword boundary? If so, skip to
|
|
|
5de29b |
the main loop. Otherwise, go through the alignment code. */
|
|
|
5de29b |
- mr r8,r9
|
|
|
5de29b |
- bt 28,L(loop_setup)
|
|
|
5de29b |
+ bf 28,L(loop_setup)
|
|
|
5de29b |
|
|
|
5de29b |
/* Handle DWORD2 of pair. */
|
|
|
5de29b |
+#ifdef __LITTLE_ENDIAN__
|
|
|
5de29b |
+ ldx r12,r8,r6
|
|
|
5de29b |
+#else
|
|
|
5de29b |
ldbrx r12,r8,r6
|
|
|
5de29b |
- cmpb r10,r12,r4
|
|
|
5de29b |
- cmpldi cr7,r10,0
|
|
|
5de29b |
- bne cr7,L(done)
|
|
|
5de29b |
-
|
|
|
5de29b |
- /* Are we done already. */
|
|
|
5de29b |
+#endif
|
|
|
5de29b |
addi r8,r8,-8
|
|
|
5de29b |
- cmpld cr6,r8,r7
|
|
|
5de29b |
- ble cr6,L(null)
|
|
|
5de29b |
+ cmpb r3,r12,r4
|
|
|
5de29b |
+ cmpldi cr7,r3,0
|
|
|
5de29b |
+ bne cr7,L(done)
|
|
|
5de29b |
|
|
|
5de29b |
L(loop_setup):
|
|
|
5de29b |
- li r0,-16
|
|
|
5de29b |
- sub r5,r8,r7
|
|
|
5de29b |
- srdi r9,r5,4 /* Number of loop iterations. */
|
|
|
5de29b |
+ /* The last dword we want to read in the loop below is the one
|
|
|
5de29b |
+ containing the first byte of the string, ie. the dword at
|
|
|
5de29b |
+ s & ~7, or r0. The first dword read is at r8 - 8, we
|
|
|
5de29b |
+ read 2 * cnt dwords, so the last dword read will be at
|
|
|
5de29b |
+ r8 - 8 - 16 * cnt + 8. Solving for cnt gives
|
|
|
5de29b |
+ cnt = (r8 - r0) / 16 */
|
|
|
5de29b |
+ sub r5,r8,r0
|
|
|
5de29b |
+ addi r8,r8,-8
|
|
|
5de29b |
+ srdi r9,r5,4 /* Number of loop iterations. */
|
|
|
5de29b |
mtctr r9 /* Setup the counter. */
|
|
|
5de29b |
- b L(loop)
|
|
|
5de29b |
- /* Main loop to look for BYTE backwards in the string. Since it's a
|
|
|
5de29b |
- small loop (< 8 instructions), align it to 32-bytes. */
|
|
|
5de29b |
- .p2align 5
|
|
|
5de29b |
+
|
|
|
5de29b |
+ /* Main loop to look for BYTE backwards in the string.
|
|
|
5de29b |
+ FIXME: Investigate whether 32 byte align helps with this
|
|
|
5de29b |
+ 9 instruction loop. */
|
|
|
5de29b |
+ .align 5
|
|
|
5de29b |
L(loop):
|
|
|
5de29b |
/* Load two doublewords, compare and merge in a
|
|
|
5de29b |
single register for speed. This is an attempt
|
|
|
5de29b |
to speed up the byte-checking process for bigger strings. */
|
|
|
5de29b |
|
|
|
5de29b |
- ldbrx r12,r8,r6
|
|
|
5de29b |
- ldbrx r11,r8,r0
|
|
|
5de29b |
- addi r8,r8,-8
|
|
|
5de29b |
- cmpb r10,r12,r4
|
|
|
5de29b |
+#ifdef __LITTLE_ENDIAN__
|
|
|
5de29b |
+ ldx r12,0,r8
|
|
|
5de29b |
+ ldx r11,r8,r6
|
|
|
5de29b |
+#else
|
|
|
5de29b |
+ ldbrx r12,0,r8
|
|
|
5de29b |
+ ldbrx r11,r8,r6
|
|
|
5de29b |
+#endif
|
|
|
5de29b |
+ cmpb r3,r12,r4
|
|
|
5de29b |
cmpb r9,r11,r4
|
|
|
5de29b |
- or r5,r9,r10 /* Merge everything in one doubleword. */
|
|
|
5de29b |
+ or r5,r9,r3 /* Merge everything in one doubleword. */
|
|
|
5de29b |
cmpldi cr7,r5,0
|
|
|
5de29b |
bne cr7,L(found)
|
|
|
5de29b |
- addi r8,r8,-8
|
|
|
5de29b |
+ addi r8,r8,-16
|
|
|
5de29b |
bdnz L(loop)
|
|
|
5de29b |
- /* We're here because the counter reached 0, and that means we
|
|
|
5de29b |
- didn't have any matches for BYTE in the whole range. Just return
|
|
|
5de29b |
- the original range. */
|
|
|
5de29b |
- addi r9,r8,8
|
|
|
5de29b |
- cmpld cr6,r9,r7
|
|
|
5de29b |
- bgt cr6,L(loop_small)
|
|
|
5de29b |
- b L(null)
|
|
|
5de29b |
-
|
|
|
5de29b |
- /* OK, one (or both) of the words contains BYTE. Check
|
|
|
5de29b |
- the first word and decrement the address in case the first
|
|
|
5de29b |
- word really contains BYTE. */
|
|
|
5de29b |
+
|
|
|
5de29b |
+ /* We may have one more word to read. */
|
|
|
5de29b |
+ cmpld r8,r0
|
|
|
5de29b |
+ bnelr
|
|
|
5de29b |
+
|
|
|
5de29b |
+#ifdef __LITTLE_ENDIAN__
|
|
|
5de29b |
+ ldx r12,0,r8
|
|
|
5de29b |
+#else
|
|
|
5de29b |
+ ldbrx r12,0,r8
|
|
|
5de29b |
+#endif
|
|
|
5de29b |
+ cmpb r3,r12,r4
|
|
|
5de29b |
+ cmpldi cr7,r3,0
|
|
|
5de29b |
+ bne cr7,L(done)
|
|
|
5de29b |
+ blr
|
|
|
5de29b |
+
|
|
|
5de29b |
.align 4
|
|
|
5de29b |
L(found):
|
|
|
5de29b |
- cmpldi cr6,r10,0
|
|
|
5de29b |
- addi r8,r8,8
|
|
|
5de29b |
+ /* OK, one (or both) of the dwords contains BYTE. Check
|
|
|
5de29b |
+ the first dword. */
|
|
|
5de29b |
+ cmpldi cr6,r3,0
|
|
|
5de29b |
bne cr6,L(done)
|
|
|
5de29b |
|
|
|
5de29b |
/* BYTE must be in the second word. Adjust the address
|
|
|
5de29b |
- again and move the result of cmpb to r10 so we can calculate the
|
|
|
5de29b |
+ again and move the result of cmpb to r3 so we can calculate the
|
|
|
5de29b |
pointer. */
|
|
|
5de29b |
|
|
|
5de29b |
- mr r10,r9
|
|
|
5de29b |
+ mr r3,r9
|
|
|
5de29b |
addi r8,r8,-8
|
|
|
5de29b |
|
|
|
5de29b |
- /* r10 has the output of the cmpb instruction, that is, it contains
|
|
|
5de29b |
- 0xff in the same position as the BYTE in the original
|
|
|
5de29b |
+ /* r3 has the output of the cmpb instruction, that is, it contains
|
|
|
5de29b |
+ 0xff in the same position as BYTE in the original
|
|
|
5de29b |
word from the string. Use that to calculate the pointer.
|
|
|
5de29b |
We need to make sure BYTE is *before* the end of the
|
|
|
5de29b |
range. */
|
|
|
5de29b |
L(done):
|
|
|
5de29b |
- cntlzd r0,r10 /* Count leading zeroes before the match. */
|
|
|
5de29b |
- srdi r6,r0,3 /* Convert leading zeroes to bytes. */
|
|
|
5de29b |
- addi r0,r6,1
|
|
|
5de29b |
+ cntlzd r9,r3 /* Count leading zeros before the match. */
|
|
|
5de29b |
+ cmpld r8,r0 /* Are we on the last word? */
|
|
|
5de29b |
+ srdi r6,r9,3 /* Convert leading zeros to bytes. */
|
|
|
5de29b |
+ addi r0,r6,-7
|
|
|
5de29b |
sub r3,r8,r0
|
|
|
5de29b |
- cmpld r3,r7
|
|
|
5de29b |
- blt L(null)
|
|
|
5de29b |
+ cmpld cr7,r3,r10
|
|
|
5de29b |
+ bnelr
|
|
|
5de29b |
+ bgelr cr7
|
|
|
5de29b |
+ li r3,0
|
|
|
5de29b |
blr
|
|
|
5de29b |
|
|
|
5de29b |
.align 4
|
|
|
5de29b |
@@ -150,30 +162,36 @@
|
|
|
5de29b |
cmpldi r5,0
|
|
|
5de29b |
beq L(null)
|
|
|
5de29b |
|
|
|
5de29b |
- ldbrx r12,r8,r6 /* Load reversed doubleword from memory. */
|
|
|
5de29b |
- cmpb r10,r12,r4 /* Check for BYTE in DWORD1. */
|
|
|
5de29b |
- sld r10,r10,r0
|
|
|
5de29b |
- srd r10,r10,r0
|
|
|
5de29b |
- cmpldi cr7,r10,0
|
|
|
5de29b |
+#ifdef __LITTLE_ENDIAN__
|
|
|
5de29b |
+ ldx r12,0,r8
|
|
|
5de29b |
+#else
|
|
|
5de29b |
+ ldbrx r12,0,r8 /* Load reversed doubleword from memory. */
|
|
|
5de29b |
+#endif
|
|
|
5de29b |
+ cmpb r3,r12,r4 /* Check for BYTE in DWORD1. */
|
|
|
5de29b |
+ and r3,r3,r9
|
|
|
5de29b |
+ cmpldi cr7,r3,0
|
|
|
5de29b |
bne cr7,L(done)
|
|
|
5de29b |
|
|
|
5de29b |
/* Are we done already? */
|
|
|
5de29b |
+ cmpld r8,r0
|
|
|
5de29b |
addi r8,r8,-8
|
|
|
5de29b |
- cmpld r8,r7
|
|
|
5de29b |
- ble L(null)
|
|
|
5de29b |
- b L(loop_small)
|
|
|
5de29b |
+ beqlr
|
|
|
5de29b |
|
|
|
5de29b |
- .p2align 5
|
|
|
5de29b |
+ .align 5
|
|
|
5de29b |
L(loop_small):
|
|
|
5de29b |
- ldbrx r12,r8,r6
|
|
|
5de29b |
- cmpb r10,r12,r4
|
|
|
5de29b |
- cmpldi cr6,r10,0
|
|
|
5de29b |
- bne cr6,L(done)
|
|
|
5de29b |
+#ifdef __LITTLE_ENDIAN__
|
|
|
5de29b |
+ ldx r12,0,r8
|
|
|
5de29b |
+#else
|
|
|
5de29b |
+ ldbrx r12,0,r8
|
|
|
5de29b |
+#endif
|
|
|
5de29b |
+ cmpb r3,r12,r4
|
|
|
5de29b |
+ cmpld r8,r0
|
|
|
5de29b |
+ cmpldi cr7,r3,0
|
|
|
5de29b |
+ bne cr7,L(done)
|
|
|
5de29b |
addi r8,r8,-8
|
|
|
5de29b |
- cmpld r8,r7
|
|
|
5de29b |
- ble L(null)
|
|
|
5de29b |
- b L(loop_small)
|
|
|
5de29b |
+ bne L(loop_small)
|
|
|
5de29b |
+ blr
|
|
|
5de29b |
|
|
|
5de29b |
-END (BP_SYM (__memrchr))
|
|
|
5de29b |
-weak_alias (BP_SYM (__memrchr), BP_SYM(memrchr))
|
|
|
5de29b |
+END (__memrchr)
|
|
|
5de29b |
+weak_alias (__memrchr, memrchr)
|
|
|
5de29b |
libc_hidden_builtin_def (memrchr)
|
|
|
12745e |
diff -urN glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/power7/rawmemchr.S glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/power7/rawmemchr.S
|
|
|
12745e |
--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/power7/rawmemchr.S 2014-05-29 13:09:17.000000000 -0500
|
|
|
12745e |
+++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/power7/rawmemchr.S 2014-05-29 13:09:19.000000000 -0500
|
|
|
5de29b |
@@ -29,8 +29,8 @@
|
|
|
5de29b |
clrrdi r8,r3,3 /* Align the address to doubleword boundary. */
|
|
|
5de29b |
|
|
|
5de29b |
/* Replicate byte to doubleword. */
|
|
|
5de29b |
- rlwimi r4,r4,8,16,23
|
|
|
5de29b |
- rlwimi r4,r4,16,0,15
|
|
|
5de29b |
+ insrdi r4,r4,8,48
|
|
|
5de29b |
+ insrdi r4,r4,16,32
|
|
|
5de29b |
insrdi r4,r4,32,0
|
|
|
5de29b |
|
|
|
5de29b |
/* Now r4 has a doubleword of c bytes. */
|
|
|
5de29b |
@@ -38,8 +38,13 @@
|
|
|
5de29b |
rlwinm r6,r3,3,26,28 /* Calculate padding. */
|
|
|
5de29b |
ld r12,0(r8) /* Load doubleword from memory. */
|
|
|
5de29b |
cmpb r5,r12,r4 /* Compare each byte against c byte. */
|
|
|
5de29b |
+#ifdef __LITTLE_ENDIAN__
|
|
|
5de29b |
+ srd r5,r5,r6
|
|
|
5de29b |
+ sld r5,r5,r6
|
|
|
5de29b |
+#else
|
|
|
5de29b |
sld r5,r5,r6 /* Move left to discard ignored bits. */
|
|
|
5de29b |
srd r5,r5,r6 /* Bring the bits back as zeros. */
|
|
|
5de29b |
+#endif
|
|
|
5de29b |
cmpdi cr7,r5,0 /* If r5 == 0, no c bytes have been found. */
|
|
|
5de29b |
bne cr7,L(done)
|
|
|
5de29b |
|
|
|
5de29b |
@@ -93,8 +98,14 @@
|
|
|
5de29b |
doubleword from the string. Use that fact to find out what is
|
|
|
5de29b |
the position of the byte inside the string. */
|
|
|
5de29b |
L(done):
|
|
|
5de29b |
+#ifdef __LITTLE_ENDIAN__
|
|
|
5de29b |
+ addi r0,r5,-1
|
|
|
5de29b |
+ andc r0,r0,r5
|
|
|
5de29b |
+ popcntd r0,r0 /* Count trailing zeros. */
|
|
|
5de29b |
+#else
|
|
|
5de29b |
cntlzd r0,r5 /* Count leading zeros before the match. */
|
|
|
5de29b |
- srdi r0,r0,3 /* Convert leading zeroes to bytes. */
|
|
|
5de29b |
+#endif
|
|
|
5de29b |
+ srdi r0,r0,3 /* Convert leading zeros to bytes. */
|
|
|
5de29b |
add r3,r8,r0 /* Return address of the matching char. */
|
|
|
5de29b |
blr
|
|
|
5de29b |
END (BP_SYM (__rawmemchr))
|