]> git.ipfire.org Git - thirdparty/glibc.git/blobdiff - sysdeps/powerpc/powerpc64/strchr.S
Update copyright dates with scripts/update-copyrights.
[thirdparty/glibc.git] / sysdeps / powerpc / powerpc64 / strchr.S
index 1317497149413caacbd8f961ee6802ed084e9cd3..19c695d7e7979eafcd745c00a5633caa264e1b61 100644 (file)
@@ -1,5 +1,5 @@
 /* Optimized strchr implementation for PowerPC64.
-   Copyright (C) 1997, 1999, 2000, 2002, 2003, 2011 Free Software Foundation, Inc.
+   Copyright (C) 1997-2016 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
    <http://www.gnu.org/licenses/>.  */
 
 #include <sysdep.h>
-#include <bp-sym.h>
-#include <bp-asm.h>
 
 /* See strlen.s for comments on how this works.  */
 
 /* char * [r3] strchr (const char *s [r3] , int c [r4] )  */
 
-ENTRY (BP_SYM (strchr))
+ENTRY (strchr)
        CALL_MCOUNT 2
 
 #define rTMP1  r0
 #define rRTN   r3      /* outgoing result */
-/* Note:  The Bounded pointer support in this code is broken.  This code
-   was inherited from PPC32 and that support was never completed.
-   Currently PPC gcc does not support -fbounds-check or -fbounded-pointers.
-   These artifacts are left in the code as a reminder in case we need
-   bounded pointer support in the future.  */
-#if __BOUNDED_POINTERS__
-# define rSTR  r4
-# define rCHR  r5      /* byte we're looking for, spread over the whole word */
-# define rWORD r8      /* the current word */
-#else
-# define rSTR  r8      /* current word pointer */
-# define rCHR  r4      /* byte we're looking for, spread over the whole word */
-# define rWORD r5      /* the current word */
-#endif
+#define rSTR   r8      /* current word pointer */
+#define rCHR   r4      /* byte we're looking for, spread over the whole word */
+#define rWORD  r5      /* the current word */
 #define rCLZB  rCHR    /* leading zero byte count */
 #define rFEFE  r6      /* constant 0xfefefefefefefeff (-0x0101010101010101) */
 #define r7F7F  r7      /* constant 0x7f7f7f7f7f7f7f7f */
@@ -50,14 +37,13 @@ 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
-
-       CHECK_BOUNDS_LOW (rSTR, rTMP1, rTMP2)
-       STORE_RETURN_BOUNDS (rTMP1, rTMP2)
+#define rTMP4  rIGN
+#define rTMP5  rMASK
 
        dcbt    0,rRTN
-       rlwimi  rCHR, rCHR, 8, 16, 23
+       insrdi  rCHR, rCHR, 8, 48
        li      rMASK, -1
-       rlwimi  rCHR, rCHR, 16, 0, 15
+       insrdi  rCHR, rCHR, 16, 32
        rlwinm  rIGN, rRTN, 3, 26, 28
        insrdi  rCHR, rCHR, 32, 0
        lis     rFEFE, -0x101
@@ -70,72 +56,96 @@ 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)
-       STORE_RETURN_VALUE (rSTR)
        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)
        blr
-END (BP_SYM (strchr))
+END (strchr)
 
-weak_alias (BP_SYM (strchr), BP_SYM (index))
+weak_alias (strchr, index)
 libc_hidden_builtin_def (strchr)