1 /*
2  * Copyright (C) 2008 The Android Open Source Project
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *  * Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  *  * Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in
12  *    the documentation and/or other materials provided with the
13  *    distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
18  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
19  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
22  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
25  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  */
28 
29 #include <string.h>
30 #include <stdint.h>
31 
strlen_generic(const char * s)32 size_t strlen_generic(const char *s)
33 {
34     __builtin_prefetch(s);
35     __builtin_prefetch(s+32);
36 
37     union {
38         const char      *b;
39         const uint32_t  *w;
40         uintptr_t       i;
41     } u;
42 
43     // these are some scratch variables for the asm code below
44     uint32_t v, t;
45 
46     // initialize the string length to zero
47     size_t l = 0;
48 
49     // align the pointer to a 32-bit word boundary
50     u.b = s;
51     while (u.i & 0x3)  {
52         if (__builtin_expect(*u.b++ == 0, 0)) {
53             goto done;
54         }
55         l++;
56     }
57 
58     // loop for each word, testing if it contains a zero byte
59     // if so, exit the loop and update the length.
60     // We need to process 32 bytes per loop to schedule PLD properly
61     // and achieve the maximum bus speed.
62     asm(
63         "ldr     %[v], [%[s]], #4           \n"
64         "sub     %[l], %[l], %[s]           \n"
65         "0:                                 \n"
66         "pld     [%[s], #64]                \n"
67         "sub     %[t], %[v], %[mask], lsr #7\n"
68         "and     %[t], %[t], %[mask]        \n"
69         "bics    %[t], %[t], %[v]           \n"
70         "bne     1f                         \n"
71         "ldr     %[v], [%[s]], #4           \n"
72 #if !defined(__OPTIMIZE_SIZE__)
73         "sub     %[t], %[v], %[mask], lsr #7\n"
74         "and     %[t], %[t], %[mask]        \n"
75         "bics    %[t], %[t], %[v]           \n"
76         "bne     1f                         \n"
77         "ldr     %[v], [%[s]], #4           \n"
78         "sub     %[t], %[v], %[mask], lsr #7\n"
79         "and     %[t], %[t], %[mask]        \n"
80         "bics    %[t], %[t], %[v]           \n"
81         "bne     1f                         \n"
82         "ldr     %[v], [%[s]], #4           \n"
83         "sub     %[t], %[v], %[mask], lsr #7\n"
84         "and     %[t], %[t], %[mask]        \n"
85         "bics    %[t], %[t], %[v]           \n"
86         "bne     1f                         \n"
87         "ldr     %[v], [%[s]], #4           \n"
88         "sub     %[t], %[v], %[mask], lsr #7\n"
89         "and     %[t], %[t], %[mask]        \n"
90         "bics    %[t], %[t], %[v]           \n"
91         "bne     1f                         \n"
92         "ldr     %[v], [%[s]], #4           \n"
93         "sub     %[t], %[v], %[mask], lsr #7\n"
94         "and     %[t], %[t], %[mask]        \n"
95         "bics    %[t], %[t], %[v]           \n"
96         "bne     1f                         \n"
97         "ldr     %[v], [%[s]], #4           \n"
98         "sub     %[t], %[v], %[mask], lsr #7\n"
99         "and     %[t], %[t], %[mask]        \n"
100         "bics    %[t], %[t], %[v]           \n"
101         "bne     1f                         \n"
102         "ldr     %[v], [%[s]], #4           \n"
103         "sub     %[t], %[v], %[mask], lsr #7\n"
104         "and     %[t], %[t], %[mask]        \n"
105         "bics    %[t], %[t], %[v]           \n"
106         "bne     1f                         \n"
107         "ldr     %[v], [%[s]], #4           \n"
108 #endif
109         "b       0b                         \n"
110         "1:                                 \n"
111         "add     %[l], %[l], %[s]           \n"
112         "tst     %[v], #0xFF                \n"
113         "beq     2f                         \n"
114         "add     %[l], %[l], #1             \n"
115         "tst     %[v], #0xFF00              \n"
116         "beq     2f                         \n"
117         "add     %[l], %[l], #1             \n"
118         "tst     %[v], #0xFF0000            \n"
119         "it      ne                         \n"
120         "addne   %[l], %[l], #1             \n"
121         "2:                                 \n"
122         : [l]"=&r"(l), [v]"=&r"(v), [t]"=&r"(t), [s]"=&r"(u.b)
123         : "%[l]"(l), "%[s]"(u.b), [mask]"r"(0x80808080UL)
124         : "cc"
125     );
126 
127 done:
128     return l;
129 }
130