/[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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1 - (hide annotations)
Wed Sep 5 17:11:21 2007 UTC (16 years, 7 months ago) by dpavlin
File size: 9381 byte(s)
import upstream CVS
1 dpavlin 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