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
// so there is no need to freeze registers here.
CpuVU0->ExecuteBlock();
CpuVU0->ExecuteBlock(vu0RunCycles);
DevCon.Warning("VU0 running when in BranchTest");
// This might be needed to keep the EE and VU0 in sync.
// 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!");
break; // Do games still need this?
}
CpuVU0->ExecuteBlock();
CpuVU0->ExecuteBlock(vu0RunCycles);
} while ((VU0.VI[REG_VPU_STAT].UL & 1) // E-bit Termination
&& (!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;
_vuExecMicroDebug(VU0);
CpuVU0->ExecuteBlock();
CpuVU0->ExecuteBlock(vu0RunCycles);
// 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)

View File

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

View File

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

View File

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

View File

@ -16,6 +16,9 @@
#pragma once
#include "VU.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
@ -61,15 +64,15 @@ public:
virtual void Reset()=0;
virtual void Step()=0;
virtual void ExecuteBlock()=0;
virtual void ExecuteBlock(u32 cycles)=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
// address of C++ methods. We need to use a wrapper function to invoke the ExecuteBlock from
// 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 Step();
void ExecuteBlock();
void ExecuteBlock(u32 cycles);
void Clear(u32 addr, u32 size) {}
};
@ -144,7 +147,7 @@ public:
void Reset() { }
void Step();
void ExecuteBlock();
void ExecuteBlock(u32 cycles);
void Clear(u32 addr, u32 size) {}
};
@ -164,7 +167,7 @@ public:
void Shutdown() throw();
void Reset();
void ExecuteBlock();
void ExecuteBlock(u32 cycles);
void Clear(u32 addr, u32 size);
void Vsync() throw();
};
@ -181,7 +184,7 @@ public:
void Allocate();
void Shutdown() throw();
void Reset();
void ExecuteBlock();
void ExecuteBlock(u32 cycles);
void Clear(u32 addr, u32 size);
void Vsync() throw();
};

View File

@ -27,7 +27,7 @@ __forceinline void vif1FLUSH()
{
int _cycles = VU1.cycle;
do { CpuVU1->ExecuteBlock(); }
do { CpuVU1->ExecuteBlock(vu1RunCycles); }
while (VU0.VI[REG_VPU_STAT].UL & 0x100);
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]);
iFlushCall(FLUSH_NOCONST);
xMOV(ecx, (uptr)CpuVU0 );
xCALL(BaseCpuProvider::ExecuteBlockFromRecs);
xCALL(BaseCpuProvider::ExecuteBlockJIT);
break;
}
}

View File

@ -19,8 +19,8 @@
#include "Common.h"
#include "VU.h"
#include "GS.h"
#include "x86emitter/x86emitter.h"
using namespace x86Emitter;
#include "iR5900.h"
#include "R5900OpcodeTables.h"
#include "microVU.h"
//------------------------------------------------------------------
@ -375,7 +375,7 @@ void recMicroVU1::Reset() {
mVUreset(&microVU1);
}
void recMicroVU0::ExecuteBlock() {
void recMicroVU0::ExecuteBlock(u32 cycles) {
pxAssert(mvu0_allocated); // please allocate me first! :|
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
// woody hangs if too high on sVU (untested on mVU)
// 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();
}
void recMicroVU1::ExecuteBlock() {
void recMicroVU1::ExecuteBlock(u32 cycles) {
pxAssert(mvu1_allocated); // please allocate me first! :|
if(!(VU0.VI[REG_VPU_STAT].UL & 0x100)) return;
XMMRegisters::Freeze();
((mVUrecCall)microVU1.startFunct)(VU1.VI[REG_TPC].UL, 3000000);
((mVUrecCall)microVU1.startFunct)(VU1.VI[REG_TPC].UL, cycles);
XMMRegisters::Thaw();
}

View File

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

View File

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

View File

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

View File

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