1/* Copyright (c) 2010-2011,2013 Linaro Limited
2   All rights reserved.
3
4   Redistribution and use in source and binary forms, with or without
5   modification, are permitted provided that the following conditions
6   are met:
7
8      * Redistributions of source code must retain the above copyright
9      notice, this list of conditions and the following disclaimer.
10
11      * Redistributions in binary form must reproduce the above copyright
12      notice, this list of conditions and the following disclaimer in the
13      documentation and/or other materials provided with the distribution.
14
15      * Neither the name of Linaro Limited nor the names of its
16      contributors may be used to endorse or promote products derived
17      from this software without specific prior written permission.
18
19   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23   HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
31   Assumes:
32   ARMv6T2 or ARMv7E-M, AArch32
33 */
34
35/* Copyright (c) 2015 ARM Ltd.
36   All rights reserved.
37
38   Redistribution and use in source and binary forms, with or without
39   modification, are permitted provided that the following conditions are met:
40       * Redistributions of source code must retain the above copyright
41	 notice, this list of conditions and the following disclaimer.
42       * Redistributions in binary form must reproduce the above copyright
43	 notice, this list of conditions and the following disclaimer in the
44	 documentation and/or other materials provided with the distribution.
45       * Neither the name of the Linaro nor the
46	 names of its contributors may be used to endorse or promote products
47	 derived from this software without specific prior written permission.
48
49   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
50   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
51   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
52   A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT
53   HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
54   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
55   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
56   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
57   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
58   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
59   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  */
60
61#include <picolibc.h>
62
63#include "arm_asm.h"
64
65	.macro def_fn f p2align=0
66	.text
67	.p2align \p2align
68	.global \f
69	.type \f, %function
70\f:
71	.endm
72
73#ifdef __ARMEB__
74#define S2LO		lsl
75#define S2HI		lsr
76#else
77#define S2LO		lsr
78#define S2HI		lsl
79#endif
80
81	/* This code requires Thumb.  */
82#if __ARM_ARCH_PROFILE == 'M'
83#if __ARM_ARCH >= 8
84	/* keep config inherited from -march=.  */
85#else
86	.arch   armv7e-m
87#endif /* if __ARM_ARCH >= 8 */
88#else
89	.arch	armv6t2
90#endif
91	.eabi_attribute Tag_ARM_ISA_use, 0
92	.thumb
93	.syntax unified
94
95/* Parameters and result.  */
96#define srcin		r0
97#define result		r0
98
99/* Internal variables.  */
100#define src		r1
101#define data1a		r2
102#define data1b		r3
103#define const_m1	r12
104#define const_0		r4
105#define tmp1		r4		/* Overlaps const_0  */
106#define tmp2		r5
107
108def_fn	strlen p2align=6
109	.fnstart
110	.cfi_sections .debug_frame
111	.cfi_startproc
112	prologue 4 5 push_ip=HAVE_PAC_LEAF
113	pld	[srcin, #0]
114	bic	src, srcin, #7
115	mvn	const_m1, #0
116	ands	tmp1, srcin, #7		/* (8 - bytes) to alignment.  */
117	pld	[src, #32]
118	bne.w	.Lmisaligned8
119	mov	const_0, #0
120	mov	result, #-8
121.Lloop_aligned:
122	/* Bytes 0-7.  */
123	ldrd	data1a, data1b, [src]
124	pld	[src, #64]
125	add	result, result, #8
126.Lstart_realigned:
127	uadd8	data1a, data1a, const_m1	/* Saturating GE<0:3> set.  */
128	sel	data1a, const_0, const_m1	/* Select based on GE<0:3>.  */
129	uadd8	data1b, data1b, const_m1
130	sel	data1b, data1a, const_m1	/* Only used if d1a == 0.  */
131	cbnz	data1b, .Lnull_found
132
133	/* Bytes 8-15.  */
134	ldrd	data1a, data1b, [src, #8]
135	uadd8	data1a, data1a, const_m1	/* Saturating GE<0:3> set.  */
136	add	result, result, #8
137	sel	data1a, const_0, const_m1	/* Select based on GE<0:3>.  */
138	uadd8	data1b, data1b, const_m1
139	sel	data1b, data1a, const_m1	/* Only used if d1a == 0.  */
140	cbnz	data1b, .Lnull_found
141
142	/* Bytes 16-23.  */
143	ldrd	data1a, data1b, [src, #16]
144	uadd8	data1a, data1a, const_m1	/* Saturating GE<0:3> set.  */
145	add	result, result, #8
146	sel	data1a, const_0, const_m1	/* Select based on GE<0:3>.  */
147	uadd8	data1b, data1b, const_m1
148	sel	data1b, data1a, const_m1	/* Only used if d1a == 0.  */
149	cbnz	data1b, .Lnull_found
150
151	/* Bytes 24-31.  */
152	ldrd	data1a, data1b, [src, #24]
153	add	src, src, #32
154	uadd8	data1a, data1a, const_m1	/* Saturating GE<0:3> set.  */
155	add	result, result, #8
156	sel	data1a, const_0, const_m1	/* Select based on GE<0:3>.  */
157	uadd8	data1b, data1b, const_m1
158	sel	data1b, data1a, const_m1	/* Only used if d1a == 0.  */
159	cmp	data1b, #0
160	beq	.Lloop_aligned
161
162.Lnull_found:
163	.cfi_remember_state
164	cmp	data1a, #0
165	itt	eq
166	addeq	result, result, #4
167	moveq	data1a, data1b
168#ifndef __ARMEB__
169	rev	data1a, data1a
170#endif
171	clz	data1a, data1a
172	add	result, result, data1a, lsr #3	/* Bits -> Bytes.  */
173	epilogue 4 5 push_ip=HAVE_PAC_LEAF
174
175.Lmisaligned8:
176	.cfi_restore_state
177	ldrd	data1a, data1b, [src]
178	and	tmp2, tmp1, #3
179	rsb	result, tmp1, #0
180	lsl	tmp2, tmp2, #3			/* Bytes -> bits.  */
181	tst	tmp1, #4
182	pld	[src, #64]
183	S2HI	tmp2, const_m1, tmp2
184	orn	data1a, data1a, tmp2
185	itt	ne
186	ornne	data1b, data1b, tmp2
187	movne	data1a, const_m1
188	mov	const_0, #0
189	b	.Lstart_realigned
190	.cfi_endproc
191	.cantunwind
192	.fnend
193	.size	strlen, . - strlen
194
195#if defined(__linux__) && defined(__ELF__)
196.section .note.GNU-stack,"",%progbits
197#endif
198