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