import less(1)
[unleashed/tickless.git] / usr / src / lib / libc / capabilities / sun4v / common / memset.s
blob1c23e6ed4b2994929dd41e4dfe42a30e29588eaf
1 /*
2 * CDDL HEADER START
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.
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.
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]
19 * CDDL HEADER END
23 * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
26 .file "memset.s"
29 * char *memset(sp, c, n)
31 * Set an array of n chars starting at sp to the character c.
32 * Return sp.
34 * Fast assembler language version of the following C-program for memset
35 * which represents the `standard' for the C-library.
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 * }
49 * Flow :
51 * For small 6 or fewer bytes stores, bytes will be stored.
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.
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.
65 #include <sys/asm_linkage.h>
66 #include <sys/niagaraasi.h>
67 #include <sys/asi.h>
69 ANSI_PRAGMA_WEAK(memset,function)
71 .section ".text"
72 .align 32
74 ENTRY(memset)
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
81 sll %o1, 8, %o3
82 or %o1, %o3, %o1 ! now o1 has 2 bytes of c
83 sll %o1, 16, %o3
85 cmp %o2, 0x20
86 blu,pn %ncc, .wdalign
87 or %o1, %o3, %o1 ! now o1 has 4 bytes of c
89 sllx %o1, 32, %o3
90 or %o1, %o3, %o1 ! now o1 has 8 bytes of c
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
98 ! Set -(%o3) bytes till sp1 double aligned
99 1: 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
104 ! Now sp1 is double aligned (sp1 is found in %o5)
105 .blkalign:
106 mov ASI_BLK_INIT_ST_QUAD_LDD_P, %asi
108 cmp %o2, 0x40 ! check if there are 64 bytes to set
109 blu,pn %ncc, 5f
110 mov %o2, %o3
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
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
121 stx %o1, [%o5]
122 addcc %o3, 8, %o3
123 bl,pt %ncc, 1b
124 add %o5, 8, %o5
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
131 cmp %o4, 0x100 ! check if there are 256 bytes to set
132 blu,pn %ncc, 3f
135 stxa %o1, [%o5+0x0]%asi
136 stxa %o1, [%o5+0x40]%asi
137 stxa %o1, [%o5+0x80]%asi
138 stxa %o1, [%o5+0xc0]%asi
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
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
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
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
172 sub %o4, 0x100, %o4
173 cmp %o4, 0x100
174 bgu,pt %ncc, 2b
175 add %o5, 0x100, %o5
178 cmp %o4, 0x40 ! check if 64 bytes to set
179 blu %ncc, 5f
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
191 subcc %o4, 0x40, %o4
192 bgu,pt %ncc, 4b
193 add %o5, 0x40, %o5
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
205 stx %o1, [%o5] ! store the doubles
206 subcc %o3, 8, %o3
207 bgeu,pt %ncc, 6b
208 add %o5, 8, %o5
210 ba .wrchar
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
218 dec %o2 ! decrement count
219 stb %o1, [%o5] ! clear a byte
220 b .wdalign
221 inc %o5 ! next byte
223 .wrword:
224 st %o1, [%o5] ! 4-byte writing loop
225 subcc %o3, 4, %o3
226 bnz,pt %ncc, .wrword
227 inc 4, %o5
229 and %o2, 3, %o2 ! leftover count, if any
231 .wrchar:
232 ! Set the remaining bytes, if any
233 cmp %o2, 0
234 be %ncc, .exit
238 deccc %o2
239 stb %o1, [%o5]
240 bgu,pt %ncc, 7b
241 inc %o5
243 .exit:
244 retl ! %o0 was preserved
247 SET_SIZE(memset)