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