xref: /illumos-gate/usr/src/lib/libc/sparc/gen/strlcpy.S (revision 55fea89d)
1*5d9d9091SRichard Lowe/*
2*5d9d9091SRichard Lowe * CDDL HEADER START
3*5d9d9091SRichard Lowe *
4*5d9d9091SRichard Lowe * The contents of this file are subject to the terms of the
5*5d9d9091SRichard Lowe * Common Development and Distribution License (the "License").
6*5d9d9091SRichard Lowe * You may not use this file except in compliance with the License.
7*5d9d9091SRichard Lowe *
8*5d9d9091SRichard Lowe * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*5d9d9091SRichard Lowe * or http://www.opensolaris.org/os/licensing.
10*5d9d9091SRichard Lowe * See the License for the specific language governing permissions
11*5d9d9091SRichard Lowe * and limitations under the License.
12*5d9d9091SRichard Lowe *
13*5d9d9091SRichard Lowe * When distributing Covered Code, include this CDDL HEADER in each
14*5d9d9091SRichard Lowe * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*5d9d9091SRichard Lowe * If applicable, add the following below this CDDL HEADER, with the
16*5d9d9091SRichard Lowe * fields enclosed by brackets "[]" replaced with your own identifying
17*5d9d9091SRichard Lowe * information: Portions Copyright [yyyy] [name of copyright owner]
18*5d9d9091SRichard Lowe *
19*5d9d9091SRichard Lowe * CDDL HEADER END
20*5d9d9091SRichard Lowe */
21*5d9d9091SRichard Lowe
22*5d9d9091SRichard Lowe/*
23*5d9d9091SRichard Lowe * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
24*5d9d9091SRichard Lowe * Use is subject to license terms.
25*5d9d9091SRichard Lowe */
26*5d9d9091SRichard Lowe
27*5d9d9091SRichard Lowe	.file	"strlcpy.s"
28*5d9d9091SRichard Lowe/*
29*5d9d9091SRichard Lowe * The strlcpy() function copies at most dstsize-1 characters
30*5d9d9091SRichard Lowe * (dstsize being the size of the string buffer dst) from src
31*5d9d9091SRichard Lowe * to dst, truncating src if necessary. The result is always
32*5d9d9091SRichard Lowe * null-terminated.  The function returns strlen(src). Buffer
33*5d9d9091SRichard Lowe * overflow can be checked as follows:
34*5d9d9091SRichard Lowe *
35*5d9d9091SRichard Lowe *   if (strlcpy(dst, src, dstsize) >= dstsize)
36*5d9d9091SRichard Lowe *           return -1;
37*5d9d9091SRichard Lowe */
38*5d9d9091SRichard Lowe
39*5d9d9091SRichard Lowe#include <sys/asm_linkage.h>
40*5d9d9091SRichard Lowe
41*5d9d9091SRichard Lowe	! strlcpy implementation is similar to that of strcpy, except
42*5d9d9091SRichard Lowe	! in this case, the maximum size of the detination must be
43*5d9d9091SRichard Lowe	! tracked since it bounds our maximum copy size.  However,
44*5d9d9091SRichard Lowe	! we must still continue to check for zero since the routine
45*5d9d9091SRichard Lowe	! is expected to null-terminate any string that is within
46*5d9d9091SRichard Lowe	! the dest size bound.
47*5d9d9091SRichard Lowe	!
48*5d9d9091SRichard Lowe	! this method starts by checking for and arranging source alignment.
49*5d9d9091SRichard Lowe	! Once this has occurred, we copy based upon destination alignment.
50*5d9d9091SRichard Lowe	! This is either by word, halfword, or byte.  As this occurs, we
51*5d9d9091SRichard Lowe	! check for a zero-byte.  If one is found, we branch to a method
52*5d9d9091SRichard Lowe	! which checks for the exact location of a zero-byte within a
53*5d9d9091SRichard Lowe	! larger word/half-word quantity.
54*5d9d9091SRichard Lowe
55*5d9d9091SRichard Lowe	ENTRY(strlcpy)
56*5d9d9091SRichard Lowe
57*5d9d9091SRichard Lowe	.align 32
58*5d9d9091SRichard Lowe	save	%sp, -SA(WINDOWSIZE), %sp
59*5d9d9091SRichard Lowe	subcc	%g0, %i2, %g4		! n = -n or n == 0 ?
60*5d9d9091SRichard Lowe	bz,pn	%icc, .getstrlen	! if 0 do nothing but strlen(src)
61*5d9d9091SRichard Lowe	add	%i1, %i2, %i3		! i3 = src + n
62*5d9d9091SRichard Lowe	andcc	%i1, 3, %i4		! word aligned?
63*5d9d9091SRichard Lowe	bz,pn	%icc, .wordaligned
64*5d9d9091SRichard Lowe	add	%i0, %i2, %i2		! n = dst + n
65*5d9d9091SRichard Lowe	sub	%i4, 4, %i4		! bytes until src aligned
66*5d9d9091SRichard Lowe
67*5d9d9091SRichard Lowe.alignsrc:
68*5d9d9091SRichard Lowe	ldub	[%i3 + %g4], %l1	! l1 = src[]
69*5d9d9091SRichard Lowe	andcc	%l1, 0xff, %g0		! null byte reached?
70*5d9d9091SRichard Lowe	stub	%l1, [%i2 + %g4]	! dst[] = src[]
71*5d9d9091SRichard Lowe	bz,a	%icc, .done
72*5d9d9091SRichard Lowe	add	%i2, %g4, %i2		! get single dest ptr for strlen
73*5d9d9091SRichard Lowe	addcc	%g4, 1, %g4		! src++ dest++ n--
74*5d9d9091SRichard Lowe	bz,pn	%icc, .forcenullunalign	! n == 0, append null byte
75*5d9d9091SRichard Lowe	addcc	%i4, 1, %i4		! incr, check align
76*5d9d9091SRichard Lowe	bnz,a 	%icc, .alignsrc
77*5d9d9091SRichard Lowe	nop
78*5d9d9091SRichard Lowe
79*5d9d9091SRichard Lowe.wordaligned:
80*5d9d9091SRichard Lowe	sethi	%hi(0x01010101), %i4
81*5d9d9091SRichard Lowe	add	%i2, %g4, %l0		! l0 = dest
82*5d9d9091SRichard Lowe	or	%i4, %lo(0x01010101), %i4
83*5d9d9091SRichard Lowe	sub	%i2, 4, %i2		! pre-incr for in cpy loop
84*5d9d9091SRichard Lowe	andcc	%l0, 3, %g1		! word aligned?
85*5d9d9091SRichard Lowe	bnz	%icc, .dstnotaligned
86*5d9d9091SRichard Lowe	sll	%i4, 7, %i5		! Mycroft part deux
87*5d9d9091SRichard Lowe
88*5d9d9091SRichard Lowe.storeword:
89*5d9d9091SRichard Lowe	ld	[%i3 + %g4], %l1	! l1 = src[]
90*5d9d9091SRichard Lowe	addcc	%g4, 4, %g4		! n += 4, src += 4, dst +=4
91*5d9d9091SRichard Lowe	bcs,pn	%icc, .lastword
92*5d9d9091SRichard Lowe	andn	%i5, %l1, %g1		! ~word & 0x80808080
93*5d9d9091SRichard Lowe	sub	%l1, %i4, %l0		! word - 0x01010101
94*5d9d9091SRichard Lowe	andcc	%l0, %g1, %g0		! doit
95*5d9d9091SRichard Lowe	bz,a,pt	%icc, .storeword	! if expr == 0, no zero byte
96*5d9d9091SRichard Lowe	st	%l1, [%i2 + %g4]	! dst[] = src[]
97*5d9d9091SRichard Lowe
98*5d9d9091SRichard Lowe.zerobyte:
99*5d9d9091SRichard Lowe	add	%i2, %g4, %i2		! ptr to dest
100*5d9d9091SRichard Lowe	srl	%l1, 24, %g1		! 1st byte
101*5d9d9091SRichard Lowe	andcc	%g1, 0xff, %g0		! test for end
102*5d9d9091SRichard Lowe	bz,pn	%icc, .done
103*5d9d9091SRichard Lowe	stb	%g1, [%i2]		! store byte
104*5d9d9091SRichard Lowe	add	%i2, 1, %i2		! dst ++
105*5d9d9091SRichard Lowe	srl	%l1, 16, %g1		! 2nd byte
106*5d9d9091SRichard Lowe	andcc	%g1, 0xff, %g0		! zero byte ?
107*5d9d9091SRichard Lowe	bz,pn	%icc, .done
108*5d9d9091SRichard Lowe	stb	%g1, [%i2]		! store byte
109*5d9d9091SRichard Lowe	add	%i2, 1, %i2		! dst ++
110*5d9d9091SRichard Lowe	srl	%l1, 8, %g1		! 3rd byte
111*5d9d9091SRichard Lowe	andcc	%g1, 0xff, %g0		! zero byte ?
112*5d9d9091SRichard Lowe	bz,pn	%icc, .done
113*5d9d9091SRichard Lowe	stb	%g1, [%i2]		! store byte
114*5d9d9091SRichard Lowe	stb	%l1, [%i2 + 1]		! store last byte
115*5d9d9091SRichard Lowe	add	%i2, 1, %i2		! dst ++
116*5d9d9091SRichard Lowe
117*5d9d9091SRichard Lowe.done:
118*5d9d9091SRichard Lowe	sub	%i2, %i0, %i0		! len = dst - orig dst
119*5d9d9091SRichard Lowe	ret
120*5d9d9091SRichard Lowe	restore	%i0, %g0, %o0
121*5d9d9091SRichard Lowe
122*5d9d9091SRichard Lowe.lastword:
123*5d9d9091SRichard Lowe	add	%i2, %g4, %i2
124*5d9d9091SRichard Lowe	sub	%g4, 4, %g4		! undo pre-incr
125*5d9d9091SRichard Lowe	add	%i3, %g4, %i3
126*5d9d9091SRichard Lowe
127*5d9d9091SRichard Lowe	srl	%l1, 24, %g1		! 1st byte
128*5d9d9091SRichard Lowe	andcc	%g1, 0xff, %g0		! zero byte?
129*5d9d9091SRichard Lowe	bz,pn	%icc, .done
130*5d9d9091SRichard Lowe	stb	%g1, [%i2]		! store byte
131*5d9d9091SRichard Lowe	inccc	%g4			! n--
132*5d9d9091SRichard Lowe	bz	.forcenull
133*5d9d9091SRichard Lowe	srl	%l1, 16, %g1		! 2nd byte
134*5d9d9091SRichard Lowe	add	%i2, 1, %i2		! dst++
135*5d9d9091SRichard Lowe	andcc	%g1, 0xff, %g0		! zero?
136*5d9d9091SRichard Lowe	bz,pn	%icc, .done
137*5d9d9091SRichard Lowe	stb	%g1, [%i2]		! store
138*5d9d9091SRichard Lowe	inccc	%g4
139*5d9d9091SRichard Lowe	bz	.forcenull
140*5d9d9091SRichard Lowe	srl	%l1, 8, %g1		! 3rd byte
141*5d9d9091SRichard Lowe	add	%i2, 1, %i2		! dst++
142*5d9d9091SRichard Lowe	andcc	%g1, 0xff, %g0		! zero?
143*5d9d9091SRichard Lowe	bz,pn	%icc, .done
144*5d9d9091SRichard Lowe	stb	%g1, [%i2]		! store
145*5d9d9091SRichard Lowe	inccc	%g4			! n--
146*5d9d9091SRichard Lowe	bz	.forcenull
147*5d9d9091SRichard Lowe	andcc	%l1, 0xff, %g0		! zero?
148*5d9d9091SRichard Lowe	add	%i2, 1, %i2		! dst++
149*5d9d9091SRichard Lowe	bz,pn	%ncc, .done
150*5d9d9091SRichard Lowe	stb	%l1, [%i2]
151*5d9d9091SRichard Lowe
152*5d9d9091SRichard Lowe.forcenull:
153*5d9d9091SRichard Lowe	stb	%g0, [%i2]
154*5d9d9091SRichard Lowe
155*5d9d9091SRichard Lowe.searchword:
156*5d9d9091SRichard Lowe	ld	[%i3], %l1
157*5d9d9091SRichard Lowe.searchword2:
158*5d9d9091SRichard Lowe	andn	%i5, %l1, %g1		! word & 0x80808080
159*5d9d9091SRichard Lowe	sub	%l1, %i4, %l0		! word - 0x01010101
160*5d9d9091SRichard Lowe	andcc	%l0, %g1, %g0		! do it
161*5d9d9091SRichard Lowe	bz,a,pt	%icc, .searchword
162*5d9d9091SRichard Lowe	add	%i3, 4, %i3		! src += 4
163*5d9d9091SRichard Lowe
164*5d9d9091SRichard Lowe	mov	0xff, %i5
165*5d9d9091SRichard Lowe	sll	%i5, 24, %i5		! mask 1st byte = 0xff000000
166*5d9d9091SRichard Lowe.searchbyte:
167*5d9d9091SRichard Lowe	andcc	%l1, %i5, %g0		! cur byte 0?
168*5d9d9091SRichard Lowe	srl	%i5, 8, %i5		! mask next byte
169*5d9d9091SRichard Lowe	bnz,a	%icc, .searchbyte	! cur !=0 continue
170*5d9d9091SRichard Lowe	add	%i3, 1, %i3
171*5d9d9091SRichard Lowe
172*5d9d9091SRichard Lowe.endfound:
173*5d9d9091SRichard Lowe	sub	%i3, %i1, %i0		! len = src - orig src
174*5d9d9091SRichard Lowe	ret
175*5d9d9091SRichard Lowe	restore	%i0, %g0, %o0
176*5d9d9091SRichard Lowe	nop
177*5d9d9091SRichard Lowe
178*5d9d9091SRichard Lowe.dstnotaligned:
179*5d9d9091SRichard Lowe	cmp	%g1, 2			! halfword aligned?
180*5d9d9091SRichard Lowe	be	.storehalfword2
181*5d9d9091SRichard Lowe	.empty
182*5d9d9091SRichard Lowe.storebyte:
183*5d9d9091SRichard Lowe	ld	[%i3 + %g4], %l1	! load src word
184*5d9d9091SRichard Lowe	addcc	%g4, 4, %g4		! src +=4 dst +=4
185*5d9d9091SRichard Lowe	bcs,pn	%icc, .lastword
186*5d9d9091SRichard Lowe	andn	%i5, %l1, %g1		! ~x & 0x80808080
187*5d9d9091SRichard Lowe	sub	%l1, %i4, %l0		! x - 0x01010101
188*5d9d9091SRichard Lowe	andcc	%l0, %g1, %g0		! get your Mycroft on
189*5d9d9091SRichard Lowe	bnz,pn	%icc, .zerobyte		! non-zero, we have zero byte
190*5d9d9091SRichard Lowe	add	%i2, %g4, %l0		! dst in ptr form
191*5d9d9091SRichard Lowe	srl	%l1, 24, %g1		! get 1st byte, then be hw aligned
192*5d9d9091SRichard Lowe	stb	%g1, [%l0]
193*5d9d9091SRichard Lowe	srl	%l1, 8, %g1		! 2nd & 3rd bytes
194*5d9d9091SRichard Lowe	sth	%g1, [%l0 + 1]
195*5d9d9091SRichard Lowe	ba	.storebyte
196*5d9d9091SRichard Lowe	stb	%l1, [%l0 + 3]		! store 4th byte
197*5d9d9091SRichard Lowe
198*5d9d9091SRichard Lowe.storehalfword:
199*5d9d9091SRichard Lowe	ld	[%i3 + %g4], %l1	! src word
200*5d9d9091SRichard Lowe.storehalfword2:
201*5d9d9091SRichard Lowe	addcc	%g4, 4, %g4		! src += 4 dst += 4
202*5d9d9091SRichard Lowe	bcs,pn	%icc, .lastword
203*5d9d9091SRichard Lowe	andn	%i5, %l1, %g1		! ~x & 0x80808080
204*5d9d9091SRichard Lowe	sub	%l1, %i4, %l0		! x - 0x01010101
205*5d9d9091SRichard Lowe	andcc	%l0, %g1, %g0		! Mycroft again...
206*5d9d9091SRichard Lowe	bnz,pn	%icc, .zerobyte		! non-zer, we have zero byte
207*5d9d9091SRichard Lowe	add	%i2, %g4, %l0		! dst in ptr form
208*5d9d9091SRichard Lowe	srl	%l1, 16, %g1		! first two bytes
209*5d9d9091SRichard Lowe	sth	%g1, [%l0]
210*5d9d9091SRichard Lowe	ba	.storehalfword
211*5d9d9091SRichard Lowe	sth	%l1, [%l0 + 2]
212*5d9d9091SRichard Lowe
213*5d9d9091SRichard Lowe.forcenullunalign:
214*5d9d9091SRichard Lowe	add	%i2, %g4, %i2		! single dst ptr
215*5d9d9091SRichard Lowe	stb	%g0, [%i2 - 1]		! store terminating null byte
216*5d9d9091SRichard Lowe
217*5d9d9091SRichard Lowe.getstrlen:
218*5d9d9091SRichard Lowe	sethi	%hi(0x01010101), %i4	! Mycroft...
219*5d9d9091SRichard Lowe	or	%i4, %lo(0x01010101), %i4
220*5d9d9091SRichard Lowe	sll	%i4, 7, %i5
221*5d9d9091SRichard Lowe
222*5d9d9091SRichard Lowe.getstrlenloop:
223*5d9d9091SRichard Lowe	andcc	%i3, 3, %g0		! word aligned?
224*5d9d9091SRichard Lowe	bz,a,pn	%icc, .searchword2	! search word at a time
225*5d9d9091SRichard Lowe	ld	[%i3], %l1		! src word
226*5d9d9091SRichard Lowe	ldub	[%i3], %l1		! src byte
227*5d9d9091SRichard Lowe	andcc	%l1, 0xff, %g0		! end of src?
228*5d9d9091SRichard Lowe	bnz,a	%icc, .getstrlenloop
229*5d9d9091SRichard Lowe	add	%i3, 1, %i3		! src ++
230*5d9d9091SRichard Lowe	sub	%i3, %i1, %i0		! len = src - orig src
231*5d9d9091SRichard Lowe	ret
232*5d9d9091SRichard Lowe	restore	%i0, %g0, %o0
233*5d9d9091SRichard Lowe	SET_SIZE(strlcpy)
234