From 227a651c17c9104c2e235d9ede278234c5e670e3 Mon Sep 17 00:00:00 2001 From: cottonvibes Date: Tue, 23 Feb 2010 09:22:40 +0000 Subject: [PATCH] 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 --- pcsx2/R5900.cpp | 2 +- pcsx2/VU0.cpp | 2 +- pcsx2/VU0micro.cpp | 2 +- pcsx2/VU0microInterp.cpp | 2 +- pcsx2/VU1micro.cpp | 4 ++-- pcsx2/VU1microInterp.cpp | 2 +- pcsx2/VUmicro.h | 17 ++++++++++------- pcsx2/Vif1_Dma.cpp | 2 +- pcsx2/x86/iCOP2.cpp | 2 +- pcsx2/x86/microVU.cpp | 12 ++++++------ pcsx2/x86/microVU.h | 3 ++- pcsx2/x86/microVU_Macro.inl | 4 +--- pcsx2/x86/sVU_zerorec.cpp | 4 ++-- pcsx2/x86/sVU_zerorec.h | 4 ++-- 14 files changed, 32 insertions(+), 30 deletions(-) diff --git a/pcsx2/R5900.cpp b/pcsx2/R5900.cpp index d695c90696..46f5abdb19 100644 --- a/pcsx2/R5900.cpp +++ b/pcsx2/R5900.cpp @@ -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. -_- diff --git a/pcsx2/VU0.cpp b/pcsx2/VU0.cpp index e16b426b71..627573dfcb 100644 --- a/pcsx2/VU0.cpp +++ b/pcsx2/VU0.cpp @@ -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 diff --git a/pcsx2/VU0micro.cpp b/pcsx2/VU0micro.cpp index b5509e9b98..d7639b2f1b 100644 --- a/pcsx2/VU0micro.cpp +++ b/pcsx2/VU0micro.cpp @@ -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) diff --git a/pcsx2/VU0microInterp.cpp b/pcsx2/VU0microInterp.cpp index 3fb3f9f7b6..b19479d841 100644 --- a/pcsx2/VU0microInterp.cpp +++ b/pcsx2/VU0microInterp.cpp @@ -203,7 +203,7 @@ void InterpVU0::Step() vu0Exec( &VU0 ); } -void InterpVU0::ExecuteBlock() +void InterpVU0::ExecuteBlock(u32 cycles) { for (int i = 128; i--;) { diff --git a/pcsx2/VU1micro.cpp b/pcsx2/VU1micro.cpp index 3f83013977..36688cb04d 100644 --- a/pcsx2/VU1micro.cpp +++ b/pcsx2/VU1micro.cpp @@ -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); diff --git a/pcsx2/VU1microInterp.cpp b/pcsx2/VU1microInterp.cpp index 604bd78593..229713baac 100644 --- a/pcsx2/VU1microInterp.cpp +++ b/pcsx2/VU1microInterp.cpp @@ -186,7 +186,7 @@ void InterpVU1::Step() vu1Exec( &VU1 ); } -void InterpVU1::ExecuteBlock() +void InterpVU1::ExecuteBlock(u32 cycles) { for (int i = 128; i--;) { diff --git a/pcsx2/VUmicro.h b/pcsx2/VUmicro.h index 1a81b9f85d..2328124542 100644 --- a/pcsx2/VUmicro.h +++ b/pcsx2/VUmicro.h @@ -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(); }; diff --git a/pcsx2/Vif1_Dma.cpp b/pcsx2/Vif1_Dma.cpp index e1eb3943e1..ae8b9e6da6 100644 --- a/pcsx2/Vif1_Dma.cpp +++ b/pcsx2/Vif1_Dma.cpp @@ -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; diff --git a/pcsx2/x86/iCOP2.cpp b/pcsx2/x86/iCOP2.cpp index ed43376ea4..99e7543043 100644 --- a/pcsx2/x86/iCOP2.cpp +++ b/pcsx2/x86/iCOP2.cpp @@ -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; } } diff --git a/pcsx2/x86/microVU.cpp b/pcsx2/x86/microVU.cpp index 53ae3b48c3..281bff65fa 100644 --- a/pcsx2/x86/microVU.cpp +++ b/pcsx2/x86/microVU.cpp @@ -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(µVU1); } -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(); } diff --git a/pcsx2/x86/microVU.h b/pcsx2/x86/microVU.h index 00a766f8ef..b76e56007e 100644 --- a/pcsx2/x86/microVU.h +++ b/pcsx2/x86/microVU.h @@ -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" diff --git a/pcsx2/x86/microVU_Macro.inl b/pcsx2/x86/microVU_Macro.inl index 1c83b51ff0..2b47fcc479 100644 --- a/pcsx2/x86/microVU_Macro.inl +++ b/pcsx2/x86/microVU_Macro.inl @@ -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)µVU0.regs->VI[_Rd_].UL, _Rt_); xMOV(ecx, (uptr)CpuVU0); - xCALL(BaseCpuProvider::ExecuteBlockFromRecs); + xCALL(BaseCpuProvider::ExecuteBlockJIT); break; } } diff --git a/pcsx2/x86/sVU_zerorec.cpp b/pcsx2/x86/sVU_zerorec.cpp index c339a496d1..b0c679eff9 100644 --- a/pcsx2/x86/sVU_zerorec.cpp +++ b/pcsx2/x86/sVU_zerorec.cpp @@ -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 ); diff --git a/pcsx2/x86/sVU_zerorec.h b/pcsx2/x86/sVU_zerorec.h index 5e252e5d0c..44231a0d4f 100644 --- a/pcsx2/x86/sVU_zerorec.h +++ b/pcsx2/x86/sVU_zerorec.h @@ -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); };