pcsx2: tlb: add a new lut (Virtual PS2 to Physical PS2)

note: automatic gamefixes are done after done after the init that why code was splitted.
note2: The LUT is 4MB and only used for only 1 game. So I only allocate it when the gamefix is
    enabled
This commit is contained in:
Gregory Hainaut 2014-06-12 00:25:36 +02:00
parent 2e8f56fc86
commit 9452444a9f
4 changed files with 59 additions and 2 deletions

View File

@ -277,6 +277,10 @@ static int loadGameSettings(Pcsx2Config& dest, const Game_Data& game, bool verbo
dest.Gamefixes.Set(id, enableIt);
if(verbose) Console.WriteLn(L"(GameDB) %s Gamefix: " + key, enableIt ? L"Enabled" : L"Disabled" );
gf++;
// The LUT is only used for 1 game so we allocate it only when the gamefix is enabled (save 4MB)
if (id == Fix_GoemonTlbMiss && enableIt)
vtlb_Alloc_Ppmap();
}
}

View File

@ -583,6 +583,13 @@ __fi void* vtlb_GetPhyPtr(u32 paddr)
return reinterpret_cast<void*>(vtlbdata.pmap[paddr>>VTLB_PAGE_BITS]+(paddr&VTLB_PAGE_MASK));
}
__fi u32 vtlb_V2P(u32 vaddr)
{
u32 paddr = vtlbdata.ppmap[vaddr>>VTLB_PAGE_BITS];
paddr |= vaddr & VTLB_PAGE_MASK;
return paddr;
}
//virtual mappings
//TODO: Add invalid paddr checks
void vtlb_VMap(u32 vaddr,u32 paddr,u32 size)
@ -610,6 +617,10 @@ void vtlb_VMap(u32 vaddr,u32 paddr,u32 size)
}
vtlbdata.vmap[vaddr>>VTLB_PAGE_BITS] = pme-vaddr;
if (vtlbdata.ppmap)
if (!(vaddr & 0x80000000)) // those address are already physical don't change them
vtlbdata.ppmap[vaddr>>VTLB_PAGE_BITS] = paddr & ~VTLB_PAGE_MASK;
vaddr += VTLB_PAGE_SIZE;
paddr += VTLB_PAGE_SIZE;
size -= VTLB_PAGE_SIZE;
@ -630,6 +641,7 @@ void vtlb_VMapBuffer(u32 vaddr,void* buffer,u32 size)
size -= VTLB_PAGE_SIZE;
}
}
void vtlb_VMapUnmap(u32 vaddr,u32 size)
{
verify(0==(vaddr&VTLB_PAGE_MASK));
@ -688,6 +700,10 @@ void vtlb_Init()
//yeah i know, its stupid .. but this code has to be here for now ;p
vtlb_VMapUnmap((VTLB_VMAP_ITEMS-1)*VTLB_PAGE_SIZE,VTLB_PAGE_SIZE);
// The LUT is only used for 1 game so we allocate it only when the gamefix is enabled (save 4MB)
if (EmuConfig.Gamefixes.GoemonTlbHack)
vtlb_Alloc_Ppmap();
extern void vtlb_dynarec_init();
vtlb_dynarec_init();
}
@ -720,9 +736,26 @@ void vtlb_Core_Alloc()
}
}
// The LUT is only used for 1 game so we allocate it only when the gamefix is enabled (save 4MB)
// However automatic gamefix is done after the standard init so a new init function was done.
void vtlb_Alloc_Ppmap()
{
if (vtlbdata.ppmap) return;
vtlbdata.ppmap = (u32*)_aligned_malloc( VTLB_VMAP_ITEMS * sizeof(*vtlbdata.ppmap), 16 );
if (!vtlbdata.ppmap)
throw Exception::OutOfMemory( L"VTLB PS2 Virtual Address Translation LUT" )
.SetDiagMsg(pxsFmt("(%u megs)", VTLB_VMAP_ITEMS * sizeof(*vtlbdata.ppmap) / _1mb));
// By default a 1:1 virtual to physical mapping
for (u32 i = 0; i < VTLB_VMAP_ITEMS; i++)
vtlbdata.ppmap[i] = i<<VTLB_PAGE_BITS;
}
void vtlb_Core_Free()
{
safe_aligned_free( vtlbdata.vmap );
safe_aligned_free( vtlbdata.ppmap );
}
static wxString GetHostVmErrorMsg()

View File

@ -39,6 +39,7 @@ typedef u32 vtlbHandler;
extern void vtlb_Core_Alloc();
extern void vtlb_Core_Free();
extern void vtlb_Alloc_Ppmap();
extern void vtlb_Init();
extern void vtlb_Reset();
extern void vtlb_Term();
@ -61,6 +62,8 @@ extern void vtlb_MapHandler(vtlbHandler handler,u32 start,u32 size);
extern void vtlb_MapBlock(void* base,u32 start,u32 size,u32 blocksize=0);
extern void* vtlb_GetPhyPtr(u32 paddr);
//extern void vtlb_Mirror(u32 new_region,u32 start,u32 size); // -> not working yet :(
extern u32 vtlb_V2P(u32 vaddr);
extern void vtlb_DynV2P();
//virtual mappings
extern void vtlb_VMap(u32 vaddr,u32 paddr,u32 sz);
@ -194,9 +197,11 @@ namespace vtlb_private
// third indexer -- 128 possible handlers!
void* RWFT[5][2][VTLB_HANDLER_ITEMS];
s32 pmap[VTLB_PMAP_ITEMS]; //512KB
s32 pmap[VTLB_PMAP_ITEMS]; //512KB // PS2 physical to x86 physical
s32* vmap; //4MB (allocated by vtlb_init)
s32* vmap; //4MB (allocated by vtlb_init) // PS2 virtual to x86 physical
u32* ppmap; //4MB (allocated by vtlb_init) // PS2 virtual to PS2 physical
MapData()
{

View File

@ -557,3 +557,18 @@ void vtlb_DynGenWrite_Const( u32 bits, u32 addr_const )
}
}
//////////////////////////////////////////////////////////////////////////////////////////
// Extra Implementations
// ecx - virtual address
// Returns physical address in eax.
void vtlb_DynV2P()
{
xMOV(eax, ecx);
xAND(ecx, VTLB_PAGE_MASK); // vaddr & VTLB_PAGE_MASK
xSHR(eax, VTLB_PAGE_BITS);
xMOV(eax, ptr[(eax*4) + vtlbdata.ppmap]); //vtlbdata.ppmap[vaddr>>VTLB_PAGE_BITS];
xOR(eax, ecx);
}