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