]>
Commit | Line | Data |
---|---|---|
2601bc18 WN |
1 | /* Copyright (C) 2010-2011,2013 Free Software Foundation, Inc. |
2 | This file is part of the GNU C Library. | |
3 | ||
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. | |
8 | ||
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. | |
13 | ||
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/>. */ | |
17 | ||
18 | /* | |
19 | Assumes: | |
20 | ARMv6T2, AArch32 | |
21 | ||
22 | */ | |
23 | ||
24 | #include <sysdep.h> | |
25 | ||
26 | #ifdef __ARMEB__ | |
27 | #define S2LO lsl | |
28 | #define S2HI lsr | |
29 | #else | |
30 | #define S2LO lsr | |
31 | #define S2HI lsl | |
32 | #endif | |
33 | ||
34 | /* This code requires Thumb. */ | |
35 | .thumb | |
36 | .syntax unified | |
37 | ||
38 | /* Parameters and result. */ | |
39 | #define srcin r0 | |
40 | #define result r0 | |
41 | ||
42 | /* Internal variables. */ | |
43 | #define src r1 | |
44 | #define data1a r2 | |
45 | #define data1b r3 | |
46 | #define const_m1 r12 | |
47 | #define const_0 r4 | |
48 | #define tmp1 r4 /* Overlaps const_0 */ | |
49 | #define tmp2 r5 | |
50 | ||
51 | .text | |
52 | .p2align 6 | |
53 | ENTRY(strlen) | |
54 | pld [srcin, #0] | |
55 | strd r4, r5, [sp, #-8]! | |
56 | cfi_adjust_cfa_offset (8) | |
57 | cfi_rel_offset (r4, 0) | |
58 | cfi_rel_offset (r5, 4) | |
59 | cfi_remember_state | |
60 | bic src, srcin, #7 | |
61 | mvn const_m1, #0 | |
62 | ands tmp1, srcin, #7 /* (8 - bytes) to alignment. */ | |
63 | pld [src, #32] | |
64 | bne.w .Lmisaligned8 | |
65 | mov const_0, #0 | |
66 | mov result, #-8 | |
67 | .Lloop_aligned: | |
68 | /* Bytes 0-7. */ | |
69 | ldrd data1a, data1b, [src] | |
70 | pld [src, #64] | |
71 | add result, result, #8 | |
72 | .Lstart_realigned: | |
73 | uadd8 data1a, data1a, const_m1 /* Saturating GE<0:3> set. */ | |
74 | sel data1a, const_0, const_m1 /* Select based on GE<0:3>. */ | |
75 | uadd8 data1b, data1b, const_m1 | |
76 | sel data1b, data1a, const_m1 /* Only used if d1a == 0. */ | |
77 | cbnz data1b, .Lnull_found | |
78 | ||
79 | /* Bytes 8-15. */ | |
80 | ldrd data1a, data1b, [src, #8] | |
81 | uadd8 data1a, data1a, const_m1 /* Saturating GE<0:3> set. */ | |
82 | add result, result, #8 | |
83 | sel data1a, const_0, const_m1 /* Select based on GE<0:3>. */ | |
84 | uadd8 data1b, data1b, const_m1 | |
85 | sel data1b, data1a, const_m1 /* Only used if d1a == 0. */ | |
86 | cbnz data1b, .Lnull_found | |
87 | ||
88 | /* Bytes 16-23. */ | |
89 | ldrd data1a, data1b, [src, #16] | |
90 | uadd8 data1a, data1a, const_m1 /* Saturating GE<0:3> set. */ | |
91 | add result, result, #8 | |
92 | sel data1a, const_0, const_m1 /* Select based on GE<0:3>. */ | |
93 | uadd8 data1b, data1b, const_m1 | |
94 | sel data1b, data1a, const_m1 /* Only used if d1a == 0. */ | |
95 | cbnz data1b, .Lnull_found | |
96 | ||
97 | /* Bytes 24-31. */ | |
98 | ldrd data1a, data1b, [src, #24] | |
99 | add src, src, #32 | |
100 | uadd8 data1a, data1a, const_m1 /* Saturating GE<0:3> set. */ | |
101 | add result, result, #8 | |
102 | sel data1a, const_0, const_m1 /* Select based on GE<0:3>. */ | |
103 | uadd8 data1b, data1b, const_m1 | |
104 | sel data1b, data1a, const_m1 /* Only used if d1a == 0. */ | |
105 | cmp data1b, #0 | |
106 | beq .Lloop_aligned | |
107 | ||
108 | .Lnull_found: | |
109 | cmp data1a, #0 | |
110 | itt eq | |
111 | addeq result, result, #4 | |
112 | moveq data1a, data1b | |
113 | #ifndef __ARMEB__ | |
114 | rev data1a, data1a | |
115 | #endif | |
116 | clz data1a, data1a | |
117 | ldrd r4, r5, [sp], #8 | |
118 | cfi_adjust_cfa_offset (-8) | |
119 | cfi_restore (r4) | |
120 | cfi_restore (r5) | |
121 | add result, result, data1a, lsr #3 /* Bits -> Bytes. */ | |
122 | DO_RET(lr) | |
123 | ||
124 | .Lmisaligned8: | |
125 | cfi_restore_state | |
126 | ldrd data1a, data1b, [src] | |
127 | and tmp2, tmp1, #3 | |
128 | rsb result, tmp1, #0 | |
129 | lsl tmp2, tmp2, #3 /* Bytes -> bits. */ | |
130 | tst tmp1, #4 | |
131 | pld [src, #64] | |
132 | S2HI tmp2, const_m1, tmp2 | |
133 | orn data1a, data1a, tmp2 | |
134 | itt ne | |
135 | ornne data1b, data1b, tmp2 | |
136 | movne data1a, const_m1 | |
137 | mov const_0, #0 | |
138 | b .Lstart_realigned | |
139 | ||
140 | END(strlen) | |
141 | libc_hidden_builtin_def (strlen) |