mirror of https://github.com/PCSX2/pcsx2.git
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:
parent
50a93750e7
commit
227a651c17
|
@ -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. -_-
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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--;)
|
||||||
{
|
{
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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--;)
|
||||||
{
|
{
|
||||||
|
|
|
@ -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();
|
||||||
};
|
};
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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(µVU1);
|
mVUreset(µVU1);
|
||||||
}
|
}
|
||||||
|
|
||||||
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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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"
|
||||||
|
|
||||||
|
|
|
@ -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)µVU0.regs->VI[_Rd_].UL, _Rt_);
|
if (_Rd_) _eeMoveGPRtoM((uptr)µVU0.regs->VI[_Rd_].UL, _Rt_);
|
||||||
xMOV(ecx, (uptr)CpuVU0);
|
xMOV(ecx, (uptr)CpuVU0);
|
||||||
xCALL(BaseCpuProvider::ExecuteBlockFromRecs);
|
xCALL(BaseCpuProvider::ExecuteBlockJIT);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 );
|
||||||
|
|
|
@ -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);
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue