1/* ANSI C standard library function strlen.
2
3   Copyright (c) 2001-2008 Tensilica Inc.
4
5   Permission is hereby granted, free of charge, to any person obtaining
6   a copy of this software and associated documentation files (the
7   "Software"), to deal in the Software without restriction, including
8   without limitation the rights to use, copy, modify, merge, publish,
9   distribute, sublicense, and/or sell copies of the Software, and to
10   permit persons to whom the Software is furnished to do so, subject to
11   the following conditions:
12
13   The above copyright notice and this permission notice shall be included
14   in all copies or substantial portions of the Software.
15
16   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19   IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
20   CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21   TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22   SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
23
24#include "xtensa-asm.h"
25
26	.text
27	.begin schedule
28	.align	4
29	.literal_position
30	.global	strlen
31	.type	strlen, @function
32strlen:
33	leaf_entry sp, 16
34	/* a2 = s */
35
36	addi	a3, a2, -4	// because we overincrement at the end
37	movi	a4, MASK0
38	movi	a5, MASK1
39	movi	a6, MASK2
40	movi	a7, MASK3
41	bbsi.l	a2, 0, .L1mod2
42	bbsi.l	a2, 1, .L2mod4
43	j	.Laligned
44
45.L1mod2: // address is odd
46	l8ui	a8, a3, 4	// get byte 0
47	addi	a3, a3, 1	// advance string pointer
48	beqz	a8, .Lz3	// if byte 0 is zero
49	bbci.l	a3, 1, .Laligned // if string pointer is now word-aligned
50
51.L2mod4: // address is 2 mod 4
52	addi	a3, a3, 2	// advance ptr for aligned access
53	l32i	a8, a3, 0	// get word with first two bytes of string
54	bnone	a8, a6, .Lz2	// if byte 2 (of word, not string) is zero
55	bany	a8, a7, .Laligned // if byte 3 (of word, not string) is nonzero
56
57	/* Byte 3 is zero.  */
58	addi	a3, a3, 3	// point to zero byte
59	sub	a2, a3, a2	// subtract to get length
60	leaf_return
61
62
63/* String is word-aligned.  */
64
65	.align	4
66#if XCHAL_HAVE_LOOPS
67#if XCHAL_HAVE_DENSITY
68	/* (2 mod 4) alignment for loop instruction */
69#else
70	/* (1 mod 4) alignment for loop instruction */
71	.byte	0
72	.byte	0
73#endif
74#endif
75.Laligned:
76#if XCHAL_HAVE_LOOPS
77#if XCHAL_HAVE_DENSITY
78	_movi.n	a8, 0		// set up for the maximum loop count
79#else
80	_movi	a8, 0		// set up for the maximum loop count
81#endif
82	loop	a8, .Lz3	// loop forever (almost anyway)
83#endif
841:	l32i	a8, a3, 4	// get next word of string
85	addi	a3, a3, 4	// advance string pointer
86	bnone	a8, a4, .Lz0	// if byte 0 is zero
87	bnone	a8, a5, .Lz1	// if byte 1 is zero
88	bnone	a8, a6, .Lz2	// if byte 2 is zero
89#if XCHAL_HAVE_LOOPS
90	bnone	a8, a7, .Lz3	// if byte 3 is zero
91#else
92	bany	a8, a7, 1b	// repeat if byte 3 is non-zero
93#endif
94
95.Lz3:	/* Byte 3 is zero.  */
96	addi	a3, a3, 3	// point to zero byte
97	/* Fall through....  */
98
99.Lz0:	/* Byte 0 is zero.  */
100	sub	a2, a3, a2	// subtract to get length
101	leaf_return
102
103.Lz1:	/* Byte 1 is zero.  */
104	addi	a3, a3, 1	// point to zero byte
105	sub	a2, a3, a2	// subtract to get length
106	leaf_return
107
108.Lz2:	/* Byte 2 is zero.  */
109	addi	a3, a3, 2	// point to zero byte
110	sub	a2, a3, a2	// subtract to get length
111	leaf_return
112
113	.end schedule
114
115	.size	strlen, . - strlen
116