mirror of https://github.com/PCSX2/pcsx2.git
VU: Run sync ahead on small blocks
This commit is contained in:
parent
eabda670ac
commit
6dc5087cbd
|
@ -20,6 +20,19 @@
|
||||||
#include "GS.h"
|
#include "GS.h"
|
||||||
#include "Gif_Unit.h"
|
#include "Gif_Unit.h"
|
||||||
|
|
||||||
|
__inline u32 CalculateMinRunCycles(u32 cycles, bool requiresAccurateCycles)
|
||||||
|
{
|
||||||
|
// If we're running an interlocked COP2 operation
|
||||||
|
// run for an exact amount of cycles
|
||||||
|
if(requiresAccurateCycles)
|
||||||
|
return cycles;
|
||||||
|
|
||||||
|
// Allow a minimum of 16 cycles to avoid running small blocks
|
||||||
|
// Running a block of like 3 cycles is highly inefficient
|
||||||
|
// so while sync isn't tight, it's okay to run ahead a little bit.
|
||||||
|
return std::max(16U, cycles);
|
||||||
|
}
|
||||||
|
|
||||||
// Executes a Block based on EE delta time
|
// Executes a Block based on EE delta time
|
||||||
void BaseVUmicroCPU::ExecuteBlock(bool startUp)
|
void BaseVUmicroCPU::ExecuteBlock(bool startUp)
|
||||||
{
|
{
|
||||||
|
@ -57,12 +70,12 @@ void BaseVUmicroCPU::ExecuteBlock(bool startUp)
|
||||||
if (EmuConfig.Gamefixes.VUKickstartHack)
|
if (EmuConfig.Gamefixes.VUKickstartHack)
|
||||||
{
|
{
|
||||||
if (delta > 0) // When kickstarting we just need 1 cycle for run ahead
|
if (delta > 0) // When kickstarting we just need 1 cycle for run ahead
|
||||||
Execute(delta);
|
Execute(CalculateMinRunCycles(delta, false));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (delta >= nextblockcycles && delta > 0) // When running behind, make sure we have enough cycles passed for the block to run
|
if (delta >= nextblockcycles && delta > 0) // When running behind, make sure we have enough cycles passed for the block to run
|
||||||
Execute(delta);
|
Execute(CalculateMinRunCycles(delta, false));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -71,7 +84,7 @@ void BaseVUmicroCPU::ExecuteBlock(bool startUp)
|
||||||
// EE data to VU0's registers. We want to run VU0 Micro right after this
|
// EE data to VU0's registers. We want to run VU0 Micro right after this
|
||||||
// to ensure that the register is used at the correct time.
|
// to ensure that the register is used at the correct time.
|
||||||
// This fixes spinning/hanging in some games like Ratchet and Clank's Intro.
|
// This fixes spinning/hanging in some games like Ratchet and Clank's Intro.
|
||||||
void BaseVUmicroCPU::ExecuteBlockJIT(BaseVUmicroCPU* cpu)
|
void BaseVUmicroCPU::ExecuteBlockJIT(BaseVUmicroCPU* cpu, bool interlocked)
|
||||||
{
|
{
|
||||||
const u32& stat = VU0.VI[REG_VPU_STAT].UL;
|
const u32& stat = VU0.VI[REG_VPU_STAT].UL;
|
||||||
const int test = 1;
|
const int test = 1;
|
||||||
|
@ -83,7 +96,7 @@ void BaseVUmicroCPU::ExecuteBlockJIT(BaseVUmicroCPU* cpu)
|
||||||
|
|
||||||
if (delta > 0)
|
if (delta > 0)
|
||||||
{
|
{
|
||||||
cpu->Execute(delta); // Execute the time since the last call
|
cpu->Execute(CalculateMinRunCycles(delta, interlocked)); // Execute the time since the last call
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -147,7 +147,7 @@ public:
|
||||||
// Executes a Block based on EE delta time (see VUmicro.cpp)
|
// Executes a Block based on EE delta time (see VUmicro.cpp)
|
||||||
virtual void ExecuteBlock(bool startUp=0);
|
virtual void ExecuteBlock(bool startUp=0);
|
||||||
|
|
||||||
static void __fastcall ExecuteBlockJIT(BaseVUmicroCPU* cpu);
|
static void __fastcall ExecuteBlockJIT(BaseVUmicroCPU* cpu, bool interlocked);
|
||||||
|
|
||||||
// VU1 sometimes needs to break execution on XGkick Path1 transfers if
|
// VU1 sometimes needs to break execution on XGkick Path1 transfers if
|
||||||
// there is another gif path 2/3 transfer already taking place.
|
// there is another gif path 2/3 transfer already taking place.
|
||||||
|
|
|
@ -27,6 +27,7 @@ extern u32 pc; // recompiler pc
|
||||||
extern int g_branch; // set for branch
|
extern int g_branch; // set for branch
|
||||||
extern u32 target; // branch target
|
extern u32 target; // branch target
|
||||||
extern u32 s_nBlockCycles; // cycles of current block recompiling
|
extern u32 s_nBlockCycles; // cycles of current block recompiling
|
||||||
|
extern bool s_nBlockInterlocked; // Current block has VU0 interlocking
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
|
|
|
@ -61,7 +61,7 @@ alignas(16) static u32 hwLUT[_64kb];
|
||||||
static __fi u32 HWADDR(u32 mem) { return hwLUT[mem >> 16] + mem; }
|
static __fi u32 HWADDR(u32 mem) { return hwLUT[mem >> 16] + mem; }
|
||||||
|
|
||||||
u32 s_nBlockCycles = 0; // cycles of current block recompiling
|
u32 s_nBlockCycles = 0; // cycles of current block recompiling
|
||||||
|
bool s_nBlockInterlocked = false; // Block is VU0 interlocked
|
||||||
u32 pc; // recompiler pc
|
u32 pc; // recompiler pc
|
||||||
int g_branch; // set for branch
|
int g_branch; // set for branch
|
||||||
|
|
||||||
|
@ -1927,6 +1927,7 @@ static void __fastcall recRecompile(const u32 startpc)
|
||||||
|
|
||||||
// reset recomp state variables
|
// reset recomp state variables
|
||||||
s_nBlockCycles = 0;
|
s_nBlockCycles = 0;
|
||||||
|
s_nBlockInterlocked = false;
|
||||||
pc = startpc;
|
pc = startpc;
|
||||||
g_cpuHasConstReg = g_cpuFlushedConstReg = 1;
|
g_cpuHasConstReg = g_cpuFlushedConstReg = 1;
|
||||||
pxAssert(g_cpuConstRegs[0].UD[0] == 0);
|
pxAssert(g_cpuConstRegs[0].UD[0] == 0);
|
||||||
|
|
|
@ -963,7 +963,8 @@ void recLQC2()
|
||||||
xForwardJL32 skip;
|
xForwardJL32 skip;
|
||||||
_cop2BackupRegs();
|
_cop2BackupRegs();
|
||||||
xLoadFarAddr(arg1reg, CpuVU0);
|
xLoadFarAddr(arg1reg, CpuVU0);
|
||||||
xFastCall((void*)BaseVUmicroCPU::ExecuteBlockJIT, arg1reg);
|
xMOV(arg2reg, s_nBlockInterlocked);
|
||||||
|
xFastCall((void*)BaseVUmicroCPU::ExecuteBlockJIT, arg1reg, arg2reg);
|
||||||
_cop2RestoreRegs();
|
_cop2RestoreRegs();
|
||||||
skip.SetTarget();
|
skip.SetTarget();
|
||||||
skipvuidle.SetTarget();
|
skipvuidle.SetTarget();
|
||||||
|
@ -1012,7 +1013,8 @@ void recSQC2()
|
||||||
xForwardJL32 skip;
|
xForwardJL32 skip;
|
||||||
_cop2BackupRegs();
|
_cop2BackupRegs();
|
||||||
xLoadFarAddr(arg1reg, CpuVU0);
|
xLoadFarAddr(arg1reg, CpuVU0);
|
||||||
xFastCall((void*)BaseVUmicroCPU::ExecuteBlockJIT, arg1reg);
|
xMOV(arg2reg, s_nBlockInterlocked);
|
||||||
|
xFastCall((void*)BaseVUmicroCPU::ExecuteBlockJIT, arg1reg, arg2reg);
|
||||||
_cop2RestoreRegs();
|
_cop2RestoreRegs();
|
||||||
skip.SetTarget();
|
skip.SetTarget();
|
||||||
skipvuidle.SetTarget();
|
skipvuidle.SetTarget();
|
||||||
|
|
|
@ -327,6 +327,7 @@ void COP2_Interlock(bool mBitSync)
|
||||||
|
|
||||||
if (cpuRegs.code & 1)
|
if (cpuRegs.code & 1)
|
||||||
{
|
{
|
||||||
|
s_nBlockInterlocked = true;
|
||||||
_freeX86reg(eax);
|
_freeX86reg(eax);
|
||||||
xMOV(eax, ptr32[&cpuRegs.cycle]);
|
xMOV(eax, ptr32[&cpuRegs.cycle]);
|
||||||
xADD(eax, scaleblockcycles_clear());
|
xADD(eax, scaleblockcycles_clear());
|
||||||
|
@ -342,7 +343,8 @@ void COP2_Interlock(bool mBitSync)
|
||||||
xCMP(eax, 0);
|
xCMP(eax, 0);
|
||||||
xForwardJL32 skip;
|
xForwardJL32 skip;
|
||||||
xLoadFarAddr(arg1reg, CpuVU0);
|
xLoadFarAddr(arg1reg, CpuVU0);
|
||||||
xFastCall((void*)BaseVUmicroCPU::ExecuteBlockJIT, arg1reg);
|
xMOV(arg2reg, s_nBlockInterlocked);
|
||||||
|
xFastCall((void*)BaseVUmicroCPU::ExecuteBlockJIT, arg1reg, arg2reg);
|
||||||
skip.SetTarget();
|
skip.SetTarget();
|
||||||
|
|
||||||
xFastCall((void*)_vu0WaitMicro);
|
xFastCall((void*)_vu0WaitMicro);
|
||||||
|
@ -387,7 +389,8 @@ static void recCFC2()
|
||||||
xForwardJL32 skip;
|
xForwardJL32 skip;
|
||||||
_cop2BackupRegs();
|
_cop2BackupRegs();
|
||||||
xLoadFarAddr(arg1reg, CpuVU0);
|
xLoadFarAddr(arg1reg, CpuVU0);
|
||||||
xFastCall((void*)BaseVUmicroCPU::ExecuteBlockJIT, arg1reg);
|
xMOV(arg2reg, s_nBlockInterlocked);
|
||||||
|
xFastCall((void*)BaseVUmicroCPU::ExecuteBlockJIT, arg1reg, arg2reg);
|
||||||
_cop2RestoreRegs();
|
_cop2RestoreRegs();
|
||||||
skip.SetTarget();
|
skip.SetTarget();
|
||||||
skipvuidle.SetTarget();
|
skipvuidle.SetTarget();
|
||||||
|
@ -449,7 +452,8 @@ static void recCTC2()
|
||||||
xForwardJL32 skip;
|
xForwardJL32 skip;
|
||||||
_cop2BackupRegs();
|
_cop2BackupRegs();
|
||||||
xLoadFarAddr(arg1reg, CpuVU0);
|
xLoadFarAddr(arg1reg, CpuVU0);
|
||||||
xFastCall((void*)BaseVUmicroCPU::ExecuteBlockJIT, arg1reg);
|
xMOV(arg2reg, s_nBlockInterlocked);
|
||||||
|
xFastCall((void*)BaseVUmicroCPU::ExecuteBlockJIT, arg1reg, arg2reg);
|
||||||
_cop2RestoreRegs();
|
_cop2RestoreRegs();
|
||||||
skip.SetTarget();
|
skip.SetTarget();
|
||||||
skipvuidle.SetTarget();
|
skipvuidle.SetTarget();
|
||||||
|
@ -551,7 +555,8 @@ static void recQMFC2()
|
||||||
xForwardJL32 skip;
|
xForwardJL32 skip;
|
||||||
_cop2BackupRegs();
|
_cop2BackupRegs();
|
||||||
xLoadFarAddr(arg1reg, CpuVU0);
|
xLoadFarAddr(arg1reg, CpuVU0);
|
||||||
xFastCall((void*)BaseVUmicroCPU::ExecuteBlockJIT, arg1reg);
|
xMOV(arg2reg, s_nBlockInterlocked);
|
||||||
|
xFastCall((void*)BaseVUmicroCPU::ExecuteBlockJIT, arg1reg, arg2reg);
|
||||||
_cop2RestoreRegs();
|
_cop2RestoreRegs();
|
||||||
skip.SetTarget();
|
skip.SetTarget();
|
||||||
skipvuidle.SetTarget();
|
skipvuidle.SetTarget();
|
||||||
|
@ -591,7 +596,8 @@ static void recQMTC2()
|
||||||
xForwardJL32 skip;
|
xForwardJL32 skip;
|
||||||
_cop2BackupRegs();
|
_cop2BackupRegs();
|
||||||
xLoadFarAddr(arg1reg, CpuVU0);
|
xLoadFarAddr(arg1reg, CpuVU0);
|
||||||
xFastCall((void*)BaseVUmicroCPU::ExecuteBlockJIT, arg1reg);
|
xMOV(arg2reg, s_nBlockInterlocked);
|
||||||
|
xFastCall((void*)BaseVUmicroCPU::ExecuteBlockJIT, arg1reg, arg2reg);
|
||||||
_cop2RestoreRegs();
|
_cop2RestoreRegs();
|
||||||
skip.SetTarget();
|
skip.SetTarget();
|
||||||
skipvuidle.SetTarget();
|
skipvuidle.SetTarget();
|
||||||
|
|
Loading…
Reference in New Issue