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

Contents of /trunk/pcsx2/Memory.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 280 - (show annotations) (download)
Thu Dec 23 12:02:12 2010 UTC (9 years, 1 month ago) by william
File size: 27324 byte(s)
re-commit (had local access denied errors when committing)
1 /* 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 #include "IopCommon.h"
41 #include "VUmicro.h"
42 #include "GS.h"
43
44 #include "ps2/HwInternal.h"
45 #include "ps2/BiosTools.h"
46
47 #include "Utilities/PageFaultSource.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 #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 static vtlbHandler
92 null_handler,
93
94 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
103 vu0_micro_mem,
104 vu1_micro_mem,
105
106 hw_by_page[0x10] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
107
108 gs_page_0,
109 gs_page_1,
110
111 iopHw_by_page_01,
112 iopHw_by_page_03,
113 iopHw_by_page_08;
114
115
116 void memMapVUmicro()
117 {
118 // 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
124 // 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 vtlb_MapBlock(VU0.Mem,0x11004000,0x00004000,0x1000);
134 vtlb_MapBlock(VU1.Mem,0x1100c000,0x00004000);
135 }
136
137 void memMapPhy()
138 {
139 // Main memory
140 vtlb_MapBlock(eeMem->Main, 0x00000000,Ps2MemSize::MainRam);//mirrored on first 256 mb ?
141 // High memory, uninstalled on the configuration we emulate
142 vtlb_MapHandler(null_handler, Ps2MemSize::MainRam, 0x10000000 - Ps2MemSize::MainRam);
143
144 // Various ROMs (all read-only)
145 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
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 vtlb_MapBlock(iopMem->Main,0x1c000000,0x00800000);
154
155 // Generic Handlers; These fallback to mem* stuff...
156 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
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 for( uint i=0; i<16; ++i)
169 vtlb_MapHandler(hw_by_page[i], 0x10000000 + (0x01000 * i), 0x01000);
170
171 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 vtlb_VMap(0x80000000, 0x00000000, _1mb*512);
190 //0xa* mirror
191 vtlb_VMap(0xA0000000, 0x00000000, _1mb*512);
192 }
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 ZeroQWC(out);
222 }
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 static mem8_t __fastcall _ext_memRead8 (u32 mem)
246 {
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 static mem16_t __fastcall _ext_memRead16(u32 mem)
268 {
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 static mem32_t __fastcall _ext_memRead32(u32 mem)
296 {
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 static void __fastcall _ext_memRead64(u32 mem, mem64_t *out)
316 {
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 static void __fastcall _ext_memRead128(u32 mem, mem128_t *out)
329 {
330 switch (p)
331 {
332 //case 1: // hwm
333 // hwRead128(mem & ~0xa0000000, out); return;
334 case 6: // gsm
335 CopyQWC(out,PS2GS_BASE(mem));
336 return;
337 }
338
339 MEM_LOG("Unknown Memory read128 from address %8.8x", mem);
340 cpuTlbMissR(mem, cpuRegs.branch);
341 }
342
343 template<int p>
344 static void __fastcall _ext_memWrite8 (u32 mem, mem8_t value)
345 {
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
361 template<int p>
362 static void __fastcall _ext_memWrite16(u32 mem, mem16_t value)
363 {
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 static void __fastcall _ext_memWrite32(u32 mem, mem32_t value)
383 {
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 static void __fastcall _ext_memWrite64(u32 mem, const mem64_t* value)
398 {
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 static void __fastcall _ext_memWrite128(u32 mem, const mem128_t *value)
414 {
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 template<int vunum>
435 static __fi void ClearVuFunc( u32 addr, u32 size )
436 {
437 if( vunum==0 )
438 CpuVU0->Clear(addr,size);
439 else
440 CpuVU1->Clear(addr,size);
441 }
442
443 template<int vunum>
444 static mem8_t __fastcall vuMicroRead8(u32 addr)
445 {
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 static mem16_t __fastcall vuMicroRead16(u32 addr)
454 {
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 static mem32_t __fastcall vuMicroRead32(u32 addr)
463 {
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 static void __fastcall vuMicroRead64(u32 addr,mem64_t* data)
472 {
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 static void __fastcall vuMicroRead128(u32 addr,mem128_t* data)
481 {
482 addr&=(vunum==0)?0xfff:0x3fff;
483 VURegs* vu=(vunum==0)?&VU0:&VU1;
484
485 CopyQWC(data,&vu->Micro[addr]);
486 }
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 template<int vunum>
492 static void __fastcall vuMicroWrite8(u32 addr,mem8_t data)
493 {
494 addr &= (vunum==0) ? 0xfff : 0x3fff;
495 VURegs& vu = (vunum==0) ? VU0 : VU1;
496
497 if (vu.Micro[addr]!=data)
498 {
499 ClearVuFunc<vunum>(addr&(~7), 8); // Clear before writing new data (clearing 8 bytes because an instruction is 8 bytes) (cottonvibes)
500 vu.Micro[addr]=data;
501 }
502 }
503
504 template<int vunum>
505 static void __fastcall vuMicroWrite16(u32 addr,mem16_t data)
506 {
507 addr &= (vunum==0) ? 0xfff : 0x3fff;
508 VURegs& vu = (vunum==0) ? VU0 : VU1;
509
510 if (*(u16*)&vu.Micro[addr]!=data)
511 {
512 ClearVuFunc<vunum>(addr&(~7), 8);
513 *(u16*)&vu.Micro[addr]=data;
514 }
515 }
516
517 template<int vunum>
518 static void __fastcall vuMicroWrite32(u32 addr,mem32_t data)
519 {
520 addr &= (vunum==0) ? 0xfff : 0x3fff;
521 VURegs& vu = (vunum==0) ? VU0 : VU1;
522
523 if (*(u32*)&vu.Micro[addr]!=data)
524 {
525 ClearVuFunc<vunum>(addr&(~7), 8);
526 *(u32*)&vu.Micro[addr]=data;
527 }
528 }
529
530 template<int vunum>
531 static void __fastcall vuMicroWrite64(u32 addr,const mem64_t* data)
532 {
533 addr &= (vunum==0) ? 0xfff : 0x3fff;
534 VURegs& vu = (vunum==0) ? VU0 : VU1;
535
536 if (*(u64*)&vu.Micro[addr]!=data[0])
537 {
538 ClearVuFunc<vunum>(addr&(~7), 8);
539 *(u64*)&vu.Micro[addr]=data[0];
540 }
541 }
542
543 template<int vunum>
544 static void __fastcall vuMicroWrite128(u32 addr,const mem128_t* data)
545 {
546 addr &= (vunum==0) ? 0xfff : 0x3fff;
547 VURegs& vu = (vunum==0) ? VU0 : VU1;
548
549 if ((u128&)vu.Micro[addr] != *data)
550 {
551 ClearVuFunc<vunum>(addr&(~7), 16);
552 CopyQWC(&vu.Micro[addr],data);
553 }
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 public:
582 void OnPageFaultEvent( const PageFaultInfo& info, bool& handled );
583 };
584
585 static mmap_PageFaultHandler* mmap_faultHandler = NULL;
586
587 EEVM_MemoryAllocMess* eeMem = NULL;
588 __pagealigned u8 eeHw[Ps2MemSize::Hardware];
589
590
591 void memBindConditionalHandlers()
592 {
593 if( hw_by_page[0xf] == -1 ) return;
594
595 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
601 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 }
618
619
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 // Resets memory mappings, unmaps TLBs, reloads bios roms, etc.
641 void eeMemoryReserve::Reset()
642 {
643 if (!mmap_faultHandler)
644 {
645 pxAssume(Source_PageFault);
646 mmap_faultHandler = new mmap_PageFaultHandler();
647 }
648
649 _parent::Reset();
650
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 pxAssume( eeMem );
657
658 #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 vu0_micro_mem = vtlb_RegisterHandlerTempl1(vuMicro,0);
676 vu1_micro_mem = vtlb_RegisterHandlerTempl1(vuMicro,1);
677
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
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
714 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 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 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 // 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 // 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 u32 ReverseRamMap;
825
826 vtlb_ProtectionMode Mode;
827 };
828
829 static __aligned16 vtlb_PageProtectionInfo m_PageProtectInfo[Ps2MemSize::MainRam >> 12];
830
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 pxAssume( eeMem );
841
842 paddr &= ~0xfff;
843
844 uptr ptr = (uptr)PSM( paddr );
845 uptr rampage = ptr - (uptr)eeMem->Main;
846
847 if (rampage >= Ps2MemSize::MainRam)
848 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 // paddr - physically mapped PS2 address
855 void mmap_MarkCountedRamPage( u32 paddr )
856 {
857 pxAssume( eeMem );
858
859 paddr &= ~0xfff;
860
861 uptr ptr = (uptr)PSM( paddr );
862 int rampage = (ptr - (uptr)eeMem->Main) >> 12;
863
864 // Important: Update the ReverseRamMap here because TLB changes could alter the paddr
865 // mapping into eeMem->Main.
866
867 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 eeRecPerfLog.Write( (m_PageProtectInfo[rampage].Mode == ProtMode_Manual) ?
873 "Re-protecting page @ 0x%05x" : "Protected page @ 0x%05x",
874 paddr>>12
875 );
876
877 m_PageProtectInfo[rampage].Mode = ProtMode_Write;
878 HostSys::MemProtect( &eeMem->Main[rampage<<12], __pagesize, PageAccess_ReadOnly() );
879 }
880
881 // offset - offset of address relative to psM.
882 // 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 {
886 pxAssume( eeMem );
887
888 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 HostSys::MemProtect( &eeMem->Main[rampage<<12], __pagesize, PageAccess_ReadWrite() );
896 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 pxAssume( eeMem );
903
904 // get bad virtual address
905 uptr offset = info.addr - (uptr)eeMem->Main;
906 if( offset >= Ps2MemSize::MainRam ) return;
907
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 // (this function is called by default from the eerecReset).
916 void mmap_ResetBlockTracking()
917 {
918 //DbgCon.WriteLn( "vtlb/mmap: Block Tracking reset..." );
919 memzero( m_PageProtectInfo );
920 if (eeMem) HostSys::MemProtect( eeMem->Main, Ps2MemSize::MainRam, PageAccess_ReadWrite() );
921 }

  ViewVC Help
Powered by ViewVC 1.1.22