VU interpreters/recompilers: Started working on a way where we can run the VU's based on how much time has actually passed, instead of constant fixed cycles.

Currently still using the fixed-cycle method... so should behave the same as before.

git-svn-id: http://pcsx2.googlecode.com/svn/trunk@2628 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
cottonvibes 2010-02-23 09:22:40 +00:00
parent 50a93750e7
commit 227a651c17
14 changed files with 32 additions and 30 deletions

View File

@ -427,7 +427,7 @@ __forceinline void _cpuBranchTest_Shared()
{ {
// We're in a BranchTest. All dynarec registers are flushed // We're in a BranchTest. All dynarec registers are flushed
// so there is no need to freeze registers here. // so there is no need to freeze registers here.
CpuVU0->ExecuteBlock(); CpuVU0->ExecuteBlock(vu0RunCycles);
DevCon.Warning("VU0 running when in BranchTest"); DevCon.Warning("VU0 running when in BranchTest");
// This might be needed to keep the EE and VU0 in sync. // This might be needed to keep the EE and VU0 in sync.
// A better fix will require hefty changes to the VU recs. -_- // A better fix will require hefty changes to the VU recs. -_-

View File

@ -73,7 +73,7 @@ __forceinline void _vu0run(bool breakOnMbit, bool addCycles) {
Console.Warning("VU0 stuck in infinite loop? Breaking execution!"); Console.Warning("VU0 stuck in infinite loop? Breaking execution!");
break; // Do games still need this? break; // Do games still need this?
} }
CpuVU0->ExecuteBlock(); CpuVU0->ExecuteBlock(vu0RunCycles);
} while ((VU0.VI[REG_VPU_STAT].UL & 1) // E-bit Termination } while ((VU0.VI[REG_VPU_STAT].UL & 1) // E-bit Termination
&& (!breakOnMbit || !(VU0.flags & VUFLAG_MFLAGSET))); // M-bit Break && (!breakOnMbit || !(VU0.flags & VUFLAG_MFLAGSET))); // M-bit Break

View File

@ -56,7 +56,7 @@ void __fastcall vu0ExecMicro(u32 addr) {
if ((s32)addr != -1) VU0.VI[REG_TPC].UL = addr; if ((s32)addr != -1) VU0.VI[REG_TPC].UL = addr;
_vuExecMicroDebug(VU0); _vuExecMicroDebug(VU0);
CpuVU0->ExecuteBlock(); CpuVU0->ExecuteBlock(vu0RunCycles);
// If the VU0 program didn't finish then we'll want to finish it up // If the VU0 program didn't finish then we'll want to finish it up
// pretty soon. This fixes vmhacks in some games (Naruto Ultimate Ninja 2) // pretty soon. This fixes vmhacks in some games (Naruto Ultimate Ninja 2)

View File

@ -203,7 +203,7 @@ void InterpVU0::Step()
vu0Exec( &VU0 ); vu0Exec( &VU0 );
} }
void InterpVU0::ExecuteBlock() void InterpVU0::ExecuteBlock(u32 cycles)
{ {
for (int i = 128; i--;) for (int i = 128; i--;)
{ {

View File

@ -46,7 +46,7 @@ void __fastcall vu1ExecMicro(u32 addr)
{ {
while(VU0.VI[REG_VPU_STAT].UL & 0x100) { while(VU0.VI[REG_VPU_STAT].UL & 0x100) {
VUM_LOG("vu1ExecMicro > Stalling until current microprogram finishes"); VUM_LOG("vu1ExecMicro > Stalling until current microprogram finishes");
CpuVU1->ExecuteBlock(); CpuVU1->ExecuteBlock(vu1RunCycles);
} }
VUM_LOG("vu1ExecMicro %x", addr); VUM_LOG("vu1ExecMicro %x", addr);
@ -59,7 +59,7 @@ void __fastcall vu1ExecMicro(u32 addr)
if ((s32)addr != -1) VU1.VI[REG_TPC].UL = addr; if ((s32)addr != -1) VU1.VI[REG_TPC].UL = addr;
_vuExecMicroDebug(VU1); _vuExecMicroDebug(VU1);
CpuVU1->ExecuteBlock(); CpuVU1->ExecuteBlock(vu1RunCycles);
} }
_vuRegsTables(VU1, VU1regs); _vuRegsTables(VU1, VU1regs);

View File

@ -186,7 +186,7 @@ void InterpVU1::Step()
vu1Exec( &VU1 ); vu1Exec( &VU1 );
} }
void InterpVU1::ExecuteBlock() void InterpVU1::ExecuteBlock(u32 cycles)
{ {
for (int i = 128; i--;) for (int i = 128; i--;)
{ {

View File

@ -16,6 +16,9 @@
#pragma once #pragma once
#include "VU.h" #include "VU.h"
#include "VUops.h" #include "VUops.h"
#define vuRunCycles (512*12) // Cycles to run ExecuteBlockJIT() for (called from within recs)
#define vu0RunCycles (512*12) // Cycles to run vu0 for whenever ExecuteBlock() is called
#define vu1RunCycles (3000000) // mVU1 uses this for inf loop detection on dev builds
// -------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------
// BaseCpuProvider // BaseCpuProvider
@ -61,15 +64,15 @@ public:
virtual void Reset()=0; virtual void Reset()=0;
virtual void Step()=0; virtual void Step()=0;
virtual void ExecuteBlock()=0; virtual void ExecuteBlock(u32 cycles)=0;
virtual void Clear(u32 Addr, u32 Size)=0; virtual void Clear(u32 Addr, u32 Size)=0;
// C++ Calling Conventions are unstable, and some compilers don't even allow us to take the // C++ Calling Conventions are unstable, and some compilers don't even allow us to take the
// address of C++ methods. We need to use a wrapper function to invoke the ExecuteBlock from // address of C++ methods. We need to use a wrapper function to invoke the ExecuteBlock from
// recompiled code. // recompiled code.
static void __fastcall ExecuteBlockFromRecs( BaseCpuProvider* cpu ) static void __fastcall ExecuteBlockJIT( BaseCpuProvider* cpu )
{ {
cpu->ExecuteBlock(); cpu->ExecuteBlock(vuRunCycles);
} }
}; };
@ -126,7 +129,7 @@ public:
void Reset() { } void Reset() { }
void Step(); void Step();
void ExecuteBlock(); void ExecuteBlock(u32 cycles);
void Clear(u32 addr, u32 size) {} void Clear(u32 addr, u32 size) {}
}; };
@ -144,7 +147,7 @@ public:
void Reset() { } void Reset() { }
void Step(); void Step();
void ExecuteBlock(); void ExecuteBlock(u32 cycles);
void Clear(u32 addr, u32 size) {} void Clear(u32 addr, u32 size) {}
}; };
@ -164,7 +167,7 @@ public:
void Shutdown() throw(); void Shutdown() throw();
void Reset(); void Reset();
void ExecuteBlock(); void ExecuteBlock(u32 cycles);
void Clear(u32 addr, u32 size); void Clear(u32 addr, u32 size);
void Vsync() throw(); void Vsync() throw();
}; };
@ -181,7 +184,7 @@ public:
void Allocate(); void Allocate();
void Shutdown() throw(); void Shutdown() throw();
void Reset(); void Reset();
void ExecuteBlock(); void ExecuteBlock(u32 cycles);
void Clear(u32 addr, u32 size); void Clear(u32 addr, u32 size);
void Vsync() throw(); void Vsync() throw();
}; };

