1/*
2 * Copyright (c) 2011 The Android Open Source Project
3 * Copyright (c) 2008 ARM Ltd
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 * 2. 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 * 3. The name of the company may not be used to endorse or promote
15 *    products derived from this software without specific prior written
16 *    permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY ARM LTD ``AS IS'' AND ANY EXPRESS OR IMPLIED
19 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
20 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL ARM LTD BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
23 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30#include <machine/cpu-features.h>
31#include <private/bionic_asm.h>
32
33	.text
34
35#ifdef __ARMEB__
36#define SHFT2LSB lsl
37#define SHFT2LSBEQ lsleq
38#define SHFT2MSB lsr
39#define SHFT2MSBEQ lsreq
40#define MSB 0x000000ff
41#define LSB 0xff000000
42#else
43#define SHFT2LSB lsr
44#define SHFT2LSBEQ lsreq
45#define SHFT2MSB lsl
46#define SHFT2MSBEQ lsleq
47#define MSB 0xff000000
48#define LSB 0x000000ff
49#endif
50
51#define magic1(REG) REG
52#define magic2(REG) REG, lsl #7
53
54ENTRY(strcmp)
55	pld	[r0, #0]
56	pld	[r1, #0]
57	eor	r2, r0, r1
58	tst	r2, #3
59
60	/* Strings not at same byte offset from a word boundary.  */
61	bne	.Lstrcmp_unaligned
62	ands	r2, r0, #3
63	bic	r0, r0, #3
64	bic	r1, r1, #3
65	ldr	ip, [r0], #4
66	it	eq
67	ldreq	r3, [r1], #4
68	beq	1f
69
70	/* Although s1 and s2 have identical initial alignment, they are
71	 * not currently word aligned.  Rather than comparing bytes,
72	 * make sure that any bytes fetched from before the addressed
73	 * bytes are forced to 0xff.  Then they will always compare
74	 * equal.
75	 */
76	eor	r2, r2, #3
77	lsl	r2, r2, #3
78	mvn	r3, #MSB
79	SHFT2LSB	r2, r3, r2
80	ldr	r3, [r1], #4
81	orr	ip, ip, r2
82	orr	r3, r3, r2
831:
84	/* Load the 'magic' constant 0x01010101. */
85	str	r4, [sp, #-4]!
86	mov	r4, #1
87	orr	r4, r4, r4, lsl #8
88	orr	r4, r4, r4, lsl #16
89	.p2align	2
904:
91	pld	[r0, #8]
92	pld	[r1, #8]
93	sub	r2, ip, magic1(r4)
94	cmp	ip, r3
95	itttt	eq
96
97	/* check for any zero bytes in first word */
98	biceq	r2, r2, ip
99	tsteq	r2, magic2(r4)
100	ldreq	ip, [r0], #4
101	ldreq	r3, [r1], #4
102	beq	4b
1032:
104	/* There's a zero or a different byte in the word */
105	SHFT2MSB	r0, ip, #24
106	SHFT2LSB	ip, ip, #8
107	cmp	r0, #1
108	it	cs
109	cmpcs	r0, r3, SHFT2MSB #24
110	it	eq
111	SHFT2LSBEQ r3, r3, #8
112	beq	2b
113	/* On a big-endian machine, r0 contains the desired byte in bits
114	 * 0-7; on a little-endian machine they are in bits 24-31.  In
115	 * both cases the other bits in r0 are all zero.  For r3 the
116	 * interesting byte is at the other end of the word, but the
117	 * other bits are not necessarily zero.  We need a signed result
118	 * representing the differnece in the unsigned bytes, so for the
119	 * little-endian case we can't just shift the interesting bits up.
120	 */
121#ifdef __ARMEB__
122	sub	r0, r0, r3, lsr #24
123#else
124	and	r3, r3, #255
125	/* No RSB instruction in Thumb2 */
126#ifdef __thumb2__
127	lsr	r0, r0, #24
128	sub	r0, r0, r3
129#else
130	rsb	r0, r3, r0, lsr #24
131#endif
132#endif
133	ldr	r4, [sp], #4
134	bx	lr
135
136.Lstrcmp_unaligned:
137	wp1 .req r0
138	wp2 .req r1
139	b1  .req r2
140	w1  .req r4
141	w2  .req r5
142	t1  .req ip
143	@ r3 is scratch
144
145	/* First of all, compare bytes until wp1(sp1) is word-aligned. */
1461:
147	tst	wp1, #3
148	beq	2f
149	ldrb	r2, [wp1], #1
150	ldrb	r3, [wp2], #1
151	cmp	r2, #1
152	it	cs
153	cmpcs	r2, r3
154	beq	1b
155	sub	r0, r2, r3
156	bx	lr
157
1582:
159	str	r5, [sp, #-4]!
160	str	r4, [sp, #-4]!
161	mov	b1, #1
162	orr	b1, b1, b1, lsl #8
163	orr	b1, b1, b1, lsl #16
164
165	and	t1, wp2, #3
166	bic	wp2, wp2, #3
167	ldr	w1, [wp1], #4
168	ldr	w2, [wp2], #4
169	cmp	t1, #2
170	beq	2f
171	bhi	3f
172
173	/* Critical inner Loop: Block with 3 bytes initial overlap */
174	.p2align	2
1751:
176	bic	t1, w1, #MSB
177	cmp	t1, w2, SHFT2LSB #8
178	sub	r3, w1, b1
179	bic	r3, r3, w1
180	bne	4f
181	ands	r3, r3, b1, lsl #7
182	it	eq
183	ldreq	w2, [wp2], #4
184	bne	5f
185	eor	t1, t1, w1
186	cmp	t1, w2, SHFT2MSB #24
187	bne	6f
188	ldr	w1, [wp1], #4
189	b	1b
1904:
191	SHFT2LSB	w2, w2, #8
192	b	8f
193
1945:
195#ifdef __ARMEB__
196	/* The syndrome value may contain false ones if the string ends
197	 * with the bytes 0x01 0x00
198	 */
199	tst	w1, #0xff000000
200	itt	ne
201	tstne	w1, #0x00ff0000
202	tstne	w1, #0x0000ff00
203	beq	7f
204#else
205	bics	r3, r3, #0xff000000
206	bne	7f
207#endif
208	ldrb	w2, [wp2]
209	SHFT2LSB	t1, w1, #24
210#ifdef __ARMEB__
211	lsl	w2, w2, #24
212#endif
213	b	8f
214
2156:
216	SHFT2LSB	t1, w1, #24
217	and	w2, w2, #LSB
218	b	8f
219
220	/* Critical inner Loop: Block with 2 bytes initial overlap */
221	.p2align	2
2222:
223	SHFT2MSB	t1, w1, #16
224	sub	r3, w1, b1
225	SHFT2LSB	t1, t1, #16
226	bic	r3, r3, w1
227	cmp	t1, w2, SHFT2LSB #16
228	bne	4f
229	ands	r3, r3, b1, lsl #7
230	it	eq
231	ldreq	w2, [wp2], #4
232	bne	5f
233	eor	t1, t1, w1
234	cmp	t1, w2, SHFT2MSB #16
235	bne	6f
236	ldr	w1, [wp1], #4
237	b	2b
238
2395:
240#ifdef __ARMEB__
241	/* The syndrome value may contain false ones if the string ends
242	 * with the bytes 0x01 0x00
243	 */
244	tst	w1, #0xff000000
245	it	ne
246	tstne	w1, #0x00ff0000
247	beq	7f
248#else
249	lsls	r3, r3, #16
250	bne	7f
251#endif
252	ldrh	w2, [wp2]
253	SHFT2LSB	t1, w1, #16
254#ifdef __ARMEB__
255	lsl	w2, w2, #16
256#endif
257	b	8f
258
2596:
260	SHFT2MSB	w2, w2, #16
261	SHFT2LSB	t1, w1, #16
2624:
263	SHFT2LSB	w2, w2, #16
264	b	8f
265
266	/* Critical inner Loop: Block with 1 byte initial overlap */
267	.p2align	2
2683:
269	and	t1, w1, #LSB
270	cmp	t1, w2, SHFT2LSB #24
271	sub	r3, w1, b1
272	bic	r3, r3, w1
273	bne	4f
274	ands	r3, r3, b1, lsl #7
275	it	eq
276	ldreq	w2, [wp2], #4
277	bne	5f
278	eor	t1, t1, w1
279	cmp	t1, w2, SHFT2MSB #8
280	bne	6f
281	ldr	w1, [wp1], #4
282	b	3b
2834:
284	SHFT2LSB	w2, w2, #24
285	b	8f
2865:
287	/* The syndrome value may contain false ones if the string ends
288	 * with the bytes 0x01 0x00
289	 */
290	tst	w1, #LSB
291	beq	7f
292	ldr	w2, [wp2], #4
2936:
294	SHFT2LSB	t1, w1, #8
295	bic	w2, w2, #MSB
296	b	8f
2977:
298	mov	r0, #0
299	ldr	r4, [sp], #4
300	ldr	r5, [sp], #4
301	bx	lr
302
3038:
304	and	r2, t1, #LSB
305	and	r0, w2, #LSB
306	cmp	r0, #1
307	it	cs
308	cmpcs	r0, r2
309	itt	eq
310	SHFT2LSBEQ	t1, t1, #8
311	SHFT2LSBEQ	w2, w2, #8
312	beq	8b
313	sub	r0, r2, r0
314	ldr	r4, [sp], #4
315	ldr	r5, [sp], #4
316	bx	lr
317END(strcmp)
318