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