/[pearpc]/src/cpu/cpu_jitc_x86/ppc_esc.cc
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Contents of /src/cpu/cpu_jitc_x86/ppc_esc.cc

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1 - (show annotations)
Wed Sep 5 17:11:21 2007 UTC (12 years, 2 months ago) by dpavlin
File size: 9381 byte(s)
import upstream CVS
1 /*
2 * PearPC
3 * ppc_esc.cc
4 *
5 * Copyright (C) 2005 Sebastian Biallas (sb@biallas.net)
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21 #include <cstring>
22
23 #include "system/types.h"
24 #include "debug/tracers.h"
25 #include "ppc_cpu.h"
26 #include "ppc_esc.h"
27 #include "ppc_mmu.h"
28 #include "jitc_asm.h"
29
30 typedef void (*ppc_escape_function)(uint32 *stack, uint32 client_pc);
31
32 static byte *memory_handle(uint32 ea, int flags)
33 {
34 uint32 pa;
35 byte *ptr = NULL;
36 if ((ppc_effective_to_physical_vm(ea, flags, pa) & flags) == flags) {
37 ppc_direct_physical_memory_handle(pa, ptr);
38 }
39 return ptr;
40 }
41
42 static byte *memory_handle_phys(uint32 pa)
43 {
44 byte *ptr = NULL;
45 ppc_direct_physical_memory_handle(pa, ptr);
46 return ptr;
47 }
48
49 static void return_to_dsi_exception_handler(uint32 ea, uint32 *stack, uint32 client_pc)
50 {
51 /*
52 * stack contains the value of ESP before calling our
53 * escape function. So we can modify
54 *
55 * (stack - 4)
56 *
57 * if we want to return to a different function.
58 */
59 PPC_ESC_TRACE(" return_to_dsi(%08x, %08x, %08x)\n", ea, stack, client_pc);
60 stack[-1] = (uint32)&ppc_dsi_exception_special_asm;
61 gCPU.pc_ofs = client_pc;
62 gCPU.dar = ea;
63 }
64
65 static void escape_version(uint32 *stack, uint32 client_pc)
66 {
67 gCPU.gpr[4] = PPC_ESCAPE_IF_VERSION;
68 }
69
70 static void escape_memset(uint32 *stack, uint32 client_pc)
71 {
72 // memset(dest [r4], c [r5], size [r6])
73 uint32 dest = gCPU.gpr[4];
74 uint32 c = gCPU.gpr[5];
75 uint32 size = gCPU.gpr[6];
76 PPC_ESC_TRACE("memest(%08x, %02x, %d)\n", dest, c, size);
77 if (!size) return;
78 if (dest & 0xfff) {
79 byte *dst = memory_handle(dest, PPC_MMU_READ | PPC_MMU_WRITE);
80 if (!dst) {
81 return_to_dsi_exception_handler(dest, stack, client_pc);
82 return;
83 }
84 uint32 a = 4096 - (dest & 0xfff);
85 a = MIN(a, size);
86 memset(dst, c, a);
87 size -= a;
88 dest += a;
89 }
90 while (size >= 4096) {
91 byte *dst = memory_handle(dest, PPC_MMU_READ | PPC_MMU_WRITE);
92 if (!dst) {
93 return_to_dsi_exception_handler(dest, stack, client_pc);
94 gCPU.gpr[4] = dest;
95 gCPU.gpr[6] = size;
96 return;
97 }
98 memset(dst, c, 4096);
99 dest += 4096;
100 size -= 4096;
101 }
102 if (size) {
103 byte *dst = memory_handle(dest, PPC_MMU_READ | PPC_MMU_WRITE);
104 if (!dst) {
105 return_to_dsi_exception_handler(dest, stack, client_pc);
106 gCPU.gpr[4] = dest;
107 gCPU.gpr[6] = size;
108 return;
109 }
110 memset(dst, c, size);
111 }
112 }
113
114 static void escape_memcpy(uint32 *stack, uint32 client_pc)
115 {
116 // memcpy(dest [r4], src [r5], size [r6])
117 uint32 dest = gCPU.gpr[4];
118 uint32 source = gCPU.gpr[5];
119 uint32 size = gCPU.gpr[6];
120 PPC_ESC_TRACE("memcpy(%08x, %08x, %d)\n", dest, source, size);
121 if (!size) return;
122 while (size) {
123 byte *dst = memory_handle(dest, PPC_MMU_READ | PPC_MMU_WRITE);
124 if (!dst) {
125 return_to_dsi_exception_handler(dest, stack, client_pc);
126 gCPU.gpr[4] = dest;
127 gCPU.gpr[5] = source;
128 gCPU.gpr[6] = size;
129 return;
130 }
131 byte *src = memory_handle(source, PPC_MMU_READ);
132 if (!src) {
133 return_to_dsi_exception_handler(source, stack, client_pc);
134 gCPU.gpr[4] = dest;
135 gCPU.gpr[5] = source;
136 gCPU.gpr[6] = size;
137 return;
138 }
139 uint32 s = 4096 - (dest & 0xfff);
140 uint32 s2 = 4096 - (source & 0xfff);
141 s = MIN(s, s2);
142 s = MIN(s, size);
143 memcpy(dst, src, s);
144 dest += s;
145 source += s;
146 size -= s;
147 }
148 }
149
150 static void escape_bzero(uint32 *stack, uint32 client_pc)
151 {
152 // bzero(dest [r4], size [r5])
153 // basically this is memset with predefined CHAR of 0x0
154
155 uint32 dest = gCPU.gpr[4];
156 const uint32 c = 0;
157 uint32 size = gCPU.gpr[5];
158 PPC_ESC_TRACE("bzero(%08x, %08x)\n", dest, size);
159 if (!size) return;
160 if (dest & 0xfff) {
161 byte *dst = memory_handle(dest, PPC_MMU_READ | PPC_MMU_WRITE);
162 if (!dst) {
163 return_to_dsi_exception_handler(dest, stack, client_pc);
164 return;
165 }
166 uint32 a = 4096 - (dest & 0xfff);
167 a = MIN(a, size);
168 memset(dst, c, a);
169 size -= a;
170 dest += a;
171 }
172 while (size >= 4096) {
173 byte *dst = memory_handle(dest, PPC_MMU_READ | PPC_MMU_WRITE);
174 if (!dst) {
175 return_to_dsi_exception_handler(dest, stack, client_pc);
176 gCPU.gpr[4] = dest;
177 gCPU.gpr[5] = size;
178 return;
179 }
180 memset(dst, c, 4096);
181 dest += 4096;
182 size -= 4096;
183 }
184 if (size) {
185 byte *dst = memory_handle(dest, PPC_MMU_READ | PPC_MMU_WRITE);
186 if (!dst) {
187 return_to_dsi_exception_handler(dest, stack, client_pc);
188 gCPU.gpr[4] = dest;
189 gCPU.gpr[5] = size;
190 return;
191 }
192 memset(dst, c, size);
193 }
194 }
195
196 static void escape_bzero_phys(uint32 *stack, uint32 client_pc)
197 {
198 // bzero(dest [r4], size [r5])
199 // basically this is memset with predefined CHAR of 0x0
200
201 uint32 dest = gCPU.gpr[4];
202 const uint32 c = 0;
203 uint32 size = gCPU.gpr[5];
204 PPC_ESC_TRACE("bzero_phys(%08x, %08x)\n", dest, size);
205 if (gCPU.msr & MSR_PR) return;
206 byte *dst = memory_handle_phys(dest);
207 memset(dst, c, size);
208 }
209
210 static void escape_bcopy(uint32 *stack, uint32 client_pc)
211 {
212 // memcpy(src [r4], dest [r5], size [r6], reverse [r7])
213 uint32 source = gCPU.gpr[4];
214 uint32 dest = gCPU.gpr[5];
215 uint32 size = gCPU.gpr[6];
216 bool reverse = gCPU.gpr[7];
217 PPC_ESC_TRACE("bcopy%s(%08x, %08x, %d)\n", reverse ? "_reverse" : "", source, dest, size);
218 if (dest == source) return;
219 if (dest < source) {
220 if (dest + size <= source) goto do_memcpy;
221 //do_memmove:
222 while (size) {
223 byte *dst = memory_handle(dest, PPC_MMU_READ | PPC_MMU_WRITE);
224 if (!dst) {
225 return_to_dsi_exception_handler(dest, stack, client_pc);
226 gCPU.gpr[4] = source;
227 gCPU.gpr[5] = dest;
228 gCPU.gpr[6] = size;
229 return;
230 }
231 byte *src = memory_handle(source, PPC_MMU_READ);
232 if (!src) {
233 return_to_dsi_exception_handler(source, stack, client_pc);
234 gCPU.gpr[4] = source;
235 gCPU.gpr[5] = dest;
236 gCPU.gpr[6] = size;
237 return;
238 }
239 uint32 s = 4096 - (dest & 0xfff);
240 uint32 s2 = 4096 - (source & 0xfff);
241 s = MIN(s, s2);
242 s = MIN(s, size);
243 memmove(dst, src, s);
244 dest += s;
245 source += s;
246 size -= s;
247 }
248 } else {
249 // dest > source
250 if (reverse) goto do_reverse_memmove;
251 if (source + size <= dest) {
252 do_memcpy:
253 while (size) {
254 byte *dst = memory_handle(dest, PPC_MMU_READ | PPC_MMU_WRITE);
255 if (!dst) {
256 return_to_dsi_exception_handler(dest, stack, client_pc);
257 gCPU.gpr[4] = source;
258 gCPU.gpr[5] = dest;
259 gCPU.gpr[6] = size;
260 return;
261 }
262 byte *src = memory_handle(source, PPC_MMU_READ);
263 if (!src) {
264 return_to_dsi_exception_handler(source, stack, client_pc);
265 gCPU.gpr[4] = source;
266 gCPU.gpr[5] = dest;
267 gCPU.gpr[6] = size;
268 return;
269 }
270 uint32 s = 4096 - (dest & 0xfff);
271 uint32 s2 = 4096 - (source & 0xfff);
272 s = MIN(s, s2);
273 s = MIN(s, size);
274 memcpy(dst, src, s);
275 dest += s;
276 source += s;
277 size -= s;
278 }
279 } else {
280 dest += size;
281 source += size;
282 do_reverse_memmove:
283 while (size) {
284 uint32 s = dest & 0xfff;
285 uint32 s2 = source & 0xfff;
286 if (!s) s = 0x1000;
287 if (!s2) s2 = 0x1000;
288 s = MIN(s, s2);
289 s = MIN(s, size);
290 dest -= s;
291 source -= s;
292 size -= s;
293 byte *dst = memory_handle(dest, PPC_MMU_READ | PPC_MMU_WRITE);
294 if (!dst) {
295 return_to_dsi_exception_handler(dest, stack, client_pc);
296 gCPU.gpr[4] = source + s;
297 gCPU.gpr[5] = dest + s;
298 gCPU.gpr[6] = size + s;
299 gCPU.gpr[7] = 1;
300 return;
301 }
302 byte *src = memory_handle(source, PPC_MMU_READ);
303 if (!src) {
304 return_to_dsi_exception_handler(source, stack, client_pc);
305 gCPU.gpr[4] = source + s;
306 gCPU.gpr[5] = dest + s;
307 gCPU.gpr[6] = size + s;
308 gCPU.gpr[7] = 1;
309 return;
310 }
311 memmove(dst, src, s);
312 }
313 }
314 }
315 }
316
317 static void escape_bcopy_phys(uint32 *stack, uint32 client_pc)
318 {
319 // bcopy_phys(src [r4], dest [r5], size [r6])
320 // bcopy_physvirt(src [r4], dest [r5], size [r6])
321 uint32 source = gCPU.gpr[4];
322 uint32 dest = gCPU.gpr[5];
323 uint32 size = gCPU.gpr[6];
324 PPC_ESC_TRACE("bcopy_phys(%08x, %08x, %d)\n", source, dest, size);
325 if (gCPU.msr & MSR_PR) return;
326 byte *dst = memory_handle_phys(dest);
327 if (!dst) return;
328 byte *src = memory_handle_phys(source);
329 if (!src) return;
330 memcpy(dst, src, size);
331 }
332
333 static void escape_copy_page(uint32 *stack, uint32 client_pc)
334 {
335 // copy_page(src [r4], dest [r5])
336 uint32 source = gCPU.gpr[4];
337 uint32 dest = gCPU.gpr[5];
338 byte *dst = memory_handle_phys(dest << 12);
339 if (!dst) return;
340 byte *src = memory_handle_phys(source << 12);
341 if (!src) return;
342 memcpy(dst, src, 4096);
343 }
344
345 static ppc_escape_function escape_functions[] = {
346 escape_version,
347
348 escape_memset,
349 escape_memcpy,
350 escape_bzero,
351 escape_bzero_phys,
352 escape_bcopy,
353 escape_bcopy_phys,
354 escape_bcopy_phys,
355 escape_copy_page,
356 };
357
358 void FASTCALL ppc_escape_vm(uint32 func, uint32 *stack, uint32 client_pc)
359 {
360 if (func >= (sizeof escape_functions / sizeof escape_functions[0])) {
361 PPC_ESC_WARN("unimplemented escape function %d\n", func);
362 } else {
363 escape_functions[func](stack, client_pc);
364 }
365 }
366

  ViewVC Help
Powered by ViewVC 1.1.26