xref: /onnv-gate/usr/src/lib/libc/sparc/gen/memcmp.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-1995,1998 by Sun Microsystems, Inc.
24*0Sstevel@tonic-gate * All rights reserved.
25*0Sstevel@tonic-gate */
26*0Sstevel@tonic-gate
27*0Sstevel@tonic-gate.ident	"%Z%%M%	%I%	%E% SMI"	/* SunOS 4.1 1.2	*/
28*0Sstevel@tonic-gate
29*0Sstevel@tonic-gate	.file	"%M%"
30*0Sstevel@tonic-gate
31*0Sstevel@tonic-gate/*
32*0Sstevel@tonic-gate * memcmp(s1, s2, len)
33*0Sstevel@tonic-gate *
34*0Sstevel@tonic-gate * Compare n bytes:  s1>s2: >0  s1==s2: 0  s1<s2: <0
35*0Sstevel@tonic-gate *
36*0Sstevel@tonic-gate * Fast assembler language version of the following C-program for memcmp
37*0Sstevel@tonic-gate * which represents the `standard' for the C-library.
38*0Sstevel@tonic-gate *
39*0Sstevel@tonic-gate *	int
40*0Sstevel@tonic-gate *	memcmp(const void *s1, const void *s2, size_t n)
41*0Sstevel@tonic-gate *	{
42*0Sstevel@tonic-gate *		if (s1 != s2 && n != 0) {
43*0Sstevel@tonic-gate *			const char *ps1 = s1;
44*0Sstevel@tonic-gate *			const char *ps2 = s2;
45*0Sstevel@tonic-gate *			do {
46*0Sstevel@tonic-gate *				if (*ps1++ != *ps2++)
47*0Sstevel@tonic-gate *					return (ps1[-1] - ps2[-1]);
48*0Sstevel@tonic-gate *			} while (--n != 0);
49*0Sstevel@tonic-gate *		}
50*0Sstevel@tonic-gate *		return (NULL);
51*0Sstevel@tonic-gate *	}
52*0Sstevel@tonic-gate */
53*0Sstevel@tonic-gate
54*0Sstevel@tonic-gate#include <sys/asm_linkage.h>
55*0Sstevel@tonic-gate
56*0Sstevel@tonic-gate	ANSI_PRAGMA_WEAK(memcmp,function)
57*0Sstevel@tonic-gate
58*0Sstevel@tonic-gate#include "synonyms.h"
59*0Sstevel@tonic-gate
60*0Sstevel@tonic-gate	ENTRY(memcmp)
61*0Sstevel@tonic-gate	st	%g2, [%sp + 68]		! g2 must be restored before retl
62*0Sstevel@tonic-gate	cmp	%o0, %o1		! s1 == s2?
63*0Sstevel@tonic-gate	be	.cmpeq
64*0Sstevel@tonic-gate	cmp	%o2, 17
65*0Sstevel@tonic-gate	bleu,a	.cmpbyt			! for small counts go do bytes
66*0Sstevel@tonic-gate	sub	%o1, %o0, %o1
67*0Sstevel@tonic-gate
68*0Sstevel@tonic-gate	andcc	%o0, 3, %o3		! is s1 aligned?
69*0Sstevel@tonic-gate	bz,a	.iss2			! if so go check s2
70*0Sstevel@tonic-gate	andcc	%o1, 3, %o4		! is s2 aligned?
71*0Sstevel@tonic-gate	cmp	%o3, 2
72*0Sstevel@tonic-gate	be	.algn2
73*0Sstevel@tonic-gate	cmp	%o3, 3
74*0Sstevel@tonic-gate
75*0Sstevel@tonic-gate.algn1:	ldub	[%o0], %o4		! cmp one byte
76*0Sstevel@tonic-gate	inc	%o0
77*0Sstevel@tonic-gate	ldub	[%o1], %o5
78*0Sstevel@tonic-gate	inc	%o1
79*0Sstevel@tonic-gate	dec	%o2
80*0Sstevel@tonic-gate	be	.algn3
81*0Sstevel@tonic-gate	cmp	%o4, %o5
82*0Sstevel@tonic-gate	be	.algn2
83*0Sstevel@tonic-gate	nop
84*0Sstevel@tonic-gate	b,a	.noteq
85*0Sstevel@tonic-gate
86*0Sstevel@tonic-gate.algn2:	lduh	[%o0], %o4
87*0Sstevel@tonic-gate	inc	2, %o0
88*0Sstevel@tonic-gate	ldub	[%o1], %o5
89*0Sstevel@tonic-gate	inc	1, %o1
90*0Sstevel@tonic-gate	srl	%o4, 8, %o3
91*0Sstevel@tonic-gate	cmp	%o3, %o5
92*0Sstevel@tonic-gate	be,a	1f
93*0Sstevel@tonic-gate	ldub	[%o1], %o5		! delay slot, get next byte from s2
94*0Sstevel@tonic-gate	b	.noteq
95*0Sstevel@tonic-gate	mov	%o3, %o4		! delay slot, move *s1 to %o4
96*0Sstevel@tonic-gate1:	inc	%o1
97*0Sstevel@tonic-gate	dec	2, %o2
98*0Sstevel@tonic-gate	and	%o4, 0xff, %o4
99*0Sstevel@tonic-gate	cmp	%o4, %o5
100*0Sstevel@tonic-gate.algn3:	be,a	.iss2
101*0Sstevel@tonic-gate	andcc	%o1, 3, %o4		! delay slot, is s2 aligned?
102*0Sstevel@tonic-gate	b,a	.noteq
103*0Sstevel@tonic-gate
104*0Sstevel@tonic-gate.cmpbyt:b	.bytcmp
105*0Sstevel@tonic-gate	deccc	%o2
106*0Sstevel@tonic-gate1:	ldub	[%o0 + %o1], %o5	! byte compare loop
107*0Sstevel@tonic-gate	inc	%o0
108*0Sstevel@tonic-gate	cmp	%o4, %o5
109*0Sstevel@tonic-gate	be,a	.bytcmp
110*0Sstevel@tonic-gate	deccc	%o2			! delay slot, compare count (len)
111*0Sstevel@tonic-gate	b,a	.noteq
112*0Sstevel@tonic-gate.bytcmp:bgeu,a	1b
113*0Sstevel@tonic-gate	ldub	[%o0], %o4
114*0Sstevel@tonic-gate.cmpeq:	ld	[%sp + 68], %g2
115*0Sstevel@tonic-gate	retl				! strings compare equal
116*0Sstevel@tonic-gate	clr	%o0
117*0Sstevel@tonic-gate
118*0Sstevel@tonic-gate.noteq_word:				! words aren't equal. find unequal byte
119*0Sstevel@tonic-gate	srl	%o4, 24, %o1		! first byte
120*0Sstevel@tonic-gate	srl	%o5, 24, %o2
121*0Sstevel@tonic-gate	cmp	%o1, %o2
122*0Sstevel@tonic-gate	bne	1f
123*0Sstevel@tonic-gate	sll	%o4, 8, %o4
124*0Sstevel@tonic-gate	sll	%o5, 8, %o5
125*0Sstevel@tonic-gate	srl	%o4, 24, %o1
126*0Sstevel@tonic-gate	srl	%o5, 24, %o2
127*0Sstevel@tonic-gate	cmp	%o1, %o2
128*0Sstevel@tonic-gate	bne	1f
129*0Sstevel@tonic-gate	sll	%o4, 8, %o4
130*0Sstevel@tonic-gate	sll	%o5, 8, %o5
131*0Sstevel@tonic-gate	srl	%o4, 24, %o1
132*0Sstevel@tonic-gate	srl	%o5, 24, %o2
133*0Sstevel@tonic-gate	cmp	%o1, %o2
134*0Sstevel@tonic-gate	bne	1f
135*0Sstevel@tonic-gate	sll	%o4, 8, %o4
136*0Sstevel@tonic-gate	sll	%o5, 8, %o5
137*0Sstevel@tonic-gate	srl	%o4, 24, %o1
138*0Sstevel@tonic-gate	srl	%o5, 24, %o2
139*0Sstevel@tonic-gate1:
140*0Sstevel@tonic-gate	ld	[%sp + 68], %g2
141*0Sstevel@tonic-gate	retl
142*0Sstevel@tonic-gate	sub	%o1, %o2, %o0		! delay slot
143*0Sstevel@tonic-gate
144*0Sstevel@tonic-gate.noteq:
145*0Sstevel@tonic-gate	ld	[%sp + 68], %g2
146*0Sstevel@tonic-gate	retl				! strings aren't equal
147*0Sstevel@tonic-gate	sub	%o4, %o5, %o0		! delay slot, return(*s1 - *s2)
148*0Sstevel@tonic-gate
149*0Sstevel@tonic-gate.iss2:	andn	%o2, 3, %o3		! count of aligned bytes
150*0Sstevel@tonic-gate	and	%o2, 3, %o2		! remaining bytes
151*0Sstevel@tonic-gate	bz	.w4cmp			! if s2 word aligned, compare words
152*0Sstevel@tonic-gate	cmp	%o4, 2
153*0Sstevel@tonic-gate	be	.w2cmp			! s2 half aligned
154*0Sstevel@tonic-gate	cmp	%o4, 1
155*0Sstevel@tonic-gate
156*0Sstevel@tonic-gate.w3cmp:
157*0Sstevel@tonic-gate	dec	4, %o3			! avoid reading beyond the last byte
158*0Sstevel@tonic-gate	inc	4, %o2
159*0Sstevel@tonic-gate	ldub	[%o1], %g1		! read a byte to align for word reads
160*0Sstevel@tonic-gate	inc	1, %o1
161*0Sstevel@tonic-gate	be	.w1cmp			! aligned to 1 or 3 bytes
162*0Sstevel@tonic-gate	sll	%g1, 24, %o5
163*0Sstevel@tonic-gate
164*0Sstevel@tonic-gate	sub	%o1, %o0, %o1
165*0Sstevel@tonic-gate2:	ld	[%o0 + %o1], %g1
166*0Sstevel@tonic-gate	ld	[%o0], %o4
167*0Sstevel@tonic-gate	inc	4, %o0
168*0Sstevel@tonic-gate	srl	%g1, 8, %g2		! merge with the other half
169*0Sstevel@tonic-gate	or	%g2, %o5, %o5
170*0Sstevel@tonic-gate	cmp	%o4, %o5
171*0Sstevel@tonic-gate	bne	.noteq_word
172*0Sstevel@tonic-gate	deccc	4, %o3
173*0Sstevel@tonic-gate	bnz	2b
174*0Sstevel@tonic-gate	sll	%g1, 24, %o5
175*0Sstevel@tonic-gate	sub	%o1, 1, %o1		! used 3 bytes of the last word read
176*0Sstevel@tonic-gate	b	.bytcmp
177*0Sstevel@tonic-gate	deccc	%o2
178*0Sstevel@tonic-gate
179*0Sstevel@tonic-gate.w1cmp:
180*0Sstevel@tonic-gate	dec	4, %o3			! avoid reading beyond the last byte
181*0Sstevel@tonic-gate	inc	4, %o2
182*0Sstevel@tonic-gate	lduh	[%o1], %g1		! read 3 bytes to word align
183*0Sstevel@tonic-gate	inc	2, %o1
184*0Sstevel@tonic-gate	sll	%g1, 8, %g2
185*0Sstevel@tonic-gate	or	%o5, %g2, %o5
186*0Sstevel@tonic-gate
187*0Sstevel@tonic-gate	sub	%o1, %o0, %o1
188*0Sstevel@tonic-gate3:	ld	[%o0 + %o1], %g1
189*0Sstevel@tonic-gate	ld	[%o0], %o4
190*0Sstevel@tonic-gate	inc	4, %o0
191*0Sstevel@tonic-gate	srl	%g1, 24, %g2		! merge with the other half
192*0Sstevel@tonic-gate	or	%g2, %o5, %o5
193*0Sstevel@tonic-gate	cmp	%o4, %o5
194*0Sstevel@tonic-gate	bne	.noteq_word
195*0Sstevel@tonic-gate	deccc	4, %o3
196*0Sstevel@tonic-gate	bnz	3b
197*0Sstevel@tonic-gate	sll	%g1, 8, %o5
198*0Sstevel@tonic-gate	sub	%o1, 3, %o1		! used 1 byte of the last word read
199*0Sstevel@tonic-gate	b	.bytcmp
200*0Sstevel@tonic-gate	deccc	%o2
201*0Sstevel@tonic-gate
202*0Sstevel@tonic-gate.w2cmp:
203*0Sstevel@tonic-gate	dec	4, %o3			! avoid reading beyond the last byte
204*0Sstevel@tonic-gate	inc	4, %o2
205*0Sstevel@tonic-gate	lduh	[%o1], %g1		! read a halfword to align s2
206*0Sstevel@tonic-gate	inc	2, %o1
207*0Sstevel@tonic-gate	sll	%g1, 16, %o5
208*0Sstevel@tonic-gate
209*0Sstevel@tonic-gate	sub	%o1, %o0, %o1
210*0Sstevel@tonic-gate4:	ld	[%o0 + %o1], %g1	! read a word from s2
211*0Sstevel@tonic-gate	ld	[%o0], %o4		! read a word from s1
212*0Sstevel@tonic-gate	inc	4, %o0
213*0Sstevel@tonic-gate	srl	%g1, 16, %g2		! merge with the other half
214*0Sstevel@tonic-gate	or	%g2, %o5, %o5
215*0Sstevel@tonic-gate	cmp	%o4, %o5
216*0Sstevel@tonic-gate	bne	.noteq_word
217*0Sstevel@tonic-gate	deccc	4, %o3
218*0Sstevel@tonic-gate	bnz	4b
219*0Sstevel@tonic-gate	sll	%g1, 16, %o5
220*0Sstevel@tonic-gate	sub	%o1, 2, %o1		! only used half of the last read word
221*0Sstevel@tonic-gate	b	.bytcmp
222*0Sstevel@tonic-gate	deccc	%o2
223*0Sstevel@tonic-gate
224*0Sstevel@tonic-gate.w4cmp:
225*0Sstevel@tonic-gate	sub	%o1, %o0, %o1
226*0Sstevel@tonic-gate	ld	[%o0 + %o1], %o5
227*0Sstevel@tonic-gate5:	ld	[%o0], %o4
228*0Sstevel@tonic-gate	inc	4, %o0
229*0Sstevel@tonic-gate	cmp	%o4, %o5
230*0Sstevel@tonic-gate	bne	.noteq_word
231*0Sstevel@tonic-gate	deccc	4, %o3
232*0Sstevel@tonic-gate	bnz,a	5b
233*0Sstevel@tonic-gate	ld	[%o0 + %o1], %o5
234*0Sstevel@tonic-gate	b	.bytcmp			! compare remaining bytes, if any
235*0Sstevel@tonic-gate	deccc	%o2
236*0Sstevel@tonic-gate
237*0Sstevel@tonic-gate	SET_SIZE(memcmp)
238