/[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 31 - (hide annotations) (download)
Tue Sep 7 03:24:11 2010 UTC (9 years, 10 months ago) by william
File size: 22377 byte(s)
committing r3113 initial commit again...
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     #ifdef PCSX2_DEVBUILD
43     #define verify(x) {if (!(x)) { (*(u8*)0)=3; }}
44     #else
45     #define verify jASSUME
46     #endif
47    
48     namespace vtlb_private
49     {
50     __aligned(64) MapData vtlbdata;
51     }
52    
53     vtlbHandler vtlbHandlerCount=0;
54    
55     vtlbHandler DefaultPhyHandler;
56     vtlbHandler UnmappedVirtHandler0;
57     vtlbHandler UnmappedVirtHandler1;
58     vtlbHandler UnmappedPhyHandler0;
59     vtlbHandler UnmappedPhyHandler1;
60    
61    
62     //////////////////////////////////////////////////////////////////////////////////////////
63     // Interpreter Implementations of VTLB Memory Operations.
64     // See recVTLB.cpp for the dynarec versions.
65    
66     // Interpreted VTLB lookup for 8, 16, and 32 bit accesses
67     template<int DataSize,typename DataType>
68     __forceinline DataType __fastcall MemOp_r0(u32 addr)
69     {
70     u32 vmv=vtlbdata.vmap[addr>>VTLB_PAGE_BITS];
71     s32 ppf=addr+vmv;
72    
73     if (!(ppf<0))
74     return *reinterpret_cast<DataType*>(ppf);
75    
76     //has to: translate, find function, call function
77     u32 hand=(u8)vmv;
78     u32 paddr=ppf-hand+0x80000000;
79     //Console.WriteLn("Translated 0x%08X to 0x%08X", addr,paddr);
80     //return reinterpret_cast<TemplateHelper<DataSize,false>::HandlerType*>(vtlbdata.RWFT[TemplateHelper<DataSize,false>::sidx][0][hand])(paddr,data);
81    
82     switch( DataSize )
83     {
84     case 8: return ((vtlbMemR8FP*)vtlbdata.RWFT[0][0][hand])(paddr);
85     case 16: return ((vtlbMemR16FP*)vtlbdata.RWFT[1][0][hand])(paddr);
86     case 32: return ((vtlbMemR32FP*)vtlbdata.RWFT[2][0][hand])(paddr);
87    
88     jNO_DEFAULT;
89     }
90    
91     return 0; // technically unreachable, but suppresses warnings.
92     }
93    
94     // ------------------------------------------------------------------------
95     // Interpreterd VTLB lookup for 64 and 128 bit accesses.
96     template<int DataSize,typename DataType>
97     __forceinline void __fastcall MemOp_r1(u32 addr, DataType* data)
98     {
99     u32 vmv=vtlbdata.vmap[addr>>VTLB_PAGE_BITS];
100     s32 ppf=addr+vmv;
101    
102     if (!(ppf<0))
103     {
104     data[0]=*reinterpret_cast<DataType*>(ppf);
105     if (DataSize==128)
106     data[1]=*reinterpret_cast<DataType*>(ppf+8);
107     }
108     else
109     {
110     //has to: translate, find function, call function
111     u32 hand=(u8)vmv;
112     u32 paddr=ppf-hand+0x80000000;
113     //Console.WriteLn("Translated 0x%08X to 0x%08X", addr,paddr);
114     //return reinterpret_cast<TemplateHelper<DataSize,false>::HandlerType*>(RWFT[TemplateHelper<DataSize,false>::sidx][0][hand])(paddr,data);
115    
116     switch( DataSize )
117     {
118     case 64: ((vtlbMemR64FP*)vtlbdata.RWFT[3][0][hand])(paddr, data); break;
119     case 128: ((vtlbMemR128FP*)vtlbdata.RWFT[4][0][hand])(paddr, data); break;
120    
121     jNO_DEFAULT;
122     }
123     }
124     }
125    
126     // ------------------------------------------------------------------------
127     template<int DataSize,typename DataType>
128     __forceinline void __fastcall MemOp_w0(u32 addr, DataType data)
129     {
130     u32 vmv=vtlbdata.vmap[addr>>VTLB_PAGE_BITS];
131     s32 ppf=addr+vmv;
132     if (!(ppf<0))
133     {
134     *reinterpret_cast<DataType*>(ppf)=data;
135     }
136     else
137     {
138     //has to: translate, find function, call function
139     u32 hand=(u8)vmv;
140     u32 paddr=ppf-hand+0x80000000;
141     //Console.WriteLn("Translated 0x%08X to 0x%08X", addr,paddr);
142    
143     switch( DataSize )
144     {
145     case 8: return ((vtlbMemW8FP*)vtlbdata.RWFT[0][1][hand])(paddr, (u8)data);
146     case 16: return ((vtlbMemW16FP*)vtlbdata.RWFT[1][1][hand])(paddr, (u16)data);
147     case 32: return ((vtlbMemW32FP*)vtlbdata.RWFT[2][1][hand])(paddr, (u32)data);
148    
149     jNO_DEFAULT;
150     }
151     }
152     }
153    
154     // ------------------------------------------------------------------------
155     template<int DataSize,typename DataType>
156     __forceinline void __fastcall MemOp_w1(u32 addr,const DataType* data)
157     {
158     verify(DataSize==128 || DataSize==64);
159     u32 vmv=vtlbdata.vmap[addr>>VTLB_PAGE_BITS];
160     s32 ppf=addr+vmv;
161     if (!(ppf<0))
162     {
163     *reinterpret_cast<DataType*>(ppf)=*data;
164     if (DataSize==128)
165     *reinterpret_cast<DataType*>(ppf+8)=data[1];
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     switch( DataSize )
174     {
175     case 64: return ((vtlbMemW64FP*)vtlbdata.RWFT[3][1][hand])(paddr, data);
176     case 128: return ((vtlbMemW128FP*)vtlbdata.RWFT[4][1][hand])(paddr, data);
177    
178     jNO_DEFAULT;
179     }
180     }
181     }
182    
183     mem8_t __fastcall vtlb_memRead8(u32 mem)
184     {
185     return MemOp_r0<8,mem8_t>(mem);
186     }
187     mem16_t __fastcall vtlb_memRead16(u32 mem)
188     {
189     return MemOp_r0<16,mem16_t>(mem);
190     }
191     mem32_t __fastcall vtlb_memRead32(u32 mem)
192     {
193     return MemOp_r0<32,mem32_t>(mem);
194     }
195     void __fastcall vtlb_memRead64(u32 mem, u64 *out)
196     {
197     return MemOp_r1<64,mem64_t>(mem,out);
198     }
199     void __fastcall vtlb_memRead128(u32 mem, u64 *out)
200     {
201     return MemOp_r1<128,mem128_t>(mem,out);
202     }
203     void __fastcall vtlb_memWrite8 (u32 mem, mem8_t value)
204     {
205     MemOp_w0<8,mem8_t>(mem,value);
206     }
207     void __fastcall vtlb_memWrite16(u32 mem, mem16_t value)
208     {
209     MemOp_w0<16,mem16_t>(mem,value);
210     }
211     void __fastcall vtlb_memWrite32(u32 mem, mem32_t value)
212     {
213     MemOp_w0<32,mem32_t>(mem,value);
214     }
215     void __fastcall vtlb_memWrite64(u32 mem, const mem64_t* value)
216     {
217     MemOp_w1<64,mem64_t>(mem,value);
218     }
219     void __fastcall vtlb_memWrite128(u32 mem, const mem128_t *value)
220     {
221     MemOp_w1<128,mem128_t>(mem,value);
222     }
223    
224     /////////////////////////////////////////////////////////////////////////
225     // Error / TLB Miss Handlers
226     //
227    
228     static const char* _getModeStr( u32 mode )
229     {
230     return (mode==0) ? "read" : "write";
231     }
232    
233     // Generates a tlbMiss Exception
234     // Note: Don't throw exceptions yet, they cause a crash when otherwise
235     // there would be a (slight) chance the game continues (rama).
236     static __forceinline void vtlb_Miss(u32 addr,u32 mode)
237     {
238     Console.Error( "vtlb miss : addr 0x%X, mode %d [%s]", addr, mode, _getModeStr(mode) );
239     //verify(false);
240     //throw R5900Exception::TLBMiss( addr, !!mode );
241     }
242    
243     // Just dies a horrible death for now.
244     // Eventually should generate a BusError exception.
245     static __forceinline void vtlb_BusError(u32 addr,u32 mode)
246     {
247     Console.Error( "vtlb bus error : addr 0x%X, mode %d\n", addr, _getModeStr(mode) );
248     //verify(false);
249     throw R5900Exception::BusError( addr, !!mode );
250     }
251    
252     ///// Virtual Mapping Errors (TLB Miss)
253     template<u32 saddr>
254     mem8_t __fastcall vtlbUnmappedVRead8(u32 addr) { vtlb_Miss(addr|saddr,0); return 0; }
255     template<u32 saddr>
256     mem16_t __fastcall vtlbUnmappedVRead16(u32 addr) { vtlb_Miss(addr|saddr,0); return 0; }
257     template<u32 saddr>
258     mem32_t __fastcall vtlbUnmappedVRead32(u32 addr) { vtlb_Miss(addr|saddr,0); return 0; }
259     template<u32 saddr>
260     void __fastcall vtlbUnmappedVRead64(u32 addr,mem64_t* data) { vtlb_Miss(addr|saddr,0); }
261     template<u32 saddr>
262     void __fastcall vtlbUnmappedVRead128(u32 addr,mem128_t* data) { vtlb_Miss(addr|saddr,0); }
263     template<u32 saddr>
264     void __fastcall vtlbUnmappedVWrite8(u32 addr,mem8_t data) { vtlb_Miss(addr|saddr,1); }
265     template<u32 saddr>
266     void __fastcall vtlbUnmappedVWrite16(u32 addr,mem16_t data) { vtlb_Miss(addr|saddr,1); }
267     template<u32 saddr>
268     void __fastcall vtlbUnmappedVWrite32(u32 addr,mem32_t data) { vtlb_Miss(addr|saddr,1); }
269     template<u32 saddr>
270     void __fastcall vtlbUnmappedVWrite64(u32 addr,const mem64_t* data) { vtlb_Miss(addr|saddr,1); }
271     template<u32 saddr>
272     void __fastcall vtlbUnmappedVWrite128(u32 addr,const mem128_t* data) { vtlb_Miss(addr|saddr,1); }
273    
274     ///// Physical Mapping Errors (Bus Error)
275     template<u32 saddr>
276     mem8_t __fastcall vtlbUnmappedPRead8(u32 addr) { vtlb_BusError(addr|saddr,0); return 0; }
277     template<u32 saddr>
278     mem16_t __fastcall vtlbUnmappedPRead16(u32 addr) { vtlb_BusError(addr|saddr,0); return 0; }
279     template<u32 saddr>
280     mem32_t __fastcall vtlbUnmappedPRead32(u32 addr) { vtlb_BusError(addr|saddr,0); return 0; }
281     template<u32 saddr>
282     void __fastcall vtlbUnmappedPRead64(u32 addr,mem64_t* data) { vtlb_BusError(addr|saddr,0); }
283     template<u32 saddr>
284     void __fastcall vtlbUnmappedPRead128(u32 addr,mem128_t* data) { vtlb_BusError(addr|saddr,0); }
285     template<u32 saddr>
286     void __fastcall vtlbUnmappedPWrite8(u32 addr,mem8_t data) { vtlb_BusError(addr|saddr,1); }
287     template<u32 saddr>
288     void __fastcall vtlbUnmappedPWrite16(u32 addr,mem16_t data) { vtlb_BusError(addr|saddr,1); }
289     template<u32 saddr>
290     void __fastcall vtlbUnmappedPWrite32(u32 addr,mem32_t data) { vtlb_BusError(addr|saddr,1); }
291     template<u32 saddr>
292     void __fastcall vtlbUnmappedPWrite64(u32 addr,const mem64_t* data) { vtlb_BusError(addr|saddr,1); }
293     template<u32 saddr>
294     void __fastcall vtlbUnmappedPWrite128(u32 addr,const mem128_t* data) { vtlb_BusError(addr|saddr,1); }
295    
296     ///// VTLB mapping errors (unmapped address spaces)
297     mem8_t __fastcall vtlbDefaultPhyRead8(u32 addr) { Console.Error("vtlbDefaultPhyRead8: 0x%X",addr); verify(false); return -1; }
298     mem16_t __fastcall vtlbDefaultPhyRead16(u32 addr) { Console.Error("vtlbDefaultPhyRead16: 0x%X",addr); verify(false); return -1; }
299     mem32_t __fastcall vtlbDefaultPhyRead32(u32 addr) { Console.Error("vtlbDefaultPhyRead32: 0x%X",addr); verify(false); return -1; }
300     void __fastcall vtlbDefaultPhyRead64(u32 addr,mem64_t* data) { Console.Error("vtlbDefaultPhyRead64: 0x%X",addr); verify(false); }
301     void __fastcall vtlbDefaultPhyRead128(u32 addr,mem128_t* data) { Console.Error("vtlbDefaultPhyRead128: 0x%X",addr); verify(false); }
302    
303     void __fastcall vtlbDefaultPhyWrite8(u32 addr,mem8_t data) { Console.Error("vtlbDefaultPhyWrite8: 0x%X",addr); verify(false); }
304     void __fastcall vtlbDefaultPhyWrite16(u32 addr,mem16_t data) { Console.Error("vtlbDefaultPhyWrite16: 0x%X",addr); verify(false); }
305     void __fastcall vtlbDefaultPhyWrite32(u32 addr,mem32_t data) { Console.Error("vtlbDefaultPhyWrite32: 0x%X",addr); verify(false); }
306     void __fastcall vtlbDefaultPhyWrite64(u32 addr,const mem64_t* data) { Console.Error("vtlbDefaultPhyWrite64: 0x%X",addr); verify(false); }
307     void __fastcall vtlbDefaultPhyWrite128(u32 addr,const mem128_t* data) { Console.Error("vtlbDefaultPhyWrite128: 0x%X",addr); verify(false); }
308    
309    
310     //////////////////////////////////////////////////////////////////////////////////////////
311     // VTLB Public API -- Init/Term/RegisterHandler stuff
312     //
313    
314     // Assigns or re-assigns the callbacks for a VTLB memory handler. The handler defines specific behavior
315     // for how memory pages bound to the handler are read from / written to. If any of the handler pointers
316     // are NULL, the memory operations will be mapped to the BusError handler (thus generating BusError
317     // exceptions if the emulated app attempts to access them).
318     //
319     // Note: All handlers persist across calls to vtlb_Reset(), but are wiped/invalidated by calls to vtlb_Init()
320     //
321     void vtlb_ReassignHandler( vtlbHandler rv,
322     vtlbMemR8FP* r8,vtlbMemR16FP* r16,vtlbMemR32FP* r32,vtlbMemR64FP* r64,vtlbMemR128FP* r128,
323     vtlbMemW8FP* w8,vtlbMemW16FP* w16,vtlbMemW32FP* w32,vtlbMemW64FP* w64,vtlbMemW128FP* w128 )
324     {
325     vtlbdata.RWFT[0][0][rv] = (r8!=0) ? (void*)(r8): (void*)vtlbDefaultPhyRead8;
326     vtlbdata.RWFT[1][0][rv] = (r16!=0) ? (void*)r16: (void*)vtlbDefaultPhyRead16;
327     vtlbdata.RWFT[2][0][rv] = (r32!=0) ? (void*)r32: (void*)vtlbDefaultPhyRead32;
328     vtlbdata.RWFT[3][0][rv] = (r64!=0) ? (void*)r64: (void*)vtlbDefaultPhyRead64;
329     vtlbdata.RWFT[4][0][rv] = (r128!=0) ? (void*)r128: (void*)vtlbDefaultPhyRead128;
330    
331     vtlbdata.RWFT[0][0][rv] = (r8!=0) ? (void*)r8:(void*)vtlbDefaultPhyRead8;
332     vtlbdata.RWFT[1][0][rv] = (r16!=0) ? (void*)r16:(void*)vtlbDefaultPhyRead16;
333     vtlbdata.RWFT[2][0][rv] = (r32!=0) ? (void*)r32:(void*)vtlbDefaultPhyRead32;
334     vtlbdata.RWFT[3][0][rv] = (r64!=0) ? (void*)r64:(void*)vtlbDefaultPhyRead64;
335     vtlbdata.RWFT[4][0][rv] = (r128!=0) ? (void*)r128:(void*)vtlbDefaultPhyRead128;
336    
337     vtlbdata.RWFT[0][1][rv] = (void*)((w8!=0) ? w8:vtlbDefaultPhyWrite8);
338     vtlbdata.RWFT[1][1][rv] = (void*)((w16!=0) ? w16:vtlbDefaultPhyWrite16);
339     vtlbdata.RWFT[2][1][rv] = (void*)((w32!=0) ? w32:vtlbDefaultPhyWrite32);
340     vtlbdata.RWFT[3][1][rv] = (void*)((w64!=0) ? w64:vtlbDefaultPhyWrite64);
341     vtlbdata.RWFT[4][1][rv] = (void*)((w128!=0) ? w128:vtlbDefaultPhyWrite128);
342     }
343    
344     vtlbHandler vtlb_NewHandler()
345     {
346     pxAssertDev( vtlbHandlerCount < 127, "VTLB allowed handler count exceeded!" );
347     return vtlbHandlerCount++;
348     }
349    
350     // Registers a handler into the VTLB's internal handler array. The handler defines specific behavior
351     // for how memory pages bound to the handler are read from / written to. If any of the handler pointers
352     // are NULL, the memory operations will be mapped to the BusError handler (thus generating BusError
353     // exceptions if the emulated app attempts to access them).
354     //
355     // Note: All handlers persist across calls to vtlb_Reset(), but are wiped/invalidated by calls to vtlb_Init()
356     //
357     // Returns a handle for the newly created handler See vtlb_MapHandler for use of the return value.
358     //
359     vtlbHandler vtlb_RegisterHandler( vtlbMemR8FP* r8,vtlbMemR16FP* r16,vtlbMemR32FP* r32,vtlbMemR64FP* r64,vtlbMemR128FP* r128,
360     vtlbMemW8FP* w8,vtlbMemW16FP* w16,vtlbMemW32FP* w32,vtlbMemW64FP* w64,vtlbMemW128FP* w128)
361     {
362     vtlbHandler rv = vtlb_NewHandler();
363     vtlb_ReassignHandler( rv, r8, r16, r32, r64, r128, w8, w16, w32, w64, w128 );
364     return rv;
365     }
366    
367    
368     //////////////////////////////////////////////////////////////////////////////////////////
369     // Maps the given hander (created with vtlb_RegisterHandler) to the specified memory region.
370     // New mappings always assume priority over previous mappings, so place "generic" mappings for
371     // large areas of memory first, and then specialize specific small regions of memory afterward.
372     // A single handler can be mapped to many different regions by using multiple calls to this
373     // function.
374     //
375     // The memory region start and size parameters must be pagesize aligned.
376     void vtlb_MapHandler(vtlbHandler handler,u32 start,u32 size)
377     {
378     verify(0==(start&VTLB_PAGE_MASK));
379     verify(0==(size&VTLB_PAGE_MASK) && size>0);
380     s32 value=handler|0x80000000;
381    
382     while(size>0)
383     {
384     vtlbdata.pmap[start>>VTLB_PAGE_BITS]=value;
385    
386     start+=VTLB_PAGE_SIZE;
387     size-=VTLB_PAGE_SIZE;
388     }
389     }
390    
391     void vtlb_MapBlock(void* base,u32 start,u32 size,u32 blocksize)
392     {
393     s32 baseint=(s32)base;
394    
395     verify(0==(start&VTLB_PAGE_MASK));
396     verify(0==(size&VTLB_PAGE_MASK) && size>0);
397     if (blocksize==0)
398     blocksize=size;
399     verify(0==(blocksize&VTLB_PAGE_MASK) && blocksize>0);
400     verify(0==(size%blocksize));
401    
402     while(size>0)
403     {
404     u32 blocksz=blocksize;
405     s32 ptr=baseint;
406    
407     while(blocksz>0)
408     {
409     vtlbdata.pmap[start>>VTLB_PAGE_BITS]=ptr;
410    
411     start+=VTLB_PAGE_SIZE;
412     ptr+=VTLB_PAGE_SIZE;
413     blocksz-=VTLB_PAGE_SIZE;
414     size-=VTLB_PAGE_SIZE;
415     }
416     }
417     }
418    
419     void vtlb_Mirror(u32 new_region,u32 start,u32 size)
420     {
421     verify(0==(new_region&VTLB_PAGE_MASK));
422     verify(0==(start&VTLB_PAGE_MASK));
423     verify(0==(size&VTLB_PAGE_MASK) && size>0);
424    
425     while(size>0)
426     {
427     vtlbdata.pmap[start>>VTLB_PAGE_BITS]=vtlbdata.pmap[new_region>>VTLB_PAGE_BITS];
428    
429     start+=VTLB_PAGE_SIZE;
430     new_region+=VTLB_PAGE_SIZE;
431     size-=VTLB_PAGE_SIZE;
432     }
433     }
434    
435     __forceinline void* vtlb_GetPhyPtr(u32 paddr)
436     {
437     if (paddr>=VTLB_PMAP_SZ || vtlbdata.pmap[paddr>>VTLB_PAGE_BITS]<0)
438     return NULL;
439     else
440     return reinterpret_cast<void*>(vtlbdata.pmap[paddr>>VTLB_PAGE_BITS]+(paddr&VTLB_PAGE_MASK));
441     }
442    
443     //virtual mappings
444     //TODO: Add invalid paddr checks
445     void vtlb_VMap(u32 vaddr,u32 paddr,u32 sz)
446     {
447     verify(0==(vaddr&VTLB_PAGE_MASK));
448     verify(0==(paddr&VTLB_PAGE_MASK));
449     verify(0==(sz&VTLB_PAGE_MASK) && sz>0);
450    
451     while(sz>0)
452     {
453     s32 pme;
454     if (paddr>=VTLB_PMAP_SZ)
455     {
456     pme=UnmappedPhyHandler0;
457     if (paddr&0x80000000)
458     pme=UnmappedPhyHandler1;
459     pme|=0x80000000;
460     pme|=paddr;// top bit is set anyway ...
461     }
462     else
463     {
464     pme=vtlbdata.pmap[paddr>>VTLB_PAGE_BITS];
465     if (pme<0)
466     pme|=paddr;// top bit is set anyway ...
467     }
468     vtlbdata.vmap[vaddr>>VTLB_PAGE_BITS]=pme-vaddr;
469     vaddr+=VTLB_PAGE_SIZE;
470     paddr+=VTLB_PAGE_SIZE;
471     sz-=VTLB_PAGE_SIZE;
472     }
473     }
474    
475     void vtlb_VMapBuffer(u32 vaddr,void* buffer,u32 sz)
476     {
477     verify(0==(vaddr&VTLB_PAGE_MASK));
478     verify(0==(sz&VTLB_PAGE_MASK) && sz>0);
479     u32 bu8=(u32)buffer;
480     while(sz>0)
481     {
482     vtlbdata.vmap[vaddr>>VTLB_PAGE_BITS]=bu8-vaddr;
483     vaddr+=VTLB_PAGE_SIZE;
484     bu8+=VTLB_PAGE_SIZE;
485     sz-=VTLB_PAGE_SIZE;
486     }
487     }
488     void vtlb_VMapUnmap(u32 vaddr,u32 sz)
489     {
490     verify(0==(vaddr&VTLB_PAGE_MASK));
491     verify(0==(sz&VTLB_PAGE_MASK) && sz>0);
492    
493     while(sz>0)
494     {
495     u32 handl=UnmappedVirtHandler0;
496     if (vaddr&0x80000000)
497     {
498     handl=UnmappedVirtHandler1;
499     }
500     handl|=vaddr; // top bit is set anyway ...
501     handl|=0x80000000;
502     vtlbdata.vmap[vaddr>>VTLB_PAGE_BITS]=handl-vaddr;
503     vaddr+=VTLB_PAGE_SIZE;
504     sz-=VTLB_PAGE_SIZE;
505     }
506     }
507    
508     //////////////////////////////////////////////////////////////////////////////////////////
509     // vtlb_init -- Clears vtlb handlers and memory mappings.
510     void vtlb_Init()
511     {
512     vtlbHandlerCount=0;
513     memzero(vtlbdata.RWFT);
514    
515     //Register default handlers
516     //Unmapped Virt handlers _MUST_ be registered first.
517     //On address translation the top bit cannot be preserved.This is not normaly a problem since
518     //the physical address space can be 'compressed' to just 29 bits.However, to properly handle exceptions
519     //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 :)
520    
521     UnmappedVirtHandler0 = vtlb_RegisterHandler(
522     vtlbUnmappedVRead8<0>,vtlbUnmappedVRead16<0>,vtlbUnmappedVRead32<0>,vtlbUnmappedVRead64<0>,vtlbUnmappedVRead128<0>,
523     vtlbUnmappedVWrite8<0>,vtlbUnmappedVWrite16<0>,vtlbUnmappedVWrite32<0>,vtlbUnmappedVWrite64<0>,vtlbUnmappedVWrite128<0>
524     );
525    
526     UnmappedVirtHandler1 = vtlb_RegisterHandler(
527     vtlbUnmappedVRead8<0x80000000>,vtlbUnmappedVRead16<0x80000000>,vtlbUnmappedVRead32<0x80000000>, vtlbUnmappedVRead64<0x80000000>,vtlbUnmappedVRead128<0x80000000>,
528     vtlbUnmappedVWrite8<0x80000000>,vtlbUnmappedVWrite16<0x80000000>,vtlbUnmappedVWrite32<0x80000000>, vtlbUnmappedVWrite64<0x80000000>,vtlbUnmappedVWrite128<0x80000000>
529     );
530    
531     UnmappedPhyHandler0 = vtlb_RegisterHandler(
532     vtlbUnmappedPRead8<0>,vtlbUnmappedPRead16<0>,vtlbUnmappedPRead32<0>,vtlbUnmappedPRead64<0>,vtlbUnmappedPRead128<0>,
533     vtlbUnmappedPWrite8<0>,vtlbUnmappedPWrite16<0>,vtlbUnmappedPWrite32<0>,vtlbUnmappedPWrite64<0>,vtlbUnmappedPWrite128<0>
534     );
535    
536     UnmappedPhyHandler1 = vtlb_RegisterHandler(
537     vtlbUnmappedPRead8<0x80000000>,vtlbUnmappedPRead16<0x80000000>,vtlbUnmappedPRead32<0x80000000>, vtlbUnmappedPRead64<0x80000000>,vtlbUnmappedPRead128<0x80000000>,
538     vtlbUnmappedPWrite8<0x80000000>,vtlbUnmappedPWrite16<0x80000000>,vtlbUnmappedPWrite32<0x80000000>, vtlbUnmappedPWrite64<0x80000000>,vtlbUnmappedPWrite128<0x80000000>
539     );
540    
541     DefaultPhyHandler = vtlb_RegisterHandler(0,0,0,0,0,0,0,0,0,0);
542    
543     //done !
544    
545     //Setup the initial mappings
546     vtlb_MapHandler(DefaultPhyHandler,0,VTLB_PMAP_SZ);
547    
548     //Set the V space as unmapped
549     vtlb_VMapUnmap(0,(VTLB_VMAP_ITEMS-1)*VTLB_PAGE_SIZE);
550     //yeah i know, its stupid .. but this code has to be here for now ;p
551     vtlb_VMapUnmap((VTLB_VMAP_ITEMS-1)*VTLB_PAGE_SIZE,VTLB_PAGE_SIZE);
552    
553     extern void vtlb_dynarec_init();
554     vtlb_dynarec_init();
555     }
556    
557     //////////////////////////////////////////////////////////////////////////////////////////
558     // vtlb_Reset -- Performs a COP0-level reset of the PS2's TLB.
559     // This function should probably be part of the COP0 rather than here in VTLB.
560     void vtlb_Reset()
561     {
562     for(int i=0; i<48; i++) UnmapTLB(i);
563     }
564    
565     void vtlb_Term()
566     {
567     //nothing to do for now
568     }
569    
570     //////////////////////////////////////////////////////////////////////////////////////////
571     // Reserves the vtlb core allocation used by various emulation components!
572     //
573     void vtlb_Core_Alloc()
574     {
575     if( vtlbdata.alloc_base != NULL ) return;
576    
577     vtlbdata.alloc_current = 0;
578    
579     #ifdef __LINUX__
580     vtlbdata.alloc_base = SysMmapEx( 0x16000000, VTLB_ALLOC_SIZE, 0x80000000, "Vtlb" );
581     #else
582     // Win32 just needs this, since malloc always maps below 2GB.
583     vtlbdata.alloc_base = (u8*)_aligned_malloc( VTLB_ALLOC_SIZE, 4096 );
584     if( vtlbdata.alloc_base == NULL )
585     throw Exception::OutOfMemory( "Fatal Error: could not allocate 42Meg buffer for PS2's mappable system ram." );
586     #endif
587     }
588    
589     //////////////////////////////////////////////////////////////////////////////////////////
590     //
591     void vtlb_Core_Shutdown()
592     {
593     if( vtlbdata.alloc_base == NULL ) return;
594    
595     #ifdef __LINUX__
596     SafeSysMunmap( vtlbdata.alloc_base, VTLB_ALLOC_SIZE );
597     #else
598     // Make sure and unprotect memory first, since CrtDebug will try to write to it.
599     HostSys::MemProtect( vtlbdata.alloc_base, VTLB_ALLOC_SIZE, Protect_ReadWrite );
600     safe_aligned_free( vtlbdata.alloc_base );
601     #endif
602    
603     }
604    
605     //////////////////////////////////////////////////////////////////////////////////////////
606     // This function allocates memory block with are compatible with the Vtlb's requirements
607     // for memory locations. The Vtlb requires the topmost bit (Sign bit) of the memory
608     // pointer to be cleared. Some operating systems and/or implementations of malloc do that,
609     // but others do not. So use this instead to allocate the memory correctly for your
610     // platform.
611     //
612     u8* vtlb_malloc( uint size, uint align )
613     {
614     vtlbdata.alloc_current += align-1;
615     vtlbdata.alloc_current &= ~(align-1);
616    
617     int rv = vtlbdata.alloc_current;
618     vtlbdata.alloc_current += size;
619     return &vtlbdata.alloc_base[rv];
620     }
621    
622     //////////////////////////////////////////////////////////////////////////////////////////
623     //
624     void vtlb_free( void* pmem, uint size )
625     {
626     // Does nothing anymore! Alloc/dealloc is now handled by vtlb_Core_Alloc /
627     // vtlb_Core_Shutdown. Placebo is left in place in case it becomes useful again
628     // at a later date.
629    
630     return;
631     }

  ViewVC Help
Powered by ViewVC 1.1.22