xref: /titanic_52/usr/src/lib/libc/sparc/gen/strncmp.s (revision 9a70fc3be3b1e966bf78825cdb8d509963a6f0a1)
17c478bd9Sstevel@tonic-gate/*
27c478bd9Sstevel@tonic-gate * CDDL HEADER START
37c478bd9Sstevel@tonic-gate *
47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
57257d1b4Sraf * Common Development and Distribution License (the "License").
67257d1b4Sraf * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate *
87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate * and limitations under the License.
127c478bd9Sstevel@tonic-gate *
137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate *
197c478bd9Sstevel@tonic-gate * CDDL HEADER END
207c478bd9Sstevel@tonic-gate */
217257d1b4Sraf
227c478bd9Sstevel@tonic-gate/*
237257d1b4Sraf * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
247257d1b4Sraf * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate */
267c478bd9Sstevel@tonic-gate
27*9a70fc3bSMark J. Nelson	.file	"strncmp.s"
287c478bd9Sstevel@tonic-gate
297c478bd9Sstevel@tonic-gate/*
307c478bd9Sstevel@tonic-gate * strncmp(s1, s2, n)
317c478bd9Sstevel@tonic-gate *
327c478bd9Sstevel@tonic-gate * Compare strings (at most n bytes):  s1>s2: >0  s1==s2: 0  s1<s2: <0
337c478bd9Sstevel@tonic-gate *
347c478bd9Sstevel@tonic-gate * Fast assembler language version of the following C-program for strncmp
357c478bd9Sstevel@tonic-gate * which represents the `standard' for the C-library.
367c478bd9Sstevel@tonic-gate *
377c478bd9Sstevel@tonic-gate *	int
387c478bd9Sstevel@tonic-gate *	strncmp(const char *s1, const char *s2, size_t n)
397c478bd9Sstevel@tonic-gate *	{
407c478bd9Sstevel@tonic-gate *		n++;
417c478bd9Sstevel@tonic-gate *		if (s1 == s2)
427c478bd9Sstevel@tonic-gate *			return (0);
437c478bd9Sstevel@tonic-gate *		while (--n != 0 && *s1 == *s2++)
447c478bd9Sstevel@tonic-gate *			if (*s1++ == '\0')
457c478bd9Sstevel@tonic-gate *				return (0);
467c478bd9Sstevel@tonic-gate *		return ((n == 0) ? 0 : (*s1 - s2[-1]));
477c478bd9Sstevel@tonic-gate *	}
487c478bd9Sstevel@tonic-gate */
497c478bd9Sstevel@tonic-gate
507c478bd9Sstevel@tonic-gate#include <sys/asm_linkage.h>
517c478bd9Sstevel@tonic-gate
527c478bd9Sstevel@tonic-gate	ENTRY(strncmp)
537c478bd9Sstevel@tonic-gate	save	%sp, -SA(WINDOWSIZE), %sp
547c478bd9Sstevel@tonic-gate	cmp	%i2, 8
557c478bd9Sstevel@tonic-gate	blu,a	.cmp_bytes		! for small counts go do bytes
567c478bd9Sstevel@tonic-gate	sub	%i0, %i1, %i0		! delay slot, get diff from s1 - s2
577c478bd9Sstevel@tonic-gate	andcc	%i0, 3, %g0		! is s1 aligned
587c478bd9Sstevel@tonic-gate1:	bz	.iss2			! if so go check s2
597c478bd9Sstevel@tonic-gate	andcc	%i1, 3, %i3		! is s2 aligned
607c478bd9Sstevel@tonic-gate
617c478bd9Sstevel@tonic-gate	deccc	%i2			! --n >= 0 ?
627c478bd9Sstevel@tonic-gate	bcs	.doneq
637c478bd9Sstevel@tonic-gate	nop				! delay slot
647c478bd9Sstevel@tonic-gate
657c478bd9Sstevel@tonic-gate	ldub	[%i0], %i4		! else cmp one byte
667c478bd9Sstevel@tonic-gate	ldub	[%i1], %i5
677c478bd9Sstevel@tonic-gate	inc	%i0
687c478bd9Sstevel@tonic-gate	cmp	%i4, %i5
697c478bd9Sstevel@tonic-gate	bne	.noteqb
707c478bd9Sstevel@tonic-gate	inc	%i1
717c478bd9Sstevel@tonic-gate	tst	%i4			! terminating zero
727c478bd9Sstevel@tonic-gate	bnz	1b
737c478bd9Sstevel@tonic-gate	andcc	%i0, 3, %g0
747c478bd9Sstevel@tonic-gate	b,a	.doneq
757c478bd9Sstevel@tonic-gate
767c478bd9Sstevel@tonic-gate.iss2:
777c478bd9Sstevel@tonic-gate	set     0x7efefeff, %l6
787c478bd9Sstevel@tonic-gate	set     0x81010100, %l7
797c478bd9Sstevel@tonic-gate	sethi	%hi(0xff000000), %l0	! masks to test for terminating null
807c478bd9Sstevel@tonic-gate	sethi	%hi(0x00ff0000), %l1
817c478bd9Sstevel@tonic-gate	srl	%l1, 8, %l2		! generate 0x0000ff00 mask
827c478bd9Sstevel@tonic-gate
837c478bd9Sstevel@tonic-gate	bz	.w4cmp			! if s2 word aligned, compare words
847c478bd9Sstevel@tonic-gate	cmp	%i3, 2			! check if s2 half aligned
857c478bd9Sstevel@tonic-gate	be	.w2cmp
867c478bd9Sstevel@tonic-gate	cmp	%i3, 1			! check if aligned to 1 or 3 bytes
877c478bd9Sstevel@tonic-gate.w3cmp:	ldub	[%i1], %i5
887c478bd9Sstevel@tonic-gate	inc	1, %i1
897c478bd9Sstevel@tonic-gate	be	.w1cmp
907c478bd9Sstevel@tonic-gate	sll	%i5, 24, %i5
917c478bd9Sstevel@tonic-gate	sub	%i0, %i1, %i0
927c478bd9Sstevel@tonic-gate2:
937c478bd9Sstevel@tonic-gate	deccc	4, %i2			! n >= 4 ?
947c478bd9Sstevel@tonic-gate	bgeu,a	3f
957c478bd9Sstevel@tonic-gate	ld	[%i1], %i3		! delay slot
967c478bd9Sstevel@tonic-gate	dec	%i1			! reset s2
977c478bd9Sstevel@tonic-gate	inc	%i0			! reset s1 diff
987c478bd9Sstevel@tonic-gate	b	.cmp_bytes		! do a byte at a time if n < 4
997c478bd9Sstevel@tonic-gate	inc	4, %i2
1007c478bd9Sstevel@tonic-gate3:
1017c478bd9Sstevel@tonic-gate	ld	[%i0 + %i1], %i4
1027c478bd9Sstevel@tonic-gate	inc	4, %i1
1037c478bd9Sstevel@tonic-gate	srl	%i3, 8, %l4		! merge with the other half
1047c478bd9Sstevel@tonic-gate	or	%l4, %i5, %i5
1057c478bd9Sstevel@tonic-gate	cmp	%i4, %i5
1067c478bd9Sstevel@tonic-gate	be	1f
1077c478bd9Sstevel@tonic-gate
1087c478bd9Sstevel@tonic-gate	add	%i4, %l6, %l3
1097c478bd9Sstevel@tonic-gate	b,a	.noteq
1107c478bd9Sstevel@tonic-gate1:	xor	%l3, %i4, %l3
1117c478bd9Sstevel@tonic-gate	and	%l3, %l7, %l3
1127c478bd9Sstevel@tonic-gate	cmp	%l3, %l7
1137c478bd9Sstevel@tonic-gate	be,a	2b
1147c478bd9Sstevel@tonic-gate	sll	%i3, 24, %i5
1157c478bd9Sstevel@tonic-gate
1167c478bd9Sstevel@tonic-gate	!
1177c478bd9Sstevel@tonic-gate	! For 7-bit characters, we know one of the bytes is zero, but for
1187c478bd9Sstevel@tonic-gate	! 8-bit characters, the zero detection algorithm gives some false
1197c478bd9Sstevel@tonic-gate	! triggers ... check every byte individually.
1207c478bd9Sstevel@tonic-gate	!
1217c478bd9Sstevel@tonic-gate	andcc	%i4, %l0, %g0		! check if first byte was zero
1227c478bd9Sstevel@tonic-gate	bnz	1f
1237c478bd9Sstevel@tonic-gate	andcc	%i4, %l1, %g0		! check if second byte was zero
1247c478bd9Sstevel@tonic-gate	b,a	.doneq
1257c478bd9Sstevel@tonic-gate1:	bnz	1f
1267c478bd9Sstevel@tonic-gate	andcc 	%i4, %l2, %g0		! check if third byte was zero
1277c478bd9Sstevel@tonic-gate	b,a	.doneq
1287c478bd9Sstevel@tonic-gate1:	bnz	1f
1297c478bd9Sstevel@tonic-gate	andcc	%i4, 0xff, %g0		! check if last byte is zero
1307c478bd9Sstevel@tonic-gate	b,a	.doneq
1317c478bd9Sstevel@tonic-gate1:	bnz	2b
1327c478bd9Sstevel@tonic-gate	sll	%i3, 24, %i5
1337c478bd9Sstevel@tonic-gate	b,a	.doneq
1347c478bd9Sstevel@tonic-gate
1357c478bd9Sstevel@tonic-gate.w1cmp:	clr	%l4
1367c478bd9Sstevel@tonic-gate	lduh	[%i1], %l4
1377c478bd9Sstevel@tonic-gate	inc	2, %i1
1387c478bd9Sstevel@tonic-gate	sll	%l4, 8, %l4
1397c478bd9Sstevel@tonic-gate	or	%i5, %l4, %i5
1407c478bd9Sstevel@tonic-gate
1417c478bd9Sstevel@tonic-gate	sub	%i0, %i1, %i0
1427c478bd9Sstevel@tonic-gate3:
1437c478bd9Sstevel@tonic-gate	deccc	4, %i2			! n >= 4 ?
1447c478bd9Sstevel@tonic-gate	bgeu,a	4f
1457c478bd9Sstevel@tonic-gate	ld	[%i1], %i3		! delay slot
1467c478bd9Sstevel@tonic-gate	dec	3, %i1			! reset s2
1477c478bd9Sstevel@tonic-gate	inc	3, %i0			! reset s1 diff
1487c478bd9Sstevel@tonic-gate	b	.cmp_bytes		! do a byte at a time if n < 4
1497c478bd9Sstevel@tonic-gate	inc	4, %i2
1507c478bd9Sstevel@tonic-gate4:
1517c478bd9Sstevel@tonic-gate	ld	[%i0 + %i1], %i4
1527c478bd9Sstevel@tonic-gate	inc	4, %i1
1537c478bd9Sstevel@tonic-gate	srl	%i3, 24, %l4		! merge with the other half
1547c478bd9Sstevel@tonic-gate	or	%l4, %i5, %i5
1557c478bd9Sstevel@tonic-gate	cmp	%i4, %i5
1567c478bd9Sstevel@tonic-gate	be	1f
1577c478bd9Sstevel@tonic-gate
1587c478bd9Sstevel@tonic-gate	add	%i4, %l6, %l3
1597c478bd9Sstevel@tonic-gate	b,a	.noteq
1607c478bd9Sstevel@tonic-gate1:	xor	%l3, %i4, %l3
1617c478bd9Sstevel@tonic-gate	and	%l3, %l7, %l3
1627c478bd9Sstevel@tonic-gate	cmp	%l3, %l7
1637c478bd9Sstevel@tonic-gate	be,a	3b
1647c478bd9Sstevel@tonic-gate	sll	%i3, 8, %i5
1657c478bd9Sstevel@tonic-gate
1667c478bd9Sstevel@tonic-gate	andcc	%i4, %l0, %g0		! check if first byte was zero
1677c478bd9Sstevel@tonic-gate	bnz	1f
1687c478bd9Sstevel@tonic-gate	andcc	%i4, %l1, %g0		! check if second byte was zero
1697c478bd9Sstevel@tonic-gate	b,a	.doneq
1707c478bd9Sstevel@tonic-gate1:	bnz	1f
1717c478bd9Sstevel@tonic-gate	andcc 	%i4, %l2, %g0		! check if third byte was zero
1727c478bd9Sstevel@tonic-gate	b,a	.doneq
1737c478bd9Sstevel@tonic-gate1:	bnz	1f
1747c478bd9Sstevel@tonic-gate	andcc	%i4, 0xff, %g0		! check if last byte is zero
1757c478bd9Sstevel@tonic-gate	b,a	.doneq
1767c478bd9Sstevel@tonic-gate1:	bnz	3b
1777c478bd9Sstevel@tonic-gate	sll	%i3, 8, %i5
1787c478bd9Sstevel@tonic-gate	b,a	.doneq
1797c478bd9Sstevel@tonic-gate
1807c478bd9Sstevel@tonic-gate.w2cmp:
1817c478bd9Sstevel@tonic-gate	lduh	[%i1], %i5		! read a halfword to align s2
1827c478bd9Sstevel@tonic-gate	inc	2, %i1
1837c478bd9Sstevel@tonic-gate	sll	%i5, 16, %i5
1847c478bd9Sstevel@tonic-gate
1857c478bd9Sstevel@tonic-gate	sub	%i0, %i1, %i0
1867c478bd9Sstevel@tonic-gate4:
1877c478bd9Sstevel@tonic-gate	deccc	4, %i2			! n >= 4 ?
1887c478bd9Sstevel@tonic-gate	bgeu,a	5f
1897c478bd9Sstevel@tonic-gate	ld	[%i1], %i3		! delay slot
1907c478bd9Sstevel@tonic-gate	dec	2, %i1			! reset s2
1917c478bd9Sstevel@tonic-gate	inc	2, %i0			! reset s1 diff
1927c478bd9Sstevel@tonic-gate	b	.cmp_bytes		! do a byte at a time if n < 4
1937c478bd9Sstevel@tonic-gate	inc	4, %i2			! delay slot
1947c478bd9Sstevel@tonic-gate5:
1957c478bd9Sstevel@tonic-gate	ld	[%i1 + %i0], %i4	! read a word from s2
1967c478bd9Sstevel@tonic-gate	inc	4, %i1
1977c478bd9Sstevel@tonic-gate	srl	%i3, 16, %l4		! merge with the other half
1987c478bd9Sstevel@tonic-gate	or	%l4, %i5, %i5
1997c478bd9Sstevel@tonic-gate	cmp	%i4, %i5
2007c478bd9Sstevel@tonic-gate	be	1f
2017c478bd9Sstevel@tonic-gate
2027c478bd9Sstevel@tonic-gate	add	%i4, %l6, %l3
2037c478bd9Sstevel@tonic-gate	b,a	.noteq
2047c478bd9Sstevel@tonic-gate1:	xor	%l3, %i4, %l3		! are any bytes 0?
2057c478bd9Sstevel@tonic-gate	and	%l3, %l7, %l3
2067c478bd9Sstevel@tonic-gate	cmp	%l3, %l7
2077c478bd9Sstevel@tonic-gate	be,a	4b
2087c478bd9Sstevel@tonic-gate	sll	%i3, 16, %i5
2097c478bd9Sstevel@tonic-gate
2107c478bd9Sstevel@tonic-gate	andcc	%i4, %l0, %g0		! check if first byte was zero
2117c478bd9Sstevel@tonic-gate	bnz	1f
2127c478bd9Sstevel@tonic-gate	andcc	%i4, %l1, %g0		! check if second byte was zero
2137c478bd9Sstevel@tonic-gate	b,a	.doneq
2147c478bd9Sstevel@tonic-gate1:	bnz	1f
2157c478bd9Sstevel@tonic-gate	andcc 	%i4, %l2, %g0		! check if third byte was zero
2167c478bd9Sstevel@tonic-gate	b,a	.doneq
2177c478bd9Sstevel@tonic-gate1:	bnz	1f
2187c478bd9Sstevel@tonic-gate	andcc	%i4, 0xff, %g0		! check if last byte is zero
2197c478bd9Sstevel@tonic-gate	b,a	.doneq
2207c478bd9Sstevel@tonic-gate1:	bnz	4b
2217c478bd9Sstevel@tonic-gate	sll	%i3, 16, %i5
2227c478bd9Sstevel@tonic-gate	b,a	.doneq
2237c478bd9Sstevel@tonic-gate
2247c478bd9Sstevel@tonic-gate.w4cmp:	sub	%i0, %i1, %i0
2257c478bd9Sstevel@tonic-gate	ld	[%i1], %i5		! read a word from s1
2267c478bd9Sstevel@tonic-gate5:	cmp     %i2,0
2277c478bd9Sstevel@tonic-gate	be,a    .doneq
2287c478bd9Sstevel@tonic-gate	nop
2297c478bd9Sstevel@tonic-gate	ld      [%i1], %i5              ! read a word from s1
2307c478bd9Sstevel@tonic-gate	deccc	4, %i2			! n >= 4 ?
2317c478bd9Sstevel@tonic-gate	bcs,a	.cmp_bytes		! do a byte at a time if n < 4
2327c478bd9Sstevel@tonic-gate	inc	4, %i2
2337c478bd9Sstevel@tonic-gate
2347c478bd9Sstevel@tonic-gate	ld	[%i1 + %i0], %i4	! read a word from s2
2357c478bd9Sstevel@tonic-gate	cmp	%i4, %i5
2367c478bd9Sstevel@tonic-gate	inc	4, %i1
2377c478bd9Sstevel@tonic-gate	be	1f
2387c478bd9Sstevel@tonic-gate
2397c478bd9Sstevel@tonic-gate	add	%i4, %l6, %l3
2407c478bd9Sstevel@tonic-gate	b,a	.noteq
2417c478bd9Sstevel@tonic-gate1:	xor	%l3, %i4, %l3
2427c478bd9Sstevel@tonic-gate	and	%l3, %l7, %l3
2437c478bd9Sstevel@tonic-gate	cmp	%l3, %l7
2447c478bd9Sstevel@tonic-gate	be,a	5b
2457c478bd9Sstevel@tonic-gate	nop
2467c478bd9Sstevel@tonic-gate
2477c478bd9Sstevel@tonic-gate	andcc	%i4, %l0, %g0		! check if first byte was zero
2487c478bd9Sstevel@tonic-gate	bnz	1f
2497c478bd9Sstevel@tonic-gate	andcc	%i4, %l1, %g0		! check if second byte was zero
2507c478bd9Sstevel@tonic-gate	b,a	.doneq
2517c478bd9Sstevel@tonic-gate1:	bnz	1f
2527c478bd9Sstevel@tonic-gate	andcc 	%i4, %l2, %g0		! check if third byte was zero
2537c478bd9Sstevel@tonic-gate	b,a	.doneq
2547c478bd9Sstevel@tonic-gate1:	bnz	1f
2557c478bd9Sstevel@tonic-gate	andcc	%i4, 0xff, %g0		! check if last byte is zero
2567c478bd9Sstevel@tonic-gate	b,a	.doneq
2577c478bd9Sstevel@tonic-gate1:	bnz,a	5b
2587c478bd9Sstevel@tonic-gate	ld	[%i1], %i5
2597c478bd9Sstevel@tonic-gate.doneq:	ret
2607c478bd9Sstevel@tonic-gate	restore	%g0, %g0, %o0		! equal return zero
2617c478bd9Sstevel@tonic-gate
2627c478bd9Sstevel@tonic-gate.noteq:	srl	%i4, 24, %l4
2637c478bd9Sstevel@tonic-gate	srl	%i5, 24, %l5
2647c478bd9Sstevel@tonic-gate	subcc	%l4, %l5, %i0
2657c478bd9Sstevel@tonic-gate	bne	6f
2667c478bd9Sstevel@tonic-gate	andcc	%l4, 0xff, %g0
2677c478bd9Sstevel@tonic-gate	bz	.doneq
2687c478bd9Sstevel@tonic-gate	sll	%i4, 8, %l4
2697c478bd9Sstevel@tonic-gate	sll	%i5, 8, %l5
2707c478bd9Sstevel@tonic-gate	srl	%l4, 24, %l4
2717c478bd9Sstevel@tonic-gate	srl	%l5, 24, %l5
2727c478bd9Sstevel@tonic-gate	subcc	%l4, %l5, %i0
2737c478bd9Sstevel@tonic-gate	bne	6f
2747c478bd9Sstevel@tonic-gate	andcc	%l4, 0xff, %g0
2757c478bd9Sstevel@tonic-gate	bz	.doneq
2767c478bd9Sstevel@tonic-gate	sll	%i4, 16, %l4
2777c478bd9Sstevel@tonic-gate	sll	%i5, 16, %l5
2787c478bd9Sstevel@tonic-gate	srl	%l4, 24, %l4
2797c478bd9Sstevel@tonic-gate	srl	%l5, 24, %l5
2807c478bd9Sstevel@tonic-gate	subcc	%l4, %l5, %i0
2817c478bd9Sstevel@tonic-gate	bne	6f
2827c478bd9Sstevel@tonic-gate	andcc	%l4, 0xff, %g0
2837c478bd9Sstevel@tonic-gate	bz	.doneq
2847c478bd9Sstevel@tonic-gate	nop
2857c478bd9Sstevel@tonic-gate.noteqb:
2867c478bd9Sstevel@tonic-gate	and	%i4, 0xff, %l4
2877c478bd9Sstevel@tonic-gate	and	%i5, 0xff, %l5
2887c478bd9Sstevel@tonic-gate	subcc	%l4, %l5, %i0
2897c478bd9Sstevel@tonic-gate6:	ret
2907c478bd9Sstevel@tonic-gate	restore	%i0, %g0, %o0
2917c478bd9Sstevel@tonic-gate
2927c478bd9Sstevel@tonic-gate	! Do a byte by byte comparison, disregarding alignments
2937c478bd9Sstevel@tonic-gate.cmp_bytes:
2947c478bd9Sstevel@tonic-gate	deccc	%i2			! --n >= 0 ?
2957c478bd9Sstevel@tonic-gate1:
2967c478bd9Sstevel@tonic-gate	bcs	.doneq
2977c478bd9Sstevel@tonic-gate	nop				! delay slot
2987c478bd9Sstevel@tonic-gate	ldub	[%i1 + %i0], %i4	! read a word from s1
2997c478bd9Sstevel@tonic-gate	ldub	[%i1], %i5		! read a word from s2
3007c478bd9Sstevel@tonic-gate
3017c478bd9Sstevel@tonic-gate	inc	%i1
3027c478bd9Sstevel@tonic-gate	cmp	%i4, %i5
3037c478bd9Sstevel@tonic-gate	bne	.noteqb
3047c478bd9Sstevel@tonic-gate	tst	%i4			! terminating zero
3057c478bd9Sstevel@tonic-gate	bnz	1b
3067c478bd9Sstevel@tonic-gate	deccc	%i2			! --n >= 0
3077c478bd9Sstevel@tonic-gate	b,a	.doneq
3087c478bd9Sstevel@tonic-gate
3097c478bd9Sstevel@tonic-gate	SET_SIZE(strncmp)
310