13
13
Lesser General Public License for more details.
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
16
License along with the GNU C Library. If not, see
17
<http://www.gnu.org/licenses/>. */
20
/* size_t strlen(const char *S)
26
.type strlen, %function
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
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.
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.
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
56
Llastword: @ drop through to here once we find a
58
tst r2, $0xff000000 @ word that has a zero byte in it
60
tstne r2, $0x00ff0000 @ and add up to 3 bytes on to it
62
tstne r2, $0x0000ff00 @ (if first three all non-zero, 4th
63
addne r0, r0, $1 @ must be zero)
65
tst r2, $0x000000ff @ word that has a zero byte in it
67
tstne r2, $0x0000ff00 @ and add up to 3 bytes on to it
69
tstne r2, $0x00ff0000 @ (if first three all non-zero, 4th
70
addne r0, r0, $1 @ must be zero)
24
.type strlen,%function
27
@ r0 = start of string
28
ldrb r2, [r0] @ load the first byte asap
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
37
mov r1, r0 @ Save the input pointer
38
rsb r3, r3, #15 @ 16 - 1 peeled loop iteration
42
@ Loop until we find ...
45
subs r3, r3, #1 @ ... the aligment point
47
cmpne r2, #0 @ ... or EOS
50
@ Disambiguate the exit possibilites above
51
cmp r2, #0 @ Found EOS
55
@ So now we're aligned.
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.
71
2: uqsub8 r2, ip, r2 @ Find EOS
73
pld [r0, #128] @ Prefetch 2 lines ahead
74
orrs r3, r3, r2 @ Combine the two words
76
ldrdeq r2, r3, [r0], #8
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.
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.
92
rev r2, r2 @ For LE, count from the little end
95
add r0, r0, r2, lsr #3 @ Adjust the pointer to the found byte
97
sub r0, r0, r1 @ Subtract input to compute length