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