~linaro-toolchain-dev/cortex-strings/trunk

103 by Will Newton
Split bionic reference code into A15 and A9 versions.
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
#undef strlen
32
33
#define __ARM_HAVE_PLD  1
34
35
size_t strlen(const char *s)
36
{
37
    __builtin_prefetch(s);
38
    __builtin_prefetch(s+32);
39
    
40
    union {
41
        const char      *b;
42
        const uint32_t  *w;
43
        uintptr_t       i;
44
    } u;
45
    
46
    // these are some scratch variables for the asm code below
47
    uint32_t v, t;
48
    
49
    // initialize the string length to zero
50
    size_t l = 0;
51
52
    // align the pointer to a 32-bit word boundary
53
    u.b = s;
54
    while (u.i & 0x3)  {
55
        if (__builtin_expect(*u.b++ == 0, 0)) {
56
            goto done;
57
        }
58
        l++;
59
    }
60
61
    // loop for each word, testing if it contains a zero byte
62
    // if so, exit the loop and update the length.
63
    // We need to process 32 bytes per loop to schedule PLD properly
64
    // and achieve the maximum bus speed.
65
    asm(
66
        "ldr     %[v], [%[s]], #4         \n"
67
        "sub     %[l], %[l], %[s]           \n"
68
        "0:                                 \n"
69
#if __ARM_HAVE_PLD
70
        "pld     [%[s], #64]              \n"
71
#endif
72
        "sub     %[t], %[v], %[mask], lsr #7\n"
73
        "and     %[t], %[t], %[mask]        \n"
74
        "bics    %[t], %[t], %[v]           \n"
75
        "ldreq   %[v], [%[s]], #4         \n"
76
#if !defined(__OPTIMIZE_SIZE__)
77
        "bne     1f                         \n"
78
        "sub     %[t], %[v], %[mask], lsr #7\n"
79
        "and     %[t], %[t], %[mask]        \n"
80
        "bics    %[t], %[t], %[v]           \n"
81
        "ldreq   %[v], [%[s]], #4         \n"
82
        "bne     1f                         \n"
83
        "sub     %[t], %[v], %[mask], lsr #7\n"
84
        "and     %[t], %[t], %[mask]        \n"
85
        "bics    %[t], %[t], %[v]           \n"
86
        "ldreq   %[v], [%[s]], #4         \n"
87
        "bne     1f                         \n"
88
        "sub     %[t], %[v], %[mask], lsr #7\n"
89
        "and     %[t], %[t], %[mask]        \n"
90
        "bics    %[t], %[t], %[v]           \n"
91
        "ldreq   %[v], [%[s]], #4         \n"
92
        "bne     1f                         \n"
93
        "sub     %[t], %[v], %[mask], lsr #7\n"
94
        "and     %[t], %[t], %[mask]        \n"
95
        "bics    %[t], %[t], %[v]           \n"
96
        "ldreq   %[v], [%[s]], #4         \n"
97
        "bne     1f                         \n"
98
        "sub     %[t], %[v], %[mask], lsr #7\n"
99
        "and     %[t], %[t], %[mask]        \n"
100
        "bics    %[t], %[t], %[v]           \n"
101
        "ldreq   %[v], [%[s]], #4         \n"
102
        "bne     1f                         \n"
103
        "sub     %[t], %[v], %[mask], lsr #7\n"
104
        "and     %[t], %[t], %[mask]        \n"
105
        "bics    %[t], %[t], %[v]           \n"
106
        "ldreq   %[v], [%[s]] , #4         \n"
107
        "bne     1f                         \n"
108
        "sub     %[t], %[v], %[mask], lsr #7\n"
109
        "and     %[t], %[t], %[mask]        \n"
110
        "bics    %[t], %[t], %[v]           \n"
111
        "ldreq   %[v], [%[s]], #4         \n"
112
#endif
113
        "beq     0b                         \n"
114
        "1:                                 \n"
115
        "add     %[l], %[l], %[s]           \n"
116
        "tst     %[v], #0xFF                \n"
117
        "beq     2f                         \n"
118
        "add     %[l], %[l], #1             \n"
119
        "tst     %[v], #0xFF00              \n"
120
        "beq     2f                         \n"
121
        "add     %[l], %[l], #1             \n"
122
        "tst     %[v], #0xFF0000            \n"
123
        "addne   %[l], %[l], #1             \n"
124
        "2:                                 \n"
125
        : [l]"=&r"(l), [v]"=&r"(v), [t]"=&r"(t), [s]"=&r"(u.b)
126
        : "%[l]"(l), "%[s]"(u.b), [mask]"r"(0x80808080UL)
127
        : "cc"
128
    );
129
    
130
done:
131
    return l;
132
}