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