Update copyright dates with scripts/update-copyrights.
[glibc.git] / sysdeps / arm / armv6 / rawmemchr.S
blobc478756a7d6efda4123d4f07347b7423a640f8ff
1 /* rawmemchr -- find a byte within an unsized memory block.
2    Copyright (C) 2013-2015 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         sfi_breg r0, \
29         ldrb    r2, [\B]                @ load first byte asap
31         @ To cater to long strings, we want to search through a few
32         @ characters until we reach an aligned pointer.  To cater to
33         @ small strings, we don't want to start doing word operations
34         @ immediately.  The compromise is a maximum of 16 bytes less
35         @ whatever is required to end with an aligned pointer.
36         @ r3 = number of characters to search in alignment loop
37         and     r3, r0, #7
38         uxtb    r1, r1
39         rsb     r3, r3, #15             @ 16 - 1 peeled loop iteration
40         cmp     r2, r1
41         it      eq
42         bxeq    lr
44         @ Loop until we find ...
45 1:      sfi_breg r0, \
46         ldrb    r2, [\B, #1]!
47         subs    r3, r3, #1              @ ... the alignment point
48         it      ne
49         cmpne   r2, r1                  @ ... or C
50         bne     1b
52         @ Disambiguate the exit possibilites above
53         cmp     r2, r1                  @ Found C
54         it      eq
55         bxeq    lr
56         add     r0, r0, #1
58         @ So now we're aligned.
59         sfi_breg r0, \
60         ldrd    r2, r3, [\B], #8
61         orr     r1, r1, r1, lsl #8      @ Replicate C to all bytes
62 #ifdef ARCH_HAS_T2
63         movw    ip, #0x0101
64         sfi_pld r0, #64
65         movt    ip, #0x0101
66 #else
67         ldr     ip, =0x01010101
68         sfi_pld r0, #64
69 #endif
70         orr     r1, r1, r1, lsl #16
72         @ Loop searching for C, 8 bytes at a time.
73         @ Subtracting (unsigned saturating) from 1 means result of 1 for
74         @ any byte that was originally zero and 0 otherwise.  Therefore
75         @ we consider the lsb of each byte the "found" bit.
76 2:      eor     r2, r2, r1              @ Convert C bytes to 0
77         eor     r3, r3, r1
78         uqsub8  r2, ip, r2              @ Find C
79         uqsub8  r3, ip, r3
80         sfi_pld r0, #128
81         orrs    r3, r3, r2              @ Test both words for found
82         it      eq
83         sfi_breg r0, \
84         ldrdeq  r2, r3, [\B], #8
85         beq     2b
87         @ Found something.  Disambiguate between first and second words.
88         @ Adjust r0 to point to the word containing the match.
89         @ Adjust r2 to the found bits for the word containing the match.
90         cmp     r2, #0
91         sub     r0, r0, #4
92         ite     eq
93         moveq   r2, r3
94         subne   r0, r0, #4
96         @ Find the bit-offset of the match within the word.  Note that the
97         @ bit result from clz will be 7 higher than "true", but we'll
98         @ immediately discard those bits converting to a byte offset.
99 #ifdef __ARMEL__
100         rev     r2, r2                  @ For LE, count from the little end
101 #endif
102         clz     r2, r2
103         add     r0, r0, r2, lsr #3      @ Adjust the pointer to the found byte
104         bx      lr
106 END (__rawmemchr)
108 weak_alias (__rawmemchr, rawmemchr)
109 libc_hidden_def (__rawmemchr)