]>
Commit | Line | Data |
---|---|---|
1c79356b | 1 | /* |
de355530 | 2 | * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. |
1c79356b A |
3 | * |
4 | * @APPLE_LICENSE_HEADER_START@ | |
5 | * | |
de355530 A |
6 | * The contents of this file constitute Original Code as defined in and |
7 | * are subject to the Apple Public Source License Version 1.1 (the | |
8 | * "License"). You may not use this file except in compliance with the | |
9 | * License. Please obtain a copy of the License at | |
10 | * http://www.apple.com/publicsource and read it before using this file. | |
1c79356b | 11 | * |
de355530 A |
12 | * This Original Code and all software distributed under the License are |
13 | * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER | |
1c79356b A |
14 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, |
15 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, | |
de355530 A |
16 | * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the |
17 | * License for the specific language governing rights and limitations | |
18 | * under the License. | |
1c79356b A |
19 | * |
20 | * @APPLE_LICENSE_HEADER_END@ | |
21 | */ | |
de355530 A |
22 | /* |
23 | * @OSF_FREE_COPYRIGHT@ | |
24 | */ | |
1c79356b A |
25 | |
26 | #include <ppc/asm.h> | |
de355530 A |
27 | #include <ppc/proc_reg.h> /* For CACHE_LINE_SIZE */ |
28 | ||
29 | /* | |
30 | * void bzero(char *addr, unsigned int length) | |
31 | * | |
32 | * bzero implementation for PowerPC | |
33 | * - assumes cacheable memory (i.e. uses DCBZ) | |
34 | * - assumes non-pic code | |
35 | * | |
36 | * returns start address in r3, as per memset (called by memset) | |
37 | */ | |
38 | ||
39 | ENTRY(bzero, TAG_NO_FRAME_USED) | |
40 | ||
41 | cmpwi cr0, r4, 0 /* no bytes to zero? */ | |
42 | mr r7, r3 | |
43 | mr r8, r3 /* use r8 as counter to where we are */ | |
44 | beqlr- | |
45 | cmpwi cr0, r4, CACHE_LINE_SIZE /* clear less than a block? */ | |
46 | li r0, 0 /* use r0 as source of zeros */ | |
47 | blt .L_bzeroEndWord | |
48 | ||
49 | /* first, clear bytes up to the next word boundary */ | |
50 | addis r6, 0, HIGH_CADDR(.L_bzeroBeginWord) | |
51 | addi r6, r6, LOW_ADDR(.L_bzeroBeginWord) | |
52 | /* extract byte offset as word offset */ | |
53 | rlwinm. r5, r8, 2, 28, 29 | |
54 | addi r8, r8, -1 /* adjust for update */ | |
55 | beq .L_bzeroBeginWord /* no bytes to zero */ | |
56 | subfic r5, r5, 16 /* compute the number of instructions */ | |
57 | sub r6, r6, r5 /* back from word clear to execute */ | |
58 | mtctr r6 | |
59 | bctr | |
60 | ||
61 | stbu r0, 1(r8) | |
62 | stbu r0, 1(r8) | |
63 | stbu r0, 1(r8) | |
64 | ||
65 | /* clear words up to the next block boundary */ | |
66 | .L_bzeroBeginWord: | |
67 | addis r6, 0, HIGH_CADDR(.L_bzeroBlock) | |
68 | addi r6, r6, LOW_ADDR(.L_bzeroBlock) | |
69 | addi r8, r8, 1 | |
70 | rlwinm. r5, r8, 0, 27, 29 /* extract word offset */ | |
71 | addi r8, r8, -4 /* adjust for update */ | |
72 | beq .L_bzeroBlock /* no words to zero */ | |
73 | /* compute the number of instructions */ | |
74 | subfic r5, r5, CACHE_LINE_SIZE | |
75 | sub r6, r6, r5 /* back from word clear to execute */ | |
76 | mtctr r6 | |
77 | bctr | |
78 | ||
79 | stwu r0, 4(r8) | |
80 | stwu r0, 4(r8) | |
81 | stwu r0, 4(r8) | |
82 | stwu r0, 4(r8) | |
83 | stwu r0, 4(r8) | |
84 | stwu r0, 4(r8) | |
85 | stwu r0, 4(r8) | |
86 | ||
87 | /* clear cache blocks */ | |
88 | .L_bzeroBlock: | |
89 | addi r8, r8, 4 /* remove update adjust */ | |
90 | sub r5, r8, r7 /* bytes zeroed */ | |
91 | sub r4, r4, r5 | |
92 | srwi. r5, r4, CACHE_LINE_POW2 /* blocks to zero */ | |
93 | beq .L_bzeroEndWord | |
94 | mtctr r5 | |
95 | ||
96 | .L_bzeroBlock1: | |
97 | dcbz 0, r8 | |
98 | addi r8, r8, CACHE_LINE_SIZE | |
99 | bdnz .L_bzeroBlock1 | |
100 | ||
101 | /* clear remaining words */ | |
102 | .L_bzeroEndWord: | |
103 | addis r6, 0, HIGH_CADDR(.L_bzeroEndByte) | |
104 | addi r6, r6, LOW_ADDR(.L_bzeroEndByte) | |
105 | rlwinm. r5, r4, 0, 27, 29 /* extract word offset */ | |
106 | addi r8, r8, -4 /* adjust for update */ | |
107 | beq .L_bzeroEndByte /* no words to zero */ | |
108 | sub r6, r6, r5 /* back from word clear to execute */ | |
109 | mtctr r6 | |
110 | bctr | |
111 | ||
112 | stwu r0, 4(r8) | |
113 | stwu r0, 4(r8) | |
114 | stwu r0, 4(r8) | |
115 | stwu r0, 4(r8) | |
116 | stwu r0, 4(r8) | |
117 | stwu r0, 4(r8) | |
118 | stwu r0, 4(r8) | |
119 | ||
120 | /* clear remaining bytes */ | |
121 | .L_bzeroEndByte: | |
122 | addis r6, 0, HIGH_CADDR(.L_bzeroEnd) | |
123 | addi r6, r6, LOW_ADDR(.L_bzeroEnd) | |
124 | /* extract byte offset as word offset */ | |
125 | rlwinm. r5, r4, 2, 28, 29 | |
126 | addi r8, r8, 3 /* adjust for update */ | |
127 | beqlr | |
128 | sub r6, r6, r5 /* back from word clear to execute */ | |
129 | mtctr r6 | |
130 | bctr | |
131 | ||
132 | stbu r0, 1(r8) | |
133 | stbu r0, 1(r8) | |
134 | stbu r0, 1(r8) | |
135 | ||
136 | .L_bzeroEnd: | |
137 | blr | |
138 | ||
139 | /* | |
140 | * void *memset(void *from, int c, vm_size_t nbytes) | |
141 | * | |
142 | * almost everywhere in the kernel | |
143 | * this appears to be called with argument c==0. We optimise for those | |
144 | * cases and call bzero if we can. | |
145 | * | |
146 | */ | |
147 | ||
148 | ENTRY(memset, TAG_NO_FRAME_USED) | |
149 | ||
150 | mr. ARG3, ARG1 | |
151 | mr ARG1, ARG2 | |
152 | /* optimised case - do a bzero */ | |
153 | beq+ EXT(bzero) | |
154 | ||
155 | /* If count is zero, return straight away */ | |
156 | cmpi cr0, ARG1, 0 | |
157 | beqlr- | |
158 | ||
159 | /* Now, ARG0 = addr, ARG1=len, ARG3=value */ | |
160 | ||
161 | subi ARG2, ARG0, 1 /* use ARG2 as our counter */ | |
162 | ||
163 | 0: | |
164 | subi ARG1, ARG1, 1 | |
165 | cmpi cr0, ARG1, 0 | |
166 | stbu ARG3, 1(ARG2) | |
167 | bne+ 0b | |
168 | ||
169 | /* Return original address in ARG0 */ | |
170 | ||
171 | blr | |
172 | ||
173 | /* | |
174 | * void bzero_nc(char *addr, unsigned int length) | |
175 | * | |
176 | * bzero implementation for PowerPC | |
177 | * - assumes non-pic code | |
178 | * | |
179 | * returns start address in r3, as per memset (called by memset) | |
180 | */ | |
181 | ||
182 | ENTRY(bzero_nc, TAG_NO_FRAME_USED) | |
183 | ||
184 | cmpwi cr0, r4, 0 /* no bytes to zero? */ | |
185 | mr r7, r3 | |
186 | mr r8, r3 /* use r8 as counter to where we are */ | |
187 | beqlr- | |
188 | cmpwi cr0, r4, CACHE_LINE_SIZE /* clear less than a block? */ | |
189 | li r0, 0 /* use r0 as source of zeros */ | |
190 | blt .L_bzeroNCEndWord | |
191 | ||
192 | /* first, clear bytes up to the next word boundary */ | |
193 | addis r6, 0, HIGH_CADDR(.L_bzeroNCBeginWord) | |
194 | addi r6, r6, LOW_ADDR(.L_bzeroNCBeginWord) | |
195 | /* extract byte offset as word offset */ | |
196 | rlwinm. r5, r8, 2, 28, 29 | |
197 | addi r8, r8, -1 /* adjust for update */ | |
198 | beq .L_bzeroNCBeginWord /* no bytes to zero */ | |
199 | subfic r5, r5, 16 /* compute the number of instructions */ | |
200 | sub r6, r6, r5 /* back from word clear to execute */ | |
201 | mtctr r6 | |
202 | bctr | |
203 | ||
204 | stbu r0, 1(r8) | |
205 | stbu r0, 1(r8) | |
206 | stbu r0, 1(r8) | |
207 | ||
208 | /* clear words up to the next block boundary */ | |
209 | .L_bzeroNCBeginWord: | |
210 | addis r6, 0, HIGH_CADDR(.L_bzeroNCBlock) | |
211 | addi r6, r6, LOW_ADDR(.L_bzeroNCBlock) | |
212 | addi r8, r8, 1 | |
213 | rlwinm. r5, r8, 0, 27, 29 /* extract word offset */ | |
214 | addi r8, r8, -4 /* adjust for update */ | |
215 | beq .L_bzeroNCBlock /* no words to zero */ | |
216 | /* compute the number of instructions */ | |
217 | subfic r5, r5, CACHE_LINE_SIZE | |
218 | sub r6, r6, r5 /* back from word clear to execute */ | |
219 | mtctr r6 | |
220 | bctr | |
221 | ||
222 | stwu r0, 4(r8) | |
223 | stwu r0, 4(r8) | |
224 | stwu r0, 4(r8) | |
225 | stwu r0, 4(r8) | |
226 | stwu r0, 4(r8) | |
227 | stwu r0, 4(r8) | |
228 | stwu r0, 4(r8) | |
229 | ||
230 | /* clear cache blocks */ | |
231 | .L_bzeroNCBlock: | |
232 | addi r8, r8, 4 /* remove update adjust */ | |
233 | sub r5, r8, r7 /* bytes zeroed */ | |
234 | sub r4, r4, r5 | |
235 | srwi. r5, r4, CACHE_LINE_POW2 /* blocks to zero */ | |
236 | beq .L_bzeroNCEndWord | |
237 | mtctr r5 | |
238 | ||
239 | .L_bzeroNCBlock1: | |
240 | stw r0, 0(r8) | |
241 | stw r0, 4(r8) | |
242 | stw r0, 8(r8) | |
243 | stw r0, 12(r8) | |
244 | stw r0, 16(r8) | |
245 | stw r0, 20(r8) | |
246 | stw r0, 24(r8) | |
247 | stw r0, 28(r8) | |
248 | addi r8, r8, CACHE_LINE_SIZE | |
249 | bdnz .L_bzeroNCBlock1 | |
250 | ||
251 | /* clear remaining words */ | |
252 | .L_bzeroNCEndWord: | |
253 | addis r6, 0, HIGH_CADDR(.L_bzeroNCEndByte) | |
254 | addi r6, r6, LOW_ADDR(.L_bzeroNCEndByte) | |
255 | rlwinm. r5, r4, 0, 27, 29 /* extract word offset */ | |
256 | addi r8, r8, -4 /* adjust for update */ | |
257 | beq .L_bzeroNCEndByte /* no words to zero */ | |
258 | sub r6, r6, r5 /* back from word clear to execute */ | |
259 | mtctr r6 | |
260 | bctr | |
261 | ||
262 | stwu r0, 4(r8) | |
263 | stwu r0, 4(r8) | |
264 | stwu r0, 4(r8) | |
265 | stwu r0, 4(r8) | |
266 | stwu r0, 4(r8) | |
267 | stwu r0, 4(r8) | |
268 | stwu r0, 4(r8) | |
269 | ||
270 | /* clear remaining bytes */ | |
271 | .L_bzeroNCEndByte: | |
272 | addis r6, 0, HIGH_CADDR(.L_bzeroNCEnd) | |
273 | addi r6, r6, LOW_ADDR(.L_bzeroNCEnd) | |
274 | /* extract byte offset as word offset */ | |
275 | rlwinm. r5, r4, 2, 28, 29 | |
276 | addi r8, r8, 3 /* adjust for update */ | |
277 | beqlr | |
278 | sub r6, r6, r5 /* back from word clear to execute */ | |
279 | mtctr r6 | |
280 | bctr | |
281 | ||
282 | stbu r0, 1(r8) | |
283 | stbu r0, 1(r8) | |
284 | stbu r0, 1(r8) | |
9bccf70c | 285 | |
de355530 A |
286 | .L_bzeroNCEnd: |
287 | blr |