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 <picolibc.h>
25
26#include "xtensa-asm.h"
27
28	.text
29	.begin schedule
30	.align	4
31	.literal_position
32	.global	strlen
33	.type	strlen, @function
34strlen:
35	leaf_entry sp, 16
36	/* a2 = s */
37
38	addi	a3, a2, -4	// because we overincrement at the end
39	movi	a4, MASK0
40	movi	a5, MASK1
41	movi	a6, MASK2
42	movi	a7, MASK3
43	bbsi.l	a2, 0, .L1mod2
44	bbsi.l	a2, 1, .L2mod4
45	j	.Laligned
46
47.L1mod2: // address is odd
48	l8ui	a8, a3, 4	// get byte 0
49	addi	a3, a3, 1	// advance string pointer
50	beqz	a8, .Lz3	// if byte 0 is zero
51	bbci.l	a3, 1, .Laligned // if string pointer is now word-aligned
52
53.L2mod4: // address is 2 mod 4
54	addi	a3, a3, 2	// advance ptr for aligned access
55	l32i	a8, a3, 0	// get word with first two bytes of string
56	bnone	a8, a6, .Lz2	// if byte 2 (of word, not string) is zero
57	bany	a8, a7, .Laligned // if byte 3 (of word, not string) is nonzero
58
59	/* Byte 3 is zero.  */
60	addi	a3, a3, 3	// point to zero byte
61	sub	a2, a3, a2	// subtract to get length
62	leaf_return
63
64
65/* String is word-aligned.  */
66
67	.align	4
68#if XCHAL_HAVE_LOOPS
69#if XCHAL_HAVE_DENSITY
70	/* (2 mod 4) alignment for loop instruction */
71#else
72	/* (1 mod 4) alignment for loop instruction */
73	.byte	0
74	.byte	0
75#endif
76#endif
77.Laligned:
78#if XCHAL_HAVE_LOOPS
79#if XCHAL_HAVE_DENSITY
80	_movi.n	a8, 0		// set up for the maximum loop count
81#else
82	_movi	a8, 0		// set up for the maximum loop count
83#endif
84	loop	a8, .Lz3	// loop forever (almost anyway)
85#endif
861:	l32i	a8, a3, 4	// get next word of string
87	addi	a3, a3, 4	// advance string pointer
88	bnone	a8, a4, .Lz0	// if byte 0 is zero
89	bnone	a8, a5, .Lz1	// if byte 1 is zero
90	bnone	a8, a6, .Lz2	// if byte 2 is zero
91#if XCHAL_HAVE_LOOPS
92	bnone	a8, a7, .Lz3	// if byte 3 is zero
93#else
94	bany	a8, a7, 1b	// repeat if byte 3 is non-zero
95#endif
96
97.Lz3:	/* Byte 3 is zero.  */
98	addi	a3, a3, 3	// point to zero byte
99	/* Fall through....  */
100
101.Lz0:	/* Byte 0 is zero.  */
102	sub	a2, a3, a2	// subtract to get length
103	leaf_return
104
105.Lz1:	/* Byte 1 is zero.  */
106	addi	a3, a3, 1	// point to zero byte
107	sub	a2, a3, a2	// subtract to get length
108	leaf_return
109
110.Lz2:	/* Byte 2 is zero.  */
111	addi	a3, a3, 2	// point to zero byte
112	sub	a2, a3, a2	// subtract to get length
113	leaf_return
114
115	.end schedule
116
117	.size	strlen, . - strlen
118