arm: Implement armv6 optimized string routines
[glibc.git] / ports / sysdeps / arm / armv6 / rawmemchr.S
blob7877bcf6d67e605590e01e59c293375a136ad8c5
1 /* rawmemchr -- find a byte within an unsized memory block.
2    Copyright (C) 2013 Free Software Foundation, Inc.
3    This file is part of the GNU C Library.
5    The GNU C Library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Lesser General Public
7    License as published by the Free Software Foundation; either
8    version 2.1 of the License, or (at your option) any later version.
10    The GNU C Library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Lesser General Public License for more details.
15    You should have received a copy of the GNU Lesser General Public
16    License along with the GNU C Library.  If not, see
17    <http://www.gnu.org/licenses/>.  */
19 #include <sysdep.h>
21         .syntax unified
22         .text
24 ENTRY (__rawmemchr)
25         @ r0 = start of string
26         @ r1 = character to match
27         @ returns a pointer to the match, which must be present.
28         ldrb    r2, [r0]                @ load first byte asap
30         @ To cater to long strings, we want to search through a few
31         @ characters until we reach an aligned pointer.  To cater to
32         @ small strings, we don't want to start doing word operations
33         @ immediately.  The compromise is a maximum of 16 bytes less
34         @ whatever is required to end with an aligned pointer.
35         @ r3 = number of characters to search in alignment loop
36         and     r3, r0, #7
37         uxtb    r1, r1
38         rsb     r3, r3, #15             @ 16 - 1 peeled loop iteration
39         cmp     r2, r1
40         it      eq
41         bxeq    lr
43         @ Loop until we find ...
44 1:      ldrb    r2, [r0, #1]!
45         subs    r3, r3, #1              @ ... the alignment point
46         it      ne
47         cmpne   r2, r1                  @ ... or C
48         bne     1b
50         @ Disambiguate the exit possibilites above
51         cmp     r2, r1                  @ Found C
52         it      eq
53         bxeq    lr
54         add     r0, r0, #1
56         @ So now we're aligned.
57         ldrd    r2, r3, [r0], #8
58         orr     r1, r1, r1, lsl #8      @ Replicate C to all bytes
59 #ifdef ARCH_HAS_T2
60         movw    ip, #0x0101
61         pld     [r0, #64]
62         movt    ip, #0x0101
63 #else
64         ldr     ip, =0x01010101
65         pld     [r0, #64]
66 #endif
67         orr     r1, r1, r1, lsl #16
69         @ Loop searching for C, 8 bytes at a time.
70         @ Subtracting (unsigned saturating) from 1 means result of 1 for
71         @ any byte that was originally zero and 0 otherwise.  Therefore
72         @ we consider the lsb of each byte the "found" bit.
73 2:      eor     r2, r2, r1              @ Convert C bytes to 0
74         eor     r3, r3, r1
75         uqsub8  r2, ip, r2              @ Find C
76         uqsub8  r3, ip, r3
77         pld     [r0, #128]
78         orrs    r3, r3, r2              @ Test both words for found
79         it      eq
80         ldrdeq  r2, r3, [r0], #8
81         beq     2b
83         @ Found something.  Disambiguate between first and second words.
84         @ Adjust r0 to point to the word containing the match.
85         @ Adjust r2 to the found bits for the word containing the match.
86         cmp     r2, #0
87         sub     r0, r0, #4
88         ite     eq
89         moveq   r2, r3
90         subne   r0, r0, #4
92         @ Find the bit-offset of the match within the word.  Note that the
93         @ bit result from clz will be 7 higher than "true", but we'll
94         @ immediately discard those bits converting to a byte offset.
95 #ifdef __ARMEL__
96         rev     r2, r2                  @ For LE, count from the little end
97 #endif
98         clz     r2, r2
99         add     r0, r0, r2, lsr #3      @ Adjust the pointer to the found byte
100         bx      lr
102 END (__rawmemchr)
104 weak_alias (__rawmemchr, rawmemchr)
105 libc_hidden_def (__rawmemchr)