xref: /onnv-gate/usr/src/lib/libc/sparc/gen/strncmp.s (revision 7298:b69e27387f74)
10Sstevel@tonic-gate/*
20Sstevel@tonic-gate * CDDL HEADER START
30Sstevel@tonic-gate *
40Sstevel@tonic-gate * The contents of this file are subject to the terms of the
56812Sraf * Common Development and Distribution License (the "License").
66812Sraf * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate *
80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate * See the License for the specific language governing permissions
110Sstevel@tonic-gate * and limitations under the License.
120Sstevel@tonic-gate *
130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate *
190Sstevel@tonic-gate * CDDL HEADER END
200Sstevel@tonic-gate */
216812Sraf
220Sstevel@tonic-gate/*
236812Sraf * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
246812Sraf * Use is subject to license terms.
250Sstevel@tonic-gate */
260Sstevel@tonic-gate
27*7298SMark.J.Nelson@Sun.COM	.file	"strncmp.s"
280Sstevel@tonic-gate
290Sstevel@tonic-gate/*
300Sstevel@tonic-gate * strncmp(s1, s2, n)
310Sstevel@tonic-gate *
320Sstevel@tonic-gate * Compare strings (at most n bytes):  s1>s2: >0  s1==s2: 0  s1<s2: <0
330Sstevel@tonic-gate *
340Sstevel@tonic-gate * Fast assembler language version of the following C-program for strncmp
350Sstevel@tonic-gate * which represents the `standard' for the C-library.
360Sstevel@tonic-gate *
370Sstevel@tonic-gate *	int
380Sstevel@tonic-gate *	strncmp(const char *s1, const char *s2, size_t n)
390Sstevel@tonic-gate *	{
400Sstevel@tonic-gate *		n++;
410Sstevel@tonic-gate *		if (s1 == s2)
420Sstevel@tonic-gate *			return (0);
430Sstevel@tonic-gate *		while (--n != 0 && *s1 == *s2++)
440Sstevel@tonic-gate *			if (*s1++ == '\0')
450Sstevel@tonic-gate *				return (0);
460Sstevel@tonic-gate *		return ((n == 0) ? 0 : (*s1 - s2[-1]));
470Sstevel@tonic-gate *	}
480Sstevel@tonic-gate */
490Sstevel@tonic-gate
500Sstevel@tonic-gate#include <sys/asm_linkage.h>
510Sstevel@tonic-gate
520Sstevel@tonic-gate	ENTRY(strncmp)
530Sstevel@tonic-gate	save	%sp, -SA(WINDOWSIZE), %sp
540Sstevel@tonic-gate	cmp	%i2, 8
550Sstevel@tonic-gate	blu,a	.cmp_bytes		! for small counts go do bytes
560Sstevel@tonic-gate	sub	%i0, %i1, %i0		! delay slot, get diff from s1 - s2
570Sstevel@tonic-gate	andcc	%i0, 3, %g0		! is s1 aligned
580Sstevel@tonic-gate1:	bz	.iss2			! if so go check s2
590Sstevel@tonic-gate	andcc	%i1, 3, %i3		! is s2 aligned
600Sstevel@tonic-gate
610Sstevel@tonic-gate	deccc	%i2			! --n >= 0 ?
620Sstevel@tonic-gate	bcs	.doneq
630Sstevel@tonic-gate	nop				! delay slot
640Sstevel@tonic-gate
650Sstevel@tonic-gate	ldub	[%i0], %i4		! else cmp one byte
660Sstevel@tonic-gate	ldub	[%i1], %i5
670Sstevel@tonic-gate	inc	%i0
680Sstevel@tonic-gate	cmp	%i4, %i5
690Sstevel@tonic-gate	bne	.noteqb
700Sstevel@tonic-gate	inc	%i1
710Sstevel@tonic-gate	tst	%i4			! terminating zero
720Sstevel@tonic-gate	bnz	1b
730Sstevel@tonic-gate	andcc	%i0, 3, %g0
740Sstevel@tonic-gate	b,a	.doneq
750Sstevel@tonic-gate
760Sstevel@tonic-gate.iss2:
770Sstevel@tonic-gate	set     0x7efefeff, %l6
780Sstevel@tonic-gate	set     0x81010100, %l7
790Sstevel@tonic-gate	sethi	%hi(0xff000000), %l0	! masks to test for terminating null
800Sstevel@tonic-gate	sethi	%hi(0x00ff0000), %l1
810Sstevel@tonic-gate	srl	%l1, 8, %l2		! generate 0x0000ff00 mask
820Sstevel@tonic-gate
830Sstevel@tonic-gate	bz	.w4cmp			! if s2 word aligned, compare words
840Sstevel@tonic-gate	cmp	%i3, 2			! check if s2 half aligned
850Sstevel@tonic-gate	be	.w2cmp
860Sstevel@tonic-gate	cmp	%i3, 1			! check if aligned to 1 or 3 bytes
870Sstevel@tonic-gate.w3cmp:	ldub	[%i1], %i5
880Sstevel@tonic-gate	inc	1, %i1
890Sstevel@tonic-gate	be	.w1cmp
900Sstevel@tonic-gate	sll	%i5, 24, %i5
910Sstevel@tonic-gate	sub	%i0, %i1, %i0
920Sstevel@tonic-gate2:
930Sstevel@tonic-gate	deccc	4, %i2			! n >= 4 ?
940Sstevel@tonic-gate	bgeu,a	3f
950Sstevel@tonic-gate	ld	[%i1], %i3		! delay slot
960Sstevel@tonic-gate	dec	%i1			! reset s2
970Sstevel@tonic-gate	inc	%i0			! reset s1 diff
980Sstevel@tonic-gate	b	.cmp_bytes		! do a byte at a time if n < 4
990Sstevel@tonic-gate	inc	4, %i2
1000Sstevel@tonic-gate3:
1010Sstevel@tonic-gate	ld	[%i0 + %i1], %i4
1020Sstevel@tonic-gate	inc	4, %i1
1030Sstevel@tonic-gate	srl	%i3, 8, %l4		! merge with the other half
1040Sstevel@tonic-gate	or	%l4, %i5, %i5
1050Sstevel@tonic-gate	cmp	%i4, %i5
1060Sstevel@tonic-gate	be	1f
1070Sstevel@tonic-gate
1080Sstevel@tonic-gate	add	%i4, %l6, %l3
1090Sstevel@tonic-gate	b,a	.noteq
1100Sstevel@tonic-gate1:	xor	%l3, %i4, %l3
1110Sstevel@tonic-gate	and	%l3, %l7, %l3
1120Sstevel@tonic-gate	cmp	%l3, %l7
1130Sstevel@tonic-gate	be,a	2b
1140Sstevel@tonic-gate	sll	%i3, 24, %i5
1150Sstevel@tonic-gate
1160Sstevel@tonic-gate	!
1170Sstevel@tonic-gate	! For 7-bit characters, we know one of the bytes is zero, but for
1180Sstevel@tonic-gate	! 8-bit characters, the zero detection algorithm gives some false
1190Sstevel@tonic-gate	! triggers ... check every byte individually.
1200Sstevel@tonic-gate	!
1210Sstevel@tonic-gate	andcc	%i4, %l0, %g0		! check if first byte was zero
1220Sstevel@tonic-gate	bnz	1f
1230Sstevel@tonic-gate	andcc	%i4, %l1, %g0		! check if second byte was zero
1240Sstevel@tonic-gate	b,a	.doneq
1250Sstevel@tonic-gate1:	bnz	1f
1260Sstevel@tonic-gate	andcc 	%i4, %l2, %g0		! check if third byte was zero
1270Sstevel@tonic-gate	b,a	.doneq
1280Sstevel@tonic-gate1:	bnz	1f
1290Sstevel@tonic-gate	andcc	%i4, 0xff, %g0		! check if last byte is zero
1300Sstevel@tonic-gate	b,a	.doneq
1310Sstevel@tonic-gate1:	bnz	2b
1320Sstevel@tonic-gate	sll	%i3, 24, %i5
1330Sstevel@tonic-gate	b,a	.doneq
1340Sstevel@tonic-gate
1350Sstevel@tonic-gate.w1cmp:	clr	%l4
1360Sstevel@tonic-gate	lduh	[%i1], %l4
1370Sstevel@tonic-gate	inc	2, %i1
1380Sstevel@tonic-gate	sll	%l4, 8, %l4
1390Sstevel@tonic-gate	or	%i5, %l4, %i5
1400Sstevel@tonic-gate
1410Sstevel@tonic-gate	sub	%i0, %i1, %i0
1420Sstevel@tonic-gate3:
1430Sstevel@tonic-gate	deccc	4, %i2			! n >= 4 ?
1440Sstevel@tonic-gate	bgeu,a	4f
1450Sstevel@tonic-gate	ld	[%i1], %i3		! delay slot
1460Sstevel@tonic-gate	dec	3, %i1			! reset s2
1470Sstevel@tonic-gate	inc	3, %i0			! reset s1 diff
1480Sstevel@tonic-gate	b	.cmp_bytes		! do a byte at a time if n < 4
1490Sstevel@tonic-gate	inc	4, %i2
1500Sstevel@tonic-gate4:
1510Sstevel@tonic-gate	ld	[%i0 + %i1], %i4
1520Sstevel@tonic-gate	inc	4, %i1
1530Sstevel@tonic-gate	srl	%i3, 24, %l4		! merge with the other half
1540Sstevel@tonic-gate	or	%l4, %i5, %i5
1550Sstevel@tonic-gate	cmp	%i4, %i5
1560Sstevel@tonic-gate	be	1f
1570Sstevel@tonic-gate
1580Sstevel@tonic-gate	add	%i4, %l6, %l3
1590Sstevel@tonic-gate	b,a	.noteq
1600Sstevel@tonic-gate1:	xor	%l3, %i4, %l3
1610Sstevel@tonic-gate	and	%l3, %l7, %l3
1620Sstevel@tonic-gate	cmp	%l3, %l7
1630Sstevel@tonic-gate	be,a	3b
1640Sstevel@tonic-gate	sll	%i3, 8, %i5
1650Sstevel@tonic-gate
1660Sstevel@tonic-gate	andcc	%i4, %l0, %g0		! check if first byte was zero
1670Sstevel@tonic-gate	bnz	1f
1680Sstevel@tonic-gate	andcc	%i4, %l1, %g0		! check if second byte was zero
1690Sstevel@tonic-gate	b,a	.doneq
1700Sstevel@tonic-gate1:	bnz	1f
1710Sstevel@tonic-gate	andcc 	%i4, %l2, %g0		! check if third byte was zero
1720Sstevel@tonic-gate	b,a	.doneq
1730Sstevel@tonic-gate1:	bnz	1f
1740Sstevel@tonic-gate	andcc	%i4, 0xff, %g0		! check if last byte is zero
1750Sstevel@tonic-gate	b,a	.doneq
1760Sstevel@tonic-gate1:	bnz	3b
1770Sstevel@tonic-gate	sll	%i3, 8, %i5
1780Sstevel@tonic-gate	b,a	.doneq
1790Sstevel@tonic-gate
1800Sstevel@tonic-gate.w2cmp:
1810Sstevel@tonic-gate	lduh	[%i1], %i5		! read a halfword to align s2
1820Sstevel@tonic-gate	inc	2, %i1
1830Sstevel@tonic-gate	sll	%i5, 16, %i5
1840Sstevel@tonic-gate
1850Sstevel@tonic-gate	sub	%i0, %i1, %i0
1860Sstevel@tonic-gate4:
1870Sstevel@tonic-gate	deccc	4, %i2			! n >= 4 ?
1880Sstevel@tonic-gate	bgeu,a	5f
1890Sstevel@tonic-gate	ld	[%i1], %i3		! delay slot
1900Sstevel@tonic-gate	dec	2, %i1			! reset s2
1910Sstevel@tonic-gate	inc	2, %i0			! reset s1 diff
1920Sstevel@tonic-gate	b	.cmp_bytes		! do a byte at a time if n < 4
1930Sstevel@tonic-gate	inc	4, %i2			! delay slot
1940Sstevel@tonic-gate5:
1950Sstevel@tonic-gate	ld	[%i1 + %i0], %i4	! read a word from s2
1960Sstevel@tonic-gate	inc	4, %i1
1970Sstevel@tonic-gate	srl	%i3, 16, %l4		! merge with the other half
1980Sstevel@tonic-gate	or	%l4, %i5, %i5
1990Sstevel@tonic-gate	cmp	%i4, %i5
2000Sstevel@tonic-gate	be	1f
2010Sstevel@tonic-gate
2020Sstevel@tonic-gate	add	%i4, %l6, %l3
2030Sstevel@tonic-gate	b,a	.noteq
2040Sstevel@tonic-gate1:	xor	%l3, %i4, %l3		! are any bytes 0?
2050Sstevel@tonic-gate	and	%l3, %l7, %l3
2060Sstevel@tonic-gate	cmp	%l3, %l7
2070Sstevel@tonic-gate	be,a	4b
2080Sstevel@tonic-gate	sll	%i3, 16, %i5
2090Sstevel@tonic-gate
2100Sstevel@tonic-gate	andcc	%i4, %l0, %g0		! check if first byte was zero
2110Sstevel@tonic-gate	bnz	1f
2120Sstevel@tonic-gate	andcc	%i4, %l1, %g0		! check if second byte was zero
2130Sstevel@tonic-gate	b,a	.doneq
2140Sstevel@tonic-gate1:	bnz	1f
2150Sstevel@tonic-gate	andcc 	%i4, %l2, %g0		! check if third byte was zero
2160Sstevel@tonic-gate	b,a	.doneq
2170Sstevel@tonic-gate1:	bnz	1f
2180Sstevel@tonic-gate	andcc	%i4, 0xff, %g0		! check if last byte is zero
2190Sstevel@tonic-gate	b,a	.doneq
2200Sstevel@tonic-gate1:	bnz	4b
2210Sstevel@tonic-gate	sll	%i3, 16, %i5
2220Sstevel@tonic-gate	b,a	.doneq
2230Sstevel@tonic-gate
2240Sstevel@tonic-gate.w4cmp:	sub	%i0, %i1, %i0
2250Sstevel@tonic-gate	ld	[%i1], %i5		! read a word from s1
2260Sstevel@tonic-gate5:	cmp     %i2,0
2270Sstevel@tonic-gate	be,a    .doneq
2280Sstevel@tonic-gate	nop
2290Sstevel@tonic-gate	ld      [%i1], %i5              ! read a word from s1
2300Sstevel@tonic-gate	deccc	4, %i2			! n >= 4 ?
2310Sstevel@tonic-gate	bcs,a	.cmp_bytes		! do a byte at a time if n < 4
2320Sstevel@tonic-gate	inc	4, %i2
2330Sstevel@tonic-gate
2340Sstevel@tonic-gate	ld	[%i1 + %i0], %i4	! read a word from s2
2350Sstevel@tonic-gate	cmp	%i4, %i5
2360Sstevel@tonic-gate	inc	4, %i1
2370Sstevel@tonic-gate	be	1f
2380Sstevel@tonic-gate
2390Sstevel@tonic-gate	add	%i4, %l6, %l3
2400Sstevel@tonic-gate	b,a	.noteq
2410Sstevel@tonic-gate1:	xor	%l3, %i4, %l3
2420Sstevel@tonic-gate	and	%l3, %l7, %l3
2430Sstevel@tonic-gate	cmp	%l3, %l7
2440Sstevel@tonic-gate	be,a	5b
2450Sstevel@tonic-gate	nop
2460Sstevel@tonic-gate
2470Sstevel@tonic-gate	andcc	%i4, %l0, %g0		! check if first byte was zero
2480Sstevel@tonic-gate	bnz	1f
2490Sstevel@tonic-gate	andcc	%i4, %l1, %g0		! check if second byte was zero
2500Sstevel@tonic-gate	b,a	.doneq
2510Sstevel@tonic-gate1:	bnz	1f
2520Sstevel@tonic-gate	andcc 	%i4, %l2, %g0		! check if third byte was zero
2530Sstevel@tonic-gate	b,a	.doneq
2540Sstevel@tonic-gate1:	bnz	1f
2550Sstevel@tonic-gate	andcc	%i4, 0xff, %g0		! check if last byte is zero
2560Sstevel@tonic-gate	b,a	.doneq
2570Sstevel@tonic-gate1:	bnz,a	5b
2580Sstevel@tonic-gate	ld	[%i1], %i5
2590Sstevel@tonic-gate.doneq:	ret
2600Sstevel@tonic-gate	restore	%g0, %g0, %o0		! equal return zero
2610Sstevel@tonic-gate
2620Sstevel@tonic-gate.noteq:	srl	%i4, 24, %l4
2630Sstevel@tonic-gate	srl	%i5, 24, %l5
2640Sstevel@tonic-gate	subcc	%l4, %l5, %i0
2650Sstevel@tonic-gate	bne	6f
2660Sstevel@tonic-gate	andcc	%l4, 0xff, %g0
2670Sstevel@tonic-gate	bz	.doneq
2680Sstevel@tonic-gate	sll	%i4, 8, %l4
2690Sstevel@tonic-gate	sll	%i5, 8, %l5
2700Sstevel@tonic-gate	srl	%l4, 24, %l4
2710Sstevel@tonic-gate	srl	%l5, 24, %l5
2720Sstevel@tonic-gate	subcc	%l4, %l5, %i0
2730Sstevel@tonic-gate	bne	6f
2740Sstevel@tonic-gate	andcc	%l4, 0xff, %g0
2750Sstevel@tonic-gate	bz	.doneq
2760Sstevel@tonic-gate	sll	%i4, 16, %l4
2770Sstevel@tonic-gate	sll	%i5, 16, %l5
2780Sstevel@tonic-gate	srl	%l4, 24, %l4
2790Sstevel@tonic-gate	srl	%l5, 24, %l5
2800Sstevel@tonic-gate	subcc	%l4, %l5, %i0
2810Sstevel@tonic-gate	bne	6f
2820Sstevel@tonic-gate	andcc	%l4, 0xff, %g0
2830Sstevel@tonic-gate	bz	.doneq
2840Sstevel@tonic-gate	nop
2850Sstevel@tonic-gate.noteqb:
2860Sstevel@tonic-gate	and	%i4, 0xff, %l4
2870Sstevel@tonic-gate	and	%i5, 0xff, %l5
2880Sstevel@tonic-gate	subcc	%l4, %l5, %i0
2890Sstevel@tonic-gate6:	ret
2900Sstevel@tonic-gate	restore	%i0, %g0, %o0
2910Sstevel@tonic-gate
2920Sstevel@tonic-gate	! Do a byte by byte comparison, disregarding alignments
2930Sstevel@tonic-gate.cmp_bytes:
2940Sstevel@tonic-gate	deccc	%i2			! --n >= 0 ?
2950Sstevel@tonic-gate1:
2960Sstevel@tonic-gate	bcs	.doneq
2970Sstevel@tonic-gate	nop				! delay slot
2980Sstevel@tonic-gate	ldub	[%i1 + %i0], %i4	! read a word from s1
2990Sstevel@tonic-gate	ldub	[%i1], %i5		! read a word from s2
3000Sstevel@tonic-gate
3010Sstevel@tonic-gate	inc	%i1
3020Sstevel@tonic-gate	cmp	%i4, %i5
3030Sstevel@tonic-gate	bne	.noteqb
3040Sstevel@tonic-gate	tst	%i4			! terminating zero
3050Sstevel@tonic-gate	bnz	1b
3060Sstevel@tonic-gate	deccc	%i2			! --n >= 0
3070Sstevel@tonic-gate	b,a	.doneq
3080Sstevel@tonic-gate
3090Sstevel@tonic-gate	SET_SIZE(strncmp)
310