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

« back to all changes in this revision

Viewing changes to reference/glibc/strlen.S

  • Committer: Will Newton
  • Date: 2013-08-08 13:03:41 UTC
  • Revision ID: will.newton@linaro.org-20130808130341-hrlxfley3qo3s3pe
Import latest strlen code from glibc.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* Copyright (C) 1998, 2003 Free Software Foundation, Inc.
 
1
/* strlen -- find the length of a nul-terminated string.
 
2
   Copyright (C) 2013 Free Software Foundation, Inc.
2
3
   This file is part of the GNU C Library.
3
 
   Code contributed by Matthew Wilcox <willy@odie.barnet.ac.uk>
4
4
 
5
5
   The GNU C Library is free software; you can redistribute it and/or
6
6
   modify it under the terms of the GNU Lesser General Public
13
13
   Lesser General Public License for more details.
14
14
 
15
15
   You should have received a copy of the GNU Lesser General Public
16
 
   License along with the GNU C Library; if not, write to the Free
17
 
   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18
 
   02111-1307 USA.  */
 
16
   License along with the GNU C Library.  If not, see
 
17
   <http://www.gnu.org/licenses/>.  */
19
18
 
20
 
/* size_t strlen(const char *S)
21
 
 * entry: r0 -> string
22
 
 * exit: r0 = len
23
 
 */
 
19
#define ARCH_HAS_T2
 
20
        
 
21
        .syntax unified
24
22
        .text
25
 
        .globl strlen
26
 
        .type strlen, %function
27
 
        
28
 
strlen: 
29
 
        bic     r1, r0, $3              @ addr of word containing first byte
30
 
        ldr     r2, [r1], $4            @ get the first word
31
 
        ands    r3, r0, $3              @ how many bytes are duff?
32
 
        rsb     r0, r3, $0              @ get - that number into counter.
33
 
        beq     Laligned                @ skip into main check routine if no
34
 
                                        @ more
35
 
#ifdef __ARMEB__
36
 
        orr     r2, r2, $0xff000000     @ set this byte to non-zero
37
 
        subs    r3, r3, $1              @ any more to do?
38
 
        orrgt   r2, r2, $0x00ff0000     @ if so, set this byte
39
 
        subs    r3, r3, $1              @ more?
40
 
        orrgt   r2, r2, $0x0000ff00     @ then set.
41
 
#else
42
 
        orr     r2, r2, $0x000000ff     @ set this byte to non-zero
43
 
        subs    r3, r3, $1              @ any more to do?
44
 
        orrgt   r2, r2, $0x0000ff00     @ if so, set this byte
45
 
        subs    r3, r3, $1              @ more?
46
 
        orrgt   r2, r2, $0x00ff0000     @ then set.
47
 
#endif
48
 
Laligned:                               @ here, we have a word in r2.  Does it
49
 
        tst     r2, $0x000000ff         @ contain any zeroes?
50
 
        tstne   r2, $0x0000ff00         @
51
 
        tstne   r2, $0x00ff0000         @
52
 
        tstne   r2, $0xff000000         @
53
 
        addne   r0, r0, $4              @ if not, the string is 4 bytes longer
54
 
        ldrne   r2, [r1], $4            @ and we continue to the next word
55
 
        bne     Laligned                @
56
 
Llastword:                              @ drop through to here once we find a
57
 
#ifdef __ARMEB__
58
 
        tst     r2, $0xff000000         @ word that has a zero byte in it
59
 
        addne   r0, r0, $1              @
60
 
        tstne   r2, $0x00ff0000         @ and add up to 3 bytes on to it
61
 
        addne   r0, r0, $1              @
62
 
        tstne   r2, $0x0000ff00         @ (if first three all non-zero, 4th
63
 
        addne   r0, r0, $1              @  must be zero)
64
 
#else
65
 
        tst     r2, $0x000000ff         @ word that has a zero byte in it
66
 
        addne   r0, r0, $1              @
67
 
        tstne   r2, $0x0000ff00         @ and add up to 3 bytes on to it
68
 
        addne   r0, r0, $1              @
69
 
        tstne   r2, $0x00ff0000         @ (if first three all non-zero, 4th
70
 
        addne   r0, r0, $1              @  must be zero)
71
 
#endif
72
 
        bx lr
73
 
        
 
23
        .global strlen
 
24
        .type strlen,%function
 
25
        .align 4
 
26
strlen:
 
27
        @ r0 = start of string
 
28
        ldrb    r2, [r0]                @ load the first byte asap
 
29
 
 
30
        @ To cater to long strings, we want to search through a few
 
31
        @ characters until we reach an aligned pointer.  To cater to
 
32
        @ small strings, we don't want to start doing word operations
 
33
        @ immediately.  The compromise is a maximum of 16 bytes less
 
34
        @ whatever is required to end with an aligned pointer.
 
35
        @ r3 = number of characters to search in alignment loop
 
36
        and     r3, r0, #7
 
37
        mov     r1, r0                  @ Save the input pointer
 
38
        rsb     r3, r3, #15             @ 16 - 1 peeled loop iteration
 
39
        cmp     r2, #0
 
40
        beq     99f
 
41
 
 
42
        @ Loop until we find ...
 
43
1:
 
44
        ldrb    r2, [r0, #1]!
 
45
        subs    r3, r3, #1              @ ... the aligment point
 
46
        it      ne
 
47
        cmpne   r2, #0                  @ ... or EOS
 
48
        bne     1b
 
49
 
 
50
        @ Disambiguate the exit possibilites above
 
51
        cmp     r2, #0                  @ Found EOS
 
52
        beq     99f
 
53
        add     r0, r0, #1
 
54
 
 
55
        @ So now we're aligned.
 
56
        ldrd    r2, r3, [r0], #8
 
57
#ifdef ARCH_HAS_T2
 
58
        movw    ip, #0x0101
 
59
        pld     [r0, #64]
 
60
        movt    ip, #0x0101
 
61
#else
 
62
        ldr     ip, =0x01010101
 
63
        pld     [r0, #64]
 
64
#endif
 
65
 
 
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
        pld     [r0, #128]              @ Prefetch 2 lines ahead
 
74
        orrs    r3, r3, r2              @ Combine the two words
 
75
        it      eq
 
76
        ldrdeq  r2, r3, [r0], #8
 
77
        beq     2b
 
78
 
 
79
        @ Found something.  Disambiguate between first and second words.
 
80
        @ Adjust r0 to point to the word containing the match.
 
81
        @ Adjust r2 to the found bits for the word containing the match.
 
82
        cmp     r2, #0
 
83
        sub     r0, r0, #4
 
84
        ite     eq
 
85
        moveq   r2, r3
 
86
        subne   r0, r0, #4
 
87
 
 
88
        @ Find the bit-offset of the match within the word.  Note that the
 
89
        @ bit result from clz will be 7 higher than "true", but we'll
 
90
        @ immediately discard those bits converting to a byte offset.
 
91
#ifdef __ARMEL__
 
92
        rev     r2, r2                  @ For LE, count from the little end
 
93
#endif
 
94
        clz     r2, r2
 
95
        add     r0, r0, r2, lsr #3      @ Adjust the pointer to the found byte
 
96
99:
 
97
        sub     r0, r0, r1              @ Subtract input to compute length
 
98
        bx      lr
 
99
        .size strlen,.-strlen