VU: Improve sync during interlock and Scratchpad VU mem writes

Also added some setting of next block cycles to 0 in cases where we don't know ahead of compile time or the VU is ending.
This commit is contained in:
refractionpcsx2 2021-09-05 16:37:43 +01:00
parent 420b675746
commit ddb300027c
5 changed files with 19 additions and 8 deletions

View File

@ -437,14 +437,11 @@ __fi void _cpuEventTest_Shared()
iopEventAction = false;
}
// ---- VU0 -------------
// ---- VU Sync -------------
// We're in a EventTest. All dynarec registers are flushed
// so there is no need to freeze registers here.
CpuVU0->ExecuteBlock();
CpuVU1->ExecuteBlock();
// Note: We don't update the VU1 here because it runs it's micro-programs in
// one shot always. That is, when a program is executed the VU1 doesn't even
// bother to return until the program is completely finished.
// ---- Schedule Next Event Test --------------

View File

@ -30,6 +30,11 @@ static void TestClearVUs(u32 madr, u32 qwc, bool isWrite)
{
if (madr >= 0x11000000 && (madr < 0x11010000))
{
// Sync the VU's if they're running, writing/reading from VU memory while they're running can be timing sensitive.
// Use Psychonauts for testing
CpuVU0->ExecuteBlock(0);
CpuVU1->ExecuteBlock(0);
if (madr < 0x11004000)
{
if(isWrite)

View File

@ -78,6 +78,7 @@ __fi void _vu0run(bool breakOnMbit, bool addCycles) {
{
cpuRegs.cycle += (VU0.cycle - startcycle);
VU0.cycle = cpuRegs.cycle;
CpuVU1->ExecuteBlock(0); // Catch up VU1 as it's likely fallen behind
}
}

View File

@ -44,10 +44,7 @@ void BaseVUmicroCPU::ExecuteBlock(bool startUp)
s32 delta = (s32)(u32)(cpuRegs.cycle - cycle);
s32 nextblockcycles = m_Idx ? VU1.nextBlockCycles : VU0.nextBlockCycles;
if (delta < nextblockcycles)
return;
if (delta > 0) // Enough time has passed
if (delta >= nextblockcycles) // Enough time has passed
Execute(delta); // Execute the time since the last call
}
}

View File

@ -307,6 +307,7 @@ void normJumpCompile(mV, microFlagCycles& mFC, bool isEvilJump)
//So if it is taken, you need to end the program, else you get infinite loops.
mVUendProgram(mVU, &mFC, 2);
xMOV(ptr32[&mVU.regs().VI[REG_TPC].UL], arg1regd);
xMOV(ptr32[&mVU.regs().nextBlockCycles], 0);
xJMP(mVU.exitFunct);
}
@ -367,6 +368,7 @@ void normBranch(mV, microFlagCycles& mFC)
mVUendProgram(mVU, &mFC, 3);
iPC = branchAddr(mVU) / 4;
xMOV(ptr32[&mVU.regs().VI[REG_TPC].UL], xPC);
xMOV(ptr32[&mVU.regs().nextBlockCycles], 0);
xJMP(mVU.exitFunct);
iPC = tempPC;
}
@ -464,6 +466,7 @@ void condBranch(mV, microFlagCycles& mFC, int JMPcc)
incPC(-4); // Go Back to Branch Opcode to get branchAddr
iPC = branchAddr(mVU) / 4;
xMOV(ptr32[&mVU.regs().VI[REG_TPC].UL], xPC);
xMOV(ptr32[&mVU.regs().nextBlockCycles], 0);
xJMP(mVU.exitFunct);
eJMP.SetTarget();
iPC = tempPC;
@ -483,11 +486,13 @@ void condBranch(mV, microFlagCycles& mFC, int JMPcc)
xForwardJump32 dJMP(xInvertCond((JccComparisonType)JMPcc));
incPC(4); // Set PC to First instruction of Non-Taken Side
xMOV(ptr32[&mVU.regs().VI[REG_TPC].UL], xPC);
xMOV(ptr32[&mVU.regs().nextBlockCycles], 0);
xJMP(mVU.exitFunct);
dJMP.SetTarget();
incPC(-4); // Go Back to Branch Opcode to get branchAddr
iPC = branchAddr(mVU) / 4;
xMOV(ptr32[&mVU.regs().VI[REG_TPC].UL], xPC);
xMOV(ptr32[&mVU.regs().nextBlockCycles], 0);
xJMP(mVU.exitFunct);
eJMP.SetTarget();
iPC = tempPC;
@ -511,6 +516,7 @@ void condBranch(mV, microFlagCycles& mFC, int JMPcc)
incPC(-4); // Go Back to Branch Opcode to get branchAddr
iPC = branchAddr(mVU) / 4;
xMOV(ptr32[&mVU.regs().VI[REG_TPC].UL], xPC);
xMOV(ptr32[&mVU.regs().nextBlockCycles], 0);
xJMP(mVU.exitFunct);
iPC = tempPC;
}
@ -526,12 +532,14 @@ void condBranch(mV, microFlagCycles& mFC, int JMPcc)
xForwardJump32 eJMP(((JccComparisonType)JMPcc));
incPC(1); // Set PC to First instruction of Non-Taken Side
xMOV(ptr32[&mVU.regs().VI[REG_TPC].UL], xPC);
xMOV(ptr32[&mVU.regs().nextBlockCycles], 0);
xJMP(mVU.exitFunct);
eJMP.SetTarget();
incPC(-4); // Go Back to Branch Opcode to get branchAddr
iPC = branchAddr(mVU) / 4;
xMOV(ptr32[&mVU.regs().VI[REG_TPC].UL], xPC);
xMOV(ptr32[&mVU.regs().nextBlockCycles], 0);
xJMP(mVU.exitFunct);
return;
}
@ -624,6 +632,7 @@ void normJump(mV, microFlagCycles& mFC)
mVUDTendProgram(mVU, &mFC, 2);
xMOV(gprT1, ptr32[&mVU.branch]);
xMOV(ptr32[&mVU.regs().VI[REG_TPC].UL], gprT1);
xMOV(ptr32[&mVU.regs().nextBlockCycles], 0);
xJMP(mVU.exitFunct);
eJMP.SetTarget();
}
@ -639,6 +648,7 @@ void normJump(mV, microFlagCycles& mFC)
mVUDTendProgram(mVU, &mFC, 2);
xMOV(gprT1, ptr32[&mVU.branch]);
xMOV(ptr32[&mVU.regs().VI[REG_TPC].UL], gprT1);
xMOV(ptr32[&mVU.regs().nextBlockCycles], 0);
xJMP(mVU.exitFunct);
eJMP.SetTarget();
}
@ -647,6 +657,7 @@ void normJump(mV, microFlagCycles& mFC)
mVUendProgram(mVU, &mFC, 2);
xMOV(gprT1, ptr32[&mVU.branch]);
xMOV(ptr32[&mVU.regs().VI[REG_TPC].UL], gprT1);
xMOV(ptr32[&mVU.regs().nextBlockCycles], 0);
xJMP(mVU.exitFunct);
}
else