bzero.S revision 1.11.4.1 1 /* $NetBSD: bzero.S,v 1.11.4.1 2014/05/22 11:36:48 yamt Exp $ */
2
3 /*-
4 * Copyright (C) 2001 Martin J. Laubach <mjl (at) NetBSD.org>
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29 /*----------------------------------------------------------------------*/
30
31 #include <machine/asm.h>
32
33
34 #if defined(LIBC_SCCS) && !defined(lint)
35 __RCSID("$NetBSD: bzero.S,v 1.11.4.1 2014/05/22 11:36:48 yamt Exp $")
36 #endif /* LIBC_SCCS && !lint */
37
38 #include "assym.h"
39
40 #define USE_STSWX 0 /* don't. slower than trivial copy loop */
41
42 /*----------------------------------------------------------------------*/
43 /*
44 void bzero(void *b %r3, size_t len %r4);
45 void * memset(void *b %r3, int c %r4, size_t len %r5);
46 */
47 /*----------------------------------------------------------------------*/
48
49 #define r_dst %r3
50 #define r_len %r4
51 #define r_val %r0
52
53 .text
54 .align 4
55 ENTRY(bzero)
56 li r_val, 0 /* Value to stuff in */
57 b cb_memset
58 END(bzero)
59
60 ENTRY(memset)
61 cmplwi %cr1, %r5, 0
62 mr. %r0, %r4
63 mr %r8, %r3
64 beqlr- %cr1 /* Nothing to do */
65
66 rlwimi %r0, %r4, 8, 16, 23 /* word extend fill value */
67 rlwimi %r0, %r0, 16, 0, 15
68 mr %r4, %r5
69 bne- simple_fill /* =! 0, use trivial fill */
70 cb_memset:
71
72 /*----------------------------------------------------------------------*/
73 #ifndef _KERNEL
74 #ifdef __PIC__
75 /* First get cache line size */
76 mflr %r9
77 bcl 20,31,1f
78 1: mflr %r10
79 mtlr %r9
80 addis %r10,%r10,_libc_powerpc_cache_info+CACHE_INFO_DCACHE_LINE_SIZE-1b@ha
81 lwz %r9,_libc_powerpc_cache_info+CACHE_INFO_DCACHE_LINE_SIZE-1b@l(%r10)
82 #else
83 lis %r10,_libc_powerpc_cache_info+CACHE_INFO_DCACHE_LINE_SIZE@ha
84 lwz %r9,_libc_powerpc_cache_info+CACHE_INFO_DCACHE_LINE_SIZE@l(%r10)
85 #endif
86 cmplwi %cr1, %r9, 0 /* Unknown? */
87 beq- simple_fill /* a trivial fill routine */
88 #else /* _KERNEL */
89 #ifdef MULTIPROCESSOR
90 mfsprg %r10, 0 /* Get cpu_info pointer */
91 #else
92 lis %r10, cpu_info_store@ha
93 addi %r10, %r10, cpu_info_store@l
94 #endif
95 lwz %r9, CPU_CI+CACHE_INFO_DCACHE_LINE_SIZE(%r10) /* Load D$ line size */
96 #endif /* _KERNEL */
97 cntlzw %r10, %r9 /* Calculate shift.. */
98 li %r6, 31
99 subf %r10, %r10, %r6
100 /* Back in memory filling business */
101
102 cmplwi %cr1, r_len, 0 /* Nothing to do? */
103 add %r5, %r9, %r9
104 cmplw r_len, %r5 /* <= 2*CL bytes to move? */
105 beqlr- %cr1 /* then do nothing */
106
107 blt+ simple_fill /* a trivial fill routine */
108
109 /* Word align the block, fill bytewise until dst even*/
110
111 andi. %r5, r_dst, 0x03
112 li %r6, 4
113 beq+ cb_aligned_w /* already aligned to word? */
114
115 subf %r5, %r5, %r6 /* bytes to fill to align4 */
116 #if USE_STSWX
117 mtxer %r5
118 stswx %r0, 0, r_dst
119 add r_dst, %r5, r_dst
120 #else
121 mtctr %r5
122
123 subi r_dst, r_dst, 1
124 1: stbu r_val, 1(r_dst) /* Fill bytewise */
125 bdnz 1b
126
127 addi r_dst, r_dst, 1
128 #endif
129 subf r_len, %r5, r_len
130
131 cb_aligned_w: /* Cache block align, fill wordwise until dst aligned */
132
133 /* I know I have something to do since we had > 2*CL initially */
134 /* so no need to check for r_len = 0 */
135
136 subi %r6, %r9, 1 /* CL mask */
137 and. %r5, r_dst, %r6
138 srwi %r5, %r5, 2
139 srwi %r6, %r9, 2
140 beq cb_aligned_cb /* already on CL boundary? */
141
142 subf %r5, %r5, %r6 /* words to fill to alignment */
143 mtctr %r5
144 slwi %r5, %r5, 2
145 subf r_len, %r5, r_len
146
147 subi r_dst, r_dst, 4
148 1: stwu r_val, 4(r_dst) /* Fill wordwise */
149 bdnz 1b
150 addi r_dst, r_dst, 4
151
152 cb_aligned_cb: /* no need to check r_len, see above */
153
154 srw. %r5, r_len, %r10 /* Number of cache blocks */
155 mtctr %r5
156 beq cblocks_done
157
158 slw %r5, %r5, %r10
159 subf r_len, %r5, r_len
160
161 1: dcbz 0, r_dst /* Clear blockwise */
162 add r_dst, r_dst, %r9
163 bdnz 1b
164
165 cblocks_done: /* still CL aligned, but less than CL bytes left */
166 cmplwi %cr1, r_len, 0
167 cmplwi r_len, 8
168 beq- %cr1, sf_return
169
170 blt- sf_bytewise /* <8 remaining? */
171 b sf_aligned_w
172
173 /*----------------------------------------------------------------------*/
174 wbzero: li r_val, 0
175
176 cmplwi r_len, 0
177 beqlr- /* Nothing to do */
178
179 simple_fill:
180 #if USE_STSWX
181 cmplwi %cr1, r_len, 12 /* < 12 bytes to move? */
182 #else
183 cmplwi %cr1, r_len, 8 /* < 8 bytes to move? */
184 #endif
185 andi. %r5, r_dst, 0x03 /* bytes to fill to align4 */
186 blt %cr1, sf_bytewise /* trivial byte mover */
187
188 li %r6, 4
189 subf %r5, %r5, %r6
190 beq+ sf_aligned_w /* dest is word aligned */
191
192 #if USE_STSWX
193 mtxer %r5
194 stswx %r0, 0, r_dst
195 add r_dst, %r5, r_dst
196 #else
197 mtctr %r5 /* nope, then fill bytewise */
198 subi r_dst, r_dst, 1 /* until it is */
199 1: stbu r_val, 1(r_dst)
200 bdnz 1b
201
202 addi r_dst, r_dst, 1
203 #endif
204 subf r_len, %r5, r_len
205
206 sf_aligned_w: /* no need to check r_len since it were >= 8 bytes initially */
207 #if USE_STSWX
208 mr %r6, %r0
209 mr %r7, %r0
210
211 srwi %r5, r_len, 3
212 mtctr %r5
213
214 slwi %r5, %r5, 3 /* adjust len */
215 subf. r_len, %r5, r_len
216
217 1: stswi %r6, r_dst, 8
218 addi r_dst, r_dst, 8
219 bdnz 1b
220 #else
221 srwi %r5, r_len, 2 /* words to fill */
222 mtctr %r5
223
224 slwi %r5, %r5, 2
225 subf. r_len, %r5, r_len /* adjust len for fill */
226
227 subi r_dst, r_dst, 4
228 1: stwu r_val, 4(r_dst)
229 bdnz 1b
230 addi r_dst, r_dst, 4
231 #endif
232
233 sf_word_done: bne- sf_bytewise
234
235 sf_return: mr %r3, %r8 /* restore orig ptr */
236 blr /* for memset functionality */
237
238 sf_bytewise:
239 #if USE_STSWX
240 mr %r5, %r0
241 mr %r6, %r0
242 mr %r7, %r0
243
244 mtxer r_len
245 stswx %r5, 0, r_dst
246 #else
247 mtctr r_len
248
249 subi r_dst, r_dst, 1
250 1: stbu r_val, 1(r_dst)
251 bdnz 1b
252 #endif
253 mr %r3, %r8 /* restore orig ptr */
254 blr /* for memset functionality */
255 END(memset)
256
257 /*----------------------------------------------------------------------*/
258 #ifndef _KERNEL
259 .data
260 .p2align 2
261 cache_info: .long -1, -1, -1, -1
262 cache_sh: .long 0
263
264 #endif
265 /*----------------------------------------------------------------------*/
266