View File

@ -27,7 +27,7 @@ __forceinline void vif1FLUSH()
{ {
int _cycles = VU1.cycle; int _cycles = VU1.cycle;
do { CpuVU1->ExecuteBlock(); } do { CpuVU1->ExecuteBlock(vu1RunCycles); }
while (VU0.VI[REG_VPU_STAT].UL & 0x100); while (VU0.VI[REG_VPU_STAT].UL & 0x100);
g_vifCycles += (VU1.cycle - _cycles) * BIAS; g_vifCycles += (VU1.cycle - _cycles) * BIAS;

View File

@ -158,7 +158,7 @@ static void recCTC2(s32 info)
MOV32ItoM((uptr)&VU0.VI[_Fs_].UL,g_cpuConstRegs[_Rt_].UL[0]); MOV32ItoM((uptr)&VU0.VI[_Fs_].UL,g_cpuConstRegs[_Rt_].UL[0]);
iFlushCall(FLUSH_NOCONST); iFlushCall(FLUSH_NOCONST);
xMOV(ecx, (uptr)CpuVU0 ); xMOV(ecx, (uptr)CpuVU0 );
xCALL(BaseCpuProvider::ExecuteBlockFromRecs); xCALL(BaseCpuProvider::ExecuteBlockJIT);
break; break;
} }
} }

View File

