Update copyright dates with scripts/update-copyrights.
[glibc.git] / sysdeps / arm / armv6t2 / strlen.S
blob7c7a63ab0bb7ede78edd0f145f936c37492386f6
1 /* Copyright (C) 2010-2015 Free Software Foundation, Inc.
2    This file is part of the GNU C Library.
4    The GNU C Library is free software; you can redistribute it and/or
5    modify it under the terms of the GNU Lesser General Public
6    License as published by the Free Software Foundation; either
7    version 2.1 of the License, or (at your option) any later version.
9    The GNU C Library is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12    Lesser General Public License for more details.
14    You should have received a copy of the GNU Lesser General Public
15    License along with the GNU C Library.  If not, see
16    <http://www.gnu.org/licenses/>.  */
19    Assumes:
20    ARMv6T2, AArch32
22  */
24 #include <arm-features.h>               /* This might #define NO_THUMB.  */
25 #include <sysdep.h>
27 #ifdef __ARMEB__
28 #define S2LO            lsl
29 #define S2HI            lsr
30 #else
31 #define S2LO            lsr
32 #define S2HI            lsl
33 #endif
35 #ifndef NO_THUMB
36 /* This code is best on Thumb.  */
37         .thumb
38 #else
39 /* Using bne.w explicitly is desirable in Thumb mode because it helps
40    align the following label without a nop.  In ARM mode there is no
41    such difference.  */
42 .macro bne.w label
43         bne \label
44 .endm
46 /* This clobbers the condition codes, which the real Thumb cbnz instruction
47    does not do.  But it doesn't matter for any of the uses here.  */
48 .macro cbnz reg, label
49         cmp \reg, #0
50         bne \label
51 .endm
52 #endif
54 /* Parameters and result.  */
55 #define srcin           r0
56 #define result          r0
58 /* Internal variables.  */
59 #define src             r1
60 #define data1a          r2
61 #define data1b          r3
62 #define const_m1        r12
63 #define const_0         r4
64 #define tmp1            r4              /* Overlaps const_0  */
65 #define tmp2            r5
67         .text
68         .p2align 6
69 ENTRY(strlen)
70         sfi_pld srcin, #0
71         strd    r4, r5, [sp, #-8]!
72         cfi_adjust_cfa_offset (8)
73         cfi_rel_offset (r4, 0)
74         cfi_rel_offset (r5, 4)
75         cfi_remember_state
76         bic     src, srcin, #7
77         mvn     const_m1, #0
78         ands    tmp1, srcin, #7         /* (8 - bytes) to alignment.  */
79         sfi_pld src, #32
80         bne.w   .Lmisaligned8
81         mov     const_0, #0
82         mov     result, #-8
83 .Lloop_aligned:
84         /* Bytes 0-7.  */
85         sfi_breg src, \
86         ldrd    data1a, data1b, [\B]
87         sfi_pld src, #64
88         add     result, result, #8
89 .Lstart_realigned:
90         uadd8   data1a, data1a, const_m1        /* Saturating GE<0:3> set.  */
91         sel     data1a, const_0, const_m1       /* Select based on GE<0:3>.  */
92         uadd8   data1b, data1b, const_m1
93         sel     data1b, data1a, const_m1        /* Only used if d1a == 0.  */
94         cbnz    data1b, .Lnull_found
96         /* Bytes 8-15.  */
97         sfi_breg src, \
98         ldrd    data1a, data1b, [\B, #8]
99         uadd8   data1a, data1a, const_m1        /* Saturating GE<0:3> set.  */
100         add     result, result, #8
101         sel     data1a, const_0, const_m1       /* Select based on GE<0:3>.  */
102         uadd8   data1b, data1b, const_m1
103         sel     data1b, data1a, const_m1        /* Only used if d1a == 0.  */
104         cbnz    data1b, .Lnull_found
106         /* Bytes 16-23.  */
107         sfi_breg src, \
108         ldrd    data1a, data1b, [\B, #16]
109         uadd8   data1a, data1a, const_m1        /* Saturating GE<0:3> set.  */
110         add     result, result, #8
111         sel     data1a, const_0, const_m1       /* Select based on GE<0:3>.  */
112         uadd8   data1b, data1b, const_m1
113         sel     data1b, data1a, const_m1        /* Only used if d1a == 0.  */
114         cbnz    data1b, .Lnull_found
116         /* Bytes 24-31.  */
117         sfi_breg src, \
118         ldrd    data1a, data1b, [\B, #24]
119         add     src, src, #32
120         uadd8   data1a, data1a, const_m1        /* Saturating GE<0:3> set.  */
121         add     result, result, #8
122         sel     data1a, const_0, const_m1       /* Select based on GE<0:3>.  */
123         uadd8   data1b, data1b, const_m1
124         sel     data1b, data1a, const_m1        /* Only used if d1a == 0.  */
125         cmp     data1b, #0
126         beq     .Lloop_aligned
128 .Lnull_found:
129         cmp     data1a, #0
130         itt     eq
131         addeq   result, result, #4
132         moveq   data1a, data1b
133 #ifndef __ARMEB__
134         rev     data1a, data1a
135 #endif
136         clz     data1a, data1a
137         ldrd    r4, r5, [sp], #8
138         cfi_adjust_cfa_offset (-8)
139         cfi_restore (r4)
140         cfi_restore (r5)
141         add     result, result, data1a, lsr #3  /* Bits -> Bytes.  */
142         DO_RET(lr)
144 .Lmisaligned8:
145         cfi_restore_state
146         sfi_breg src, \
147         ldrd    data1a, data1b, [\B]
148         and     tmp2, tmp1, #3
149         rsb     result, tmp1, #0
150         lsl     tmp2, tmp2, #3                  /* Bytes -> bits.  */
151         tst     tmp1, #4
152         sfi_pld src, #64
153         S2HI    tmp2, const_m1, tmp2
154 #ifdef NO_THUMB
155         mvn     tmp1, tmp2
156         orr     data1a, data1a, tmp1
157         itt     ne
158         orrne   data1b, data1b, tmp1
159 #else
160         orn     data1a, data1a, tmp2
161         itt     ne
162         ornne   data1b, data1b, tmp2
163 #endif
164         movne   data1a, const_m1
165         mov     const_0, #0
166         b       .Lstart_realigned
168 END(strlen)
169 libc_hidden_builtin_def (strlen)