2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
23 * @APPLE_LICENSE_HEADER_END@
26 * @OSF_FREE_COPYRIGHT@
30 #include <ppc/proc_reg.h> /* For CACHE_LINE_SIZE */
33 * void bzero(char *addr, unsigned int length)
35 * bzero implementation for PowerPC
36 * - assumes cacheable memory (i.e. uses DCBZ)
37 * - assumes non-pic code
39 * returns start address in r3, as per memset (called by memset)
42 ENTRY(bzero, TAG_NO_FRAME_USED)
44 cmpwi cr0, r4, 0 /* no bytes to zero? */
46 mr r8, r3 /* use r8 as counter to where we are */
48 cmpwi cr0, r4, CACHE_LINE_SIZE /* clear less than a block? */
49 li r0, 0 /* use r0 as source of zeros */
52 /* first, clear bytes up to the next word boundary */
53 addis r6, 0, HIGH_CADDR(.L_bzeroBeginWord)
54 addi r6, r6, LOW_ADDR(.L_bzeroBeginWord)
55 /* extract byte offset as word offset */
56 rlwinm. r5, r8, 2, 28, 29
57 addi r8, r8, -1 /* adjust for update */
58 beq .L_bzeroBeginWord /* no bytes to zero */
59 subfic r5, r5, 16 /* compute the number of instructions */
60 sub r6, r6, r5 /* back from word clear to execute */
68 /* clear words up to the next block boundary */
70 addis r6, 0, HIGH_CADDR(.L_bzeroBlock)
71 addi r6, r6, LOW_ADDR(.L_bzeroBlock)
73 rlwinm. r5, r8, 0, 27, 29 /* extract word offset */
74 addi r8, r8, -4 /* adjust for update */
75 beq .L_bzeroBlock /* no words to zero */
76 /* compute the number of instructions */
77 subfic r5, r5, CACHE_LINE_SIZE
78 sub r6, r6, r5 /* back from word clear to execute */
90 /* clear cache blocks */
92 addi r8, r8, 4 /* remove update adjust */
93 sub r5, r8, r7 /* bytes zeroed */
95 srwi. r5, r4, CACHE_LINE_POW2 /* blocks to zero */
101 addi r8, r8, CACHE_LINE_SIZE
104 /* clear remaining words */
106 addis r6, 0, HIGH_CADDR(.L_bzeroEndByte)
107 addi r6, r6, LOW_ADDR(.L_bzeroEndByte)
108 rlwinm. r5, r4, 0, 27, 29 /* extract word offset */
109 addi r8, r8, -4 /* adjust for update */
110 beq .L_bzeroEndByte /* no words to zero */
111 sub r6, r6, r5 /* back from word clear to execute */
123 /* clear remaining bytes */
125 addis r6, 0, HIGH_CADDR(.L_bzeroEnd)
126 addi r6, r6, LOW_ADDR(.L_bzeroEnd)
127 /* extract byte offset as word offset */
128 rlwinm. r5, r4, 2, 28, 29
129 addi r8, r8, 3 /* adjust for update */
131 sub r6, r6, r5 /* back from word clear to execute */
143 * void *memset(void *from, int c, vm_size_t nbytes)
145 * almost everywhere in the kernel
146 * this appears to be called with argument c==0. We optimise for those
147 * cases and call bzero if we can.
151 ENTRY(memset, TAG_NO_FRAME_USED)
155 /* optimised case - do a bzero */
158 /* If count is zero, return straight away */
162 /* Now, ARG0 = addr, ARG1=len, ARG3=value */
164 subi ARG2, ARG0, 1 /* use ARG2 as our counter */
172 /* Return original address in ARG0 */
177 * void bzero_nc(char *addr, unsigned int length)
179 * bzero implementation for PowerPC
180 * - assumes non-pic code
182 * returns start address in r3, as per memset (called by memset)
185 ENTRY(bzero_nc, TAG_NO_FRAME_USED)
187 cmpwi cr0, r4, 0 /* no bytes to zero? */
189 mr r8, r3 /* use r8 as counter to where we are */
191 cmpwi cr0, r4, CACHE_LINE_SIZE /* clear less than a block? */
192 li r0, 0 /* use r0 as source of zeros */
193 blt .L_bzeroNCEndWord
195 /* first, clear bytes up to the next word boundary */
196 addis r6, 0, HIGH_CADDR(.L_bzeroNCBeginWord)
197 addi r6, r6, LOW_ADDR(.L_bzeroNCBeginWord)
198 /* extract byte offset as word offset */
199 rlwinm. r5, r8, 2, 28, 29
200 addi r8, r8, -1 /* adjust for update */
201 beq .L_bzeroNCBeginWord /* no bytes to zero */
202 subfic r5, r5, 16 /* compute the number of instructions */
203 sub r6, r6, r5 /* back from word clear to execute */
211 /* clear words up to the next block boundary */
213 addis r6, 0, HIGH_CADDR(.L_bzeroNCBlock)
214 addi r6, r6, LOW_ADDR(.L_bzeroNCBlock)
216 rlwinm. r5, r8, 0, 27, 29 /* extract word offset */
217 addi r8, r8, -4 /* adjust for update */
218 beq .L_bzeroNCBlock /* no words to zero */
219 /* compute the number of instructions */
220 subfic r5, r5, CACHE_LINE_SIZE
221 sub r6, r6, r5 /* back from word clear to execute */
233 /* clear cache blocks */
235 addi r8, r8, 4 /* remove update adjust */
236 sub r5, r8, r7 /* bytes zeroed */
238 srwi. r5, r4, CACHE_LINE_POW2 /* blocks to zero */
239 beq .L_bzeroNCEndWord
251 addi r8, r8, CACHE_LINE_SIZE
252 bdnz .L_bzeroNCBlock1
254 /* clear remaining words */
256 addis r6, 0, HIGH_CADDR(.L_bzeroNCEndByte)
257 addi r6, r6, LOW_ADDR(.L_bzeroNCEndByte)
258 rlwinm. r5, r4, 0, 27, 29 /* extract word offset */
259 addi r8, r8, -4 /* adjust for update */
260 beq .L_bzeroNCEndByte /* no words to zero */
261 sub r6, r6, r5 /* back from word clear to execute */
273 /* clear remaining bytes */
275 addis r6, 0, HIGH_CADDR(.L_bzeroNCEnd)
276 addi r6, r6, LOW_ADDR(.L_bzeroNCEnd)
277 /* extract byte offset as word offset */
278 rlwinm. r5, r4, 2, 28, 29
279 addi r8, r8, 3 /* adjust for update */
281 sub r6, r6, r5 /* back from word clear to execute */