@ -19,8 +19,8 @@
#include "Common.h" #include "Common.h"
#include "VU.h" #include "VU.h"
#include "GS.h" #include "GS.h"
#include "x86emitter/x86emitter.h" #include "iR5900.h"
using namespace x86Emitter; #include "R5900OpcodeTables.h"
#include "microVU.h" #include "microVU.h"
//------------------------------------------------------------------ //------------------------------------------------------------------
@ -375,7 +375,7 @@ void recMicroVU1::Reset() {
mVUreset(&microVU1); mVUreset(&microVU1);
} }
void recMicroVU0::ExecuteBlock() { void recMicroVU0::ExecuteBlock(u32 cycles) {
pxAssert(mvu0_allocated); // please allocate me first! :| pxAssert(mvu0_allocated); // please allocate me first! :|
if(!(VU0.VI[REG_VPU_STAT].UL & 1)) return; if(!(VU0.VI[REG_VPU_STAT].UL & 1)) return;
@ -384,16 +384,16 @@ void recMicroVU0::ExecuteBlock() {
// sometimes games spin on vu0, so be careful with this value // sometimes games spin on vu0, so be careful with this value
// woody hangs if too high on sVU (untested on mVU) // woody hangs if too high on sVU (untested on mVU)
// Edit: Need to test this again, if anyone ever has a "Woody" game :p // Edit: Need to test this again, if anyone ever has a "Woody" game :p
((mVUrecCall)microVU0.startFunct)(VU0.VI[REG_TPC].UL, 512*12); ((mVUrecCall)microVU0.startFunct)(VU0.VI[REG_TPC].UL, cycles);
XMMRegisters::Thaw(); XMMRegisters::Thaw();
} }
void recMicroVU1::ExecuteBlock() { void recMicroVU1::ExecuteBlock(u32 cycles) {
pxAssert(mvu1_allocated); // please allocate me first! :| pxAssert(mvu1_allocated); // please allocate me first! :|
if(!(VU0.VI[REG_VPU_STAT].UL & 0x100)) return; if(!(VU0.VI[REG_VPU_STAT].UL & 0x100)) return;
XMMRegisters::Freeze(); XMMRegisters::Freeze();
((mVUrecCall)microVU1.startFunct)(VU1.VI[REG_TPC].UL, 3000000); ((mVUrecCall)microVU1.startFunct)(VU1.VI[REG_TPC].UL, cycles);
XMMRegisters::Thaw(); XMMRegisters::Thaw();
} }

View File

@ -18,7 +18,8 @@
//#define mVUlogProg // Dumps MicroPrograms to \logs\*.html //#define mVUlogProg // Dumps MicroPrograms to \logs\*.html
class AsciiFile; class AsciiFile;
#include "x86emitter/x86emitter.h"
using namespace x86Emitter;
#include "microVU_IR.h" #include "microVU_IR.h"
#include "microVU_Misc.h" #include "microVU_Misc.h"

View File

@ -16,8 +16,6 @@
#ifdef CHECK_MACROVU0 #ifdef CHECK_MACROVU0
#pragma once #pragma once
#include "iR5900.h"
#include "R5900OpcodeTables.h"
extern void _vu0WaitMicro(); extern void _vu0WaitMicro();
extern void _vu0FinishMicro(); extern void _vu0FinishMicro();
@ -338,7 +336,7 @@ static void recCTC2() {
// sVU's COP2 has a comment that "Donald Duck" needs this too... // sVU's COP2 has a comment that "Donald Duck" needs this too...
if (_Rd_) _eeMoveGPRtoM((uptr)&microVU0.regs->VI[_Rd_].UL, _Rt_); if (_Rd_) _eeMoveGPRtoM((uptr)&microVU0.regs->VI[_Rd_].UL, _Rt_);
xMOV(ecx, (uptr)CpuVU0); xMOV(ecx, (uptr)CpuVU0);
xCALL(BaseCpuProvider::ExecuteBlockFromRecs); xCALL(BaseCpuProvider::ExecuteBlockJIT);
break; break;
} }
} }

View File

@ -4628,7 +4628,7 @@ void recSuperVU0::Reset()
SuperVUReset( 0 ); SuperVUReset( 0 );
} }
void recSuperVU0::ExecuteBlock() void recSuperVU0::ExecuteBlock(u32 cycles)
{ {
if ((VU0.VI[REG_VPU_STAT].UL & 1) == 0) return; if ((VU0.VI[REG_VPU_STAT].UL & 1) == 0) return;
@ -4666,7 +4666,7 @@ void recSuperVU1::Reset()
SuperVUReset( 1 ); SuperVUReset( 1 );
} }
void recSuperVU1::ExecuteBlock() void recSuperVU1::ExecuteBlock(u32 cycles)
{ {
if ((VU0.VI[REG_VPU_STAT].UL & 0x100) == 0) return; if ((VU0.VI[REG_VPU_STAT].UL & 0x100) == 0) return;
pxAssert( (VU1.VI[REG_TPC].UL&7) == 0 ); pxAssert( (VU1.VI[REG_TPC].UL&7) == 0 );

View File

@ -53,7 +53,7 @@ public:
void Allocate(); void Allocate();
void Shutdown() throw(); void Shutdown() throw();
void Reset(); void Reset();
void ExecuteBlock(); void ExecuteBlock(u32 cycles);
void Clear(u32 Addr, u32 Size); void Clear(u32 Addr, u32 Size);
}; };
@ -68,6 +68,6 @@ public:
void Allocate(); void Allocate();
void Shutdown() throw(); void Shutdown() throw();
void Reset(); void Reset();
void ExecuteBlock(); void ExecuteBlock(u32 cycles);
void Clear(u32 Addr, u32 Size); void Clear(u32 Addr, u32 Size);
}; };