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