/[pcsx2_0.9.7]/trunk/pcsx2/Memory.cpp
ViewVC logotype

Annotation of /trunk/pcsx2/Memory.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 31 - (hide annotations) (download)
Tue Sep 7 03:24:11 2010 UTC (9 years, 5 months ago) by william
File size: 30216 byte(s)
committing r3113 initial commit again...
1 william 31 /* PCSX2 - PS2 Emulator for PCs
2     * Copyright (C) 2002-2010 PCSX2 Dev Team
3     *
4     * PCSX2 is free software: you can redistribute it and/or modify it under the terms
5     * of the GNU Lesser General Public License as published by the Free Software Found-
6     * ation, either version 3 of the License, or (at your option) any later version.
7     *
8     * PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
9     * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
10     * PURPOSE. See the GNU General Public License for more details.
11     *
12     * You should have received a copy of the GNU General Public License along with PCSX2.
13     * If not, see <http://www.gnu.org/licenses/>.
14     */
15    
16     /*
17    
18     RAM
19     ---
20     0x00100000-0x01ffffff this is the physical address for the ram.its cached there
21     0x20100000-0x21ffffff uncached
22     0x30100000-0x31ffffff uncached & accelerated
23     0xa0000000-0xa1ffffff MIRROR might...???
24     0x80000000-0x81ffffff MIRROR might... ????
25    
26     scratch pad
27     ----------
28     0x70000000-0x70003fff scratch pad
29    
30     BIOS
31     ----
32     0x1FC00000 - 0x1FFFFFFF un-cached
33     0x9FC00000 - 0x9FFFFFFF cached
34     0xBFC00000 - 0xBFFFFFFF un-cached
35     */
36    
37     #include "PrecompiledHeader.h"
38     #include "IopCommon.h"
39    
40     #pragma warning(disable:4799) // No EMMS at end of function
41    
42     #include <wx/file.h>
43    
44     #include "VUmicro.h"
45     #include "GS.h"
46     #include "System/PageFaultSource.h"
47     #include "ps2/BiosTools.h"
48    
49     #ifdef ENABLECACHE
50     #include "Cache.h"
51     #endif
52    
53     int MemMode = 0; // 0 is Kernel Mode, 1 is Supervisor Mode, 2 is User Mode
54    
55     void memSetKernelMode() {
56     //Do something here
57     MemMode = 0;
58     }
59    
60     void memSetSupervisorMode() {
61     }
62    
63     void memSetUserMode() {
64    
65     }
66    
67     u16 ba0R16(u32 mem)
68     {
69     //MEM_LOG("ba00000 Memory read16 address %x", mem);
70    
71     if (mem == 0x1a000006) {
72     static int ba6;
73     ba6++;
74     if (ba6 == 3) ba6 = 0;
75     return ba6;
76     }
77     return 0;
78     }
79    
80    
81     u8 *psM = NULL; //32mb Main Ram
82     u8 *psR = NULL; //4mb rom area
83     u8 *psR1 = NULL; //256kb rom1 area (actually 196kb, but can't mask this)
84     u8 *psR2 = NULL; // 0x00080000
85     u8 *psER = NULL; // 0x001C0000
86     u8 *psS = NULL; //0.015 mb, scratch pad
87    
88     // Two 1 megabyte (max DMA) buffers for reading and writing to high memory (>32MB).
89     // Such accesses are not documented as causing bus errors but as the memory does
90     // not exist, reads should continue to return 0 and writes should be discarded.
91     // Probably.
92     static __aligned16 u8 highmem[0x200000];
93    
94     u8 *psMHR = &highmem[0];
95     u8 *psMHW = &highmem[0x100000];
96    
97     #define CHECK_MEM(mem) //MyMemCheck(mem)
98    
99     void MyMemCheck(u32 mem)
100     {
101     if( mem == 0x1c02f2a0 )
102     Console.WriteLn("yo; (mem == 0x1c02f2a0) in MyMemCheck...");
103     }
104    
105     /////////////////////////////
106     // REGULAR MEM START
107     /////////////////////////////
108     vtlbHandler null_handler;
109    
110     vtlbHandler tlb_fallback_0;
111     vtlbHandler tlb_fallback_1;
112     vtlbHandler tlb_fallback_2;
113     vtlbHandler tlb_fallback_3;
114     vtlbHandler tlb_fallback_4;
115     vtlbHandler tlb_fallback_5;
116     vtlbHandler tlb_fallback_6;
117     vtlbHandler tlb_fallback_7;
118     vtlbHandler tlb_fallback_8;
119    
120     vtlbHandler vu0_micro_mem[2]; // 0 - dynarec, 1 - interpreter
121     vtlbHandler vu1_micro_mem[2]; // 0 - dynarec, 1 - interpreter
122    
123     vtlbHandler hw_by_page[0x10] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 };
124     vtlbHandler gs_page_0;
125     vtlbHandler gs_page_1;
126    
127     vtlbHandler iopHw_by_page_01;
128     vtlbHandler iopHw_by_page_03;
129     vtlbHandler iopHw_by_page_08;
130    
131    
132     // Used to remap the VUmicro memory according to the VU0/VU1 dynarec setting.
133     // (the VU memory operations are different for recs vs. interpreters)
134     void memMapVUmicro()
135     {
136     vtlb_MapHandler(vu0_micro_mem[CpuVU0->IsInterpreter],0x11000000,0x00004000);
137     vtlb_MapHandler(vu1_micro_mem[CpuVU1->IsInterpreter],0x11008000,0x00004000);
138    
139     // VU0/VU1 memory
140     // (Like IOP memory, these are generally only used by the EE Bios kernel during
141     // boot-up. Applications/games are "supposed" to use the thread-safe VIF
142     // instead.)
143     vtlb_MapBlock(VU0.Mem,0x11004000,0x00004000,0x1000);
144     vtlb_MapBlock(VU1.Mem,0x1100c000,0x00004000);
145     }
146    
147     void memMapPhy()
148     {
149     // Main memory
150     vtlb_MapBlock(psM, 0x00000000,Ps2MemSize::Base);//mirrored on first 256 mb ?
151     // High memory, uninstalled on the configuration we emulate
152     vtlb_MapHandler(null_handler, Ps2MemSize::Base, 0x10000000 - Ps2MemSize::Base);
153    
154     // Various ROMs (all read-only)
155     vtlb_MapBlock(psR, 0x1fc00000,Ps2MemSize::Rom);
156     vtlb_MapBlock(psR1, 0x1e000000,Ps2MemSize::Rom1);
157     vtlb_MapBlock(psR2, 0x1e400000,Ps2MemSize::Rom2);
158     vtlb_MapBlock(psER, 0x1e040000,Ps2MemSize::ERom);
159    
160     // IOP memory
161     // (used by the EE Bios Kernel during initial hardware initialization, Apps/Games
162     // are "supposed" to use the thread-safe SIF instead.)
163     vtlb_MapBlock(psxM,0x1c000000,0x00800000);
164    
165     // Generic Handlers; These fallback to mem* stuff...
166     vtlb_MapHandler(tlb_fallback_1,0x10000000,0x10000);
167     vtlb_MapHandler(tlb_fallback_7,0x14000000,0x10000);
168     vtlb_MapHandler(tlb_fallback_4,0x18000000,0x10000);
169     vtlb_MapHandler(tlb_fallback_5,0x1a000000,0x10000);
170     vtlb_MapHandler(tlb_fallback_6,0x12000000,0x10000);
171     vtlb_MapHandler(tlb_fallback_8,0x1f000000,0x10000);
172     vtlb_MapHandler(tlb_fallback_3,0x1f400000,0x10000);
173     vtlb_MapHandler(tlb_fallback_2,0x1f800000,0x10000);
174     vtlb_MapHandler(tlb_fallback_8,0x1f900000,0x10000);
175    
176     // Hardware Register Handlers : specialized/optimized per-page handling of HW register accesses
177     // (note that hw_by_page handles are assigned in memReset prior to calling this function)
178     vtlb_MapHandler(hw_by_page[0x0], 0x10000000, 0x01000);
179     vtlb_MapHandler(hw_by_page[0x1], 0x10001000, 0x01000);
180     vtlb_MapHandler(hw_by_page[0x2], 0x10002000, 0x01000);
181     vtlb_MapHandler(hw_by_page[0x3], 0x10003000, 0x01000);
182     vtlb_MapHandler(hw_by_page[0x4], 0x10004000, 0x01000);
183     vtlb_MapHandler(hw_by_page[0x5], 0x10005000, 0x01000);
184     vtlb_MapHandler(hw_by_page[0x6], 0x10006000, 0x01000);
185     vtlb_MapHandler(hw_by_page[0x7], 0x10007000, 0x01000);
186     vtlb_MapHandler(hw_by_page[0xb], 0x1000b000, 0x01000);
187     vtlb_MapHandler(hw_by_page[0xe], 0x1000e000, 0x01000);
188     vtlb_MapHandler(hw_by_page[0xf], 0x1000f000, 0x01000);
189    
190     vtlb_MapHandler(gs_page_0, 0x12000000, 0x01000);
191     vtlb_MapHandler(gs_page_1, 0x12001000, 0x01000);
192    
193     // "Secret" IOP HW mappings - Used by EE Bios Kernel during boot and generally
194     // left untouched after that, as per EE/IOP thread safety rules.
195    
196     vtlb_MapHandler(iopHw_by_page_01, 0x1f801000, 0x01000);
197     vtlb_MapHandler(iopHw_by_page_03, 0x1f803000, 0x01000);
198     vtlb_MapHandler(iopHw_by_page_08, 0x1f808000, 0x01000);
199    
200     }
201    
202     //Why is this required ?
203     void memMapKernelMem()
204     {
205     //lower 512 mb: direct map
206     //vtlb_VMap(0x00000000,0x00000000,0x20000000);
207     //0x8* mirror
208     vtlb_VMap(0x80000000,0x00000000,0x20000000);
209     //0xa* mirror
210     vtlb_VMap(0xA0000000,0x00000000,0x20000000);
211     }
212    
213     //what do do with these ?
214     void memMapSupervisorMem()
215     {
216     }
217    
218     void memMapUserMem()
219     {
220     }
221    
222     static mem8_t __fastcall nullRead8(u32 mem) {
223     MEM_LOG("Read uninstalled memory at address %08x", mem);
224     return 0;
225     }
226     static mem16_t __fastcall nullRead16(u32 mem) {
227     MEM_LOG("Read uninstalled memory at address %08x", mem);
228     return 0;
229     }
230     static mem32_t __fastcall nullRead32(u32 mem) {
231     MEM_LOG("Read uninstalled memory at address %08x", mem);
232     return 0;
233     }
234     static void __fastcall nullRead64(u32 mem, mem64_t *out) {
235     MEM_LOG("Read uninstalled memory at address %08x", mem);
236     *out = 0;
237     }
238     static void __fastcall nullRead128(u32 mem, mem128_t *out) {
239     MEM_LOG("Read uninstalled memory at address %08x", mem);
240     *out = 0;
241     }
242     static void __fastcall nullWrite8(u32 mem, mem8_t value)
243     {
244     MEM_LOG("Write uninstalled memory at address %08x", mem);
245     }
246     static void __fastcall nullWrite16(u32 mem, mem16_t value)
247     {
248     MEM_LOG("Write uninstalled memory at address %08x", mem);
249     }
250     static void __fastcall nullWrite32(u32 mem, mem32_t value)
251     {
252     MEM_LOG("Write uninstalled memory at address %08x", mem);
253     }
254     static void __fastcall nullWrite64(u32 mem, const mem64_t *value)
255     {
256     MEM_LOG("Write uninstalled memory at address %08x", mem);
257     }
258     static void __fastcall nullWrite128(u32 mem, const mem128_t *value)
259     {
260     MEM_LOG("Write uninstalled memory at address %08x", mem);
261     }
262    
263     template<int p>
264     mem8_t __fastcall _ext_memRead8 (u32 mem)
265     {
266     switch (p)
267     {
268     case 1: // hwm
269     return hwRead8(mem);
270     case 3: // psh4
271     return psxHw4Read8(mem);
272     case 6: // gsm
273     return gsRead8(mem);
274     case 7: // dev9
275     {
276     mem8_t retval = DEV9read8(mem & ~0xa4000000);
277     Console.WriteLn("DEV9 read8 %8.8lx: %2.2lx", mem & ~0xa4000000, retval);
278     return retval;
279     }
280     }
281    
282     MEM_LOG("Unknown Memory Read8 from address %8.8x", mem);
283     cpuTlbMissR(mem, cpuRegs.branch);
284     return 0;
285     }
286    
287     template<int p>
288     mem16_t __fastcall _ext_memRead16(u32 mem)
289     {
290     switch (p)
291     {
292     case 1: // hwm
293     return hwRead16(mem);
294     case 4: // b80
295     MEM_LOG("b800000 Memory read16 address %x", mem);
296     return 0;
297     case 5: // ba0
298     return ba0R16(mem);
299     case 6: // gsm
300     return gsRead16(mem);
301    
302     case 7: // dev9
303     {
304     mem16_t retval = DEV9read16(mem & ~0xa4000000);
305     Console.WriteLn("DEV9 read16 %8.8lx: %4.4lx", mem & ~0xa4000000, retval);
306     return retval;
307     }
308    
309     case 8: // spu2
310     return SPU2read(mem);
311     }
312     MEM_LOG("Unknown Memory read16 from address %8.8x", mem);
313     cpuTlbMissR(mem, cpuRegs.branch);
314     return 0;
315     }
316    
317     template<int p>
318     mem32_t __fastcall _ext_memRead32(u32 mem)
319     {
320     switch (p)
321     {
322     case 6: // gsm
323     return gsRead32(mem);
324     case 7: // dev9
325     {
326     mem32_t retval = DEV9read32(mem & ~0xa4000000);
327     Console.WriteLn("DEV9 read32 %8.8lx: %8.8lx", mem & ~0xa4000000, retval);
328     return retval;
329     }
330     }
331    
332     MEM_LOG("Unknown Memory read32 from address %8.8x (Status=%8.8x)", mem, cpuRegs.CP0.n.Status.val);
333     cpuTlbMissR(mem, cpuRegs.branch);
334     return 0;
335     }
336    
337     template<int p>
338     void __fastcall _ext_memRead64(u32 mem, mem64_t *out)
339     {
340     switch (p)
341     {
342     case 6: // gsm
343     *out = gsRead64(mem); return;
344     }
345    
346     MEM_LOG("Unknown Memory read64 from address %8.8x", mem);
347     cpuTlbMissR(mem, cpuRegs.branch);
348     }
349    
350     template<int p>
351     void __fastcall _ext_memRead128(u32 mem, mem128_t *out)
352     {
353     switch (p)
354     {
355     //case 1: // hwm
356     // hwRead128(mem & ~0xa0000000, out); return;
357     case 6: // gsm
358     out[0] = gsRead64(mem );
359     out[1] = gsRead64(mem+8); return;
360     }
361    
362     MEM_LOG("Unknown Memory read128 from address %8.8x", mem);
363     cpuTlbMissR(mem, cpuRegs.branch);
364     }
365    
366     template<int p>
367     void __fastcall _ext_memWrite8 (u32 mem, mem8_t value)
368     {
369     switch (p) {
370     case 1: // hwm
371     hwWrite8(mem, value);
372     return;
373     case 3: // psh4
374     psxHw4Write8(mem, value); return;
375     case 6: // gsm
376     gsWrite8(mem, value); return;
377     case 7: // dev9
378     DEV9write8(mem & ~0xa4000000, value);
379     Console.WriteLn("DEV9 write8 %8.8lx: %2.2lx", mem & ~0xa4000000, value);
380     return;
381     }
382    
383     MEM_LOG("Unknown Memory write8 to address %x with data %2.2x", mem, value);
384     cpuTlbMissW(mem, cpuRegs.branch);
385     }
386     template<int p>
387     void __fastcall _ext_memWrite16(u32 mem, mem16_t value)
388     {
389     switch (p) {
390     case 1: // hwm
391     hwWrite16(mem, value);
392     return;
393     case 5: // ba0
394     MEM_LOG("ba00000 Memory write16 to address %x with data %x", mem, value);
395     return;
396     case 6: // gsm
397     gsWrite16(mem, value); return;
398     case 7: // dev9
399     DEV9write16(mem & ~0xa4000000, value);
400     Console.WriteLn("DEV9 write16 %8.8lx: %4.4lx", mem & ~0xa4000000, value);
401     return;
402     case 8: // spu2
403     SPU2write(mem, value); return;
404     }
405     MEM_LOG("Unknown Memory write16 to address %x with data %4.4x", mem, value);
406     cpuTlbMissW(mem, cpuRegs.branch);
407     }
408    
409     template<int p>
410     void __fastcall _ext_memWrite32(u32 mem, mem32_t value)
411     {
412     switch (p) {
413     case 6: // gsm
414     gsWrite32(mem, value); return;
415     case 7: // dev9
416     DEV9write32(mem & ~0xa4000000, value);
417     Console.WriteLn("DEV9 write32 %8.8lx: %8.8lx", mem & ~0xa4000000, value);
418     return;
419     }
420     MEM_LOG("Unknown Memory write32 to address %x with data %8.8x", mem, value);
421     cpuTlbMissW(mem, cpuRegs.branch);
422     }
423    
424     template<int p>
425     void __fastcall _ext_memWrite64(u32 mem, const mem64_t* value)
426     {
427    
428     /*switch (p) {
429     //case 1: // hwm
430     // hwWrite64(mem & ~0xa0000000, *value);
431     // return;
432     //case 6: // gsm
433     // gsWrite64(mem & ~0xa0000000, *value); return;
434     }*/
435    
436     MEM_LOG("Unknown Memory write64 to address %x with data %8.8x_%8.8x", mem, (u32)(*value>>32), (u32)*value);
437     cpuTlbMissW(mem, cpuRegs.branch);
438     }
439    
440     template<int p>
441     void __fastcall _ext_memWrite128(u32 mem, const mem128_t *value)
442     {
443     /*switch (p) {
444     //case 1: // hwm
445     // hwWrite128(mem & ~0xa0000000, value);
446     // return;
447     //case 6: // gsm
448     // mem &= ~0xa0000000;
449     // gsWrite64(mem, value[0]);
450     // gsWrite64(mem+8, value[1]); return;
451     }*/
452    
453     MEM_LOG("Unknown Memory write128 to address %x with data %8.8x_%8.8x_%8.8x_%8.8x", mem, ((u32*)value)[3], ((u32*)value)[2], ((u32*)value)[1], ((u32*)value)[0]);
454     cpuTlbMissW(mem, cpuRegs.branch);
455     }
456    
457     #define vtlb_RegisterHandlerTempl1(nam,t) vtlb_RegisterHandler(nam##Read8<t>,nam##Read16<t>,nam##Read32<t>,nam##Read64<t>,nam##Read128<t>, \
458     nam##Write8<t>,nam##Write16<t>,nam##Write32<t>,nam##Write64<t>,nam##Write128<t>)
459    
460     #define vtlb_RegisterHandlerTempl2(nam,t,rec) vtlb_RegisterHandler(nam##Read8<t>,nam##Read16<t>,nam##Read32<t>,nam##Read64<t>,nam##Read128<t>, \
461     nam##Write8<t,rec>,nam##Write16<t,rec>,nam##Write32<t,rec>,nam##Write64<t,rec>,nam##Write128<t,rec>)
462    
463     typedef void __fastcall ClearFunc_t( u32 addr, u32 qwc );
464    
465     template<int vunum, bool dynarec>
466     static __forceinline void ClearVuFunc( u32 addr, u32 size )
467     {
468     if( dynarec )
469     {
470     if( vunum==0 )
471     CpuVU0->Clear(addr,size);
472     else
473     CpuVU1->Clear(addr,size);
474     }
475     else
476     {
477     if( vunum==0 )
478     CpuVU0->Clear(addr,size);
479     else
480     CpuVU1->Clear(addr,size);
481     }
482     }
483    
484     template<int vunum>
485     mem8_t __fastcall vuMicroRead8(u32 addr)
486     {
487     addr&=(vunum==0)?0xfff:0x3fff;
488     VURegs* vu=(vunum==0)?&VU0:&VU1;
489    
490     return vu->Micro[addr];
491     }
492    
493     template<int vunum>
494     mem16_t __fastcall vuMicroRead16(u32 addr)
495     {
496     addr&=(vunum==0)?0xfff:0x3fff;
497     VURegs* vu=(vunum==0)?&VU0:&VU1;
498    
499     return *(u16*)&vu->Micro[addr];
500     }
501    
502     template<int vunum>
503     mem32_t __fastcall vuMicroRead32(u32 addr)
504     {
505     addr&=(vunum==0)?0xfff:0x3fff;
506     VURegs* vu=(vunum==0)?&VU0:&VU1;
507    
508     return *(u32*)&vu->Micro[addr];
509     }
510    
511     template<int vunum>
512     void __fastcall vuMicroRead64(u32 addr,mem64_t* data)
513     {
514     addr&=(vunum==0)?0xfff:0x3fff;
515     VURegs* vu=(vunum==0)?&VU0:&VU1;
516    
517     *data=*(u64*)&vu->Micro[addr];
518     }
519    
520     template<int vunum>
521     void __fastcall vuMicroRead128(u32 addr,mem128_t* data)
522     {
523     addr&=(vunum==0)?0xfff:0x3fff;
524     VURegs* vu=(vunum==0)?&VU0:&VU1;
525    
526     data[0]=*(u64*)&vu->Micro[addr];
527     data[1]=*(u64*)&vu->Micro[addr+8];
528     }
529    
530     // Profiled VU writes: Happen very infrequently, with exception of BIOS initialization (at most twice per
531     // frame in-game, and usually none at all after BIOS), so cpu clears aren't much of a big deal.
532    
533     template<int vunum, bool dynrec>
534     void __fastcall vuMicroWrite8(u32 addr,mem8_t data)
535     {
536     addr &= (vunum==0) ? 0xfff : 0x3fff;
537     VURegs& vu = (vunum==0) ? VU0 : VU1;
538    
539     if (vu.Micro[addr]!=data)
540     {
541     ClearVuFunc<vunum, dynrec>(addr&(~7), 8); // Clear before writing new data (clearing 8 bytes because an instruction is 8 bytes) (cottonvibes)
542     vu.Micro[addr]=data;
543     }
544     }
545    
546     template<int vunum, bool dynrec>
547     void __fastcall vuMicroWrite16(u32 addr,mem16_t data)
548     {
549     addr &= (vunum==0) ? 0xfff : 0x3fff;
550     VURegs& vu = (vunum==0) ? VU0 : VU1;
551    
552     if (*(u16*)&vu.Micro[addr]!=data)
553     {
554     ClearVuFunc<vunum, dynrec>(addr&(~7), 8);
555     *(u16*)&vu.Micro[addr]=data;
556     }
557     }
558    
559     template<int vunum, bool dynrec>
560     void __fastcall vuMicroWrite32(u32 addr,mem32_t data)
561     {
562     addr &= (vunum==0) ? 0xfff : 0x3fff;
563     VURegs& vu = (vunum==0) ? VU0 : VU1;
564    
565     if (*(u32*)&vu.Micro[addr]!=data)
566     {
567     ClearVuFunc<vunum, dynrec>(addr&(~7), 8);
568     *(u32*)&vu.Micro[addr]=data;
569     }
570     }
571    
572     template<int vunum, bool dynrec>
573     void __fastcall vuMicroWrite64(u32 addr,const mem64_t* data)
574     {
575     addr &= (vunum==0) ? 0xfff : 0x3fff;
576     VURegs& vu = (vunum==0) ? VU0 : VU1;
577    
578     if (*(u64*)&vu.Micro[addr]!=data[0])
579     {
580     ClearVuFunc<vunum, dynrec>(addr&(~7), 8);
581     *(u64*)&vu.Micro[addr]=data[0];
582     }
583     }
584    
585     template<int vunum, bool dynrec>
586     void __fastcall vuMicroWrite128(u32 addr,const mem128_t* data)
587     {
588     addr &= (vunum==0) ? 0xfff : 0x3fff;
589     VURegs& vu = (vunum==0) ? VU0 : VU1;
590    
591     if (*(u64*)&vu.Micro[addr]!=data[0] || *(u64*)&vu.Micro[addr+8]!=data[1])
592     {
593     ClearVuFunc<vunum, dynrec>(addr&(~7), 16);
594     *(u64*)&vu.Micro[addr]=data[0];
595     *(u64*)&vu.Micro[addr+8]=data[1];
596     }
597     }
598    
599     void memSetPageAddr(u32 vaddr, u32 paddr)
600     {
601     //Console.WriteLn("memSetPageAddr: %8.8x -> %8.8x", vaddr, paddr);
602    
603     vtlb_VMap(vaddr,paddr,0x1000);
604    
605     }
606    
607     void memClearPageAddr(u32 vaddr)
608     {
609     //Console.WriteLn("memClearPageAddr: %8.8x", vaddr);
610    
611     vtlb_VMapUnmap(vaddr,0x1000); // -> whut ?
612    
613     #ifdef FULLTLB
614     // memLUTRK[vaddr >> 12] = 0;
615     // memLUTWK[vaddr >> 12] = 0;
616     #endif
617     }
618    
619     ///////////////////////////////////////////////////////////////////////////
620     // PS2 Memory Init / Reset / Shutdown
621    
622     class mmap_PageFaultHandler : public EventListener_PageFault
623     {
624     protected:
625     void OnPageFaultEvent( const PageFaultInfo& info, bool& handled );
626     };
627    
628     mmap_PageFaultHandler mmap_faultHandler;
629    
630     static const uint m_allMemSize =
631     Ps2MemSize::Rom + Ps2MemSize::Rom1 + Ps2MemSize::Rom2 + Ps2MemSize::ERom +
632     Ps2MemSize::Base + Ps2MemSize::Hardware + Ps2MemSize::Scratch;
633    
634     static u8* m_psAllMem = NULL;
635    
636     void memAlloc()
637     {
638     if( m_psAllMem == NULL )
639     m_psAllMem = vtlb_malloc( m_allMemSize, 4096 );
640    
641     if( m_psAllMem == NULL)
642     throw Exception::OutOfMemory( "memAlloc > failed to allocate PS2's base ram/rom/scratchpad." );
643    
644     u8* curpos = m_psAllMem;
645     psM = curpos; curpos += Ps2MemSize::Base;
646     psR = curpos; curpos += Ps2MemSize::Rom;
647     psR1 = curpos; curpos += Ps2MemSize::Rom1;
648     psR2 = curpos; curpos += Ps2MemSize::Rom2;
649     psER = curpos; curpos += Ps2MemSize::ERom;
650     psH = curpos; curpos += Ps2MemSize::Hardware;
651     psS = curpos; //curpos += Ps2MemSize::Scratch;
652    
653     Source_PageFault.Add( mmap_faultHandler );
654     }
655    
656     void memShutdown()
657     {
658     Source_PageFault.Remove( mmap_faultHandler );
659    
660     vtlb_free( m_psAllMem, m_allMemSize );
661     m_psAllMem = NULL;
662     psM = psR = psR1 = psR2 = psER = psS = psH = NULL;
663     vtlb_Term();
664     }
665    
666     void memBindConditionalHandlers()
667     {
668     if( hw_by_page[0xf] == -1 ) return;
669    
670     vtlbMemR32FP* page0F32( EmuConfig.Speedhacks.IntcStat ? hwRead32_page_0F_INTC_HACK : hwRead32_page_0F );
671     vtlbMemR64FP* page0F64( EmuConfig.Speedhacks.IntcStat ? hwRead64_generic_INTC_HACK : hwRead64_generic );
672    
673     vtlb_ReassignHandler( hw_by_page[0xf],
674     _ext_memRead8<1>, _ext_memRead16<1>, page0F32, page0F64, hwRead128_generic,
675     _ext_memWrite8<1>, _ext_memWrite16<1>, hwWrite32_page_0F, hwWrite64_generic, hwWrite128_generic
676     );
677     }
678    
679     // Resets memory mappings, unmaps TLBs, reloads bios roms, etc.
680     void memReset()
681     {
682     // VTLB Protection Preparations.
683     //HostSys::MemProtect( m_psAllMem, m_allMemSize, Protect_ReadWrite );
684    
685     // Note!! Ideally the vtlb should only be initialized once, and then subsequent
686     // resets of the system hardware would only clear vtlb mappings, but since the
687     // rest of the emu is not really set up to support a "soft" reset of that sort
688     // we opt for the hard/safe version.
689    
690     memzero_ptr<m_allMemSize>( m_psAllMem );
691     #ifdef ENABLECACHE
692     memset(pCache,0,sizeof(_cacheS)*64);
693     #endif
694    
695     vtlb_Init();
696    
697     null_handler = vtlb_RegisterHandler(nullRead8, nullRead16, nullRead32, nullRead64, nullRead128,
698     nullWrite8, nullWrite16, nullWrite32, nullWrite64, nullWrite128);
699    
700     tlb_fallback_0 = vtlb_RegisterHandlerTempl1(_ext_mem,0);
701     tlb_fallback_3 = vtlb_RegisterHandlerTempl1(_ext_mem,3);
702     tlb_fallback_4 = vtlb_RegisterHandlerTempl1(_ext_mem,4);
703     tlb_fallback_5 = vtlb_RegisterHandlerTempl1(_ext_mem,5);
704     //tlb_fallback_6 = vtlb_RegisterHandlerTempl1(_ext_mem,6);
705     tlb_fallback_7 = vtlb_RegisterHandlerTempl1(_ext_mem,7);
706     tlb_fallback_8 = vtlb_RegisterHandlerTempl1(_ext_mem,8);
707    
708     // Dynarec versions of VUs
709     vu0_micro_mem[0] = vtlb_RegisterHandlerTempl2(vuMicro,0,true);
710     vu1_micro_mem[0] = vtlb_RegisterHandlerTempl2(vuMicro,1,true);
711    
712     // Interpreter versions of VUs
713     vu0_micro_mem[1] = vtlb_RegisterHandlerTempl2(vuMicro,0,false);
714     vu1_micro_mem[1] = vtlb_RegisterHandlerTempl2(vuMicro,1,false);
715    
716     //////////////////////////////////////////////////////////////////////////////////////////
717     // IOP's "secret" Hardware Register mapping, accessible from the EE (and meant for use
718     // by debugging or BIOS only). The IOP's hw regs are divided into three main pages in
719     // the 0x1f80 segment, and then another oddball page for CDVD in the 0x1f40 segment.
720     //
721    
722     using namespace IopMemory;
723    
724     tlb_fallback_2 = vtlb_RegisterHandler(
725     iopHwRead8_generic, iopHwRead16_generic, iopHwRead32_generic, _ext_memRead64<2>, _ext_memRead128<2>,
726     iopHwWrite8_generic, iopHwWrite16_generic, iopHwWrite32_generic, _ext_memWrite64<2>, _ext_memWrite128<2>
727     );
728    
729     iopHw_by_page_01 = vtlb_RegisterHandler(
730     iopHwRead8_Page1, iopHwRead16_Page1, iopHwRead32_Page1, _ext_memRead64<2>, _ext_memRead128<2>,
731     iopHwWrite8_Page1, iopHwWrite16_Page1, iopHwWrite32_Page1, _ext_memWrite64<2>, _ext_memWrite128<2>
732     );
733    
734     iopHw_by_page_03 = vtlb_RegisterHandler(
735     iopHwRead8_Page3, iopHwRead16_Page3, iopHwRead32_Page3, _ext_memRead64<2>, _ext_memRead128<2>,
736     iopHwWrite8_Page3, iopHwWrite16_Page3, iopHwWrite32_Page3, _ext_memWrite64<2>, _ext_memWrite128<2>
737     );
738    
739     iopHw_by_page_08 = vtlb_RegisterHandler(
740     iopHwRead8_Page8, iopHwRead16_Page8, iopHwRead32_Page8, _ext_memRead64<2>, _ext_memRead128<2>,
741     iopHwWrite8_Page8, iopHwWrite16_Page8, iopHwWrite32_Page8, _ext_memWrite64<2>, _ext_memWrite128<2>
742     );
743    
744    
745     //////////////////////////////////////////////////////////////////////////////////////////
746     // psHw Optimized Mappings
747     // The HW Registers have been split into pages to improve optimization.
748     // Anything not explicitly mapped into one of the hw_by_page handlers will be handled
749     // by the default/generic tlb_fallback_1 handler.
750    
751     tlb_fallback_1 = vtlb_RegisterHandler(
752     _ext_memRead8<1>, _ext_memRead16<1>, hwRead32_generic, hwRead64_generic, hwRead128_generic,
753     _ext_memWrite8<1>, _ext_memWrite16<1>, hwWrite32_generic, hwWrite64_generic, hwWrite128_generic
754     );
755    
756     hw_by_page[0x0] = vtlb_RegisterHandler(
757     _ext_memRead8<1>, _ext_memRead16<1>, hwRead32_page_00, hwRead64_page_00, hwRead128_page_00,
758     _ext_memWrite8<1>, _ext_memWrite16<1>, hwWrite32_page_00, hwWrite64_page_00, hwWrite128_generic
759     );
760    
761     hw_by_page[0x1] = vtlb_RegisterHandler(
762     _ext_memRead8<1>, _ext_memRead16<1>, hwRead32_page_01, hwRead64_page_01, hwRead128_page_01,
763     _ext_memWrite8<1>, _ext_memWrite16<1>, hwWrite32_page_01, hwWrite64_page_01, hwWrite128_generic
764     );
765    
766     hw_by_page[0x2] = vtlb_RegisterHandler(
767     _ext_memRead8<1>, _ext_memRead16<1>, hwRead32_page_02, hwRead64_page_02, hwRead128_page_02,
768     _ext_memWrite8<1>, _ext_memWrite16<1>, hwWrite32_page_02, hwWrite64_page_02, hwWrite128_generic
769     );
770    
771     hw_by_page[0x3] = vtlb_RegisterHandler(
772     _ext_memRead8<1>, _ext_memRead16<1>, hwRead32_generic, hwRead64_generic, hwRead128_generic,
773     _ext_memWrite8<1>, _ext_memWrite16<1>, hwWrite32_page_03, hwWrite64_page_03, hwWrite128_generic
774     );
775    
776     hw_by_page[0x4] = vtlb_RegisterHandler(
777     _ext_memRead8<1>, _ext_memRead16<1>, hwRead32_generic, hwRead64_generic, ReadFIFO_page_4,
778     _ext_memWrite8<1>, _ext_memWrite16<1>, hwWrite32_generic, hwWrite64_generic, WriteFIFO_page_4
779     );
780    
781     hw_by_page[0x5] = vtlb_RegisterHandler(
782     _ext_memRead8<1>, _ext_memRead16<1>, hwRead32_generic, hwRead64_generic, ReadFIFO_page_5,
783     _ext_memWrite8<1>, _ext_memWrite16<1>, hwWrite32_generic, hwWrite64_generic, WriteFIFO_page_5
784     );
785    
786     hw_by_page[0x6] = vtlb_RegisterHandler(
787     _ext_memRead8<1>, _ext_memRead16<1>, hwRead32_generic, hwRead64_generic, ReadFIFO_page_6,
788     _ext_memWrite8<1>, _ext_memWrite16<1>, hwWrite32_generic, hwWrite64_generic, WriteFIFO_page_6
789     );
790    
791     hw_by_page[0x7] = vtlb_RegisterHandler(
792     _ext_memRead8<1>, _ext_memRead16<1>, hwRead32_generic, hwRead64_generic, ReadFIFO_page_7,
793     _ext_memWrite8<1>, _ext_memWrite16<1>, hwWrite32_generic, hwWrite64_generic, WriteFIFO_page_7
794     );
795    
796     hw_by_page[0xb] = vtlb_RegisterHandler(
797     _ext_memRead8<1>, _ext_memRead16<1>, hwRead32_generic, hwRead64_generic, hwRead128_generic,
798     _ext_memWrite8<1>, _ext_memWrite16<1>, hwWrite32_page_0B, hwWrite64_generic, hwWrite128_generic
799     );
800    
801     hw_by_page[0xe] = vtlb_RegisterHandler(
802     _ext_memRead8<1>, _ext_memRead16<1>, hwRead32_generic, hwRead64_generic, hwRead128_generic,
803     _ext_memWrite8<1>, _ext_memWrite16<1>, hwWrite32_page_0E, hwWrite64_page_0E, hwWrite128_generic
804     );
805    
806     hw_by_page[0xf] = vtlb_NewHandler();
807     memBindConditionalHandlers();
808    
809     //////////////////////////////////////////////////////////////////////
810     // GS Optimized Mappings
811    
812     tlb_fallback_6 = vtlb_RegisterHandler(
813     _ext_memRead8<6>, _ext_memRead16<6>, _ext_memRead32<6>, _ext_memRead64<6>, _ext_memRead128<6>,
814     _ext_memWrite8<6>, _ext_memWrite16<6>, _ext_memWrite32<6>, gsWrite64_generic, gsWrite128_generic
815     );
816    
817     gs_page_0 = vtlb_RegisterHandler(
818     _ext_memRead8<6>, _ext_memRead16<6>, _ext_memRead32<6>, _ext_memRead64<6>, _ext_memRead128<6>,
819     _ext_memWrite8<6>, _ext_memWrite16<6>, _ext_memWrite32<6>, gsWrite64_page_00, gsWrite128_page_00
820     );
821    
822     gs_page_1 = vtlb_RegisterHandler(
823     _ext_memRead8<6>, _ext_memRead16<6>, _ext_memRead32<6>, _ext_memRead64<6>, _ext_memRead128<6>,
824     _ext_memWrite8<6>, _ext_memWrite16<6>, _ext_memWrite32<6>, gsWrite64_page_01, gsWrite128_page_01
825     );
826    
827     //vtlb_Reset();
828    
829     // reset memLUT (?)
830     //vtlb_VMap(0x00000000,0x00000000,0x20000000);
831     //vtlb_VMapUnmap(0x20000000,0x60000000);
832    
833     memMapPhy();
834     memMapVUmicro();
835     memMapKernelMem();
836     memMapSupervisorMem();
837     memMapUserMem();
838     memSetKernelMode();
839    
840     vtlb_VMap(0x00000000,0x00000000,0x20000000);
841     vtlb_VMapUnmap(0x20000000,0x60000000);
842    
843     LoadBIOS();
844     }
845    
846     //////////////////////////////////////////////////////////////////////////////////////////
847     // Memory Protection and Block Checking, vtlb Style!
848     //
849     // For the first time code is recompiled (executed), the PS2 ram page for that code is
850     // protected using Virtual Memory (mprotect). If the game modifies its own code then this
851     // protection causes an *exception* to be raised (signal in Linux), which is handled by
852     // unprotecting the page and switching the recompiled block to "manual" protection.
853     //
854     // Manual protection uses a simple brute-force memcmp of the recompiled code to the code
855     // currently in RAM for *each time* the block is executed. Fool-proof, but slow, which
856     // is why we default to using the exception-based protection scheme described above.
857     //
858     // Why manual blocks? Because many games contain code and data in the same 4k page, so
859     // we *cannot* automatically recompile and reprotect pages, lest we end up recompiling and
860     // reprotecting them constantly (Which would be very slow). As a counter, the R5900 side
861     // of the block checking code does try to periodically re-protect blocks [going from manual
862     // back to protected], so that blocks which underwent a single invalidation don't need to
863     // incur a permanent performance penalty.
864     //
865     // Page Granularity:
866     // Fortunately for us MIPS and x86 use the same page granularity for TLB and memory
867     // protection, so we can use a 1:1 correspondence when protecting pages. Page granularity
868     // is 4096 (4k), which is why you'll see a lot of 0xfff's, >><< 12's, and 0x1000's in the
869     // code below.
870     //
871    
872     enum vtlb_ProtectionMode
873     {
874     ProtMode_None = 0, // page is 'unaccounted' -- neither protected nor unprotected
875     ProtMode_Write, // page is under write protection (exception handler)
876     ProtMode_Manual // page is under manual protection (self-checked at execution)
877     };
878    
879     struct vtlb_PageProtectionInfo
880     {
881     // Ram De-mapping -- used to convert fully translated/mapped offsets into psM back
882     // into their originating ps2 physical ram address. Values are assigned when pages
883     // are marked for protection.
884     u32 ReverseRamMap;
885    
886     vtlb_ProtectionMode Mode;
887     };
888    
889     static __aligned16 vtlb_PageProtectionInfo m_PageProtectInfo[Ps2MemSize::Base >> 12];
890    
891    
892     // returns:
893     // -1 - unchecked block (resides in ROM, thus is integrity is constant)
894     // 0 - page is using Write protection
895     // 1 - page is using manual protection (recompiler must include execution-time
896     // self-checking of block integrity)
897     //
898     int mmap_GetRamPageInfo( u32 paddr )
899     {
900     paddr &= ~0xfff;
901    
902     uptr ptr = (uptr)PSM( paddr );
903     uptr rampage = ptr - (uptr)psM;
904    
905     if (rampage >= Ps2MemSize::Base)
906     return -1; //not in ram, no tracking done ...
907    
908     rampage >>= 12;
909     return ( m_PageProtectInfo[rampage].Mode == ProtMode_Manual ) ? 1 : 0;
910     }
911    
912     // paddr - physically mapped address
913     void mmap_MarkCountedRamPage( u32 paddr )
914     {
915     paddr &= ~0xfff;
916    
917     uptr ptr = (uptr)PSM( paddr );
918     int rampage = (ptr - (uptr)psM) >> 12;
919    
920     // Important: reassign paddr here, since TLB changes could alter the paddr->psM mapping
921     // (and clear blocks accordingly), but don't necessarily clear the protection status.
922     m_PageProtectInfo[rampage].ReverseRamMap = paddr;
923    
924     if( m_PageProtectInfo[rampage].Mode == ProtMode_Write )
925     return; // skip town if we're already protected.
926    
927     DbgCon.WriteLn( Color_Gray, (m_PageProtectInfo[rampage].Mode == ProtMode_Manual) ?
928     "dyna_page_reset @ 0x%05x" : "Write-protected page @ 0x%05x",
929     paddr>>12
930     );
931    
932     m_PageProtectInfo[rampage].Mode = ProtMode_Write;
933     HostSys::MemProtect( &psM[rampage<<12], __pagesize, Protect_ReadOnly );
934     }
935    
936     // offset - offset of address relative to psM.
937     static __forceinline void mmap_ClearCpuBlock( uint offset )
938     {
939     int rampage = offset >> 12;
940    
941     // Assertion: This function should never be run on a block that's already under
942     // manual protection. Indicates a logic error in the recompiler or protection code.
943     pxAssertMsg( m_PageProtectInfo[rampage].Mode != ProtMode_Manual,
944     "Attempted to clear a block that is already under manual protection." );
945    
946     HostSys::MemProtect( &psM[rampage<<12], __pagesize, Protect_ReadWrite );
947     m_PageProtectInfo[rampage].Mode = ProtMode_Manual;
948     Cpu->Clear( m_PageProtectInfo[rampage].ReverseRamMap, 0x400 );
949     }
950    
951     void mmap_PageFaultHandler::OnPageFaultEvent( const PageFaultInfo& info, bool& handled )
952     {
953     // get bad virtual address
954     uptr offset = info.addr - (uptr)psM;
955     if( offset >= Ps2MemSize::Base ) return;
956    
957     mmap_ClearCpuBlock( offset );
958     handled = true;
959     }
960    
961     // Clears all block tracking statuses, manual protection flags, and write protection.
962     // This does not clear any recompiler blocks. It is assumed (and necessary) for the caller
963     // to ensure the EErec is also reset in conjunction with calling this function.
964     void mmap_ResetBlockTracking()
965     {
966     DevCon.WriteLn( "vtlb/mmap: Block Tracking reset..." );
967     memzero( m_PageProtectInfo );
968     HostSys::MemProtect( psM, Ps2MemSize::Base, Protect_ReadWrite );
969     }

  ViewVC Help
Powered by ViewVC 1.1.22