xref: /illumos-gate/usr/src/lib/libc/sparc/gen/strlcpy.S (revision 55fea89d)
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.
247c478bd9Sstevel@tonic-gate * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate */
267c478bd9Sstevel@tonic-gate
279a70fc3bSMark J. Nelson	.file	"strlcpy.s"
287c478bd9Sstevel@tonic-gate/*
297c478bd9Sstevel@tonic-gate * The strlcpy() function copies at most dstsize-1 characters
307c478bd9Sstevel@tonic-gate * (dstsize being the size of the string buffer dst) from src
317c478bd9Sstevel@tonic-gate * to dst, truncating src if necessary. The result is always
327c478bd9Sstevel@tonic-gate * null-terminated.  The function returns strlen(src). Buffer
337c478bd9Sstevel@tonic-gate * overflow can be checked as follows:
347c478bd9Sstevel@tonic-gate *
357c478bd9Sstevel@tonic-gate *   if (strlcpy(dst, src, dstsize) >= dstsize)
367c478bd9Sstevel@tonic-gate *           return -1;
377c478bd9Sstevel@tonic-gate */
387c478bd9Sstevel@tonic-gate
397c478bd9Sstevel@tonic-gate#include <sys/asm_linkage.h>
407c478bd9Sstevel@tonic-gate
417c478bd9Sstevel@tonic-gate	! strlcpy implementation is similar to that of strcpy, except
427c478bd9Sstevel@tonic-gate	! in this case, the maximum size of the detination must be
437c478bd9Sstevel@tonic-gate	! tracked since it bounds our maximum copy size.  However,
447c478bd9Sstevel@tonic-gate	! we must still continue to check for zero since the routine
457c478bd9Sstevel@tonic-gate	! is expected to null-terminate any string that is within
467c478bd9Sstevel@tonic-gate	! the dest size bound.
477c478bd9Sstevel@tonic-gate	!
487c478bd9Sstevel@tonic-gate	! this method starts by checking for and arranging source alignment.
497c478bd9Sstevel@tonic-gate	! Once this has occurred, we copy based upon destination alignment.
507c478bd9Sstevel@tonic-gate	! This is either by word, halfword, or byte.  As this occurs, we
517c478bd9Sstevel@tonic-gate	! check for a zero-byte.  If one is found, we branch to a method
52*55fea89dSDan Cross	! which checks for the exact location of a zero-byte within a
537c478bd9Sstevel@tonic-gate	! larger word/half-word quantity.
547c478bd9Sstevel@tonic-gate
557c478bd9Sstevel@tonic-gate	ENTRY(strlcpy)
567c478bd9Sstevel@tonic-gate
577c478bd9Sstevel@tonic-gate	.align 32
587c478bd9Sstevel@tonic-gate	save	%sp, -SA(WINDOWSIZE), %sp
597c478bd9Sstevel@tonic-gate	subcc	%g0, %i2, %g4		! n = -n or n == 0 ?
607c478bd9Sstevel@tonic-gate	bz,pn	%icc, .getstrlen	! if 0 do nothing but strlen(src)
617c478bd9Sstevel@tonic-gate	add	%i1, %i2, %i3		! i3 = src + n
627c478bd9Sstevel@tonic-gate	andcc	%i1, 3, %i4		! word aligned?
637c478bd9Sstevel@tonic-gate	bz,pn	%icc, .wordaligned
647c478bd9Sstevel@tonic-gate	add	%i0, %i2, %i2		! n = dst + n
657c478bd9Sstevel@tonic-gate	sub	%i4, 4, %i4		! bytes until src aligned
667c478bd9Sstevel@tonic-gate
677c478bd9Sstevel@tonic-gate.alignsrc:
687c478bd9Sstevel@tonic-gate	ldub	[%i3 + %g4], %l1	! l1 = src[]
697c478bd9Sstevel@tonic-gate	andcc	%l1, 0xff, %g0		! null byte reached?
707c478bd9Sstevel@tonic-gate	stub	%l1, [%i2 + %g4]	! dst[] = src[]
717c478bd9Sstevel@tonic-gate	bz,a	%icc, .done
727c478bd9Sstevel@tonic-gate	add	%i2, %g4, %i2		! get single dest ptr for strlen
737c478bd9Sstevel@tonic-gate	addcc	%g4, 1, %g4		! src++ dest++ n--
747c478bd9Sstevel@tonic-gate	bz,pn	%icc, .forcenullunalign	! n == 0, append null byte
757c478bd9Sstevel@tonic-gate	addcc	%i4, 1, %i4		! incr, check align
767c478bd9Sstevel@tonic-gate	bnz,a 	%icc, .alignsrc
777c478bd9Sstevel@tonic-gate	nop
787c478bd9Sstevel@tonic-gate
797c478bd9Sstevel@tonic-gate.wordaligned:
807c478bd9Sstevel@tonic-gate	sethi	%hi(0x01010101), %i4
817c478bd9Sstevel@tonic-gate	add	%i2, %g4, %l0		! l0 = dest
827c478bd9Sstevel@tonic-gate	or	%i4, %lo(0x01010101), %i4
837c478bd9Sstevel@tonic-gate	sub	%i2, 4, %i2		! pre-incr for in cpy loop
847c478bd9Sstevel@tonic-gate	andcc	%l0, 3, %g1		! word aligned?
857c478bd9Sstevel@tonic-gate	bnz	%icc, .dstnotaligned
867c478bd9Sstevel@tonic-gate	sll	%i4, 7, %i5		! Mycroft part deux
877c478bd9Sstevel@tonic-gate
887c478bd9Sstevel@tonic-gate.storeword:
897c478bd9Sstevel@tonic-gate	ld	[%i3 + %g4], %l1	! l1 = src[]
907c478bd9Sstevel@tonic-gate	addcc	%g4, 4, %g4		! n += 4, src += 4, dst +=4
917c478bd9Sstevel@tonic-gate	bcs,pn	%icc, .lastword
927c478bd9Sstevel@tonic-gate	andn	%i5, %l1, %g1		! ~word & 0x80808080
937c478bd9Sstevel@tonic-gate	sub	%l1, %i4, %l0		! word - 0x01010101
947c478bd9Sstevel@tonic-gate	andcc	%l0, %g1, %g0		! doit
957c478bd9Sstevel@tonic-gate	bz,a,pt	%icc, .storeword	! if expr == 0, no zero byte
967c478bd9Sstevel@tonic-gate	st	%l1, [%i2 + %g4]	! dst[] = src[]
977c478bd9Sstevel@tonic-gate
987c478bd9Sstevel@tonic-gate.zerobyte:
997c478bd9Sstevel@tonic-gate	add	%i2, %g4, %i2		! ptr to dest
1007c478bd9Sstevel@tonic-gate	srl	%l1, 24, %g1		! 1st byte
1017c478bd9Sstevel@tonic-gate	andcc	%g1, 0xff, %g0		! test for end
1027c478bd9Sstevel@tonic-gate	bz,pn	%icc, .done
1037c478bd9Sstevel@tonic-gate	stb	%g1, [%i2]		! store byte
1047c478bd9Sstevel@tonic-gate	add	%i2, 1, %i2		! dst ++
1057c478bd9Sstevel@tonic-gate	srl	%l1, 16, %g1		! 2nd byte
1067c478bd9Sstevel@tonic-gate	andcc	%g1, 0xff, %g0		! zero byte ?
1077c478bd9Sstevel@tonic-gate	bz,pn	%icc, .done
1087c478bd9Sstevel@tonic-gate	stb	%g1, [%i2]		! store byte
1097c478bd9Sstevel@tonic-gate	add	%i2, 1, %i2		! dst ++
1107c478bd9Sstevel@tonic-gate	srl	%l1, 8, %g1		! 3rd byte
1117c478bd9Sstevel@tonic-gate	andcc	%g1, 0xff, %g0		! zero byte ?
1127c478bd9Sstevel@tonic-gate	bz,pn	%icc, .done
1137c478bd9Sstevel@tonic-gate	stb	%g1, [%i2]		! store byte
1147c478bd9Sstevel@tonic-gate	stb	%l1, [%i2 + 1]		! store last byte
1157c478bd9Sstevel@tonic-gate	add	%i2, 1, %i2		! dst ++
1167c478bd9Sstevel@tonic-gate
1177c478bd9Sstevel@tonic-gate.done:
1187c478bd9Sstevel@tonic-gate	sub	%i2, %i0, %i0		! len = dst - orig dst
1197c478bd9Sstevel@tonic-gate	ret
1207c478bd9Sstevel@tonic-gate	restore	%i0, %g0, %o0
1217c478bd9Sstevel@tonic-gate
1227c478bd9Sstevel@tonic-gate.lastword:
1237c478bd9Sstevel@tonic-gate	add	%i2, %g4, %i2
1247c478bd9Sstevel@tonic-gate	sub	%g4, 4, %g4		! undo pre-incr
1257c478bd9Sstevel@tonic-gate	add	%i3, %g4, %i3
1267c478bd9Sstevel@tonic-gate
1277c478bd9Sstevel@tonic-gate	srl	%l1, 24, %g1		! 1st byte
1287c478bd9Sstevel@tonic-gate	andcc	%g1, 0xff, %g0		! zero byte?
1297c478bd9Sstevel@tonic-gate	bz,pn	%icc, .done
1307c478bd9Sstevel@tonic-gate	stb	%g1, [%i2]		! store byte
1317c478bd9Sstevel@tonic-gate	inccc	%g4			! n--
1327c478bd9Sstevel@tonic-gate	bz	.forcenull
1337c478bd9Sstevel@tonic-gate	srl	%l1, 16, %g1		! 2nd byte
1347c478bd9Sstevel@tonic-gate	add	%i2, 1, %i2		! dst++
1357c478bd9Sstevel@tonic-gate	andcc	%g1, 0xff, %g0		! zero?
1367c478bd9Sstevel@tonic-gate	bz,pn	%icc, .done
1377c478bd9Sstevel@tonic-gate	stb	%g1, [%i2]		! store
1387c478bd9Sstevel@tonic-gate	inccc	%g4
1397c478bd9Sstevel@tonic-gate	bz	.forcenull
1407c478bd9Sstevel@tonic-gate	srl	%l1, 8, %g1		! 3rd byte
1417c478bd9Sstevel@tonic-gate	add	%i2, 1, %i2		! dst++
1427c478bd9Sstevel@tonic-gate	andcc	%g1, 0xff, %g0		! zero?
1437c478bd9Sstevel@tonic-gate	bz,pn	%icc, .done
1447c478bd9Sstevel@tonic-gate	stb	%g1, [%i2]		! store
1457c478bd9Sstevel@tonic-gate	inccc	%g4			! n--
1467c478bd9Sstevel@tonic-gate	bz	.forcenull
1477c478bd9Sstevel@tonic-gate	andcc	%l1, 0xff, %g0		! zero?
1487c478bd9Sstevel@tonic-gate	add	%i2, 1, %i2		! dst++
1497c478bd9Sstevel@tonic-gate	bz,pn	%ncc, .done
1507c478bd9Sstevel@tonic-gate	stb	%l1, [%i2]
1517c478bd9Sstevel@tonic-gate
1527c478bd9Sstevel@tonic-gate.forcenull:
1537c478bd9Sstevel@tonic-gate	stb	%g0, [%i2]
1547c478bd9Sstevel@tonic-gate
1557c478bd9Sstevel@tonic-gate.searchword:
1567c478bd9Sstevel@tonic-gate	ld	[%i3], %l1
1577c478bd9Sstevel@tonic-gate.searchword2:
1587c478bd9Sstevel@tonic-gate	andn	%i5, %l1, %g1		! word & 0x80808080
1597c478bd9Sstevel@tonic-gate	sub	%l1, %i4, %l0		! word - 0x01010101
1607c478bd9Sstevel@tonic-gate	andcc	%l0, %g1, %g0		! do it
1617c478bd9Sstevel@tonic-gate	bz,a,pt	%icc, .searchword
1627c478bd9Sstevel@tonic-gate	add	%i3, 4, %i3		! src += 4
1637c478bd9Sstevel@tonic-gate
1647c478bd9Sstevel@tonic-gate	mov	0xff, %i5
1657c478bd9Sstevel@tonic-gate	sll	%i5, 24, %i5		! mask 1st byte = 0xff000000
1667c478bd9Sstevel@tonic-gate.searchbyte:
1677c478bd9Sstevel@tonic-gate	andcc	%l1, %i5, %g0		! cur byte 0?
1687c478bd9Sstevel@tonic-gate	srl	%i5, 8, %i5		! mask next byte
1697c478bd9Sstevel@tonic-gate	bnz,a	%icc, .searchbyte	! cur !=0 continue
1707c478bd9Sstevel@tonic-gate	add	%i3, 1, %i3
1717c478bd9Sstevel@tonic-gate
1727c478bd9Sstevel@tonic-gate.endfound:
1737c478bd9Sstevel@tonic-gate	sub	%i3, %i1, %i0		! len = src - orig src
1747c478bd9Sstevel@tonic-gate	ret
1757c478bd9Sstevel@tonic-gate	restore	%i0, %g0, %o0
1767c478bd9Sstevel@tonic-gate	nop
1777c478bd9Sstevel@tonic-gate
1787c478bd9Sstevel@tonic-gate.dstnotaligned:
1797c478bd9Sstevel@tonic-gate	cmp	%g1, 2			! halfword aligned?
1807c478bd9Sstevel@tonic-gate	be	.storehalfword2
1817c478bd9Sstevel@tonic-gate	.empty
1827c478bd9Sstevel@tonic-gate.storebyte:
1837c478bd9Sstevel@tonic-gate	ld	[%i3 + %g4], %l1	! load src word
1847c478bd9Sstevel@tonic-gate	addcc	%g4, 4, %g4		! src +=4 dst +=4
1857c478bd9Sstevel@tonic-gate	bcs,pn	%icc, .lastword
1867c478bd9Sstevel@tonic-gate	andn	%i5, %l1, %g1		! ~x & 0x80808080
1877c478bd9Sstevel@tonic-gate	sub	%l1, %i4, %l0		! x - 0x01010101
1887c478bd9Sstevel@tonic-gate	andcc	%l0, %g1, %g0		! get your Mycroft on
1897c478bd9Sstevel@tonic-gate	bnz,pn	%icc, .zerobyte		! non-zero, we have zero byte
1907c478bd9Sstevel@tonic-gate	add	%i2, %g4, %l0		! dst in ptr form
1917c478bd9Sstevel@tonic-gate	srl	%l1, 24, %g1		! get 1st byte, then be hw aligned
1927c478bd9Sstevel@tonic-gate	stb	%g1, [%l0]
1937c478bd9Sstevel@tonic-gate	srl	%l1, 8, %g1		! 2nd & 3rd bytes
1947c478bd9Sstevel@tonic-gate	sth	%g1, [%l0 + 1]
1957c478bd9Sstevel@tonic-gate	ba	.storebyte
1967c478bd9Sstevel@tonic-gate	stb	%l1, [%l0 + 3]		! store 4th byte
1977c478bd9Sstevel@tonic-gate
1987c478bd9Sstevel@tonic-gate.storehalfword:
1997c478bd9Sstevel@tonic-gate	ld	[%i3 + %g4], %l1	! src word
2007c478bd9Sstevel@tonic-gate.storehalfword2:
2017c478bd9Sstevel@tonic-gate	addcc	%g4, 4, %g4		! src += 4 dst += 4
2027c478bd9Sstevel@tonic-gate	bcs,pn	%icc, .lastword
2037c478bd9Sstevel@tonic-gate	andn	%i5, %l1, %g1		! ~x & 0x80808080
2047c478bd9Sstevel@tonic-gate	sub	%l1, %i4, %l0		! x - 0x01010101
2057c478bd9Sstevel@tonic-gate	andcc	%l0, %g1, %g0		! Mycroft again...
2067c478bd9Sstevel@tonic-gate	bnz,pn	%icc, .zerobyte		! non-zer, we have zero byte
2077c478bd9Sstevel@tonic-gate	add	%i2, %g4, %l0		! dst in ptr form
2087c478bd9Sstevel@tonic-gate	srl	%l1, 16, %g1		! first two bytes
2097c478bd9Sstevel@tonic-gate	sth	%g1, [%l0]
2107c478bd9Sstevel@tonic-gate	ba	.storehalfword
2117c478bd9Sstevel@tonic-gate	sth	%l1, [%l0 + 2]
2127c478bd9Sstevel@tonic-gate
2137c478bd9Sstevel@tonic-gate.forcenullunalign:
2147c478bd9Sstevel@tonic-gate	add	%i2, %g4, %i2		! single dst ptr
2157c478bd9Sstevel@tonic-gate	stb	%g0, [%i2 - 1]		! store terminating null byte
2167c478bd9Sstevel@tonic-gate
2177c478bd9Sstevel@tonic-gate.getstrlen:
2187c478bd9Sstevel@tonic-gate	sethi	%hi(0x01010101), %i4	! Mycroft...
2197c478bd9Sstevel@tonic-gate	or	%i4, %lo(0x01010101), %i4
2207c478bd9Sstevel@tonic-gate	sll	%i4, 7, %i5
2217c478bd9Sstevel@tonic-gate
2227c478bd9Sstevel@tonic-gate.getstrlenloop:
2237c478bd9Sstevel@tonic-gate	andcc	%i3, 3, %g0		! word aligned?
2247c478bd9Sstevel@tonic-gate	bz,a,pn	%icc, .searchword2	! search word at a time
2257c478bd9Sstevel@tonic-gate	ld	[%i3], %l1		! src word
2267c478bd9Sstevel@tonic-gate	ldub	[%i3], %l1		! src byte
2277c478bd9Sstevel@tonic-gate	andcc	%l1, 0xff, %g0		! end of src?
2287c478bd9Sstevel@tonic-gate	bnz,a	%icc, .getstrlenloop
2297c478bd9Sstevel@tonic-gate	add	%i3, 1, %i3		! src ++
2307c478bd9Sstevel@tonic-gate	sub	%i3, %i1, %i0		! len = src - orig src
2317c478bd9Sstevel@tonic-gate	ret
2327c478bd9Sstevel@tonic-gate	restore	%i0, %g0, %o0
2337c478bd9Sstevel@tonic-gate	SET_SIZE(strlcpy)
234