xref: /illumos-gate/usr/src/lib/libc/capabilities/sun4v/common/memset.S (revision ddb365bfc9e868ad24ccdcb0dc91af18b10df082)
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 (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
24 */
25
26	.file	"memset.s"
27
28/*
29 * char *memset(sp, c, n)
30 *
31 * Set an array of n chars starting at sp to the character c.
32 * Return sp.
33 *
34 * Fast assembler language version of the following C-program for memset
35 * which represents the `standard' for the C-library.
36 *
37 *	void *
38 *	memset(void *sp1, int c, size_t n)
39 *	{
40 *	    if (n != 0) {
41 *		char *sp = sp1;
42 *		do {
43 *		    *sp++ = (char)c;
44 *		} while (--n != 0);
45 *	    }
46 *	    return (sp1);
47 *	}
48 *
49 * Flow :
50 *
51 *	For small 6 or fewer bytes stores, bytes will be stored.
52 *
53 *	For less than 32 bytes stores, align the address on 4 byte boundary.
54 *	Then store as many 4-byte chunks, followed by trailing bytes.
55 *
56 *	For sizes greater than 32 bytes, align the address on 8 byte boundary.
57 *	if (count > 64) {
58 *		store as many 8-bytes chunks to block align the address
59 *		store using ASI_BLK_INIT_ST_QUAD_LDD_P
60 *	}
61 *	Store as many 8-byte chunks, followed by trialing bytes.
62 *
63 */
64
65#include <sys/asm_linkage.h>
66#include <sys/niagaraasi.h>
67#include <sys/asi.h>
68
69	ANSI_PRAGMA_WEAK(memset,function)
70
71	.section        ".text"
72	.align 32
73
74	ENTRY(memset)
75
76	mov	%o0, %o5		! copy sp1 before using it
77	cmp	%o2, 7			! if small counts, just write bytes
78	blu,pn	%ncc, .wrchar
79	and	%o1, 0xff, %o1		! o1 is (char)c
80
81	sll	%o1, 8, %o3
82	or	%o1, %o3, %o1		! now o1 has 2 bytes of c
83	sll	%o1, 16, %o3
84
85	cmp	%o2, 0x20
86	blu,pn	%ncc, .wdalign
87	or	%o1, %o3, %o1		! now o1 has 4 bytes of c
88
89	sllx	%o1, 32, %o3
90	or	%o1, %o3, %o1		! now o1 has 8 bytes of c
91
92.dbalign:
93	andcc	%o5, 7, %o3		! is sp1 aligned on a 8 byte bound
94	bz,pt	%ncc, .blkalign		! already double aligned
95	sub	%o3, 8, %o3		! -(bytes till double aligned)
96	add	%o2, %o3, %o2		! update o2 with new count
97
98	! Set -(%o3) bytes till sp1 double aligned
991:	stb	%o1, [%o5]		! there is at least 1 byte to set
100	inccc	%o3			! byte clearing loop
101	bl,pt	%ncc, 1b
102	inc	%o5
103
104	! Now sp1 is double aligned (sp1 is found in %o5)
105.blkalign:
106	mov	ASI_BLK_INIT_ST_QUAD_LDD_P, %asi
107
108	cmp	%o2, 0x40		! check if there are 64 bytes to set
109	blu,pn	%ncc, 5f
110	mov	%o2, %o3
111
112	andcc	%o5, 63, %o3		! is sp1 block aligned?
113	bz,pt	%ncc, .blkwr		! now block aligned
114	sub	%o3, 64, %o3		! o3 is -(bytes till block aligned)
115	add	%o2, %o3, %o2		! o2 is the remainder
116
117	! Store -(%o3) bytes till dst is block (64 byte) aligned.
118	! Use double word stores.
119	! Recall that dst is already double word aligned
1201:
121	stx	%o1, [%o5]
122	addcc	%o3, 8, %o3
123	bl,pt	%ncc, 1b
124	add	%o5, 8, %o5
125
126	! Now sp1 is block aligned
127.blkwr:
128	and	%o2, 63, %o3		! calc bytes left after blk store.
129	andn	%o2, 63, %o4		! calc size of blocks in bytes
130
131	cmp	%o4, 0x100		! check if there are 256 bytes to set
132	blu,pn	%ncc, 3f
133	nop
1342:
135	stxa	%o1, [%o5+0x0]%asi
136	stxa	%o1, [%o5+0x40]%asi
137	stxa	%o1, [%o5+0x80]%asi
138	stxa	%o1, [%o5+0xc0]%asi
139
140	stxa	%o1, [%o5+0x8]%asi
141	stxa	%o1, [%o5+0x10]%asi
142	stxa	%o1, [%o5+0x18]%asi
143	stxa	%o1, [%o5+0x20]%asi
144	stxa	%o1, [%o5+0x28]%asi
145	stxa	%o1, [%o5+0x30]%asi
146	stxa	%o1, [%o5+0x38]%asi
147
148	stxa	%o1, [%o5+0x48]%asi
149	stxa	%o1, [%o5+0x50]%asi
150	stxa	%o1, [%o5+0x58]%asi
151	stxa	%o1, [%o5+0x60]%asi
152	stxa	%o1, [%o5+0x68]%asi
153	stxa	%o1, [%o5+0x70]%asi
154	stxa	%o1, [%o5+0x78]%asi
155
156	stxa	%o1, [%o5+0x88]%asi
157	stxa	%o1, [%o5+0x90]%asi
158	stxa	%o1, [%o5+0x98]%asi
159	stxa	%o1, [%o5+0xa0]%asi
160	stxa	%o1, [%o5+0xa8]%asi
161	stxa	%o1, [%o5+0xb0]%asi
162	stxa	%o1, [%o5+0xb8]%asi
163
164	stxa	%o1, [%o5+0xc8]%asi
165	stxa	%o1, [%o5+0xd0]%asi
166	stxa	%o1, [%o5+0xd8]%asi
167	stxa	%o1, [%o5+0xe0]%asi
168	stxa	%o1, [%o5+0xe8]%asi
169	stxa	%o1, [%o5+0xf0]%asi
170	stxa	%o1, [%o5+0xf8]%asi
171
172	sub	%o4, 0x100, %o4
173	cmp	%o4, 0x100
174	bgu,pt	%ncc, 2b
175	add	%o5, 0x100, %o5
176
1773:
178	cmp	%o4, 0x40		! check if 64 bytes to set
179	blu	%ncc, 5f
180	nop
1814:
182	stxa	%o1, [%o5+0x0]%asi
183	stxa	%o1, [%o5+0x8]%asi
184	stxa	%o1, [%o5+0x10]%asi
185	stxa	%o1, [%o5+0x18]%asi
186	stxa	%o1, [%o5+0x20]%asi
187	stxa	%o1, [%o5+0x28]%asi
188	stxa	%o1, [%o5+0x30]%asi
189	stxa	%o1, [%o5+0x38]%asi
190
191	subcc	%o4, 0x40, %o4
192	bgu,pt	%ncc, 4b
193	add	%o5, 0x40, %o5
194
1955:
196	! Set the remaining doubles
197	membar	#Sync
198	mov	ASI_PNF, %asi		! restore %asi to default
199					! ASI_PRIMARY_NOFAULT value
200	subcc	%o3, 8, %o3		! Can we store any doubles?
201	blu,pn	%ncc, .wrchar
202	and	%o2, 7, %o2		! calc bytes left after doubles
203
2046:
205	stx	%o1, [%o5]		! store the doubles
206	subcc	%o3, 8, %o3
207	bgeu,pt	%ncc, 6b
208	add	%o5, 8, %o5
209
210	ba	.wrchar
211	nop
212
213.wdalign:
214	andcc	%o5, 3, %o3		! is sp1 aligned on a word boundary
215	bz,pn	%ncc, .wrword
216	andn	%o2, 3, %o3		! create word sized count in %o3
217
218	dec	%o2			! decrement count
219	stb	%o1, [%o5]		! clear a byte
220	b	.wdalign
221	inc	%o5			! next byte
222
223.wrword:
224	st	%o1, [%o5]		! 4-byte writing loop
225	subcc	%o3, 4, %o3
226	bnz,pt	%ncc, .wrword
227	inc	4, %o5
228
229	and	%o2, 3, %o2		! leftover count, if any
230
231.wrchar:
232	! Set the remaining bytes, if any
233	cmp	%o2, 0
234	be	%ncc, .exit
235	nop
236
2377:
238	deccc	%o2
239	stb	%o1, [%o5]
240	bgu,pt	%ncc, 7b
241	inc	%o5
242
243.exit:
244	retl				! %o0 was preserved
245	nop
246
247	SET_SIZE(memset)
248