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