xref: /onnv-gate/usr/src/lib/libc/sparc/gen/strcmp.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 2003 Sun Microsystems, Inc.  All rights reserved.
24*0Sstevel@tonic-gate * Use is subject to license terms.
25*0Sstevel@tonic-gate */
26*0Sstevel@tonic-gate
27*0Sstevel@tonic-gate.ident	"%Z%%M%	%I%	%E% SMI"
28*0Sstevel@tonic-gate
29*0Sstevel@tonic-gate	.file	"%M%"
30*0Sstevel@tonic-gate
31*0Sstevel@tonic-gate/* strcmp(s1, s2)
32*0Sstevel@tonic-gate *
33*0Sstevel@tonic-gate * Compare strings:  s1>s2: >0  s1==s2: 0  s1<s2: <0
34*0Sstevel@tonic-gate *
35*0Sstevel@tonic-gate * Fast assembler language version of the following C-program for strcmp
36*0Sstevel@tonic-gate * which represents the `standard' for the C-library.
37*0Sstevel@tonic-gate *
38*0Sstevel@tonic-gate *	int
39*0Sstevel@tonic-gate *	strcmp(s1, s2)
40*0Sstevel@tonic-gate *	register const char *s1;
41*0Sstevel@tonic-gate *	register const char *s2;
42*0Sstevel@tonic-gate *	{
43*0Sstevel@tonic-gate *
44*0Sstevel@tonic-gate *		if(s1 == s2)
45*0Sstevel@tonic-gate *			return(0);
46*0Sstevel@tonic-gate *		while(*s1 == *s2++)
47*0Sstevel@tonic-gate *			if(*s1++ == '\0')
48*0Sstevel@tonic-gate *				return(0);
49*0Sstevel@tonic-gate *		return(*s1 - s2[-1]);
50*0Sstevel@tonic-gate *	}
51*0Sstevel@tonic-gate */
52*0Sstevel@tonic-gate
53*0Sstevel@tonic-gate#include <sys/asm_linkage.h>
54*0Sstevel@tonic-gate#include "synonyms.h"
55*0Sstevel@tonic-gate
56*0Sstevel@tonic-gate	! This strcmp implementation first determines whether s1 is aligned.
57*0Sstevel@tonic-gate	! If it is not, it attempts to align it and then checks the
58*0Sstevel@tonic-gate	! alignment of the destination string.  If it is possible to
59*0Sstevel@tonic-gate	! align s2, this also happens and then the compare begins.  Otherwise,
60*0Sstevel@tonic-gate	! a different compare for non-aligned strings is used.
61*0Sstevel@tonic-gate	! In this case, we have multiple routines depending upon the
62*0Sstevel@tonic-gate	! degree to which a string is mis-aligned.
63*0Sstevel@tonic-gate
64*0Sstevel@tonic-gate	ENTRY(strcmp)
65*0Sstevel@tonic-gate
66*0Sstevel@tonic-gate	.align 32
67*0Sstevel@tonic-gate
68*0Sstevel@tonic-gate	subcc	%o0, %o1, %o2		! s1 == s2 ?
69*0Sstevel@tonic-gate	bz	.stringsequal1		! yup, same string, done
70*0Sstevel@tonic-gate	sethi	%hi(0x01010101), %o5	! start loading Mycroft's magic2
71*0Sstevel@tonic-gate	andcc	%o0, 3, %o3		! s1 word-aligned ?
72*0Sstevel@tonic-gate	or	%o5, %lo(0x01010101),%o5! finish loading Mycroft's magic2
73*0Sstevel@tonic-gate	bz	.s1aligned		! yup
74*0Sstevel@tonic-gate	sll	%o5, 7, %o4		! load Mycroft's magic1
75*0Sstevel@tonic-gate	sub	%o3, 4, %o3		! number of bytes till aligned
76*0Sstevel@tonic-gate
77*0Sstevel@tonic-gate.aligns1:
78*0Sstevel@tonic-gate	ldub	[%o1 + %o2], %o0	! s1[]
79*0Sstevel@tonic-gate	ldub	[%o1], %g1		! s2[]
80*0Sstevel@tonic-gate	subcc	%o0, %g1, %o0		! s1[] != s2[] ?
81*0Sstevel@tonic-gate	bne	.done			! yup, done
82*0Sstevel@tonic-gate	addcc	%o0, %g1, %g0		! s1[] == 0 ?
83*0Sstevel@tonic-gate	bz	.done			! yup, done
84*0Sstevel@tonic-gate	inccc	%o3			! s1 aligned yet?
85*0Sstevel@tonic-gate	bnz	.aligns1		! nope, compare another pair of bytes
86*0Sstevel@tonic-gate	inc	%o1			! s1++, s2++
87*0Sstevel@tonic-gate
88*0Sstevel@tonic-gate.s1aligned:
89*0Sstevel@tonic-gate	andcc	%o1, 3, %o3		! s2 word aligned ?
90*0Sstevel@tonic-gate	bz	.word4			! yup
91*0Sstevel@tonic-gate	cmp	%o3, 2			! s2 half-word aligned ?
92*0Sstevel@tonic-gate	be	.word2			! yup
93*0Sstevel@tonic-gate	cmp	%o3, 3			! s2 offset to dword == 3 ?
94*0Sstevel@tonic-gate	be,a	.word3			! yup
95*0Sstevel@tonic-gate	ldub	[%o1], %o0		! new lower word in s2
96*0Sstevel@tonic-gate
97*0Sstevel@tonic-gate.word1:
98*0Sstevel@tonic-gate	lduw	[%o1 - 1], %o0		! new lower word in s2
99*0Sstevel@tonic-gate	sethi	%hi(0xff000000), %o3	! mask for forcing byte 1 non-zero
100*0Sstevel@tonic-gate	sll	%o0, 8, %g1		! partial unaligned word from s2
101*0Sstevel@tonic-gate	or	%o0, %o3, %o0		! force byte 1 non-zero
102*0Sstevel@tonic-gate
103*0Sstevel@tonic-gate.cmp1:
104*0Sstevel@tonic-gate	andn	%o4, %o0, %o3		! ~word & 0x80808080
105*0Sstevel@tonic-gate	sub	%o0, %o5, %o0		! word - 0x01010101
106*0Sstevel@tonic-gate	andcc	%o0, %o3, %g0		! (word - 0x01010101) & ~word & 0x80808080
107*0Sstevel@tonic-gate	bz,a	.doload1		! no null byte in previous word from s2
108*0Sstevel@tonic-gate	lduw	[%o1 + 3], %o0		! load next aligned word from s2
109*0Sstevel@tonic-gate.doload1:
110*0Sstevel@tonic-gate	srl	%o0, 24, %o3		! byte 1 of new aligned word from s2
111*0Sstevel@tonic-gate	or	%g1, %o3, %g1		! merge to get unaligned word from s2
112*0Sstevel@tonic-gate	lduw	[%o1 + %o2], %o3	! word from s1
113*0Sstevel@tonic-gate	cmp	%o3, %g1		! *s1 != *s2 ?
114*0Sstevel@tonic-gate	bne	.wordsdiffer		! yup, find the byte that is different
115*0Sstevel@tonic-gate	add	%o1, 4, %o1		! s1+=4, s2+=4
116*0Sstevel@tonic-gate	andn	%o4, %o3, %g1		! ~word & 0x80808080
117*0Sstevel@tonic-gate	sub	%o3, %o5, %o3		! word - 0x01010101
118*0Sstevel@tonic-gate	andcc	%o3, %g1, %g0		! (word - 0x01010101) & ~word & 0x80808080
119*0Sstevel@tonic-gate	bz	.cmp1			! no null-byte in s1 yet
120*0Sstevel@tonic-gate	sll	%o0, 8, %g1		! partial unaligned word from s2
121*0Sstevel@tonic-gate
122*0Sstevel@tonic-gate	! words are equal but the end of s1 has been reached
123*0Sstevel@tonic-gate	! this means the strings must be equal
124*0Sstevel@tonic-gate.stringsequal1:
125*0Sstevel@tonic-gate	retl				! return from leaf function
126*0Sstevel@tonic-gate	mov	%g0, %o0		! return 0, i.e. strings are equal
127*0Sstevel@tonic-gate	nop				! pad for optimal alignment of .cmp2
128*0Sstevel@tonic-gate	nop				! pad for optimal alignment of .cmp2
129*0Sstevel@tonic-gate
130*0Sstevel@tonic-gate.word2:
131*0Sstevel@tonic-gate	lduh	[%o1], %o0		! new lower word in s2
132*0Sstevel@tonic-gate	sethi	%hi(0xffff0000), %o3	! mask for forcing bytes 1,2 non-zero
133*0Sstevel@tonic-gate	sll	%o0, 16, %g1		! partial unaligned word from s2
134*0Sstevel@tonic-gate	or	%o0, %o3, %o0		! force bytes 1,2 non-zero
135*0Sstevel@tonic-gate
136*0Sstevel@tonic-gate.cmp2:
137*0Sstevel@tonic-gate	andn	%o4, %o0, %o3		! ~word & 0x80808080
138*0Sstevel@tonic-gate	sub	%o0, %o5, %o0		! word - 0x01010101
139*0Sstevel@tonic-gate	andcc	%o0, %o3, %g0		! (word - 0x01010101) & ~word & 0x80808080
140*0Sstevel@tonic-gate	bz,a	.doload2		! no null byte in previous word from s2
141*0Sstevel@tonic-gate	lduw	[%o1 + 2], %o0		! load next aligned word from s2
142*0Sstevel@tonic-gate.doload2:
143*0Sstevel@tonic-gate	srl	%o0, 16, %o3		! bytes 1,2 of new aligned word from s2
144*0Sstevel@tonic-gate	or	%g1, %o3, %g1		! merge to get unaligned word from s2
145*0Sstevel@tonic-gate	lduw	[%o1 + %o2], %o3	! word from s1
146*0Sstevel@tonic-gate	cmp	%o3, %g1		! *s1 != *s2 ?
147*0Sstevel@tonic-gate	bne	.wordsdiffer		! yup, find the byte that is different
148*0Sstevel@tonic-gate	add	%o1, 4, %o1		! s1+=4, s2+=4
149*0Sstevel@tonic-gate	andn	%o4, %o3, %g1		! ~word & 0x80808080
150*0Sstevel@tonic-gate	sub	%o3, %o5, %o3		! word - 0x01010101
151*0Sstevel@tonic-gate	andcc	%o3, %g1, %g0		! (word - 0x01010101) & ~word & 0x80808080
152*0Sstevel@tonic-gate	bz	.cmp2			! no null-byte in s1 yet
153*0Sstevel@tonic-gate	sll	%o0, 16, %g1		! partial unaligned word from s2
154*0Sstevel@tonic-gate
155*0Sstevel@tonic-gate	! words are equal but the end of s1 has been reached
156*0Sstevel@tonic-gate	! this means the strings must be equal
157*0Sstevel@tonic-gate.stringsequal2:
158*0Sstevel@tonic-gate	retl				! return from leaf function
159*0Sstevel@tonic-gate	mov	%g0, %o0		! return 0, i.e. strings are equal
160*0Sstevel@tonic-gate
161*0Sstevel@tonic-gate.word3:
162*0Sstevel@tonic-gate	sll	%o0, 24, %g1		! partial unaligned word from s2
163*0Sstevel@tonic-gate	nop				! pad for optimal alignment of .cmp3
164*0Sstevel@tonic-gate.cmp3:
165*0Sstevel@tonic-gate	andcc	%o0, 0xff, %g0		! did previous word contain null-byte ?
166*0Sstevel@tonic-gate	bnz,a	.doload3		! nope, load next word from s2
167*0Sstevel@tonic-gate	lduw	[%o1 + 1], %o0		! load next aligned word from s2
168*0Sstevel@tonic-gate.doload3:
169*0Sstevel@tonic-gate	srl	%o0, 8, %o3		! bytes 1,2,3 from new aligned s2 word
170*0Sstevel@tonic-gate	or	%g1, %o3, %g1		! merge to get unaligned word from s2
171*0Sstevel@tonic-gate	lduw	[%o1 + %o2], %o3	! word from s1
172*0Sstevel@tonic-gate	cmp	%o3, %g1		! *s1 != *s2 ?
173*0Sstevel@tonic-gate	bne	.wordsdiffer		! yup, find the byte that is different
174*0Sstevel@tonic-gate	add	%o1, 4, %o1		! s1+=4, s2+=4
175*0Sstevel@tonic-gate	andn	%o4, %o3, %g1		! ~word & 0x80808080
176*0Sstevel@tonic-gate	sub	%o3, %o5, %o3		! word - 0x01010101
177*0Sstevel@tonic-gate	andcc	%o3, %g1, %g0		! (word - 0x01010101) & ~word & 0x80808080
178*0Sstevel@tonic-gate	bz	.cmp3			! no null-byte in s1 yet
179*0Sstevel@tonic-gate	sll	%o0, 24, %g1		! partial unaligned word from s2
180*0Sstevel@tonic-gate
181*0Sstevel@tonic-gate	! words are equal but the end of s1 has been reached
182*0Sstevel@tonic-gate	! this means the strings must be equal
183*0Sstevel@tonic-gate.stringsequal3:
184*0Sstevel@tonic-gate	retl				! return from leaf function
185*0Sstevel@tonic-gate	mov	%g0, %o0		! return 0, i.e. strings are equal
186*0Sstevel@tonic-gate
187*0Sstevel@tonic-gate.word4:
188*0Sstevel@tonic-gate	lduw	[%o1 + %o2], %o3	! load word from s1
189*0Sstevel@tonic-gate	nop				! pad for optimal alignment of .cmp4
190*0Sstevel@tonic-gate	nop				! pad for optimal alignment of .cmp4
191*0Sstevel@tonic-gate	nop				! pad for optimal alignment of .cmp4
192*0Sstevel@tonic-gate
193*0Sstevel@tonic-gate.cmp4:
194*0Sstevel@tonic-gate	lduw	[%o1], %g1		! load word from s2
195*0Sstevel@tonic-gate	cmp	%o3, %g1		! *scr1 == *src2 ?
196*0Sstevel@tonic-gate	bne	.wordsdiffer		! nope, find mismatching character
197*0Sstevel@tonic-gate	add	%o1, 4, %o1		! src1 += 4, src2 += 4
198*0Sstevel@tonic-gate	andn	%o4, %o3, %o0		! ~word & 0x80808080
199*0Sstevel@tonic-gate	sub	%o3, %o5, %o3		! word - 0x01010101
200*0Sstevel@tonic-gate	andcc	%o3, %o0, %g0		! (word - 0x01010101) & ~word & 0x80808080
201*0Sstevel@tonic-gate	bz,a	.cmp4			! no null-byte in s1 yet
202*0Sstevel@tonic-gate	lduw	[%o1 + %o2], %o3	! load word from s1
203*0Sstevel@tonic-gate
204*0Sstevel@tonic-gate	! words are equal but the end of s1 has been reached
205*0Sstevel@tonic-gate	! this means the strings must be equal
206*0Sstevel@tonic-gate.stringsequal4:
207*0Sstevel@tonic-gate	retl				! return from leaf function
208*0Sstevel@tonic-gate	mov	%g0, %o0		! return 0, i.e. strings are equal
209*0Sstevel@tonic-gate
210*0Sstevel@tonic-gate.wordsdiffer:
211*0Sstevel@tonic-gate	srl	%g1, 24, %o2		! first byte of mismatching word in s2
212*0Sstevel@tonic-gate	srl	%o3, 24, %o1		! first byte of mismatching word in s1
213*0Sstevel@tonic-gate	subcc	%o1, %o2, %o0		! *s1-*s2
214*0Sstevel@tonic-gate	bnz	.done			! bytes differ, return difference
215*0Sstevel@tonic-gate	srl	%g1, 16, %o2		! second byte of mismatching word in s2
216*0Sstevel@tonic-gate	andcc	%o1, 0xff, %o0		! *s1 == 0 ?
217*0Sstevel@tonic-gate	bz	.done			! yup
218*0Sstevel@tonic-gate
219*0Sstevel@tonic-gate	! we know byte 1 is equal, so can compare bytes 1,2 as a group
220*0Sstevel@tonic-gate
221*0Sstevel@tonic-gate	srl	%o3, 16, %o1		! second byte of mismatching word in s1
222*0Sstevel@tonic-gate	subcc	%o1, %o2, %o0		! *s1-*s2
223*0Sstevel@tonic-gate	bnz	.done			! bytes differ, return difference
224*0Sstevel@tonic-gate	srl	%g1, 8, %o2		! third byte of mismatching word in s2
225*0Sstevel@tonic-gate	andcc	%o1, 0xff, %o0		! *s1 == 0 ?
226*0Sstevel@tonic-gate	bz	.done			! yup
227*0Sstevel@tonic-gate
228*0Sstevel@tonic-gate	! we know bytes 1, 2 are equal, so can compare bytes 1,2,3 as a group
229*0Sstevel@tonic-gate
230*0Sstevel@tonic-gate	srl	%o3, 8, %o1		! third byte of mismatching word in s1
231*0Sstevel@tonic-gate	subcc	%o1, %o2, %o0		! *s1-*s2
232*0Sstevel@tonic-gate	bnz	.done			! bytes differ, return difference
233*0Sstevel@tonic-gate	andcc	%o1, 0xff, %g0		! *s1 == 0 ?
234*0Sstevel@tonic-gate	bz	.stringsequal1		! yup
235*0Sstevel@tonic-gate
236*0Sstevel@tonic-gate	! we know bytes 1,2,3 are equal, so can compare bytes 1,2,3,4 as group
237*0Sstevel@tonic-gate
238*0Sstevel@tonic-gate	subcc	%o3, %g1, %o0		! *s1-*s2
239*0Sstevel@tonic-gate	bz,a	.done			! bytes differ, return difference
240*0Sstevel@tonic-gate	andcc	%o3, 0xff, %o0		! *s1 == 0 ?
241*0Sstevel@tonic-gate
242*0Sstevel@tonic-gate.done:
243*0Sstevel@tonic-gate	retl				! return from leaf routine
244*0Sstevel@tonic-gate	nop				! padding
245*0Sstevel@tonic-gate
246*0Sstevel@tonic-gate
247*0Sstevel@tonic-gate	SET_SIZE(strcmp)
248