xref: /titanic_51/usr/src/lib/libc/sparc/gen/memcmp.s (revision 15d9d0b528387242011cdcc6190c9e598cfe3a07)
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) 1989-1995,1998 by Sun Microsystems, Inc.
24 * All rights reserved.
25 */
26
27.ident	"%Z%%M%	%I%	%E% SMI"	/* SunOS 4.1 1.2	*/
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 (NULL);
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	st	%g2, [%sp + 68]		! g2 must be restored before retl
62	cmp	%o0, %o1		! s1 == s2?
63	be	.cmpeq
64	cmp	%o2, 17
65	bleu,a	.cmpbyt			! for small counts go do bytes
66	sub	%o1, %o0, %o1
67
68	andcc	%o0, 3, %o3		! is s1 aligned?
69	bz,a	.iss2			! if so go check s2
70	andcc	%o1, 3, %o4		! is s2 aligned?
71	cmp	%o3, 2
72	be	.algn2
73	cmp	%o3, 3
74
75.algn1:	ldub	[%o0], %o4		! cmp one byte
76	inc	%o0
77	ldub	[%o1], %o5
78	inc	%o1
79	dec	%o2
80	be	.algn3
81	cmp	%o4, %o5
82	be	.algn2
83	nop
84	b,a	.noteq
85
86.algn2:	lduh	[%o0], %o4
87	inc	2, %o0
88	ldub	[%o1], %o5
89	inc	1, %o1
90	srl	%o4, 8, %o3
91	cmp	%o3, %o5
92	be,a	1f
93	ldub	[%o1], %o5		! delay slot, get next byte from s2
94	b	.noteq
95	mov	%o3, %o4		! delay slot, move *s1 to %o4
961:	inc	%o1
97	dec	2, %o2
98	and	%o4, 0xff, %o4
99	cmp	%o4, %o5
100.algn3:	be,a	.iss2
101	andcc	%o1, 3, %o4		! delay slot, is s2 aligned?
102	b,a	.noteq
103
104.cmpbyt:b	.bytcmp
105	deccc	%o2
1061:	ldub	[%o0 + %o1], %o5	! byte compare loop
107	inc	%o0
108	cmp	%o4, %o5
109	be,a	.bytcmp
110	deccc	%o2			! delay slot, compare count (len)
111	b,a	.noteq
112.bytcmp:bgeu,a	1b
113	ldub	[%o0], %o4
114.cmpeq:	ld	[%sp + 68], %g2
115	retl				! strings compare equal
116	clr	%o0
117
118.noteq_word:				! words aren't equal. find unequal byte
119	srl	%o4, 24, %o1		! first byte
120	srl	%o5, 24, %o2
121	cmp	%o1, %o2
122	bne	1f
123	sll	%o4, 8, %o4
124	sll	%o5, 8, %o5
125	srl	%o4, 24, %o1
126	srl	%o5, 24, %o2
127	cmp	%o1, %o2
128	bne	1f
129	sll	%o4, 8, %o4
130	sll	%o5, 8, %o5
131	srl	%o4, 24, %o1
132	srl	%o5, 24, %o2
133	cmp	%o1, %o2
134	bne	1f
135	sll	%o4, 8, %o4
136	sll	%o5, 8, %o5
137	srl	%o4, 24, %o1
138	srl	%o5, 24, %o2
1391:
140	ld	[%sp + 68], %g2
141	retl
142	sub	%o1, %o2, %o0		! delay slot
143
144.noteq:
145	ld	[%sp + 68], %g2
146	retl				! strings aren't equal
147	sub	%o4, %o5, %o0		! delay slot, return(*s1 - *s2)
148
149.iss2:	andn	%o2, 3, %o3		! count of aligned bytes
150	and	%o2, 3, %o2		! remaining bytes
151	bz	.w4cmp			! if s2 word aligned, compare words
152	cmp	%o4, 2
153	be	.w2cmp			! s2 half aligned
154	cmp	%o4, 1
155
156.w3cmp:
157	dec	4, %o3			! avoid reading beyond the last byte
158	inc	4, %o2
159	ldub	[%o1], %g1		! read a byte to align for word reads
160	inc	1, %o1
161	be	.w1cmp			! aligned to 1 or 3 bytes
162	sll	%g1, 24, %o5
163
164	sub	%o1, %o0, %o1
1652:	ld	[%o0 + %o1], %g1
166	ld	[%o0], %o4
167	inc	4, %o0
168	srl	%g1, 8, %g2		! merge with the other half
169	or	%g2, %o5, %o5
170	cmp	%o4, %o5
171	bne	.noteq_word
172	deccc	4, %o3
173	bnz	2b
174	sll	%g1, 24, %o5
175	sub	%o1, 1, %o1		! used 3 bytes of the last word read
176	b	.bytcmp
177	deccc	%o2
178
179.w1cmp:
180	dec	4, %o3			! avoid reading beyond the last byte
181	inc	4, %o2
182	lduh	[%o1], %g1		! read 3 bytes to word align
183	inc	2, %o1
184	sll	%g1, 8, %g2
185	or	%o5, %g2, %o5
186
187	sub	%o1, %o0, %o1
1883:	ld	[%o0 + %o1], %g1
189	ld	[%o0], %o4
190	inc	4, %o0
191	srl	%g1, 24, %g2		! merge with the other half
192	or	%g2, %o5, %o5
193	cmp	%o4, %o5
194	bne	.noteq_word
195	deccc	4, %o3
196	bnz	3b
197	sll	%g1, 8, %o5
198	sub	%o1, 3, %o1		! used 1 byte of the last word read
199	b	.bytcmp
200	deccc	%o2
201
202.w2cmp:
203	dec	4, %o3			! avoid reading beyond the last byte
204	inc	4, %o2
205	lduh	[%o1], %g1		! read a halfword to align s2
206	inc	2, %o1
207	sll	%g1, 16, %o5
208
209	sub	%o1, %o0, %o1
2104:	ld	[%o0 + %o1], %g1	! read a word from s2
211	ld	[%o0], %o4		! read a word from s1
212	inc	4, %o0
213	srl	%g1, 16, %g2		! merge with the other half
214	or	%g2, %o5, %o5
215	cmp	%o4, %o5
216	bne	.noteq_word
217	deccc	4, %o3
218	bnz	4b
219	sll	%g1, 16, %o5
220	sub	%o1, 2, %o1		! only used half of the last read word
221	b	.bytcmp
222	deccc	%o2
223
224.w4cmp:
225	sub	%o1, %o0, %o1
226	ld	[%o0 + %o1], %o5
2275:	ld	[%o0], %o4
228	inc	4, %o0
229	cmp	%o4, %o5
230	bne	.noteq_word
231	deccc	4, %o3
232	bnz,a	5b
233	ld	[%o0 + %o1], %o5
234	b	.bytcmp			! compare remaining bytes, if any
235	deccc	%o2
236
237	SET_SIZE(memcmp)
238