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 <private/bionic_asm.h>
31
32	.text
33
34#ifdef __ARMEB__
35#define SHFT2LSB lsl
36#define SHFT2LSBEQ lsleq
37#define SHFT2MSB lsr
38#define SHFT2MSBEQ lsreq
39#define MSB 0x000000ff
40#define LSB 0xff000000
41#else
42#define SHFT2LSB lsr
43#define SHFT2LSBEQ lsreq
44#define SHFT2MSB lsl
45#define SHFT2MSBEQ lsleq
46#define MSB 0xff000000
47#define LSB 0x000000ff
48#endif
49
50#define magic1(REG) REG
51#define magic2(REG) REG, lsl #7
52
53ENTRY(strcmp)
54	pld	[r0, #0]
55	pld	[r1, #0]
56	eor	r2, r0, r1
57	tst	r2, #3
58
59	/* Strings not at same byte offset from a word boundary.  */
60	bne	.Lstrcmp_unaligned
61	ands	r2, r0, #3
62	bic	r0, r0, #3
63	bic	r1, r1, #3
64	ldr	ip, [r0], #4
65	it	eq
66	ldreq	r3, [r1], #4
67	beq	1f
68
69	/* Although s1 and s2 have identical initial alignment, they are
70	 * not currently word aligned.  Rather than comparing bytes,
71	 * make sure that any bytes fetched from before the addressed
72	 * bytes are forced to 0xff.  Then they will always compare
73	 * equal.
74	 */
75	eor	r2, r2, #3
76	lsl	r2, r2, #3
77	mvn	r3, #MSB
78	SHFT2LSB	r2, r3, r2
79	ldr	r3, [r1], #4
80	orr	ip, ip, r2
81	orr	r3, r3, r2
821:
83	/* Load the 'magic' constant 0x01010101. */
84	str	r4, [sp, #-4]!
85	mov	r4, #1
86	orr	r4, r4, r4, lsl #8
87	orr	r4, r4, r4, lsl #16
88	.p2align	2
894:
90	pld	[r0, #8]
91	pld	[r1, #8]
92	sub	r2, ip, magic1(r4)
93	cmp	ip, r3
94	itttt	eq
95
96	/* check for any zero bytes in first word */
97	biceq	r2, r2, ip
98	tsteq	r2, magic2(r4)
99	ldreq	ip, [r0], #4
100	ldreq	r3, [r1], #4
101	beq	4b
1022:
103	/* There's a zero or a different byte in the word */
104	SHFT2MSB	r0, ip, #24
105	SHFT2LSB	ip, ip, #8
106	cmp	r0, #1
107	it	cs
108	cmpcs	r0, r3, SHFT2MSB #24
109	it	eq
110	SHFT2LSBEQ r3, r3, #8
111	beq	2b
112	/* On a big-endian machine, r0 contains the desired byte in bits
113	 * 0-7; on a little-endian machine they are in bits 24-31.  In
114	 * both cases the other bits in r0 are all zero.  For r3 the
115	 * interesting byte is at the other end of the word, but the
116	 * other bits are not necessarily zero.  We need a signed result
117	 * representing the differnece in the unsigned bytes, so for the
118	 * little-endian case we can't just shift the interesting bits up.
119	 */
120#ifdef __ARMEB__
121	sub	r0, r0, r3, lsr #24
122#else
123	and	r3, r3, #255
124	/* No RSB instruction in Thumb2 */
125#ifdef __thumb2__
126	lsr	r0, r0, #24
127	sub	r0, r0, r3
128#else
129	rsb	r0, r3, r0, lsr #24
130#endif
131#endif
132	ldr	r4, [sp], #4
133	bx	lr
134
135.Lstrcmp_unaligned:
136	wp1 .req r0
137	wp2 .req r1
138	b1  .req r2
139	w1  .req r4
140	w2  .req r5
141	t1  .req ip
142	@ r3 is scratch
143
144	/* First of all, compare bytes until wp1(sp1) is word-aligned. */
1451:
146	tst	wp1, #3
147	beq	2f
148	ldrb	r2, [wp1], #1
149	ldrb	r3, [wp2], #1
150	cmp	r2, #1
151	it	cs
152	cmpcs	r2, r3
153	beq	1b
154	sub	r0, r2, r3
155	bx	lr
156
1572:
158	str	r5, [sp, #-4]!
159	str	r4, [sp, #-4]!
160	mov	b1, #1
161	orr	b1, b1, b1, lsl #8
162	orr	b1, b1, b1, lsl #16
163
164	and	t1, wp2, #3
165	bic	wp2, wp2, #3
166	ldr	w1, [wp1], #4
167	ldr	w2, [wp2], #4
168	cmp	t1, #2
169	beq	2f
170	bhi	3f
171
172	/* Critical inner Loop: Block with 3 bytes initial overlap */
173	.p2align	2
1741:
175	bic	t1, w1, #MSB
176	cmp	t1, w2, SHFT2LSB #8
177	sub	r3, w1, b1
178	bic	r3, r3, w1
179	bne	4f
180	ands	r3, r3, b1, lsl #7
181	it	eq
182	ldreq	w2, [wp2], #4
183	bne	5f
184	eor	t1, t1, w1
185	cmp	t1, w2, SHFT2MSB #24
186	bne	6f
187	ldr	w1, [wp1], #4
188	b	1b
1894:
190	SHFT2LSB	w2, w2, #8
191	b	8f
192
1935:
194#ifdef __ARMEB__
195	/* The syndrome value may contain false ones if the string ends
196	 * with the bytes 0x01 0x00
197	 */
198	tst	w1, #0xff000000
199	itt	ne
200	tstne	w1, #0x00ff0000
201	tstne	w1, #0x0000ff00
202	beq	7f
203#else
204	bics	r3, r3, #0xff000000
205	bne	7f
206#endif
207	ldrb	w2, [wp2]
208	SHFT2LSB	t1, w1, #24
209#ifdef __ARMEB__
210	lsl	w2, w2, #24
211#endif
212	b	8f
213
2146:
215	SHFT2LSB	t1, w1, #24
216	and	w2, w2, #LSB
217	b	8f
218
219	/* Critical inner Loop: Block with 2 bytes initial overlap */
220	.p2align	2
2212:
222	SHFT2MSB	t1, w1, #16
223	sub	r3, w1, b1
224	SHFT2LSB	t1, t1, #16
225	bic	r3, r3, w1
226	cmp	t1, w2, SHFT2LSB #16
227	bne	4f
228	ands	r3, r3, b1, lsl #7
229	it	eq
230	ldreq	w2, [wp2], #4
231	bne	5f
232	eor	t1, t1, w1
233	cmp	t1, w2, SHFT2MSB #16
234	bne	6f
235	ldr	w1, [wp1], #4
236	b	2b
237
2385:
239#ifdef __ARMEB__
240	/* The syndrome value may contain false ones if the string ends
241	 * with the bytes 0x01 0x00
242	 */
243	tst	w1, #0xff000000
244	it	ne
245	tstne	w1, #0x00ff0000
246	beq	7f
247#else
248	lsls	r3, r3, #16
249	bne	7f
250#endif
251	ldrh	w2, [wp2]
252	SHFT2LSB	t1, w1, #16
253#ifdef __ARMEB__
254	lsl	w2, w2, #16
255#endif
256	b	8f
257
2586:
259	SHFT2MSB	w2, w2, #16
260	SHFT2LSB	t1, w1, #16
2614:
262	SHFT2LSB	w2, w2, #16
263	b	8f
264
265	/* Critical inner Loop: Block with 1 byte initial overlap */
266	.p2align	2
2673:
268	and	t1, w1, #LSB
269	cmp	t1, w2, SHFT2LSB #24
270	sub	r3, w1, b1
271	bic	r3, r3, w1
272	bne	4f
273	ands	r3, r3, b1, lsl #7
274	it	eq
275	ldreq	w2, [wp2], #4
276	bne	5f
277	eor	t1, t1, w1
278	cmp	t1, w2, SHFT2MSB #8
279	bne	6f
280	ldr	w1, [wp1], #4
281	b	3b
2824:
283	SHFT2LSB	w2, w2, #24
284	b	8f
2855:
286	/* The syndrome value may contain false ones if the string ends
287	 * with the bytes 0x01 0x00
288	 */
289	tst	w1, #LSB
290	beq	7f
291	ldr	w2, [wp2], #4
2926:
293	SHFT2LSB	t1, w1, #8
294	bic	w2, w2, #MSB
295	b	8f
2967:
297	mov	r0, #0
298	ldr	r4, [sp], #4
299	ldr	r5, [sp], #4
300	bx	lr
301
3028:
303	and	r2, t1, #LSB
304	and	r0, w2, #LSB
305	cmp	r0, #1
306	it	cs
307	cmpcs	r0, r2
308	itt	eq
309	SHFT2LSBEQ	t1, t1, #8
310	SHFT2LSBEQ	w2, w2, #8
311	beq	8b
312	sub	r0, r2, r0
313	ldr	r4, [sp], #4
314	ldr	r5, [sp], #4
315	bx	lr
316END(strcmp)
317