Update copyright notices with scripts/update-copyrights
[glibc.git] / ports / sysdeps / arm / armv6 / strlen.S
blob290d7bc86d668e8e3e1f90e04e6aa80ac511ebd5
1 /* strlen -- find the length of a nul-terminated string.
2    Copyright (C) 2013-2014 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 (strlen)
25         @ r0 = start of string
26         sfi_breg r0, \
27         ldrb    r2, [\B]                @ load the first byte asap
29         @ To cater to long strings, we want to search through a few
30         @ characters until we reach an aligned pointer.  To cater to
31         @ small strings, we don't want to start doing word operations
32         @ immediately.  The compromise is a maximum of 16 bytes less
33         @ whatever is required to end with an aligned pointer.
34         @ r3 = number of characters to search in alignment loop
35         and     r3, r0, #7
36         mov     r1, r0                  @ Save the input pointer
37         rsb     r3, r3, #15             @ 16 - 1 peeled loop iteration
38         cmp     r2, #0
39         beq     99f
41         @ Loop until we find ...
42 1:      sfi_breg r0, \
43         ldrb    r2, [\B, #1]!
44         subs    r3, r3, #1              @ ... the aligment point
45         it      ne
46         cmpne   r2, #0                  @ ... or EOS
47         bne     1b
49         @ Disambiguate the exit possibilites above
50         cmp     r2, #0                  @ Found EOS
51         beq     99f
52         add     r0, r0, #1
54         @ So now we're aligned.
55         sfi_breg r0, \
56         ldrd    r2, r3, [\B], #8
57 #ifdef ARCH_HAS_T2
58         movw    ip, #0x0101
59         sfi_pld r0, #64
60         movt    ip, #0x0101
61 #else
62         ldr     ip, =0x01010101
63         sfi_pld r0, #64
64 #endif
66         @ Loop searching for EOS, 8 bytes at a time.
67         @ Subtracting (unsigned saturating) from 1 for any byte means that
68         @ we get 1 for any byte that was originally zero and 0 otherwise.
69         @ Therefore we consider the lsb of each byte the "found" bit.
70         .balign 16
71 2:      uqsub8  r2, ip, r2              @ Find EOS
72         uqsub8  r3, ip, r3
73         sfi_pld r0, #128                @ Prefetch 2 lines ahead
74         orrs    r3, r3, r2              @ Combine the two words
75         it      eq
76         sfi_breg r0, \
77         ldrdeq  r2, r3, [\B], #8
78         beq     2b
80         @ Found something.  Disambiguate between first and second words.
81         @ Adjust r0 to point to the word containing the match.
82         @ Adjust r2 to the found bits for the word containing the match.
83         cmp     r2, #0
84         sub     r0, r0, #4
85         ite     eq
86         moveq   r2, r3
87         subne   r0, r0, #4
89         @ Find the bit-offset of the match within the word.  Note that the
90         @ bit result from clz will be 7 higher than "true", but we'll
91         @ immediately discard those bits converting to a byte offset.
92 #ifdef __ARMEL__
93         rev     r2, r2                  @ For LE, count from the little end
94 #endif
95         clz     r2, r2
96         add     r0, r0, r2, lsr #3      @ Adjust the pointer to the found byte
97 99:
98         sub     r0, r0, r1              @ Subtract input to compute length
99         bx      lr
101 END (strlen)
103 libc_hidden_builtin_def (strlen)