/[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 31 - (show 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 /* 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