pcsx2: tlb: goemon implement a preload hack tlb

Tlb mapping is stored @0x3d5580 (GoemonTlb[150])
The function that will populate the tlb is around pc = 0x356250, ra = 0x33ad48

The idea is to add a callback on 0x33ad48 block that will populate the tlb based on
ee mem content.

Note: The hack is based on previous Virtual PS2 => Physical PS2 LUT
This commit is contained in:
Gregory Hainaut 2014-06-12 00:35:28 +02:00
parent 9452444a9f
commit a00b8ecc55
7 changed files with 84 additions and 3 deletions

View File

@ -345,6 +345,10 @@ void BGEZALL() // Branch if Rs >= 0 and link
*********************************************************/
void JR()
{
// 0x33ad48 is the return address of the function that populate the TLB cache
if (cpuRegs.GPR.r[_Rs_].UL[0] == 0x33ad48 && EmuConfig.Gamefixes.GoemonTlbHack) {
GoemonPreloadTlb();
}
doBranch(cpuRegs.GPR.r[_Rs_].UL[0]);
}

View File

@ -423,6 +423,7 @@ extern void cpuTlbMissR(u32 addr, u32 bd);
extern void cpuTlbMissW(u32 addr, u32 bd);
extern void cpuTestHwInts();
extern void cpuClearInt(uint n);
extern __fastcall void GoemonPreloadTlb();
extern void cpuSetNextEvent( u32 startCycle, s32 delta );
extern void cpuSetNextEventDelta( s32 delta );

View File

@ -43,6 +43,7 @@ static void PostLoadPrep()
memzero(pCache);
// WriteCP0Status(cpuRegs.CP0.n.Status.val);
for(int i=0; i<48; i++) MapTLB(i);
if (EmuConfig.Gamefixes.GoemonTlbHack) GoemonPreloadTlb();
UpdateVSyncRate();
}

View File

@ -331,9 +331,45 @@ template void vtlb_memWrite<mem32_t>(u32 mem, mem32_t data);
// Important recompiler note: Mid-block Exception handling isn't reliable *yet* because
// memory ops don't flush the PC prior to invoking the indirect handlers.
static void GoemonTlbMissDebug()
{
// 0x3d5580 is the address of the TLB cache
GoemonTlb* tlb = (GoemonTlb*)&eeMem->Main[0x3d5580];
for (u32 i = 0; i < 150; i++) {
if (tlb[i].valid == 0x1 && tlb[i].low_add != tlb[i].high_add)
DevCon.WriteLn("Entry %d is valid. From V:0x%8.8x to V:0x%8.8x (P:0x%8.8x)", i, tlb[i].low_add, tlb[i].high_add, tlb[i].physical_add);
}
}
void __fastcall GoemonPreloadTlb()
{
// 0x3d5580 is the address of the TLB cache table
GoemonTlb* tlb = (GoemonTlb*)&eeMem->Main[0x3d5580];
for (u32 i = 0; i < 150; i++) {
if (tlb[i].valid == 0x1 && tlb[i].low_add != tlb[i].high_add) {
u32 size = tlb[i].high_add - tlb[i].low_add;
u32 vaddr = tlb[i].low_add;
u32 paddr = tlb[i].physical_add;
if ((u32)vtlbdata.vmap[vaddr>>VTLB_PAGE_BITS] == 0x80000000u) {
DevCon.WriteLn("Preload TLB[%d]: From V:0x%8.8x to P:0x%8.8x (%d pages)", i, vaddr, paddr, size >> VTLB_PAGE_BITS);
vtlb_VMap( vaddr , paddr, size);
vtlb_VMap(0x20000000|vaddr , paddr, size);
}
}
}
}
// Generates a tlbMiss Exception
static __ri void vtlb_Miss(u32 addr,u32 mode)
{
if (EmuConfig.Gamefixes.GoemonTlbHack)
GoemonTlbMissDebug();
// Hack to handle expected tlb miss by some games.
if (Cpu == &intCpu) {
if (mode)

View File

@ -211,3 +211,18 @@ namespace vtlb_private
extern __aligned(64) MapData vtlbdata;
}
// --------------------------------------------------------------------------------------
// Goemon game fix
// --------------------------------------------------------------------------------------
struct GoemonTlb {
u32 valid;
u32 unk1; // could be physical address also
u32 unk2;
u32 low_add;
u32 physical_add;
u32 unk3; // likely the size
u32 high_add;
u32 unk4;
u32 unk5;
};

View File

@ -971,6 +971,12 @@ void SetBranchReg( u32 reg )
_allocX86reg(ESI, X86TYPE_PCWRITEBACK, 0, MODE_WRITE);
_eeMoveGPRtoR(ESI, reg);
if (EmuConfig.Gamefixes.GoemonTlbHack) {
xMOV(ecx, esi);
vtlb_DynV2P();
xMOV(esi, eax);
}
recompileNextInstruction(1);
if( x86regs[ESI].inuse ) {
@ -1516,7 +1522,6 @@ void encodeMemcheck()
}
void recompileNextInstruction(int delayslot)
{
static u8 s_bFlushReg = 1;
@ -1862,6 +1867,11 @@ static void __fastcall recRecompile( const u32 startpc )
xCALL(PreBlockCheck);
}
// 0x33ad48 is the return address of the function that populate the TLB cache
if (pc == 0x33ad48 && EmuConfig.Gamefixes.GoemonTlbHack) {
xCALL(GoemonPreloadTlb);
}
// go until the next branch
i = startpc;
s_nEndBlock = 0xffffffff;

View File

@ -22,6 +22,8 @@
#include "R5900OpcodeTables.h"
#include "iR5900.h"
using namespace x86Emitter;
namespace R5900 {
namespace Dynarec {
namespace OpcodeImpl
@ -48,7 +50,10 @@ void recJ( void )
// SET_FPUSTATE;
u32 newpc = (_Target_ << 2) + ( pc & 0xf0000000 );
recompileNextInstruction(1);
SetBranchImm(newpc);
if (EmuConfig.Gamefixes.GoemonTlbHack)
SetBranchImm(vtlb_V2P(newpc));
else
SetBranchImm(newpc);
}
////////////////////////////////////////////////////
@ -69,7 +74,10 @@ void recJAL( void )
}
recompileNextInstruction(1);
SetBranchImm(newpc);
if (EmuConfig.Gamefixes.GoemonTlbHack)
SetBranchImm(vtlb_V2P(newpc));
else
SetBranchImm(newpc);
}
/*********************************************************
@ -89,6 +97,12 @@ void recJALR( void )
int newpc = pc + 4;
_allocX86reg(ESI, X86TYPE_PCWRITEBACK, 0, MODE_WRITE);
_eeMoveGPRtoR(ESI, _Rs_);
if (EmuConfig.Gamefixes.GoemonTlbHack) {
xMOV(ecx, esi);
vtlb_DynV2P();
xMOV(esi, eax);
}
// uncomment when there are NO instructions that need to call interpreter
// int mmreg;
// if( GPR_IS_CONST1(_Rs_) )