xref: /onnv-gate/usr/src/lib/libc/sparc/gen/strlcpy.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.
240Sstevel@tonic-gate * Use is subject to license terms.
250Sstevel@tonic-gate */
260Sstevel@tonic-gate
27*7298SMark.J.Nelson@Sun.COM	.file	"strlcpy.s"
280Sstevel@tonic-gate/*
290Sstevel@tonic-gate * The strlcpy() function copies at most dstsize-1 characters
300Sstevel@tonic-gate * (dstsize being the size of the string buffer dst) from src
310Sstevel@tonic-gate * to dst, truncating src if necessary. The result is always
320Sstevel@tonic-gate * null-terminated.  The function returns strlen(src). Buffer
330Sstevel@tonic-gate * overflow can be checked as follows:
340Sstevel@tonic-gate *
350Sstevel@tonic-gate *   if (strlcpy(dst, src, dstsize) >= dstsize)
360Sstevel@tonic-gate *           return -1;
370Sstevel@tonic-gate */
380Sstevel@tonic-gate
390Sstevel@tonic-gate#include <sys/asm_linkage.h>
400Sstevel@tonic-gate
410Sstevel@tonic-gate	! strlcpy implementation is similar to that of strcpy, except
420Sstevel@tonic-gate	! in this case, the maximum size of the detination must be
430Sstevel@tonic-gate	! tracked since it bounds our maximum copy size.  However,
440Sstevel@tonic-gate	! we must still continue to check for zero since the routine
450Sstevel@tonic-gate	! is expected to null-terminate any string that is within
460Sstevel@tonic-gate	! the dest size bound.
470Sstevel@tonic-gate	!
480Sstevel@tonic-gate	! this method starts by checking for and arranging source alignment.
490Sstevel@tonic-gate	! Once this has occurred, we copy based upon destination alignment.
500Sstevel@tonic-gate	! This is either by word, halfword, or byte.  As this occurs, we
510Sstevel@tonic-gate	! check for a zero-byte.  If one is found, we branch to a method
520Sstevel@tonic-gate	! which checks for the exact location of a zero-byte within a
530Sstevel@tonic-gate	! larger word/half-word quantity.
540Sstevel@tonic-gate
550Sstevel@tonic-gate	ENTRY(strlcpy)
560Sstevel@tonic-gate
570Sstevel@tonic-gate	.align 32
580Sstevel@tonic-gate	save	%sp, -SA(WINDOWSIZE), %sp
590Sstevel@tonic-gate	subcc	%g0, %i2, %g4		! n = -n or n == 0 ?
600Sstevel@tonic-gate	bz,pn	%icc, .getstrlen	! if 0 do nothing but strlen(src)
610Sstevel@tonic-gate	add	%i1, %i2, %i3		! i3 = src + n
620Sstevel@tonic-gate	andcc	%i1, 3, %i4		! word aligned?
630Sstevel@tonic-gate	bz,pn	%icc, .wordaligned
640Sstevel@tonic-gate	add	%i0, %i2, %i2		! n = dst + n
650Sstevel@tonic-gate	sub	%i4, 4, %i4		! bytes until src aligned
660Sstevel@tonic-gate
670Sstevel@tonic-gate.alignsrc:
680Sstevel@tonic-gate	ldub	[%i3 + %g4], %l1	! l1 = src[]
690Sstevel@tonic-gate	andcc	%l1, 0xff, %g0		! null byte reached?
700Sstevel@tonic-gate	stub	%l1, [%i2 + %g4]	! dst[] = src[]
710Sstevel@tonic-gate	bz,a	%icc, .done
720Sstevel@tonic-gate	add	%i2, %g4, %i2		! get single dest ptr for strlen
730Sstevel@tonic-gate	addcc	%g4, 1, %g4		! src++ dest++ n--
740Sstevel@tonic-gate	bz,pn	%icc, .forcenullunalign	! n == 0, append null byte
750Sstevel@tonic-gate	addcc	%i4, 1, %i4		! incr, check align
760Sstevel@tonic-gate	bnz,a 	%icc, .alignsrc
770Sstevel@tonic-gate	nop
780Sstevel@tonic-gate
790Sstevel@tonic-gate.wordaligned:
800Sstevel@tonic-gate	sethi	%hi(0x01010101), %i4
810Sstevel@tonic-gate	add	%i2, %g4, %l0		! l0 = dest
820Sstevel@tonic-gate	or	%i4, %lo(0x01010101), %i4
830Sstevel@tonic-gate	sub	%i2, 4, %i2		! pre-incr for in cpy loop
840Sstevel@tonic-gate	andcc	%l0, 3, %g1		! word aligned?
850Sstevel@tonic-gate	bnz	%icc, .dstnotaligned
860Sstevel@tonic-gate	sll	%i4, 7, %i5		! Mycroft part deux
870Sstevel@tonic-gate
880Sstevel@tonic-gate.storeword:
890Sstevel@tonic-gate	ld	[%i3 + %g4], %l1	! l1 = src[]
900Sstevel@tonic-gate	addcc	%g4, 4, %g4		! n += 4, src += 4, dst +=4
910Sstevel@tonic-gate	bcs,pn	%icc, .lastword
920Sstevel@tonic-gate	andn	%i5, %l1, %g1		! ~word & 0x80808080
930Sstevel@tonic-gate	sub	%l1, %i4, %l0		! word - 0x01010101
940Sstevel@tonic-gate	andcc	%l0, %g1, %g0		! doit
950Sstevel@tonic-gate	bz,a,pt	%icc, .storeword	! if expr == 0, no zero byte
960Sstevel@tonic-gate	st	%l1, [%i2 + %g4]	! dst[] = src[]
970Sstevel@tonic-gate
980Sstevel@tonic-gate.zerobyte:
990Sstevel@tonic-gate	add	%i2, %g4, %i2		! ptr to dest
1000Sstevel@tonic-gate	srl	%l1, 24, %g1		! 1st byte
1010Sstevel@tonic-gate	andcc	%g1, 0xff, %g0		! test for end
1020Sstevel@tonic-gate	bz,pn	%icc, .done
1030Sstevel@tonic-gate	stb	%g1, [%i2]		! store byte
1040Sstevel@tonic-gate	add	%i2, 1, %i2		! dst ++
1050Sstevel@tonic-gate	srl	%l1, 16, %g1		! 2nd byte
1060Sstevel@tonic-gate	andcc	%g1, 0xff, %g0		! zero byte ?
1070Sstevel@tonic-gate	bz,pn	%icc, .done
1080Sstevel@tonic-gate	stb	%g1, [%i2]		! store byte
1090Sstevel@tonic-gate	add	%i2, 1, %i2		! dst ++
1100Sstevel@tonic-gate	srl	%l1, 8, %g1		! 3rd byte
1110Sstevel@tonic-gate	andcc	%g1, 0xff, %g0		! zero byte ?
1120Sstevel@tonic-gate	bz,pn	%icc, .done
1130Sstevel@tonic-gate	stb	%g1, [%i2]		! store byte
1140Sstevel@tonic-gate	stb	%l1, [%i2 + 1]		! store last byte
1150Sstevel@tonic-gate	add	%i2, 1, %i2		! dst ++
1160Sstevel@tonic-gate
1170Sstevel@tonic-gate.done:
1180Sstevel@tonic-gate	sub	%i2, %i0, %i0		! len = dst - orig dst
1190Sstevel@tonic-gate	ret
1200Sstevel@tonic-gate	restore	%i0, %g0, %o0
1210Sstevel@tonic-gate
1220Sstevel@tonic-gate.lastword:
1230Sstevel@tonic-gate	add	%i2, %g4, %i2
1240Sstevel@tonic-gate	sub	%g4, 4, %g4		! undo pre-incr
1250Sstevel@tonic-gate	add	%i3, %g4, %i3
1260Sstevel@tonic-gate
1270Sstevel@tonic-gate	srl	%l1, 24, %g1		! 1st byte
1280Sstevel@tonic-gate	andcc	%g1, 0xff, %g0		! zero byte?
1290Sstevel@tonic-gate	bz,pn	%icc, .done
1300Sstevel@tonic-gate	stb	%g1, [%i2]		! store byte
1310Sstevel@tonic-gate	inccc	%g4			! n--
1320Sstevel@tonic-gate	bz	.forcenull
1330Sstevel@tonic-gate	srl	%l1, 16, %g1		! 2nd byte
1340Sstevel@tonic-gate	add	%i2, 1, %i2		! dst++
1350Sstevel@tonic-gate	andcc	%g1, 0xff, %g0		! zero?
1360Sstevel@tonic-gate	bz,pn	%icc, .done
1370Sstevel@tonic-gate	stb	%g1, [%i2]		! store
1380Sstevel@tonic-gate	inccc	%g4
1390Sstevel@tonic-gate	bz	.forcenull
1400Sstevel@tonic-gate	srl	%l1, 8, %g1		! 3rd byte
1410Sstevel@tonic-gate	add	%i2, 1, %i2		! dst++
1420Sstevel@tonic-gate	andcc	%g1, 0xff, %g0		! zero?
1430Sstevel@tonic-gate	bz,pn	%icc, .done
1440Sstevel@tonic-gate	stb	%g1, [%i2]		! store
1450Sstevel@tonic-gate	inccc	%g4			! n--
1460Sstevel@tonic-gate	bz	.forcenull
1470Sstevel@tonic-gate	andcc	%l1, 0xff, %g0		! zero?
1480Sstevel@tonic-gate	add	%i2, 1, %i2		! dst++
1490Sstevel@tonic-gate	bz,pn	%ncc, .done
1500Sstevel@tonic-gate	stb	%l1, [%i2]
1510Sstevel@tonic-gate
1520Sstevel@tonic-gate.forcenull:
1530Sstevel@tonic-gate	stb	%g0, [%i2]
1540Sstevel@tonic-gate
1550Sstevel@tonic-gate.searchword:
1560Sstevel@tonic-gate	ld	[%i3], %l1
1570Sstevel@tonic-gate.searchword2:
1580Sstevel@tonic-gate	andn	%i5, %l1, %g1		! word & 0x80808080
1590Sstevel@tonic-gate	sub	%l1, %i4, %l0		! word - 0x01010101
1600Sstevel@tonic-gate	andcc	%l0, %g1, %g0		! do it
1610Sstevel@tonic-gate	bz,a,pt	%icc, .searchword
1620Sstevel@tonic-gate	add	%i3, 4, %i3		! src += 4
1630Sstevel@tonic-gate
1640Sstevel@tonic-gate	mov	0xff, %i5
1650Sstevel@tonic-gate	sll	%i5, 24, %i5		! mask 1st byte = 0xff000000
1660Sstevel@tonic-gate.searchbyte:
1670Sstevel@tonic-gate	andcc	%l1, %i5, %g0		! cur byte 0?
1680Sstevel@tonic-gate	srl	%i5, 8, %i5		! mask next byte
1690Sstevel@tonic-gate	bnz,a	%icc, .searchbyte	! cur !=0 continue
1700Sstevel@tonic-gate	add	%i3, 1, %i3
1710Sstevel@tonic-gate
1720Sstevel@tonic-gate.endfound:
1730Sstevel@tonic-gate	sub	%i3, %i1, %i0		! len = src - orig src
1740Sstevel@tonic-gate	ret
1750Sstevel@tonic-gate	restore	%i0, %g0, %o0
1760Sstevel@tonic-gate	nop
1770Sstevel@tonic-gate
1780Sstevel@tonic-gate.dstnotaligned:
1790Sstevel@tonic-gate	cmp	%g1, 2			! halfword aligned?
1800Sstevel@tonic-gate	be	.storehalfword2
1810Sstevel@tonic-gate	.empty
1820Sstevel@tonic-gate.storebyte:
1830Sstevel@tonic-gate	ld	[%i3 + %g4], %l1	! load src word
1840Sstevel@tonic-gate	addcc	%g4, 4, %g4		! src +=4 dst +=4
1850Sstevel@tonic-gate	bcs,pn	%icc, .lastword
1860Sstevel@tonic-gate	andn	%i5, %l1, %g1		! ~x & 0x80808080
1870Sstevel@tonic-gate	sub	%l1, %i4, %l0		! x - 0x01010101
1880Sstevel@tonic-gate	andcc	%l0, %g1, %g0		! get your Mycroft on
1890Sstevel@tonic-gate	bnz,pn	%icc, .zerobyte		! non-zero, we have zero byte
1900Sstevel@tonic-gate	add	%i2, %g4, %l0		! dst in ptr form
1910Sstevel@tonic-gate	srl	%l1, 24, %g1		! get 1st byte, then be hw aligned
1920Sstevel@tonic-gate	stb	%g1, [%l0]
1930Sstevel@tonic-gate	srl	%l1, 8, %g1		! 2nd & 3rd bytes
1940Sstevel@tonic-gate	sth	%g1, [%l0 + 1]
1950Sstevel@tonic-gate	ba	.storebyte
1960Sstevel@tonic-gate	stb	%l1, [%l0 + 3]		! store 4th byte
1970Sstevel@tonic-gate
1980Sstevel@tonic-gate.storehalfword:
1990Sstevel@tonic-gate	ld	[%i3 + %g4], %l1	! src word
2000Sstevel@tonic-gate.storehalfword2:
2010Sstevel@tonic-gate	addcc	%g4, 4, %g4		! src += 4 dst += 4
2020Sstevel@tonic-gate	bcs,pn	%icc, .lastword
2030Sstevel@tonic-gate	andn	%i5, %l1, %g1		! ~x & 0x80808080
2040Sstevel@tonic-gate	sub	%l1, %i4, %l0		! x - 0x01010101
2050Sstevel@tonic-gate	andcc	%l0, %g1, %g0		! Mycroft again...
2060Sstevel@tonic-gate	bnz,pn	%icc, .zerobyte		! non-zer, we have zero byte
2070Sstevel@tonic-gate	add	%i2, %g4, %l0		! dst in ptr form
2080Sstevel@tonic-gate	srl	%l1, 16, %g1		! first two bytes
2090Sstevel@tonic-gate	sth	%g1, [%l0]
2100Sstevel@tonic-gate	ba	.storehalfword
2110Sstevel@tonic-gate	sth	%l1, [%l0 + 2]
2120Sstevel@tonic-gate
2130Sstevel@tonic-gate.forcenullunalign:
2140Sstevel@tonic-gate	add	%i2, %g4, %i2		! single dst ptr
2150Sstevel@tonic-gate	stb	%g0, [%i2 - 1]		! store terminating null byte
2160Sstevel@tonic-gate
2170Sstevel@tonic-gate.getstrlen:
2180Sstevel@tonic-gate	sethi	%hi(0x01010101), %i4	! Mycroft...
2190Sstevel@tonic-gate	or	%i4, %lo(0x01010101), %i4
2200Sstevel@tonic-gate	sll	%i4, 7, %i5
2210Sstevel@tonic-gate
2220Sstevel@tonic-gate.getstrlenloop:
2230Sstevel@tonic-gate	andcc	%i3, 3, %g0		! word aligned?
2240Sstevel@tonic-gate	bz,a,pn	%icc, .searchword2	! search word at a time
2250Sstevel@tonic-gate	ld	[%i3], %l1		! src word
2260Sstevel@tonic-gate	ldub	[%i3], %l1		! src byte
2270Sstevel@tonic-gate	andcc	%l1, 0xff, %g0		! end of src?
2280Sstevel@tonic-gate	bnz,a	%icc, .getstrlenloop
2290Sstevel@tonic-gate	add	%i3, 1, %i3		! src ++
2300Sstevel@tonic-gate	sub	%i3, %i1, %i0		! len = src - orig src
2310Sstevel@tonic-gate	ret
2320Sstevel@tonic-gate	restore	%i0, %g0, %o0
2330Sstevel@tonic-gate	SET_SIZE(strlcpy)
234