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 "arm_asm.h"
62
63	.macro def_fn f p2align=0
64	.text
65	.p2align \p2align
66	.global \f
67	.type \f, %function
68\f:
69	.endm
70
71#ifdef __ARMEB__
72#define S2LO		lsl
73#define S2HI		lsr
74#else
75#define S2LO		lsr
76#define S2HI		lsl
77#endif
78
79	/* This code requires Thumb.  */
80#if __ARM_ARCH_PROFILE == 'M'
81#if __ARM_ARCH >= 8
82	/* keep config inherited from -march=.  */
83#else
84	.arch   armv7e-m
85#endif /* if __ARM_ARCH >= 8 */
86#else
87	.arch	armv6t2
88#endif
89	.eabi_attribute Tag_ARM_ISA_use, 0
90	.thumb
91	.syntax unified
92
93/* Parameters and result.  */
94#define srcin		r0
95#define result		r0
96
97/* Internal variables.  */
98#define src		r1
99#define data1a		r2
100#define data1b		r3
101#define const_m1	r12
102#define const_0		r4
103#define tmp1		r4		/* Overlaps const_0  */
104#define tmp2		r5
105
106def_fn	strlen p2align=6
107	.fnstart
108	.cfi_startproc
109	prologue 4 5 push_ip=HAVE_PAC_LEAF
110	pld	[srcin, #0]
111	bic	src, srcin, #7
112	mvn	const_m1, #0
113	ands	tmp1, srcin, #7		/* (8 - bytes) to alignment.  */
114	pld	[src, #32]
115	bne.w	.Lmisaligned8
116	mov	const_0, #0
117	mov	result, #-8
118.Lloop_aligned:
119	/* Bytes 0-7.  */
120	ldrd	data1a, data1b, [src]
121	pld	[src, #64]
122	add	result, result, #8
123.Lstart_realigned:
124	uadd8	data1a, data1a, const_m1	/* Saturating GE<0:3> set.  */
125	sel	data1a, const_0, const_m1	/* Select based on GE<0:3>.  */
126	uadd8	data1b, data1b, const_m1
127	sel	data1b, data1a, const_m1	/* Only used if d1a == 0.  */
128	cbnz	data1b, .Lnull_found
129
130	/* Bytes 8-15.  */
131	ldrd	data1a, data1b, [src, #8]
132	uadd8	data1a, data1a, const_m1	/* Saturating GE<0:3> set.  */
133	add	result, result, #8
134	sel	data1a, const_0, const_m1	/* Select based on GE<0:3>.  */
135	uadd8	data1b, data1b, const_m1
136	sel	data1b, data1a, const_m1	/* Only used if d1a == 0.  */
137	cbnz	data1b, .Lnull_found
138
139	/* Bytes 16-23.  */
140	ldrd	data1a, data1b, [src, #16]
141	uadd8	data1a, data1a, const_m1	/* Saturating GE<0:3> set.  */
142	add	result, result, #8
143	sel	data1a, const_0, const_m1	/* Select based on GE<0:3>.  */
144	uadd8	data1b, data1b, const_m1
145	sel	data1b, data1a, const_m1	/* Only used if d1a == 0.  */
146	cbnz	data1b, .Lnull_found
147
148	/* Bytes 24-31.  */
149	ldrd	data1a, data1b, [src, #24]
150	add	src, src, #32
151	uadd8	data1a, data1a, const_m1	/* Saturating GE<0:3> set.  */
152	add	result, result, #8
153	sel	data1a, const_0, const_m1	/* Select based on GE<0:3>.  */
154	uadd8	data1b, data1b, const_m1
155	sel	data1b, data1a, const_m1	/* Only used if d1a == 0.  */
156	cmp	data1b, #0
157	beq	.Lloop_aligned
158
159.Lnull_found:
160	.cfi_remember_state
161	cmp	data1a, #0
162	itt	eq
163	addeq	result, result, #4
164	moveq	data1a, data1b
165#ifndef __ARMEB__
166	rev	data1a, data1a
167#endif
168	clz	data1a, data1a
169	add	result, result, data1a, lsr #3	/* Bits -> Bytes.  */
170	epilogue 4 5 push_ip=HAVE_PAC_LEAF
171
172.Lmisaligned8:
173	.cfi_restore_state
174	ldrd	data1a, data1b, [src]
175	and	tmp2, tmp1, #3
176	rsb	result, tmp1, #0
177	lsl	tmp2, tmp2, #3			/* Bytes -> bits.  */
178	tst	tmp1, #4
179	pld	[src, #64]
180	S2HI	tmp2, const_m1, tmp2
181	orn	data1a, data1a, tmp2
182	itt	ne
183	ornne	data1b, data1b, tmp2
184	movne	data1a, const_m1
185	mov	const_0, #0
186	b	.Lstart_realigned
187	.cfi_endproc
188	.cantunwind
189	.fnend
190	.size	strlen, . - strlen
191
192#if defined(__linux__) && defined(__ELF__)
193.section .note.GNU-stack,"",%progbits
194#endif
195