xref: /titanic_51/usr/src/lib/libc/sparcv9/gen/memcmp.s (revision 36615d24946b849e48cedbbafa9adfb4a02b590c)
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 (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22/*
23 * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
24 * Use is subject to license terms.
25 */
26
27#pragma 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	ENTRY(memcmp)
59	cmp	%o0, %o1		! s1 == s2?
60	be,pn	%xcc, .cmpeq
61	cmp	%o2, 17
62	bleu,a,pn %xcc, .cmpbyt		! for small counts go do bytes
63	sub	%o1, %o0, %o1
64
65	andcc	%o0, 3, %o3		! is s1 aligned?
66	bz,a,pn	%icc, .iss2		! if so go check s2
67	andcc	%o1, 3, %o4		! is s2 aligned?
68	cmp	%o3, 2
69	be,pn	%icc, .algn2
70	cmp	%o3, 3
71
72.algn1:	ldub	[%o0], %o4		! cmp one byte
73	inc	%o0
74	ldub	[%o1], %o5
75	inc	%o1
76	dec	%o2
77	be,pn	%icc, .algn3
78	cmp	%o4, %o5
79	be,pt	%icc, .algn2
80	nop
81	b,a	.noteq
82
83.algn2:	lduh	[%o0], %o4
84	inc	2, %o0
85	ldub	[%o1], %o5
86	inc	1, %o1
87	srl	%o4, 8, %o3
88	cmp	%o3, %o5
89	be,a,pt	%icc, 1f
90	ldub	[%o1], %o5		! delay slot, get next byte from s2
91	b	.noteq
92	mov	%o3, %o4		! delay slot, move *s1 to %o4
931:	inc	%o1
94	dec	2, %o2
95	and	%o4, 0xff, %o4
96	cmp	%o4, %o5
97.algn3:	be,a,pt	%icc, .iss2
98	andcc	%o1, 3, %o4		! delay slot, is s2 aligned?
99	b,a	.noteq
100
101.cmpbyt:b	.bytcmp
102	deccc	%o2
1031:	ldub	[%o0 + %o1], %o5	! byte compare loop
104	inc	%o0
105	cmp	%o4, %o5
106	be,a,pt	%icc, .bytcmp
107	deccc	%o2			! delay slot, compare count (len)
108	b,a	.noteq
109.bytcmp:bgeu,a,pt %xcc, 1b
110	ldub	[%o0], %o4
111.cmpeq:
112	retl				! strings compare equal
113	clr	%o0
114
115.noteq_word:				! words aren't equal. find unequal byte
116	srl	%o4, 24, %o1		! first byte
117	srl	%o5, 24, %o2
118	cmp	%o1, %o2
119	bne,pn	%icc, 1f
120	sll	%o4, 8, %o4
121	sll	%o5, 8, %o5
122	srl	%o4, 24, %o1
123	srl	%o5, 24, %o2
124	cmp	%o1, %o2
125	bne,pn	%icc, 1f
126	sll	%o4, 8, %o4
127	sll	%o5, 8, %o5
128	srl	%o4, 24, %o1
129	srl	%o5, 24, %o2
130	cmp	%o1, %o2
131	bne,pn	%icc, 1f
132	sll	%o4, 8, %o4
133	sll	%o5, 8, %o5
134	srl	%o4, 24, %o1
135	srl	%o5, 24, %o2
1361:
137	retl
138	sub	%o1, %o2, %o0		! delay slot
139
140.noteq:
141	retl				! strings aren't equal
142	sub	%o4, %o5, %o0		! delay slot, return(*s1 - *s2)
143
144.iss2:	andn	%o2, 3, %o3		! count of aligned bytes
145	and	%o2, 3, %o2		! remaining bytes
146	bz,pn	%icc, .w4cmp		! if s2 word aligned, compare words
147	cmp	%o4, 2
148	be,pn	%icc, .w2cmp		! s2 half aligned
149	cmp	%o4, 1
150
151.w3cmp:
152	dec	4, %o3			! avoid reading beyond the last byte
153	inc	4, %o2
154	ldub	[%o1], %g1		! read a byte to align for word reads
155	inc	1, %o1
156	be,pt	%icc, .w1cmp		! aligned to 1 or 3 bytes
157	sll	%g1, 24, %o5
158
159	sub	%o1, %o0, %o1
1602:	lduw	[%o0 + %o1], %g1
161	lduw	[%o0], %o4
162	inc	4, %o0
163	srl	%g1, 8, %g5		! merge with the other half
164	or	%g5, %o5, %o5
165	cmp	%o4, %o5
166	bne,pt	%icc, .noteq_word
167	deccc	4, %o3
168	bnz,pt	%xcc, 2b
169	sll	%g1, 24, %o5
170	sub	%o1, 1, %o1		! used 3 bytes of the last word read
171	b	.bytcmp
172	deccc	%o2
173
174.w1cmp:
175	dec	4, %o3			! avoid reading beyond the last byte
176	inc	4, %o2
177	lduh	[%o1], %g1		! read 3 bytes to word align
178	inc	2, %o1
179	sll	%g1, 8, %g5
180	or	%o5, %g5, %o5
181
182	sub	%o1, %o0, %o1
1833:	lduw	[%o0 + %o1], %g1
184	lduw	[%o0], %o4
185	inc	4, %o0
186	srl	%g1, 24, %g5		! merge with the other half
187	or	%g5, %o5, %o5
188	cmp	%o4, %o5
189	bne,pt	%icc, .noteq_word
190	deccc	4, %o3
191	bnz,pt	%xcc, 3b
192	sll	%g1, 8, %o5
193	sub	%o1, 3, %o1		! used 1 byte of the last word read
194	b	.bytcmp
195	deccc	%o2
196
197.w2cmp:
198	dec	4, %o3			! avoid reading beyond the last byte
199	inc	4, %o2
200	lduh	[%o1], %g1		! read a halfword to align s2
201	inc	2, %o1
202	sll	%g1, 16, %o5
203	sub	%o1, %o0, %o1
2044:	lduw	[%o0 + %o1], %g1	! read a word from s2
205	lduw	[%o0], %o4		! read a word from s1
206	inc	4, %o0
207	srl	%g1, 16, %g5		! merge with the other half
208	or	%g5, %o5, %o5
209	cmp	%o4, %o5
210	bne,pn	%icc, .noteq_word
211	deccc	4, %o3
212	bnz,pt	%xcc, 4b
213	sll	%g1, 16, %o5
214	sub	%o1, 2, %o1		! only used half of the last read word
215	b	.bytcmp
216	deccc	%o2
217
218.w4cmp:
219	sub	%o1, %o0, %o1
220	lduw	[%o0 + %o1], %o5
2215:	lduw	[%o0], %o4
222	inc	4, %o0
223	cmp	%o4, %o5
224	bne,pt	%icc, .noteq_word
225	deccc	4, %o3
226	bnz,a,pt %xcc, 5b
227	lduw	[%o0 + %o1], %o5
228	b	.bytcmp			! compare remaining bytes, if any
229	deccc	%o2
230
231	SET_SIZE(memcmp)
232