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

Annotation of /trunk/pcsx2/vtlb.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 62 - (hide annotations) (download)
Tue Sep 7 11:08:22 2010 UTC (10 years, 3 months ago) by william
File size: 20170 byte(s)
Auto Commited Import of: pcsx2-0.9.7-r3738-debug in ./trunk
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     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 william 62 #define verify pxAssume
43 william 31
44     namespace vtlb_private
45     {
46     __aligned(64) MapData vtlbdata;
47     }
48    
49 william 62 static vtlbHandler vtlbHandlerCount=0;
50 william 31
51 william 62 static vtlbHandler DefaultPhyHandler;
52     static vtlbHandler UnmappedVirtHandler0;
53     static vtlbHandler UnmappedVirtHandler1;
54     static vtlbHandler UnmappedPhyHandler0;
55     static vtlbHandler UnmappedPhyHandler1;
56 william 31
57    
58 william 62 // --------------------------------------------------------------------------------------
59 william 31 // Interpreter Implementations of VTLB Memory Operations.
60 william 62 // --------------------------------------------------------------------------------------
61 william 31 // See recVTLB.cpp for the dynarec versions.
62    
63 william 62 template< typename DataType >
64     DataType __fastcall vtlb_memRead(u32 addr)
65 william 31 {
66 william 62 static const uint DataSize = sizeof(DataType) * 8;
67 william 31 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 william 62 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 william 31
85     jNO_DEFAULT;
86     }
87    
88     return 0; // technically unreachable, but suppresses warnings.
89     }
90    
91 william 62 void __fastcall vtlb_memRead64(u32 mem, mem64_t *out)
92 william 31 {
93 william 62 u32 vmv=vtlbdata.vmap[mem>>VTLB_PAGE_BITS];
94     s32 ppf=mem+vmv;
95 william 31
96     if (!(ppf<0))
97     {
98 william 62 *out = *(mem64_t*)ppf;
99 william 31 }
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 william 62 ((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 william 31
115 william 62 if (!(ppf<0))
116     {
117     CopyQWC(out,(void*)ppf);
118 william 31 }
119 william 62 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 william 31 }
129    
130 william 62 template< typename DataType >
131     void __fastcall vtlb_memWrite(u32 addr, DataType data)
132 william 31 {
133 william 62 static const uint DataSize = sizeof(DataType) * 8;
134    
135 william 31 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 william 62 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 william 31
154     jNO_DEFAULT;
155     }
156     }
157     }
158    
159 william 62 void __fastcall vtlb_memWrite64(u32 mem, const mem64_t* value)
160 william 31 {
161 william 62 u32 vmv=vtlbdata.vmap[mem>>VTLB_PAGE_BITS];
162     s32 ppf=mem+vmv;
163 william 31 if (!(ppf<0))
164     {
165 william 62 *(mem64_t*)ppf = *value;
166 william 31 }
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 william 62 ((vtlbMemW64FP*)vtlbdata.RWFT[3][1][hand])(paddr, value);
175 william 31 }
176     }
177    
178 william 62 void __fastcall vtlb_memWrite128(u32 mem, const mem128_t *value)
179 william 31 {
180 william 62 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 william 31 }
196 william 62
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 william 31 {
218 william 62 if( IsDevBuild )
219     Cpu->ThrowCpuException( R5900Exception::TLBMiss( addr, !!mode ) );
220     else
221     Console.Error( R5900Exception::TLBMiss( addr, !!mode ).FormatMessage() );
222 william 31 }
223 william 62
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 william 31 {
229 william 62 if( IsDevBuild )
230     Cpu->ThrowCpuException( R5900Exception::BusError( addr, !!mode ) );
231     else
232     Console.Error( R5900Exception::TLBMiss( addr, !!mode ).FormatMessage() );
233 william 31 }
234 william 62
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 william 31 {
258 william 62 Console.Error("vtlbDefaultPhyRead8: 0x%08X", addr);
259     pxFailDev("(VTLB) Attempted read from an unmapped physical address.");
260     return 0;
261 william 31 }
262 william 62
263     static mem16_t __fastcall vtlbDefaultPhyRead16(u32 addr)
264 william 31 {
265 william 62 Console.Error("vtlbDefaultPhyRead16: 0x%08X", addr);
266     pxFailDev("(VTLB) Attempted read from an unmapped physical address.");
267     return 0;
268 william 31 }
269 william 62
270     static mem32_t __fastcall vtlbDefaultPhyRead32(u32 addr)
271 william 31 {
272 william 62 Console.Error("vtlbDefaultPhyRead32: 0x%08X", addr);
273     pxFailDev("(VTLB) Attempted read from an unmapped physical address.");
274     return 0;
275 william 31 }
276 william 62
277     static void __fastcall vtlbDefaultPhyRead64(u32 addr, mem64_t* dest)
278 william 31 {
279 william 62 Console.Error("vtlbDefaultPhyRead64: 0x%08X", addr);
280     pxFailDev("(VTLB) Attempted read from an unmapped physical address.");
281 william 31 }
282 william 62
283     static void __fastcall vtlbDefaultPhyRead128(u32 addr, mem128_t* dest)
284 william 31 {
285 william 62 Console.Error("vtlbDefaultPhyRead128: 0x%08X", addr);
286     pxFailDev("(VTLB) Attempted read from an unmapped physical address.");
287 william 31 }
288 william 62
289     static void __fastcall vtlbDefaultPhyWrite8(u32 addr, mem8_t data)
290 william 31 {
291 william 62 Console.Error("vtlbDefaultPhyWrite8: 0x%08X",addr);
292     pxFailDev("(VTLB) Attempted write to an unmapped physical address.");
293 william 31 }
294 william 62
295     static void __fastcall vtlbDefaultPhyWrite16(u32 addr, mem16_t data)
296 william 31 {
297 william 62 Console.Error("vtlbDefaultPhyWrite16: 0x%08X",addr);
298     pxFailDev("(VTLB) Attempted write to an unmapped physical address.");
299 william 31 }
300    
301 william 62 static void __fastcall vtlbDefaultPhyWrite32(u32 addr, mem32_t data)
302 william 31 {
303 william 62 Console.Error("vtlbDefaultPhyWrite32: 0x%08X",addr);
304     pxFailDev("(VTLB) Attempted write to an unmapped physical address.");
305 william 31 }
306    
307 william 62 static void __fastcall vtlbDefaultPhyWrite64(u32 addr,const mem64_t* data)
308 william 31 {
309 william 62 Console.Error("vtlbDefaultPhyWrite64: 0x%08X",addr);
310     pxFailDev("(VTLB) Attempted write to an unmapped physical address.");
311 william 31 }
312    
313 william 62 static void __fastcall vtlbDefaultPhyWrite128(u32 addr,const mem128_t* data)
314 william 31 {
315 william 62 Console.Error("vtlbDefaultPhyWrite128: 0x%08X",addr);
316     pxFailDev("(VTLB) Attempted write to an unmapped physical address.");
317 william 31 }
318 william 62 #undef _tmpl
319 william 31
320 william 62 // ===========================================================================================
321     // VTLB Public API -- Init/Term/RegisterHandler stuff
322     // ===========================================================================================
323 william 31 //
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 william 62 __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 william 31 {
336 william 62 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 william 31
342 william 62 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 william 31 }
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 william 62 __ri vtlbHandler vtlb_RegisterHandler( vtlbMemR8FP* r8,vtlbMemR16FP* r16,vtlbMemR32FP* r32,vtlbMemR64FP* r64,vtlbMemR128FP* r128,
365 william 31 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 william 62 __fi void* vtlb_GetPhyPtr(u32 paddr)
440 william 31 {
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 william 62 // vtlb_Init -- Clears vtlb handlers and memory mappings.
513 william 31 void vtlb_Init()
514     {
515     vtlbHandlerCount=0;
516     memzero(vtlbdata.RWFT);
517    
518 william 62 #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 william 31 //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 william 62 UnmappedVirtHandler0 = vtlb_RegisterHandler( VTLB_BuildUnmappedHandler(vtlbUnmappedV, 0) );
531     UnmappedVirtHandler1 = vtlb_RegisterHandler( VTLB_BuildUnmappedHandler(vtlbUnmappedV, 0x80000000) );
532 william 31
533 william 62 UnmappedPhyHandler0 = vtlb_RegisterHandler( VTLB_BuildUnmappedHandler(vtlbUnmappedP, 0) );
534     UnmappedPhyHandler1 = vtlb_RegisterHandler( VTLB_BuildUnmappedHandler(vtlbUnmappedP, 0x80000000) );
535 william 31
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 william 62 throw Exception::OutOfMemory( pxsFmt(L"PS2 mappable system ram (%u megs)", VTLB_ALLOC_SIZE / _1mb) );
579 william 31 #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 william 62
610     pxAssertDev( vtlbdata.alloc_current < VTLB_ALLOC_SIZE, "(vtlb_malloc) memory overflow! Please increase the size of VTLB_ALLOC_SIZE!" );
611 william 31 return &vtlbdata.alloc_base[rv];
612     }
613    
614     void vtlb_free( void* pmem, uint size )
615     {
616 william 62 vtlbdata.alloc_current -= size;
617 william 31
618 william 62 pxAssertDev( vtlbdata.alloc_current >= 0, "(vtlb_free) mismatched calls to vtlb_malloc and free detected via memory underflow." );
619    
620 william 31 return;
621     }

  ViewVC Help
Powered by ViewVC 1.1.22