/[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 280 - (hide annotations) (download)
Thu Dec 23 12:02:12 2010 UTC (9 years, 6 months ago) by william
File size: 27324 byte(s)
re-commit (had local access denied errors when committing)
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 <wx/file.h>
39    
40 william 62 #include "IopCommon.h"
41 william 31 #include "VUmicro.h"
42     #include "GS.h"
43 william 62
44     #include "ps2/HwInternal.h"
45 william 31 #include "ps2/BiosTools.h"
46    
47 william 280 #include "Utilities/PageFaultSource.h"
48    
49 william 31 #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     #define CHECK_MEM(mem) //MyMemCheck(mem)
81    
82     void MyMemCheck(u32 mem)
83     {
84     if( mem == 0x1c02f2a0 )
85     Console.WriteLn("yo; (mem == 0x1c02f2a0) in MyMemCheck...");
86     }
87    
88     /////////////////////////////
89     // REGULAR MEM START
90     /////////////////////////////
91 william 62 static vtlbHandler
92     null_handler,
93 william 31
94 william 62 tlb_fallback_0,
95     tlb_fallback_2,
96     tlb_fallback_3,
97     tlb_fallback_4,
98     tlb_fallback_5,
99     tlb_fallback_6,
100     tlb_fallback_7,
101     tlb_fallback_8,
102 william 31
103 william 62 vu0_micro_mem,
104     vu1_micro_mem,
105 william 31
106 william 62 hw_by_page[0x10] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
107 william 31
108 william 62 gs_page_0,
109     gs_page_1,
110 william 31
111 william 62 iopHw_by_page_01,
112     iopHw_by_page_03,
113     iopHw_by_page_08;
114 william 31
115 william 62
116 william 31 void memMapVUmicro()
117     {
118 william 62 // VU0/VU1 micro mem (instructions)
119     // (Like IOP memory, these are generally only used by the EE Bios kernel during
120     // boot-up. Applications/games are "supposed" to use the thread-safe VIF instead;
121     // or must ensure all VIF/GIF transfers are finished and all VUmicro execution stopped
122     // prior to accessing VU memory directly).
123 william 31
124 william 62 // The VU0 mapping actually repeats 4 times across the mapped range, but we don't bother
125     // to manually mirror it here because the indirect memory handler for it (see vuMicroRead*
126     // functions below) automatically mask and wrap the address for us.
127    
128     vtlb_MapHandler(vu0_micro_mem,0x11000000,0x00004000);
129     vtlb_MapHandler(vu1_micro_mem,0x11008000,0x00004000);
130    
131     // VU0/VU1 memory (data)
132     // VU0 is 4k, mirrored 4 times across a 16k area.
133 william 31 vtlb_MapBlock(VU0.Mem,0x11004000,0x00004000,0x1000);
134     vtlb_MapBlock(VU1.Mem,0x1100c000,0x00004000);
135     }
136    
137     void memMapPhy()
138     {
139     // Main memory
140 william 280 vtlb_MapBlock(eeMem->Main, 0x00000000,Ps2MemSize::MainRam);//mirrored on first 256 mb ?
141 william 31 // High memory, uninstalled on the configuration we emulate
142 william 280 vtlb_MapHandler(null_handler, Ps2MemSize::MainRam, 0x10000000 - Ps2MemSize::MainRam);
143 william 31
144     // Various ROMs (all read-only)
145 william 62 vtlb_MapBlock(eeMem->ROM, 0x1fc00000,Ps2MemSize::Rom);
146     vtlb_MapBlock(eeMem->ROM1, 0x1e000000,Ps2MemSize::Rom1);
147     vtlb_MapBlock(eeMem->ROM2, 0x1e400000,Ps2MemSize::Rom2);
148     vtlb_MapBlock(eeMem->EROM, 0x1e040000,Ps2MemSize::ERom);
149 william 31
150     // IOP memory
151     // (used by the EE Bios Kernel during initial hardware initialization, Apps/Games
152     // are "supposed" to use the thread-safe SIF instead.)
153 william 273 vtlb_MapBlock(iopMem->Main,0x1c000000,0x00800000);
154 william 31
155     // Generic Handlers; These fallback to mem* stuff...
156 william 280 vtlb_MapHandler(tlb_fallback_7,0x14000000, _64kb);
157     vtlb_MapHandler(tlb_fallback_4,0x18000000, _64kb);
158     vtlb_MapHandler(tlb_fallback_5,0x1a000000, _64kb);
159     vtlb_MapHandler(tlb_fallback_6,0x12000000, _64kb);
160     vtlb_MapHandler(tlb_fallback_8,0x1f000000, _64kb);
161     vtlb_MapHandler(tlb_fallback_3,0x1f400000, _64kb);
162     vtlb_MapHandler(tlb_fallback_2,0x1f800000, _64kb);
163     vtlb_MapHandler(tlb_fallback_8,0x1f900000, _64kb);
164 william 31
165     // Hardware Register Handlers : specialized/optimized per-page handling of HW register accesses
166     // (note that hw_by_page handles are assigned in memReset prior to calling this function)
167    
168 william 62 for( uint i=0; i<16; ++i)
169     vtlb_MapHandler(hw_by_page[i], 0x10000000 + (0x01000 * i), 0x01000);
170    
171 william 31 vtlb_MapHandler(gs_page_0, 0x12000000, 0x01000);
172     vtlb_MapHandler(gs_page_1, 0x12001000, 0x01000);
173    
174     // "Secret" IOP HW mappings - Used by EE Bios Kernel during boot and generally
175     // left untouched after that, as per EE/IOP thread safety rules.
176    
177     vtlb_MapHandler(iopHw_by_page_01, 0x1f801000, 0x01000);
178     vtlb_MapHandler(iopHw_by_page_03, 0x1f803000, 0x01000);
179     vtlb_MapHandler(iopHw_by_page_08, 0x1f808000, 0x01000);
180    
181     }
182    
183     //Why is this required ?
184     void memMapKernelMem()
185     {
186     //lower 512 mb: direct map
187     //vtlb_VMap(0x00000000,0x00000000,0x20000000);
188     //0x8* mirror
189 william 280 vtlb_VMap(0x80000000, 0x00000000, _1mb*512);
190 william 31 //0xa* mirror
191 william 280 vtlb_VMap(0xA0000000, 0x00000000, _1mb*512);
192 william 31 }
193    
194     //what do do with these ?
195     void memMapSupervisorMem()
196     {
197     }
198    
199     void memMapUserMem()
200     {
201     }
202    
203     static mem8_t __fastcall nullRead8(u32 mem) {
204     MEM_LOG("Read uninstalled memory at address %08x", mem);
205     return 0;
206     }
207     static mem16_t __fastcall nullRead16(u32 mem) {
208     MEM_LOG("Read uninstalled memory at address %08x", mem);
209     return 0;
210     }
211     static mem32_t __fastcall nullRead32(u32 mem) {
212     MEM_LOG("Read uninstalled memory at address %08x", mem);
213     return 0;
214     }
215     static void __fastcall nullRead64(u32 mem, mem64_t *out) {
216     MEM_LOG("Read uninstalled memory at address %08x", mem);
217     *out = 0;
218     }
219     static void __fastcall nullRead128(u32 mem, mem128_t *out) {
220     MEM_LOG("Read uninstalled memory at address %08x", mem);
221 william 62 ZeroQWC(out);
222 william 31 }
223     static void __fastcall nullWrite8(u32 mem, mem8_t value)
224     {
225     MEM_LOG("Write uninstalled memory at address %08x", mem);
226     }
227     static void __fastcall nullWrite16(u32 mem, mem16_t value)
228     {
229     MEM_LOG("Write uninstalled memory at address %08x", mem);
230     }
231     static void __fastcall nullWrite32(u32 mem, mem32_t value)
232     {
233     MEM_LOG("Write uninstalled memory at address %08x", mem);
234     }
235     static void __fastcall nullWrite64(u32 mem, const mem64_t *value)
236     {
237     MEM_LOG("Write uninstalled memory at address %08x", mem);
238     }
239     static void __fastcall nullWrite128(u32 mem, const mem128_t *value)
240     {
241     MEM_LOG("Write uninstalled memory at address %08x", mem);
242     }
243    
244     template<int p>
245 william 62 static mem8_t __fastcall _ext_memRead8 (u32 mem)
246 william 31 {
247     switch (p)
248     {
249     case 3: // psh4
250     return psxHw4Read8(mem);
251     case 6: // gsm
252     return gsRead8(mem);
253     case 7: // dev9
254     {
255     mem8_t retval = DEV9read8(mem & ~0xa4000000);
256     Console.WriteLn("DEV9 read8 %8.8lx: %2.2lx", mem & ~0xa4000000, retval);
257     return retval;
258     }
259     }
260    
261     MEM_LOG("Unknown Memory Read8 from address %8.8x", mem);
262     cpuTlbMissR(mem, cpuRegs.branch);
263     return 0;
264     }
265    
266     template<int p>
267 william 62 static mem16_t __fastcall _ext_memRead16(u32 mem)
268 william 31 {
269     switch (p)
270     {
271     case 4: // b80
272     MEM_LOG("b800000 Memory read16 address %x", mem);
273     return 0;
274     case 5: // ba0
275     return ba0R16(mem);
276     case 6: // gsm
277     return gsRead16(mem);
278    
279     case 7: // dev9
280     {
281     mem16_t retval = DEV9read16(mem & ~0xa4000000);
282     Console.WriteLn("DEV9 read16 %8.8lx: %4.4lx", mem & ~0xa4000000, retval);
283     return retval;
284     }
285    
286     case 8: // spu2
287     return SPU2read(mem);
288     }
289     MEM_LOG("Unknown Memory read16 from address %8.8x", mem);
290     cpuTlbMissR(mem, cpuRegs.branch);
291     return 0;
292     }
293    
294     template<int p>
295 william 62 static mem32_t __fastcall _ext_memRead32(u32 mem)
296 william 31 {
297     switch (p)
298     {
299     case 6: // gsm
300     return gsRead32(mem);
301     case 7: // dev9
302     {
303     mem32_t retval = DEV9read32(mem & ~0xa4000000);
304     Console.WriteLn("DEV9 read32 %8.8lx: %8.8lx", mem & ~0xa4000000, retval);
305     return retval;
306     }
307     }
308    
309     MEM_LOG("Unknown Memory read32 from address %8.8x (Status=%8.8x)", mem, cpuRegs.CP0.n.Status.val);
310     cpuTlbMissR(mem, cpuRegs.branch);
311     return 0;
312     }
313    
314     template<int p>
315 william 62 static void __fastcall _ext_memRead64(u32 mem, mem64_t *out)
316 william 31 {
317     switch (p)
318     {
319     case 6: // gsm
320     *out = gsRead64(mem); return;
321     }
322    
323     MEM_LOG("Unknown Memory read64 from address %8.8x", mem);
324     cpuTlbMissR(mem, cpuRegs.branch);
325     }
326    
327     template<int p>
328 william 62 static void __fastcall _ext_memRead128(u32 mem, mem128_t *out)
329 william 31 {
330     switch (p)
331     {
332     //case 1: // hwm
333     // hwRead128(mem & ~0xa0000000, out); return;
334     case 6: // gsm
335 william 62 CopyQWC(out,PS2GS_BASE(mem));
336     return;
337 william 31 }
338    
339     MEM_LOG("Unknown Memory read128 from address %8.8x", mem);
340     cpuTlbMissR(mem, cpuRegs.branch);
341     }
342    
343     template<int p>
344 william 62 static void __fastcall _ext_memWrite8 (u32 mem, mem8_t value)
345 william 31 {
346     switch (p) {
347     case 3: // psh4
348     psxHw4Write8(mem, value); return;
349     case 6: // gsm
350     gsWrite8(mem, value); return;
351     case 7: // dev9
352     DEV9write8(mem & ~0xa4000000, value);
353     Console.WriteLn("DEV9 write8 %8.8lx: %2.2lx", mem & ~0xa4000000, value);
354     return;
355     }
356    
357     MEM_LOG("Unknown Memory write8 to address %x with data %2.2x", mem, value);
358     cpuTlbMissW(mem, cpuRegs.branch);
359     }
360 william 62
361 william 31 template<int p>
362 william 62 static void __fastcall _ext_memWrite16(u32 mem, mem16_t value)
363 william 31 {
364     switch (p) {
365     case 5: // ba0
366     MEM_LOG("ba00000 Memory write16 to address %x with data %x", mem, value);
367     return;
368     case 6: // gsm
369     gsWrite16(mem, value); return;
370     case 7: // dev9
371     DEV9write16(mem & ~0xa4000000, value);
372     Console.WriteLn("DEV9 write16 %8.8lx: %4.4lx", mem & ~0xa4000000, value);
373     return;
374     case 8: // spu2
375     SPU2write(mem, value); return;
376     }
377     MEM_LOG("Unknown Memory write16 to address %x with data %4.4x", mem, value);
378     cpuTlbMissW(mem, cpuRegs.branch);
379     }
380    
381     template<int p>
382 william 62 static void __fastcall _ext_memWrite32(u32 mem, mem32_t value)
383 william 31 {
384     switch (p) {
385     case 6: // gsm
386     gsWrite32(mem, value); return;
387     case 7: // dev9
388     DEV9write32(mem & ~0xa4000000, value);
389     Console.WriteLn("DEV9 write32 %8.8lx: %8.8lx", mem & ~0xa4000000, value);
390     return;
391     }
392     MEM_LOG("Unknown Memory write32 to address %x with data %8.8x", mem, value);
393     cpuTlbMissW(mem, cpuRegs.branch);
394     }
395    
396     template<int p>
397 william 62 static void __fastcall _ext_memWrite64(u32 mem, const mem64_t* value)
398 william 31 {
399    
400     /*switch (p) {
401     //case 1: // hwm
402     // hwWrite64(mem & ~0xa0000000, *value);
403     // return;
404     //case 6: // gsm
405     // gsWrite64(mem & ~0xa0000000, *value); return;
406     }*/
407    
408     MEM_LOG("Unknown Memory write64 to address %x with data %8.8x_%8.8x", mem, (u32)(*value>>32), (u32)*value);
409     cpuTlbMissW(mem, cpuRegs.branch);
410     }
411    
412     template<int p>
413 william 62 static void __fastcall _ext_memWrite128(u32 mem, const mem128_t *value)
414 william 31 {
415     /*switch (p) {
416     //case 1: // hwm
417     // hwWrite128(mem & ~0xa0000000, value);
418     // return;
419     //case 6: // gsm
420     // mem &= ~0xa0000000;
421     // gsWrite64(mem, value[0]);
422     // gsWrite64(mem+8, value[1]); return;
423     }*/
424    
425     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]);
426     cpuTlbMissW(mem, cpuRegs.branch);
427     }
428    
429     #define vtlb_RegisterHandlerTempl1(nam,t) vtlb_RegisterHandler(nam##Read8<t>,nam##Read16<t>,nam##Read32<t>,nam##Read64<t>,nam##Read128<t>, \
430     nam##Write8<t>,nam##Write16<t>,nam##Write32<t>,nam##Write64<t>,nam##Write128<t>)
431    
432     typedef void __fastcall ClearFunc_t( u32 addr, u32 qwc );
433    
434 william 62 template<int vunum>
435     static __fi void ClearVuFunc( u32 addr, u32 size )
436 william 31 {
437 william 62 if( vunum==0 )
438     CpuVU0->Clear(addr,size);
439 william 31 else
440 william 62 CpuVU1->Clear(addr,size);
441 william 31 }
442    
443     template<int vunum>
444 william 62 static mem8_t __fastcall vuMicroRead8(u32 addr)
445 william 31 {
446     addr&=(vunum==0)?0xfff:0x3fff;
447     VURegs* vu=(vunum==0)?&VU0:&VU1;
448    
449     return vu->Micro[addr];
450     }
451    
452     template<int vunum>
453 william 62 static mem16_t __fastcall vuMicroRead16(u32 addr)
454 william 31 {
455     addr&=(vunum==0)?0xfff:0x3fff;
456     VURegs* vu=(vunum==0)?&VU0:&VU1;
457    
458     return *(u16*)&vu->Micro[addr];
459     }
460    
461     template<int vunum>
462 william 62 static mem32_t __fastcall vuMicroRead32(u32 addr)
463 william 31 {
464     addr&=(vunum==0)?0xfff:0x3fff;
465     VURegs* vu=(vunum==0)?&VU0:&VU1;
466    
467     return *(u32*)&vu->Micro[addr];
468     }
469    
470     template<int vunum>
471 william 62 static void __fastcall vuMicroRead64(u32 addr,mem64_t* data)
472 william 31 {
473     addr&=(vunum==0)?0xfff:0x3fff;
474     VURegs* vu=(vunum==0)?&VU0:&VU1;
475    
476     *data=*(u64*)&vu->Micro[addr];
477     }
478    
479     template<int vunum>
480 william 62 static void __fastcall vuMicroRead128(u32 addr,mem128_t* data)
481 william 31 {
482     addr&=(vunum==0)?0xfff:0x3fff;
483     VURegs* vu=(vunum==0)?&VU0:&VU1;
484    
485 william 62 CopyQWC(data,&vu->Micro[addr]);
486 william 31 }
487    
488     // Profiled VU writes: Happen very infrequently, with exception of BIOS initialization (at most twice per
489     // frame in-game, and usually none at all after BIOS), so cpu clears aren't much of a big deal.
490    
491 william 62 template<int vunum>
492     static void __fastcall vuMicroWrite8(u32 addr,mem8_t data)
493 william 31 {
494     addr &= (vunum==0) ? 0xfff : 0x3fff;
495     VURegs& vu = (vunum==0) ? VU0 : VU1;
496    
497     if (vu.Micro[addr]!=data)
498     {
499 william 62 ClearVuFunc<vunum>(addr&(~7), 8); // Clear before writing new data (clearing 8 bytes because an instruction is 8 bytes) (cottonvibes)
500 william 31 vu.Micro[addr]=data;
501     }
502     }
503    
504 william 62 template<int vunum>
505     static void __fastcall vuMicroWrite16(u32 addr,mem16_t data)
506 william 31 {
507     addr &= (vunum==0) ? 0xfff : 0x3fff;
508     VURegs& vu = (vunum==0) ? VU0 : VU1;
509    
510     if (*(u16*)&vu.Micro[addr]!=data)
511     {
512 william 62 ClearVuFunc<vunum>(addr&(~7), 8);
513 william 31 *(u16*)&vu.Micro[addr]=data;
514     }
515     }
516    
517 william 62 template<int vunum>
518     static void __fastcall vuMicroWrite32(u32 addr,mem32_t data)
519 william 31 {
520     addr &= (vunum==0) ? 0xfff : 0x3fff;
521     VURegs& vu = (vunum==0) ? VU0 : VU1;
522    
523     if (*(u32*)&vu.Micro[addr]!=data)
524     {
525 william 62 ClearVuFunc<vunum>(addr&(~7), 8);
526 william 31 *(u32*)&vu.Micro[addr]=data;
527     }
528     }
529    
530 william 62 template<int vunum>
531     static void __fastcall vuMicroWrite64(u32 addr,const mem64_t* data)
532 william 31 {
533     addr &= (vunum==0) ? 0xfff : 0x3fff;
534     VURegs& vu = (vunum==0) ? VU0 : VU1;
535    
536     if (*(u64*)&vu.Micro[addr]!=data[0])
537     {
538 william 62 ClearVuFunc<vunum>(addr&(~7), 8);
539 william 31 *(u64*)&vu.Micro[addr]=data[0];
540     }
541     }
542    
543 william 62 template<int vunum>
544     static void __fastcall vuMicroWrite128(u32 addr,const mem128_t* data)
545 william 31 {
546     addr &= (vunum==0) ? 0xfff : 0x3fff;
547     VURegs& vu = (vunum==0) ? VU0 : VU1;
548    
549 william 62 if ((u128&)vu.Micro[addr] != *data)
550 william 31 {
551 william 62 ClearVuFunc<vunum>(addr&(~7), 16);
552     CopyQWC(&vu.Micro[addr],data);
553 william 31 }
554     }
555    
556     void memSetPageAddr(u32 vaddr, u32 paddr)
557     {
558     //Console.WriteLn("memSetPageAddr: %8.8x -> %8.8x", vaddr, paddr);
559    
560     vtlb_VMap(vaddr,paddr,0x1000);
561    
562     }
563    
564     void memClearPageAddr(u32 vaddr)
565     {
566     //Console.WriteLn("memClearPageAddr: %8.8x", vaddr);
567    
568     vtlb_VMapUnmap(vaddr,0x1000); // -> whut ?
569    
570     #ifdef FULLTLB
571     // memLUTRK[vaddr >> 12] = 0;
572     // memLUTWK[vaddr >> 12] = 0;
573     #endif
574     }
575    
576     ///////////////////////////////////////////////////////////////////////////
577     // PS2 Memory Init / Reset / Shutdown
578    
579     class mmap_PageFaultHandler : public EventListener_PageFault
580     {
581 william 280 public:
582 william 31 void OnPageFaultEvent( const PageFaultInfo& info, bool& handled );
583     };
584    
585 william 280 static mmap_PageFaultHandler* mmap_faultHandler = NULL;
586 william 31
587 william 62 EEVM_MemoryAllocMess* eeMem = NULL;
588     __pagealigned u8 eeHw[Ps2MemSize::Hardware];
589 william 31
590    
591     void memBindConditionalHandlers()
592     {
593     if( hw_by_page[0xf] == -1 ) return;
594    
595 william 62 if (EmuConfig.Speedhacks.IntcStat)
596     {
597     vtlbMemR16FP* page0F16(hwRead16_page_0F_INTC_HACK);
598     vtlbMemR32FP* page0F32(hwRead32_page_0F_INTC_HACK);
599     //vtlbMemR64FP* page0F64(hwRead64_generic_INTC_HACK);
600 william 31
601 william 62 vtlb_ReassignHandler( hw_by_page[0xf],
602     hwRead8<0x0f>, page0F16, page0F32, hwRead64<0x0f>, hwRead128<0x0f>,
603     hwWrite8<0x0f>, hwWrite16<0x0f>, hwWrite32<0x0f>, hwWrite64<0x0f>, hwWrite128<0x0f>
604     );
605     }
606     else
607     {
608     vtlbMemR16FP* page0F16(hwRead16<0x0f>);
609     vtlbMemR32FP* page0F32(hwRead32<0x0f>);
610     //vtlbMemR64FP* page0F64(hwRead64<0x0f>);
611    
612     vtlb_ReassignHandler( hw_by_page[0xf],
613     hwRead8<0x0f>, page0F16, page0F32, hwRead64<0x0f>, hwRead128<0x0f>,
614     hwWrite8<0x0f>, hwWrite16<0x0f>, hwWrite32<0x0f>, hwWrite64<0x0f>, hwWrite128<0x0f>
615     );
616     }
617 william 31 }
618    
619 william 280
620     // --------------------------------------------------------------------------------------
621     // eeMemoryReserve (implementations)
622     // --------------------------------------------------------------------------------------
623     eeMemoryReserve::eeMemoryReserve()
624     : _parent( L"EE Main Memory", sizeof(*eeMem) )
625     {
626     }
627    
628     void eeMemoryReserve::Reserve()
629     {
630     _parent::Reserve(HostMemoryMap::EEmem);
631     //_parent::Reserve(EmuConfig.HostMap.IOP);
632     }
633    
634     void eeMemoryReserve::Commit()
635     {
636     _parent::Commit();
637     eeMem = (EEVM_MemoryAllocMess*)m_reserve.GetPtr();
638     }
639    
640 william 31 // Resets memory mappings, unmaps TLBs, reloads bios roms, etc.
641 william 280 void eeMemoryReserve::Reset()
642 william 31 {
643 william 280 if (!mmap_faultHandler)
644     {
645     pxAssume(Source_PageFault);
646     mmap_faultHandler = new mmap_PageFaultHandler();
647     }
648    
649     _parent::Reset();
650 william 31
651     // Note!! Ideally the vtlb should only be initialized once, and then subsequent
652     // resets of the system hardware would only clear vtlb mappings, but since the
653     // rest of the emu is not really set up to support a "soft" reset of that sort
654     // we opt for the hard/safe version.
655    
656 william 280 pxAssume( eeMem );
657 william 273
658 william 31 #ifdef ENABLECACHE
659     memset(pCache,0,sizeof(_cacheS)*64);
660     #endif
661    
662     vtlb_Init();
663    
664     null_handler = vtlb_RegisterHandler(nullRead8, nullRead16, nullRead32, nullRead64, nullRead128,
665     nullWrite8, nullWrite16, nullWrite32, nullWrite64, nullWrite128);
666    
667     tlb_fallback_0 = vtlb_RegisterHandlerTempl1(_ext_mem,0);
668     tlb_fallback_3 = vtlb_RegisterHandlerTempl1(_ext_mem,3);
669     tlb_fallback_4 = vtlb_RegisterHandlerTempl1(_ext_mem,4);
670     tlb_fallback_5 = vtlb_RegisterHandlerTempl1(_ext_mem,5);
671     tlb_fallback_7 = vtlb_RegisterHandlerTempl1(_ext_mem,7);
672     tlb_fallback_8 = vtlb_RegisterHandlerTempl1(_ext_mem,8);
673    
674     // Dynarec versions of VUs
675 william 62 vu0_micro_mem = vtlb_RegisterHandlerTempl1(vuMicro,0);
676     vu1_micro_mem = vtlb_RegisterHandlerTempl1(vuMicro,1);
677 william 31
678     //////////////////////////////////////////////////////////////////////////////////////////
679     // IOP's "secret" Hardware Register mapping, accessible from the EE (and meant for use
680     // by debugging or BIOS only). The IOP's hw regs are divided into three main pages in
681     // the 0x1f80 segment, and then another oddball page for CDVD in the 0x1f40 segment.
682     //
683    
684     using namespace IopMemory;
685    
686     tlb_fallback_2 = vtlb_RegisterHandler(
687     iopHwRead8_generic, iopHwRead16_generic, iopHwRead32_generic, _ext_memRead64<2>, _ext_memRead128<2>,
688     iopHwWrite8_generic, iopHwWrite16_generic, iopHwWrite32_generic, _ext_memWrite64<2>, _ext_memWrite128<2>
689     );
690    
691     iopHw_by_page_01 = vtlb_RegisterHandler(
692     iopHwRead8_Page1, iopHwRead16_Page1, iopHwRead32_Page1, _ext_memRead64<2>, _ext_memRead128<2>,
693     iopHwWrite8_Page1, iopHwWrite16_Page1, iopHwWrite32_Page1, _ext_memWrite64<2>, _ext_memWrite128<2>
694     );
695    
696     iopHw_by_page_03 = vtlb_RegisterHandler(
697     iopHwRead8_Page3, iopHwRead16_Page3, iopHwRead32_Page3, _ext_memRead64<2>, _ext_memRead128<2>,
698     iopHwWrite8_Page3, iopHwWrite16_Page3, iopHwWrite32_Page3, _ext_memWrite64<2>, _ext_memWrite128<2>
699     );
700    
701     iopHw_by_page_08 = vtlb_RegisterHandler(
702     iopHwRead8_Page8, iopHwRead16_Page8, iopHwRead32_Page8, _ext_memRead64<2>, _ext_memRead128<2>,
703     iopHwWrite8_Page8, iopHwWrite16_Page8, iopHwWrite32_Page8, _ext_memWrite64<2>, _ext_memWrite128<2>
704     );
705    
706    
707     // psHw Optimized Mappings
708     // The HW Registers have been split into pages to improve optimization.
709 william 62
710     #define hwHandlerTmpl(page) \
711     hwRead8<page>, hwRead16<page>, hwRead32<page>, hwRead64<page>, hwRead128<page>, \
712     hwWrite8<page>, hwWrite16<page>,hwWrite32<page>,hwWrite64<page>,hwWrite128<page>
713 william 31
714 william 62 hw_by_page[0x0] = vtlb_RegisterHandler( hwHandlerTmpl(0x00) );
715     hw_by_page[0x1] = vtlb_RegisterHandler( hwHandlerTmpl(0x01) );
716     hw_by_page[0x2] = vtlb_RegisterHandler( hwHandlerTmpl(0x02) );
717     hw_by_page[0x3] = vtlb_RegisterHandler( hwHandlerTmpl(0x03) );
718     hw_by_page[0x4] = vtlb_RegisterHandler( hwHandlerTmpl(0x04) );
719     hw_by_page[0x5] = vtlb_RegisterHandler( hwHandlerTmpl(0x05) );
720     hw_by_page[0x6] = vtlb_RegisterHandler( hwHandlerTmpl(0x06) );
721     hw_by_page[0x7] = vtlb_RegisterHandler( hwHandlerTmpl(0x07) );
722     hw_by_page[0x8] = vtlb_RegisterHandler( hwHandlerTmpl(0x08) );
723     hw_by_page[0x9] = vtlb_RegisterHandler( hwHandlerTmpl(0x09) );
724     hw_by_page[0xa] = vtlb_RegisterHandler( hwHandlerTmpl(0x0a) );
725     hw_by_page[0xb] = vtlb_RegisterHandler( hwHandlerTmpl(0x0b) );
726     hw_by_page[0xc] = vtlb_RegisterHandler( hwHandlerTmpl(0x0c) );
727     hw_by_page[0xd] = vtlb_RegisterHandler( hwHandlerTmpl(0x0d) );
728     hw_by_page[0xe] = vtlb_RegisterHandler( hwHandlerTmpl(0x0e) );
729     hw_by_page[0xf] = vtlb_NewHandler(); // redefined later based on speedhacking prefs
730 william 31 memBindConditionalHandlers();
731    
732     //////////////////////////////////////////////////////////////////////
733     // GS Optimized Mappings
734    
735     tlb_fallback_6 = vtlb_RegisterHandler(
736     _ext_memRead8<6>, _ext_memRead16<6>, _ext_memRead32<6>, _ext_memRead64<6>, _ext_memRead128<6>,
737     _ext_memWrite8<6>, _ext_memWrite16<6>, _ext_memWrite32<6>, gsWrite64_generic, gsWrite128_generic
738     );
739    
740     gs_page_0 = vtlb_RegisterHandler(
741     _ext_memRead8<6>, _ext_memRead16<6>, _ext_memRead32<6>, _ext_memRead64<6>, _ext_memRead128<6>,
742     _ext_memWrite8<6>, _ext_memWrite16<6>, _ext_memWrite32<6>, gsWrite64_page_00, gsWrite128_page_00
743     );
744    
745     gs_page_1 = vtlb_RegisterHandler(
746     _ext_memRead8<6>, _ext_memRead16<6>, _ext_memRead32<6>, _ext_memRead64<6>, _ext_memRead128<6>,
747     _ext_memWrite8<6>, _ext_memWrite16<6>, _ext_memWrite32<6>, gsWrite64_page_01, gsWrite128_page_01
748     );
749    
750     //vtlb_Reset();
751    
752     // reset memLUT (?)
753     //vtlb_VMap(0x00000000,0x00000000,0x20000000);
754     //vtlb_VMapUnmap(0x20000000,0x60000000);
755    
756     memMapPhy();
757     memMapVUmicro();
758     memMapKernelMem();
759     memMapSupervisorMem();
760     memMapUserMem();
761     memSetKernelMode();
762    
763     vtlb_VMap(0x00000000,0x00000000,0x20000000);
764     vtlb_VMapUnmap(0x20000000,0x60000000);
765    
766     LoadBIOS();
767     }
768    
769 william 280 void eeMemoryReserve::Decommit()
770     {
771     _parent::Decommit();
772     eeMem = NULL;
773     }
774    
775     void eeMemoryReserve::Release()
776     {
777     safe_delete(mmap_faultHandler);
778     _parent::Release();
779     eeMem = NULL;
780     vtlb_Term();
781     }
782    
783    
784     // ===========================================================================================
785     // Memory Protection and Block Checking, vtlb Style!
786     // ===========================================================================================
787 william 31 // For the first time code is recompiled (executed), the PS2 ram page for that code is
788     // protected using Virtual Memory (mprotect). If the game modifies its own code then this
789     // protection causes an *exception* to be raised (signal in Linux), which is handled by
790     // unprotecting the page and switching the recompiled block to "manual" protection.
791     //
792     // Manual protection uses a simple brute-force memcmp of the recompiled code to the code
793     // currently in RAM for *each time* the block is executed. Fool-proof, but slow, which
794     // is why we default to using the exception-based protection scheme described above.
795     //
796     // Why manual blocks? Because many games contain code and data in the same 4k page, so
797     // we *cannot* automatically recompile and reprotect pages, lest we end up recompiling and
798     // reprotecting them constantly (Which would be very slow). As a counter, the R5900 side
799     // of the block checking code does try to periodically re-protect blocks [going from manual
800     // back to protected], so that blocks which underwent a single invalidation don't need to
801     // incur a permanent performance penalty.
802     //
803     // Page Granularity:
804     // Fortunately for us MIPS and x86 use the same page granularity for TLB and memory
805     // protection, so we can use a 1:1 correspondence when protecting pages. Page granularity
806     // is 4096 (4k), which is why you'll see a lot of 0xfff's, >><< 12's, and 0x1000's in the
807     // code below.
808     //
809    
810     enum vtlb_ProtectionMode
811     {
812     ProtMode_None = 0, // page is 'unaccounted' -- neither protected nor unprotected
813     ProtMode_Write, // page is under write protection (exception handler)
814     ProtMode_Manual // page is under manual protection (self-checked at execution)
815     };
816    
817     struct vtlb_PageProtectionInfo
818     {
819 william 280 // Ram De-mapping -- used to convert fully translated/mapped offsets (which reside with
820     // in the eeMem->Main block) back into their originating ps2 physical ram address.
821     // Values are assigned when pages are marked for protection. since pages are automatically
822     // cleared and reset when TLB-remapped, stale values in this table (due to on-the-fly TLB
823     // changes) will be re-assigned the next time the page is accessed.
824 william 31 u32 ReverseRamMap;
825    
826     vtlb_ProtectionMode Mode;
827     };
828    
829 william 280 static __aligned16 vtlb_PageProtectionInfo m_PageProtectInfo[Ps2MemSize::MainRam >> 12];
830 william 31
831    
832     // returns:
833     // -1 - unchecked block (resides in ROM, thus is integrity is constant)
834     // 0 - page is using Write protection
835     // 1 - page is using manual protection (recompiler must include execution-time
836     // self-checking of block integrity)
837     //
838     int mmap_GetRamPageInfo( u32 paddr )
839     {
840 william 280 pxAssume( eeMem );
841    
842 william 31 paddr &= ~0xfff;
843    
844     uptr ptr = (uptr)PSM( paddr );
845 william 62 uptr rampage = ptr - (uptr)eeMem->Main;
846 william 31
847 william 280 if (rampage >= Ps2MemSize::MainRam)
848 william 31 return -1; //not in ram, no tracking done ...
849    
850     rampage >>= 12;
851     return ( m_PageProtectInfo[rampage].Mode == ProtMode_Manual ) ? 1 : 0;
852     }
853    
854 william 280 // paddr - physically mapped PS2 address
855 william 31 void mmap_MarkCountedRamPage( u32 paddr )
856     {
857 william 280 pxAssume( eeMem );
858    
859 william 31 paddr &= ~0xfff;
860    
861     uptr ptr = (uptr)PSM( paddr );
862 william 62 int rampage = (ptr - (uptr)eeMem->Main) >> 12;
863 william 31
864 william 280 // Important: Update the ReverseRamMap here because TLB changes could alter the paddr
865     // mapping into eeMem->Main.
866    
867 william 31 m_PageProtectInfo[rampage].ReverseRamMap = paddr;
868    
869     if( m_PageProtectInfo[rampage].Mode == ProtMode_Write )
870     return; // skip town if we're already protected.
871    
872 william 62 eeRecPerfLog.Write( (m_PageProtectInfo[rampage].Mode == ProtMode_Manual) ?
873     "Re-protecting page @ 0x%05x" : "Protected page @ 0x%05x",
874 william 31 paddr>>12
875     );
876    
877     m_PageProtectInfo[rampage].Mode = ProtMode_Write;
878 william 280 HostSys::MemProtect( &eeMem->Main[rampage<<12], __pagesize, PageAccess_ReadOnly() );
879 william 31 }
880    
881     // offset - offset of address relative to psM.
882 william 62 // All recompiled blocks belonging to the page are cleared, and any new blocks recompiled
883     // from code residing in this page will use manual protection.
884     static __fi void mmap_ClearCpuBlock( uint offset )
885 william 31 {
886 william 280 pxAssume( eeMem );
887    
888 william 31 int rampage = offset >> 12;
889    
890     // Assertion: This function should never be run on a block that's already under
891     // manual protection. Indicates a logic error in the recompiler or protection code.
892     pxAssertMsg( m_PageProtectInfo[rampage].Mode != ProtMode_Manual,
893     "Attempted to clear a block that is already under manual protection." );
894    
895 william 280 HostSys::MemProtect( &eeMem->Main[rampage<<12], __pagesize, PageAccess_ReadWrite() );
896 william 31 m_PageProtectInfo[rampage].Mode = ProtMode_Manual;
897     Cpu->Clear( m_PageProtectInfo[rampage].ReverseRamMap, 0x400 );
898     }
899    
900     void mmap_PageFaultHandler::OnPageFaultEvent( const PageFaultInfo& info, bool& handled )
901     {
902 william 280 pxAssume( eeMem );
903    
904 william 31 // get bad virtual address
905 william 62 uptr offset = info.addr - (uptr)eeMem->Main;
906 william 280 if( offset >= Ps2MemSize::MainRam ) return;
907 william 31
908     mmap_ClearCpuBlock( offset );
909     handled = true;
910     }
911    
912     // Clears all block tracking statuses, manual protection flags, and write protection.
913     // This does not clear any recompiler blocks. It is assumed (and necessary) for the caller
914     // to ensure the EErec is also reset in conjunction with calling this function.
915 william 62 // (this function is called by default from the eerecReset).
916 william 31 void mmap_ResetBlockTracking()
917     {
918 william 62 //DbgCon.WriteLn( "vtlb/mmap: Block Tracking reset..." );
919 william 31 memzero( m_PageProtectInfo );
920 william 280 if (eeMem) HostSys::MemProtect( eeMem->Main, Ps2MemSize::MainRam, PageAccess_ReadWrite() );
921 william 31 }

  ViewVC Help
Powered by ViewVC 1.1.22