]>
Commit | Line | Data |
---|---|---|
1c79356b A |
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 |