]> git.saurik.com Git - apple/xnu.git/blob - osfmk/ppc/bzero.s
ac0afddf99dce9aa181c40584ef7a38f0748592b
[apple/xnu.git] / osfmk / ppc / bzero.s
1 /*
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
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.
11 *
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
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
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.
19 *
20 * @APPLE_LICENSE_HEADER_END@
21 */
22 /*
23 * @OSF_FREE_COPYRIGHT@
24 */
25
26 #include <ppc/asm.h>
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