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

Contents of /trunk/pcsx2/vtlb.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 62 - (show annotations) (download)
Tue Sep 7 11:08:22 2010 UTC (10 years, 2 months ago) by william
File size: 20170 byte(s)
Auto Commited Import of: pcsx2-0.9.7-r3738-debug in ./trunk
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 EE physical map :
18 [0000 0000,1000 0000) -> Ram (mirrored ?)
19 [1000 0000,1400 0000) -> Registers
20 [1400 0000,1fc0 0000) -> Reserved (ingored writes, 'random' reads)
21 [1fc0 0000,2000 0000) -> Boot ROM
22
23 [2000 0000,4000 0000) -> Unmapped (BUS ERROR)
24 [4000 0000,8000 0000) -> "Extended memory", probably unmapped (BUS ERROR) on retail ps2's :)
25 [8000 0000,FFFF FFFF] -> Unmapped (BUS ERROR)
26
27 vtlb/phy only supports the [0000 0000,2000 0000) region, with 4k pages.
28 vtlb/vmap supports mapping to either of these locations, or some other (externaly) specified address.
29 */
30
31 #include "PrecompiledHeader.h"
32
33 #include "Common.h"
34 #include "vtlb.h"
35 #include "COP0.h"
36
37 #include "R5900Exceptions.h"
38
39 using namespace R5900;
40 using namespace vtlb_private;
41
42 #define verify pxAssume
43
44 namespace vtlb_private
45 {
46 __aligned(64) MapData vtlbdata;
47 }
48
49 static vtlbHandler vtlbHandlerCount=0;
50
51 static vtlbHandler DefaultPhyHandler;
52 static vtlbHandler UnmappedVirtHandler0;
53 static vtlbHandler UnmappedVirtHandler1;
54 static vtlbHandler UnmappedPhyHandler0;
55 static vtlbHandler UnmappedPhyHandler1;
56
57
58 // --------------------------------------------------------------------------------------
59 // Interpreter Implementations of VTLB Memory Operations.
60 // --------------------------------------------------------------------------------------
61 // See recVTLB.cpp for the dynarec versions.
62
63 template< typename DataType >
64 DataType __fastcall vtlb_memRead(u32 addr)
65 {
66 static const uint DataSize = sizeof(DataType) * 8;
67 u32 vmv=vtlbdata.vmap[addr>>VTLB_PAGE_BITS];
68 s32 ppf=addr+vmv;
69
70 if (!(ppf<0))
71 return *reinterpret_cast<DataType*>(ppf);
72
73 //has to: translate, find function, call function
74 u32 hand=(u8)vmv;
75 u32 paddr=ppf-hand+0x80000000;
76 //Console.WriteLn("Translated 0x%08X to 0x%08X", addr,paddr);
77 //return reinterpret_cast<TemplateHelper<DataSize,false>::HandlerType*>(vtlbdata.RWFT[TemplateHelper<DataSize,false>::sidx][0][hand])(paddr,data);
78
79 switch( DataSize )
80 {
81 case 8: return ((vtlbMemR8FP*)vtlbdata.RWFT[0][0][hand])(paddr);
82 case 16: return ((vtlbMemR16FP*)vtlbdata.RWFT[1][0][hand])(paddr);
83 case 32: return ((vtlbMemR32FP*)vtlbdata.RWFT[2][0][hand])(paddr);
84
85 jNO_DEFAULT;
86 }
87
88 return 0; // technically unreachable, but suppresses warnings.
89 }
90
91 void __fastcall vtlb_memRead64(u32 mem, mem64_t *out)
92 {
93 u32 vmv=vtlbdata.vmap[mem>>VTLB_PAGE_BITS];
94 s32 ppf=mem+vmv;
95
96 if (!(ppf<0))
97 {
98 *out = *(mem64_t*)ppf;
99 }
100 else
101 {
102 //has to: translate, find function, call function
103 u32 hand=(u8)vmv;
104 u32 paddr=ppf-hand+0x80000000;
105 //Console.WriteLn("Translated 0x%08X to 0x%08X", addr,paddr);
106
107 ((vtlbMemR64FP*)vtlbdata.RWFT[3][0][hand])(paddr, out);
108 }
109 }
110 void __fastcall vtlb_memRead128(u32 mem, mem128_t *out)
111 {
112 u32 vmv=vtlbdata.vmap[mem>>VTLB_PAGE_BITS];
113 s32 ppf=mem+vmv;
114
115 if (!(ppf<0))
116 {
117 CopyQWC(out,(void*)ppf);
118 }
119 else
120 {
121 //has to: translate, find function, call function
122 u32 hand=(u8)vmv;
123 u32 paddr=ppf-hand+0x80000000;
124 //Console.WriteLn("Translated 0x%08X to 0x%08X", addr,paddr);
125
126 ((vtlbMemR128FP*)vtlbdata.RWFT[4][0][hand])(paddr, out);
127 }
128 }
129
130 template< typename DataType >
131 void __fastcall vtlb_memWrite(u32 addr, DataType data)
132 {
133 static const uint DataSize = sizeof(DataType) * 8;
134
135 u32 vmv=vtlbdata.vmap[addr>>VTLB_PAGE_BITS];
136 s32 ppf=addr+vmv;
137 if (!(ppf<0))
138 {
139 *reinterpret_cast<DataType*>(ppf)=data;
140 }
141 else
142 {
143 //has to: translate, find function, call function
144 u32 hand=(u8)vmv;
145 u32 paddr=ppf-hand+0x80000000;
146 //Console.WriteLn("Translated 0x%08X to 0x%08X", addr,paddr);
147
148 switch( DataSize )
149 {
150 case 8: return ((vtlbMemW8FP*)vtlbdata.RWFT[0][1][hand])(paddr, (u8)data);
151 case 16: return ((vtlbMemW16FP*)vtlbdata.RWFT[1][1][hand])(paddr, (u16)data);
152 case 32: return ((vtlbMemW32FP*)vtlbdata.RWFT[2][1][hand])(paddr, (u32)data);
153
154 jNO_DEFAULT;
155 }
156 }
157 }
158
159 void __fastcall vtlb_memWrite64(u32 mem, const mem64_t* value)
160 {
161 u32 vmv=vtlbdata.vmap[mem>>VTLB_PAGE_BITS];
162 s32 ppf=mem+vmv;
163 if (!(ppf<0))
164 {
165 *(mem64_t*)ppf = *value;
166 }
167 else
168 {
169 //has to: translate, find function, call function
170 u32 hand=(u8)vmv;
171 u32 paddr=ppf-hand+0x80000000;
172 //Console.WriteLn("Translated 0x%08X to 0x%08X", addr,paddr);
173
174 ((vtlbMemW64FP*)vtlbdata.RWFT[3][1][hand])(paddr, value);
175 }
176 }
177
178 void __fastcall vtlb_memWrite128(u32 mem, const mem128_t *value)
179 {
180 u32 vmv=vtlbdata.vmap[mem>>VTLB_PAGE_BITS];
181 s32 ppf=mem+vmv;
182 if (!(ppf<0))
183 {
184 CopyQWC((void*)ppf, value);
185 }
186 else
187 {
188 //has to: translate, find function, call function
189 u32 hand=(u8)vmv;
190 u32 paddr=ppf-hand+0x80000000;
191 //Console.WriteLn("Translated 0x%08X to 0x%08X", addr,paddr);
192
193 ((vtlbMemW128FP*)vtlbdata.RWFT[4][1][hand])(paddr, value);
194 }
195 }
196
197 template mem8_t vtlb_memRead<mem8_t>(u32 mem);
198 template mem16_t vtlb_memRead<mem16_t>(u32 mem);
199 template mem32_t vtlb_memRead<mem32_t>(u32 mem);
200 template void vtlb_memWrite<mem8_t>(u32 mem, mem8_t data);
201 template void vtlb_memWrite<mem16_t>(u32 mem, mem16_t data);
202 template void vtlb_memWrite<mem32_t>(u32 mem, mem32_t data);
203
204 // --------------------------------------------------------------------------------------
205 // TLB Miss / BusError Handlers
206 // --------------------------------------------------------------------------------------
207 // These are valid VM memory errors that should typically be handled by the VM itself via
208 // its own cpu exception system.
209 //
210 // [TODO] Add first-chance debugging hooks to these exceptions!
211 //
212 // Important recompiler note: Mid-block Exception handling isn't reliable *yet* because
213 // memory ops don't flush the PC prior to invoking the indirect handlers.
214
215 // Generates a tlbMiss Exception
216 static __ri void vtlb_Miss(u32 addr,u32 mode)
217 {
218 if( IsDevBuild )
219 Cpu->ThrowCpuException( R5900Exception::TLBMiss( addr, !!mode ) );
220 else
221 Console.Error( R5900Exception::TLBMiss( addr, !!mode ).FormatMessage() );
222 }
223
224 // BusError exception: more serious than a TLB miss. If properly emulated the PS2 kernel
225 // itself would invoke a diagnostic/assertion screen that displays the cpu state at the
226 // time of the exception.
227 static __ri void vtlb_BusError(u32 addr,u32 mode)
228 {
229 if( IsDevBuild )
230 Cpu->ThrowCpuException( R5900Exception::BusError( addr, !!mode ) );
231 else
232 Console.Error( R5900Exception::TLBMiss( addr, !!mode ).FormatMessage() );
233 }
234
235 #define _tmpl(ret) template<typename OperandType, u32 saddr> ret __fastcall
236
237 _tmpl(OperandType) vtlbUnmappedVReadSm(u32 addr) { vtlb_Miss(addr|saddr,0); return 0; }
238 _tmpl(void) vtlbUnmappedVReadLg(u32 addr,OperandType* data) { vtlb_Miss(addr|saddr,0); }
239 _tmpl(void) vtlbUnmappedVWriteSm(u32 addr,OperandType data) { vtlb_Miss(addr|saddr,1); }
240 _tmpl(void) vtlbUnmappedVWriteLg(u32 addr,const OperandType* data) { vtlb_Miss(addr|saddr,1); }
241
242 _tmpl(OperandType) vtlbUnmappedPReadSm(u32 addr) { vtlb_BusError(addr|saddr,0); return 0; }
243 _tmpl(void) vtlbUnmappedPReadLg(u32 addr,OperandType* data) { vtlb_BusError(addr|saddr,0); }
244 _tmpl(void) vtlbUnmappedPWriteSm(u32 addr,OperandType data) { vtlb_BusError(addr|saddr,1); }
245 _tmpl(void) vtlbUnmappedPWriteLg(u32 addr,const OperandType* data) { vtlb_BusError(addr|saddr,1); }
246
247 #undef _tmpl
248
249 // --------------------------------------------------------------------------------------
250 // VTLB mapping errors
251 // --------------------------------------------------------------------------------------
252 // These errors are assertion/logic errors that should never occur if PCSX2 has been initialized
253 // properly. All addressable physical memory should be configured as TLBMiss or Bus Error.
254 //
255
256 static mem8_t __fastcall vtlbDefaultPhyRead8(u32 addr)
257 {
258 Console.Error("vtlbDefaultPhyRead8: 0x%08X", addr);
259 pxFailDev("(VTLB) Attempted read from an unmapped physical address.");
260 return 0;
261 }
262
263 static mem16_t __fastcall vtlbDefaultPhyRead16(u32 addr)
264 {
265 Console.Error("vtlbDefaultPhyRead16: 0x%08X", addr);
266 pxFailDev("(VTLB) Attempted read from an unmapped physical address.");
267 return 0;
268 }
269
270 static mem32_t __fastcall vtlbDefaultPhyRead32(u32 addr)
271 {
272 Console.Error("vtlbDefaultPhyRead32: 0x%08X", addr);
273 pxFailDev("(VTLB) Attempted read from an unmapped physical address.");
274 return 0;
275 }
276
277 static void __fastcall vtlbDefaultPhyRead64(u32 addr, mem64_t* dest)
278 {
279 Console.Error("vtlbDefaultPhyRead64: 0x%08X", addr);
280 pxFailDev("(VTLB) Attempted read from an unmapped physical address.");
281 }
282
283 static void __fastcall vtlbDefaultPhyRead128(u32 addr, mem128_t* dest)
284 {
285 Console.Error("vtlbDefaultPhyRead128: 0x%08X", addr);
286 pxFailDev("(VTLB) Attempted read from an unmapped physical address.");
287 }
288
289 static void __fastcall vtlbDefaultPhyWrite8(u32 addr, mem8_t data)
290 {
291 Console.Error("vtlbDefaultPhyWrite8: 0x%08X",addr);
292 pxFailDev("(VTLB) Attempted write to an unmapped physical address.");
293 }
294
295 static void __fastcall vtlbDefaultPhyWrite16(u32 addr, mem16_t data)
296 {
297 Console.Error("vtlbDefaultPhyWrite16: 0x%08X",addr);
298 pxFailDev("(VTLB) Attempted write to an unmapped physical address.");
299 }
300
301 static void __fastcall vtlbDefaultPhyWrite32(u32 addr, mem32_t data)
302 {
303 Console.Error("vtlbDefaultPhyWrite32: 0x%08X",addr);
304 pxFailDev("(VTLB) Attempted write to an unmapped physical address.");
305 }
306
307 static void __fastcall vtlbDefaultPhyWrite64(u32 addr,const mem64_t* data)
308 {
309 Console.Error("vtlbDefaultPhyWrite64: 0x%08X",addr);
310 pxFailDev("(VTLB) Attempted write to an unmapped physical address.");
311 }
312
313 static void __fastcall vtlbDefaultPhyWrite128(u32 addr,const mem128_t* data)
314 {
315 Console.Error("vtlbDefaultPhyWrite128: 0x%08X",addr);
316 pxFailDev("(VTLB) Attempted write to an unmapped physical address.");
317 }
318 #undef _tmpl
319
320 // ===========================================================================================
321 // VTLB Public API -- Init/Term/RegisterHandler stuff
322 // ===========================================================================================
323 //
324
325 // Assigns or re-assigns the callbacks for a VTLB memory handler. The handler defines specific behavior
326 // for how memory pages bound to the handler are read from / written to. If any of the handler pointers
327 // are NULL, the memory operations will be mapped to the BusError handler (thus generating BusError
328 // exceptions if the emulated app attempts to access them).
329 //
330 // Note: All handlers persist across calls to vtlb_Reset(), but are wiped/invalidated by calls to vtlb_Init()
331 //
332 __ri void vtlb_ReassignHandler( vtlbHandler rv,
333 vtlbMemR8FP* r8,vtlbMemR16FP* r16,vtlbMemR32FP* r32,vtlbMemR64FP* r64,vtlbMemR128FP* r128,
334 vtlbMemW8FP* w8,vtlbMemW16FP* w16,vtlbMemW32FP* w32,vtlbMemW64FP* w64,vtlbMemW128FP* w128 )
335 {
336 vtlbdata.RWFT[0][0][rv] = (void*)((r8!=0) ? r8 : vtlbDefaultPhyRead8);
337 vtlbdata.RWFT[1][0][rv] = (void*)((r16!=0) ? r16 : vtlbDefaultPhyRead16);
338 vtlbdata.RWFT[2][0][rv] = (void*)((r32!=0) ? r32 : vtlbDefaultPhyRead32);
339 vtlbdata.RWFT[3][0][rv] = (void*)((r64!=0) ? r64 : vtlbDefaultPhyRead64);
340 vtlbdata.RWFT[4][0][rv] = (void*)((r128!=0) ? r128 : vtlbDefaultPhyRead128);
341
342 vtlbdata.RWFT[0][1][rv] = (void*)((w8!=0) ? w8 : vtlbDefaultPhyWrite8);
343 vtlbdata.RWFT[1][1][rv] = (void*)((w16!=0) ? w16 : vtlbDefaultPhyWrite16);
344 vtlbdata.RWFT[2][1][rv] = (void*)((w32!=0) ? w32 : vtlbDefaultPhyWrite32);
345 vtlbdata.RWFT[3][1][rv] = (void*)((w64!=0) ? w64 : vtlbDefaultPhyWrite64);
346 vtlbdata.RWFT[4][1][rv] = (void*)((w128!=0) ? w128 : vtlbDefaultPhyWrite128);
347 }
348
349 vtlbHandler vtlb_NewHandler()
350 {
351 pxAssertDev( vtlbHandlerCount < 127, "VTLB allowed handler count exceeded!" );
352 return vtlbHandlerCount++;
353 }
354
355 // Registers a handler into the VTLB's internal handler array. The handler defines specific behavior
356 // for how memory pages bound to the handler are read from / written to. If any of the handler pointers
357 // are NULL, the memory operations will be mapped to the BusError handler (thus generating BusError
358 // exceptions if the emulated app attempts to access them).
359 //
360 // Note: All handlers persist across calls to vtlb_Reset(), but are wiped/invalidated by calls to vtlb_Init()
361 //
362 // Returns a handle for the newly created handler See vtlb_MapHandler for use of the return value.
363 //
364 __ri vtlbHandler vtlb_RegisterHandler( vtlbMemR8FP* r8,vtlbMemR16FP* r16,vtlbMemR32FP* r32,vtlbMemR64FP* r64,vtlbMemR128FP* r128,
365 vtlbMemW8FP* w8,vtlbMemW16FP* w16,vtlbMemW32FP* w32,vtlbMemW64FP* w64,vtlbMemW128FP* w128)
366 {
367 vtlbHandler rv = vtlb_NewHandler();
368 vtlb_ReassignHandler( rv, r8, r16, r32, r64, r128, w8, w16, w32, w64, w128 );
369 return rv;
370 }
371
372
373 // Maps the given hander (created with vtlb_RegisterHandler) to the specified memory region.
374 // New mappings always assume priority over previous mappings, so place "generic" mappings for
375 // large areas of memory first, and then specialize specific small regions of memory afterward.
376 // A single handler can be mapped to many different regions by using multiple calls to this
377 // function.
378 //
379 // The memory region start and size parameters must be pagesize aligned.
380 void vtlb_MapHandler(vtlbHandler handler,u32 start,u32 size)
381 {
382 verify(0==(start&VTLB_PAGE_MASK));
383 verify(0==(size&VTLB_PAGE_MASK) && size>0);
384 s32 value=handler|0x80000000;
385
386 while(size>0)
387 {
388 vtlbdata.pmap[start>>VTLB_PAGE_BITS]=value;
389
390 start+=VTLB_PAGE_SIZE;
391 size-=VTLB_PAGE_SIZE;
392 }
393 }
394
395 void vtlb_MapBlock(void* base,u32 start,u32 size,u32 blocksize)
396 {
397 s32 baseint=(s32)base;
398
399 verify(0==(start&VTLB_PAGE_MASK));
400 verify(0==(size&VTLB_PAGE_MASK) && size>0);
401 if (blocksize==0)
402 blocksize=size;
403 verify(0==(blocksize&VTLB_PAGE_MASK) && blocksize>0);
404 verify(0==(size%blocksize));
405
406 while(size>0)
407 {
408 u32 blocksz=blocksize;
409 s32 ptr=baseint;
410
411 while(blocksz>0)
412 {
413 vtlbdata.pmap[start>>VTLB_PAGE_BITS]=ptr;
414
415 start+=VTLB_PAGE_SIZE;
416 ptr+=VTLB_PAGE_SIZE;
417 blocksz-=VTLB_PAGE_SIZE;
418 size-=VTLB_PAGE_SIZE;
419 }
420 }
421 }
422
423 void vtlb_Mirror(u32 new_region,u32 start,u32 size)
424 {
425 verify(0==(new_region&VTLB_PAGE_MASK));
426 verify(0==(start&VTLB_PAGE_MASK));
427 verify(0==(size&VTLB_PAGE_MASK) && size>0);
428
429 while(size>0)
430 {
431 vtlbdata.pmap[start>>VTLB_PAGE_BITS]=vtlbdata.pmap[new_region>>VTLB_PAGE_BITS];
432
433 start+=VTLB_PAGE_SIZE;
434 new_region+=VTLB_PAGE_SIZE;
435 size-=VTLB_PAGE_SIZE;
436 }
437 }
438
439 __fi void* vtlb_GetPhyPtr(u32 paddr)
440 {
441 if (paddr>=VTLB_PMAP_SZ || vtlbdata.pmap[paddr>>VTLB_PAGE_BITS]<0)
442 return NULL;
443 else
444 return reinterpret_cast<void*>(vtlbdata.pmap[paddr>>VTLB_PAGE_BITS]+(paddr&VTLB_PAGE_MASK));
445 }
446
447 //virtual mappings
448 //TODO: Add invalid paddr checks
449 void vtlb_VMap(u32 vaddr,u32 paddr,u32 sz)
450 {
451 verify(0==(vaddr&VTLB_PAGE_MASK));
452 verify(0==(paddr&VTLB_PAGE_MASK));
453 verify(0==(sz&VTLB_PAGE_MASK) && sz>0);
454
455 while(sz>0)
456 {
457 s32 pme;
458 if (paddr>=VTLB_PMAP_SZ)
459 {
460 pme=UnmappedPhyHandler0;
461 if (paddr&0x80000000)
462 pme=UnmappedPhyHandler1;
463 pme|=0x80000000;
464 pme|=paddr;// top bit is set anyway ...
465 }
466 else
467 {
468 pme=vtlbdata.pmap[paddr>>VTLB_PAGE_BITS];
469 if (pme<0)
470 pme|=paddr;// top bit is set anyway ...
471 }
472 vtlbdata.vmap[vaddr>>VTLB_PAGE_BITS]=pme-vaddr;
473 vaddr+=VTLB_PAGE_SIZE;
474 paddr+=VTLB_PAGE_SIZE;
475 sz-=VTLB_PAGE_SIZE;
476 }
477 }
478
479 void vtlb_VMapBuffer(u32 vaddr,void* buffer,u32 sz)
480 {
481 verify(0==(vaddr&VTLB_PAGE_MASK));
482 verify(0==(sz&VTLB_PAGE_MASK) && sz>0);
483 u32 bu8=(u32)buffer;
484 while(sz>0)
485 {
486 vtlbdata.vmap[vaddr>>VTLB_PAGE_BITS]=bu8-vaddr;
487 vaddr+=VTLB_PAGE_SIZE;
488 bu8+=VTLB_PAGE_SIZE;
489 sz-=VTLB_PAGE_SIZE;
490 }
491 }
492 void vtlb_VMapUnmap(u32 vaddr,u32 sz)
493 {
494 verify(0==(vaddr&VTLB_PAGE_MASK));
495 verify(0==(sz&VTLB_PAGE_MASK) && sz>0);
496
497 while(sz>0)
498 {
499 u32 handl=UnmappedVirtHandler0;
500 if (vaddr&0x80000000)
501 {
502 handl=UnmappedVirtHandler1;
503 }
504 handl|=vaddr; // top bit is set anyway ...
505 handl|=0x80000000;
506 vtlbdata.vmap[vaddr>>VTLB_PAGE_BITS]=handl-vaddr;
507 vaddr+=VTLB_PAGE_SIZE;
508 sz-=VTLB_PAGE_SIZE;
509 }
510 }
511
512 // vtlb_Init -- Clears vtlb handlers and memory mappings.
513 void vtlb_Init()
514 {
515 vtlbHandlerCount=0;
516 memzero(vtlbdata.RWFT);
517
518 #define VTLB_BuildUnmappedHandler(baseName, highBit) \
519 baseName##ReadSm<mem8_t,0>, baseName##ReadSm<mem16_t,0>, baseName##ReadSm<mem32_t,0>, \
520 baseName##ReadLg<mem64_t,0>, baseName##ReadLg<mem128_t,0>, \
521 baseName##WriteSm<mem8_t,0>, baseName##WriteSm<mem16_t,0>, baseName##WriteSm<mem32_t,0>, \
522 baseName##WriteLg<mem64_t,0>, baseName##WriteLg<mem128_t,0>
523
524 //Register default handlers
525 //Unmapped Virt handlers _MUST_ be registered first.
526 //On address translation the top bit cannot be preserved.This is not normaly a problem since
527 //the physical address space can be 'compressed' to just 29 bits.However, to properly handle exceptions
528 //there must be a way to get the full address back.Thats why i use these 2 functions and encode the hi bit directly into em :)
529
530 UnmappedVirtHandler0 = vtlb_RegisterHandler( VTLB_BuildUnmappedHandler(vtlbUnmappedV, 0) );
531 UnmappedVirtHandler1 = vtlb_RegisterHandler( VTLB_BuildUnmappedHandler(vtlbUnmappedV, 0x80000000) );
532
533 UnmappedPhyHandler0 = vtlb_RegisterHandler( VTLB_BuildUnmappedHandler(vtlbUnmappedP, 0) );
534 UnmappedPhyHandler1 = vtlb_RegisterHandler( VTLB_BuildUnmappedHandler(vtlbUnmappedP, 0x80000000) );
535
536 DefaultPhyHandler = vtlb_RegisterHandler(0,0,0,0,0,0,0,0,0,0);
537
538 //done !
539
540 //Setup the initial mappings
541 vtlb_MapHandler(DefaultPhyHandler,0,VTLB_PMAP_SZ);
542
543 //Set the V space as unmapped
544 vtlb_VMapUnmap(0,(VTLB_VMAP_ITEMS-1)*VTLB_PAGE_SIZE);
545 //yeah i know, its stupid .. but this code has to be here for now ;p
546 vtlb_VMapUnmap((VTLB_VMAP_ITEMS-1)*VTLB_PAGE_SIZE,VTLB_PAGE_SIZE);
547
548 extern void vtlb_dynarec_init();
549 vtlb_dynarec_init();
550 }
551
552 // vtlb_Reset -- Performs a COP0-level reset of the PS2's TLB.
553 // This function should probably be part of the COP0 rather than here in VTLB.
554 void vtlb_Reset()
555 {
556 for(int i=0; i<48; i++) UnmapTLB(i);
557 }
558
559 void vtlb_Term()
560 {
561 //nothing to do for now
562 }
563
564 // Reserves the vtlb core allocation used by various emulation components!
565 //
566 void vtlb_Core_Alloc()
567 {
568 if( vtlbdata.alloc_base != NULL ) return;
569
570 vtlbdata.alloc_current = 0;
571
572 #ifdef __LINUX__
573 vtlbdata.alloc_base = SysMmapEx( 0x16000000, VTLB_ALLOC_SIZE, 0x80000000, "Vtlb" );
574 #else
575 // Win32 just needs this, since malloc always maps below 2GB.
576 vtlbdata.alloc_base = (u8*)_aligned_malloc( VTLB_ALLOC_SIZE, 4096 );
577 if( vtlbdata.alloc_base == NULL )
578 throw Exception::OutOfMemory( pxsFmt(L"PS2 mappable system ram (%u megs)", VTLB_ALLOC_SIZE / _1mb) );
579 #endif
580 }
581
582 void vtlb_Core_Shutdown()
583 {
584 if( vtlbdata.alloc_base == NULL ) return;
585
586 #ifdef __LINUX__
587 SafeSysMunmap( vtlbdata.alloc_base, VTLB_ALLOC_SIZE );
588 #else
589 // Make sure and unprotect memory first, since CrtDebug will try to write to it.
590 HostSys::MemProtect( vtlbdata.alloc_base, VTLB_ALLOC_SIZE, Protect_ReadWrite );
591 safe_aligned_free( vtlbdata.alloc_base );
592 #endif
593
594 }
595
596 // This function allocates memory block with are compatible with the Vtlb's requirements
597 // for memory locations. The Vtlb requires the topmost bit (Sign bit) of the memory
598 // pointer to be cleared. Some operating systems and/or implementations of malloc do that,
599 // but others do not. So use this instead to allocate the memory correctly for your
600 // platform.
601 //
602 u8* vtlb_malloc( uint size, uint align )
603 {
604 vtlbdata.alloc_current += align-1;
605 vtlbdata.alloc_current &= ~(align-1);
606
607 int rv = vtlbdata.alloc_current;
608 vtlbdata.alloc_current += size;
609
610 pxAssertDev( vtlbdata.alloc_current < VTLB_ALLOC_SIZE, "(vtlb_malloc) memory overflow! Please increase the size of VTLB_ALLOC_SIZE!" );
611 return &vtlbdata.alloc_base[rv];
612 }
613
614 void vtlb_free( void* pmem, uint size )
615 {
616 vtlbdata.alloc_current -= size;
617
618 pxAssertDev( vtlbdata.alloc_current >= 0, "(vtlb_free) mismatched calls to vtlb_malloc and free detected via memory underflow." );
619
620 return;
621 }

  ViewVC Help
Powered by ViewVC 1.1.22