xref: /titanic_52/usr/src/lib/libc/sparc/gen/strncmp.s (revision e1c679fa4b0ab8c4bcaa6263974ca0c46e5b027f)
1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License").  You may not use this file except in compliance
7 * with the License.
8 *
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
13 *
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 *
20 * CDDL HEADER END
21 */
22/*
23 *	Copyright (c) 1989,1998 by Sun Microsystems, Inc.
24 *	All rights reserved.
25 *
26 *	.seg	"data"
27 *	.asciz	"@(#)strncmp.s 1.2 89/08/16"
28 */
29
30.ident	"%Z%%M%	%I%	%E% SMI"	/* SunOS 4.1 1.4	*/
31
32	.file	"strncmp.s"
33
34/*
35 * strncmp(s1, s2, n)
36 *
37 * Compare strings (at most n bytes):  s1>s2: >0  s1==s2: 0  s1<s2: <0
38 *
39 * Fast assembler language version of the following C-program for strncmp
40 * which represents the `standard' for the C-library.
41 *
42 *	int
43 *	strncmp(const char *s1, const char *s2, size_t n)
44 *	{
45 *		n++;
46 *		if (s1 == s2)
47 *			return (0);
48 *		while (--n != 0 && *s1 == *s2++)
49 *			if (*s1++ == '\0')
50 *				return (0);
51 *		return ((n == 0) ? 0 : (*s1 - s2[-1]));
52 *	}
53 */
54
55#include <sys/asm_linkage.h>
56#include "synonyms.h"
57
58	ENTRY(strncmp)
59	save	%sp, -SA(WINDOWSIZE), %sp
60	cmp	%i2, 8
61	blu,a	.cmp_bytes		! for small counts go do bytes
62	sub	%i0, %i1, %i0		! delay slot, get diff from s1 - s2
63	andcc	%i0, 3, %g0		! is s1 aligned
641:	bz	.iss2			! if so go check s2
65	andcc	%i1, 3, %i3		! is s2 aligned
66
67	deccc	%i2			! --n >= 0 ?
68	bcs	.doneq
69	nop				! delay slot
70
71	ldub	[%i0], %i4		! else cmp one byte
72	ldub	[%i1], %i5
73	inc	%i0
74	cmp	%i4, %i5
75	bne	.noteqb
76	inc	%i1
77	tst	%i4			! terminating zero
78	bnz	1b
79	andcc	%i0, 3, %g0
80	b,a	.doneq
81
82.iss2:
83	set     0x7efefeff, %l6
84	set     0x81010100, %l7
85	sethi	%hi(0xff000000), %l0	! masks to test for terminating null
86	sethi	%hi(0x00ff0000), %l1
87	srl	%l1, 8, %l2		! generate 0x0000ff00 mask
88
89	bz	.w4cmp			! if s2 word aligned, compare words
90	cmp	%i3, 2			! check if s2 half aligned
91	be	.w2cmp
92	cmp	%i3, 1			! check if aligned to 1 or 3 bytes
93.w3cmp:	ldub	[%i1], %i5
94	inc	1, %i1
95	be	.w1cmp
96	sll	%i5, 24, %i5
97	sub	%i0, %i1, %i0
982:
99	deccc	4, %i2			! n >= 4 ?
100	bgeu,a	3f
101	ld	[%i1], %i3		! delay slot
102	dec	%i1			! reset s2
103	inc	%i0			! reset s1 diff
104	b	.cmp_bytes		! do a byte at a time if n < 4
105	inc	4, %i2
1063:
107	ld	[%i0 + %i1], %i4
108	inc	4, %i1
109	srl	%i3, 8, %l4		! merge with the other half
110	or	%l4, %i5, %i5
111	cmp	%i4, %i5
112	be	1f
113
114	add	%i4, %l6, %l3
115	b,a	.noteq
1161:	xor	%l3, %i4, %l3
117	and	%l3, %l7, %l3
118	cmp	%l3, %l7
119	be,a	2b
120	sll	%i3, 24, %i5
121
122	!
123	! For 7-bit characters, we know one of the bytes is zero, but for
124	! 8-bit characters, the zero detection algorithm gives some false
125	! triggers ... check every byte individually.
126	!
127	andcc	%i4, %l0, %g0		! check if first byte was zero
128	bnz	1f
129	andcc	%i4, %l1, %g0		! check if second byte was zero
130	b,a	.doneq
1311:	bnz	1f
132	andcc 	%i4, %l2, %g0		! check if third byte was zero
133	b,a	.doneq
1341:	bnz	1f
135	andcc	%i4, 0xff, %g0		! check if last byte is zero
136	b,a	.doneq
1371:	bnz	2b
138	sll	%i3, 24, %i5
139	b,a	.doneq
140
141.w1cmp:	clr	%l4
142	lduh	[%i1], %l4
143	inc	2, %i1
144	sll	%l4, 8, %l4
145	or	%i5, %l4, %i5
146
147	sub	%i0, %i1, %i0
1483:
149	deccc	4, %i2			! n >= 4 ?
150	bgeu,a	4f
151	ld	[%i1], %i3		! delay slot
152	dec	3, %i1			! reset s2
153	inc	3, %i0			! reset s1 diff
154	b	.cmp_bytes		! do a byte at a time if n < 4
155	inc	4, %i2
1564:
157	ld	[%i0 + %i1], %i4
158	inc	4, %i1
159	srl	%i3, 24, %l4		! merge with the other half
160	or	%l4, %i5, %i5
161	cmp	%i4, %i5
162	be	1f
163
164	add	%i4, %l6, %l3
165	b,a	.noteq
1661:	xor	%l3, %i4, %l3
167	and	%l3, %l7, %l3
168	cmp	%l3, %l7
169	be,a	3b
170	sll	%i3, 8, %i5
171
172	andcc	%i4, %l0, %g0		! check if first byte was zero
173	bnz	1f
174	andcc	%i4, %l1, %g0		! check if second byte was zero
175	b,a	.doneq
1761:	bnz	1f
177	andcc 	%i4, %l2, %g0		! check if third byte was zero
178	b,a	.doneq
1791:	bnz	1f
180	andcc	%i4, 0xff, %g0		! check if last byte is zero
181	b,a	.doneq
1821:	bnz	3b
183	sll	%i3, 8, %i5
184	b,a	.doneq
185
186.w2cmp:
187	lduh	[%i1], %i5		! read a halfword to align s2
188	inc	2, %i1
189	sll	%i5, 16, %i5
190
191	sub	%i0, %i1, %i0
1924:
193	deccc	4, %i2			! n >= 4 ?
194	bgeu,a	5f
195	ld	[%i1], %i3		! delay slot
196	dec	2, %i1			! reset s2
197	inc	2, %i0			! reset s1 diff
198	b	.cmp_bytes		! do a byte at a time if n < 4
199	inc	4, %i2			! delay slot
2005:
201	ld	[%i1 + %i0], %i4	! read a word from s2
202	inc	4, %i1
203	srl	%i3, 16, %l4		! merge with the other half
204	or	%l4, %i5, %i5
205	cmp	%i4, %i5
206	be	1f
207
208	add	%i4, %l6, %l3
209	b,a	.noteq
2101:	xor	%l3, %i4, %l3		! are any bytes 0?
211	and	%l3, %l7, %l3
212	cmp	%l3, %l7
213	be,a	4b
214	sll	%i3, 16, %i5
215
216	andcc	%i4, %l0, %g0		! check if first byte was zero
217	bnz	1f
218	andcc	%i4, %l1, %g0		! check if second byte was zero
219	b,a	.doneq
2201:	bnz	1f
221	andcc 	%i4, %l2, %g0		! check if third byte was zero
222	b,a	.doneq
2231:	bnz	1f
224	andcc	%i4, 0xff, %g0		! check if last byte is zero
225	b,a	.doneq
2261:	bnz	4b
227	sll	%i3, 16, %i5
228	b,a	.doneq
229
230.w4cmp:	sub	%i0, %i1, %i0
231	ld	[%i1], %i5		! read a word from s1
2325:	cmp     %i2,0
233	be,a    .doneq
234	nop
235	ld      [%i1], %i5              ! read a word from s1
236	deccc	4, %i2			! n >= 4 ?
237	bcs,a	.cmp_bytes		! do a byte at a time if n < 4
238	inc	4, %i2
239
240	ld	[%i1 + %i0], %i4	! read a word from s2
241	cmp	%i4, %i5
242	inc	4, %i1
243	be	1f
244
245	add	%i4, %l6, %l3
246	b,a	.noteq
2471:	xor	%l3, %i4, %l3
248	and	%l3, %l7, %l3
249	cmp	%l3, %l7
250	be,a	5b
251	nop
252
253	andcc	%i4, %l0, %g0		! check if first byte was zero
254	bnz	1f
255	andcc	%i4, %l1, %g0		! check if second byte was zero
256	b,a	.doneq
2571:	bnz	1f
258	andcc 	%i4, %l2, %g0		! check if third byte was zero
259	b,a	.doneq
2601:	bnz	1f
261	andcc	%i4, 0xff, %g0		! check if last byte is zero
262	b,a	.doneq
2631:	bnz,a	5b
264	ld	[%i1], %i5
265.doneq:	ret
266	restore	%g0, %g0, %o0		! equal return zero
267
268.noteq:	srl	%i4, 24, %l4
269	srl	%i5, 24, %l5
270	subcc	%l4, %l5, %i0
271	bne	6f
272	andcc	%l4, 0xff, %g0
273	bz	.doneq
274	sll	%i4, 8, %l4
275	sll	%i5, 8, %l5
276	srl	%l4, 24, %l4
277	srl	%l5, 24, %l5
278	subcc	%l4, %l5, %i0
279	bne	6f
280	andcc	%l4, 0xff, %g0
281	bz	.doneq
282	sll	%i4, 16, %l4
283	sll	%i5, 16, %l5
284	srl	%l4, 24, %l4
285	srl	%l5, 24, %l5
286	subcc	%l4, %l5, %i0
287	bne	6f
288	andcc	%l4, 0xff, %g0
289	bz	.doneq
290	nop
291.noteqb:
292	and	%i4, 0xff, %l4
293	and	%i5, 0xff, %l5
294	subcc	%l4, %l5, %i0
2956:	ret
296	restore	%i0, %g0, %o0
297
298	! Do a byte by byte comparison, disregarding alignments
299.cmp_bytes:
300	deccc	%i2			! --n >= 0 ?
3011:
302	bcs	.doneq
303	nop				! delay slot
304	ldub	[%i1 + %i0], %i4	! read a word from s1
305	ldub	[%i1], %i5		! read a word from s2
306
307	inc	%i1
308	cmp	%i4, %i5
309	bne	.noteqb
310	tst	%i4			! terminating zero
311	bnz	1b
312	deccc	%i2			! --n >= 0
313	b,a	.doneq
314
315	SET_SIZE(strncmp)
316