mVU: Rework multiple branch chaining

This commit is contained in:
refractionpcsx2 2022-01-23 14:16:01 +00:00
parent 4ab9d1a493
commit 59ab303c5c
6 changed files with 96 additions and 29 deletions

View File

@ -243,6 +243,7 @@ struct microVU
u32 branch; // Holds branch compare result (IBxx) OR Holds address to Jump to (JALR/JR)
u32 badBranch; // For Branches in Branch Delay Slots, holds Address the first Branch went to + 8
u32 evilBranch; // For Branches in Branch Delay Slots, holds Address to Jump to
u32 evilevilBranch;// For Branches in Branch Delay Slots (chained), holds Address to Jump to
u32 p; // Holds current P instance index
u32 q; // Holds current Q instance index
u32 totalCycles; // Total Cycles that mVU is expected to run for

View File

@ -584,9 +584,30 @@ static void analyzeBranchVI(mV, int xReg, bool& infoVar)
// Branch in Branch Delay-Slots
__ri int mVUbranchCheck(mV)
{
if (!mVUcount)
if (!mVUcount && !isEvilBlock)
return 0;
// This means we have jumped from an evil branch situation, so this is another branch in delay slot
if (isEvilBlock)
{
mVUlow.evilBranch = true;
mVUregs.blockType = 2;
mVUregs.needExactMatch |= 7; // This might not be necessary, but w/e...
mVUregs.flagInfo = 0;
if (mVUlow.branch == 2 || mVUlow.branch == 10)
{
Console.Error("microVU%d: %s in branch, branch delay slot requires link [%04x] - If game broken report to PCSX2 Team", mVU.index,
branchSTR[mVUlow.branch & 0xf], xPC);
}
else
{
DevCon.Warning("microVU%d: %s in branch, branch delay slot! [%04x] - If game broken report to PCSX2 Team", mVU.index,
branchSTR[mVUlow.branch & 0xf], xPC);
}
return 1;
}
incPC(-2);
if (mVUlow.branch)

View File

@ -304,7 +304,11 @@ void normJumpCompile(mV, microFlagCycles& mFC, bool isEvilJump)
}
if (isEvilJump)
{
xMOV(arg1regd, ptr32[&mVU.evilBranch]);
xMOV(gprT1, ptr32[&mVU.evilevilBranch]);
xMOV(ptr32[&mVU.evilBranch], gprT1);
}
else
xMOV(arg1regd, ptr32[&mVU.branch]);
if (doJumpCaching)

View File

@ -903,13 +903,13 @@ void* mVUcompile(microVU& mVU, u32 startPC, uptr pState)
mVU_XGKICK_DELAY(mVU);
}
if (isEvilBlock && !isConditional)
if (isEvilBlock)
{
mVUsetupRange(mVU, xPC + 8, false);
normJumpCompile(mVU, mFC, true);
goto perf_and_return;
}
else if (!mVUinfo.isBdelay && !isEvilBlock)
else if (!mVUinfo.isBdelay)
{
// Handle range wrapping
if ((xPC + 8) == mVU.microMemSize)

View File

@ -1756,16 +1756,30 @@ void condEvilBranch(mV, int JMPcc)
cJMP.SetTarget();
return;
}
xMOV(ptr32[&mVU.evilBranch], branchAddr(mVU));
xCMP(gprT1b, 0);
xForwardJump8 cJMP((JccComparisonType)JMPcc);
if (isEvilBlock)
{
xMOV(ptr32[&mVU.evilevilBranch], branchAddr(mVU));
xCMP(gprT1b, 0);
xForwardJump8 cJMP((JccComparisonType)JMPcc);
xMOV(gprT1, ptr32[&mVU.evilBranch]); // Branch Not Taken
xADD(gprT1, 8); // We have already executed 1 instruction from the original branch
xMOV(ptr32[&mVU.evilevilBranch], gprT1);
cJMP.SetTarget();
}
else
{
xMOV(ptr32[&mVU.evilBranch], branchAddr(mVU));
xCMP(gprT1b, 0);
xForwardJump8 cJMP((JccComparisonType)JMPcc);
xMOV(gprT1, ptr32[&mVU.badBranch]); // Branch Not Taken
//xADD(gprT1, 8); // We have already executed 1 instruction from the original branch
xMOV(ptr32[&mVU.evilBranch], gprT1);
cJMP.SetTarget();
incPC(-2);
if (mVUlow.branch >= 9)
DevCon.Warning("Conditional in JALR/JR delay slot - If game broken report to PCSX2 Team");
incPC(2);
cJMP.SetTarget();
incPC(-2);
if (mVUlow.branch >= 9)
DevCon.Warning("Conditional in JALR/JR delay slot - If game broken report to PCSX2 Team");
incPC(2);
}
}
mVUop(mVU_B)
@ -1774,8 +1788,8 @@ mVUop(mVU_B)
pass1 { mVUanalyzeNormBranch(mVU, 0, false); }
pass2
{
if (mVUlow.badBranch) { xMOV(ptr32[&mVU.badBranch], branchAddrN(mVU)); }
if (mVUlow.evilBranch) { xMOV(ptr32[&mVU.evilBranch], branchAddr(mVU)); }
if (mVUlow.badBranch) { xMOV(ptr32[&mVU.badBranch], branchAddr(mVU)); }
if (mVUlow.evilBranch) { if(isEvilBlock) xMOV(ptr32[&mVU.evilevilBranch], branchAddr(mVU)); else xMOV(ptr32[&mVU.evilBranch], branchAddr(mVU)); }
mVU.profiler.EmitOp(opB);
}
pass3 { mVUlog("B [<a href=\"#addr%04x\">%04x</a>]", branchAddr(mVU), branchAddr(mVU)); }
@ -1792,9 +1806,23 @@ mVUop(mVU_BAL)
xMOV(gprT1, bSaveAddr);
mVUallocVIb(mVU, gprT1, _It_);
}
else
{
incPC(-2);
DevCon.Warning("Linking BAL from %s branch taken/nottaken target! - If game broken report to PCSX2 Team", branchSTR[mVUlow.branch & 0xf]);
incPC(2);
if (isEvilBlock)
xMOV(gprT1, ptr32[&mVU.evilBranch]);
else
xMOV(gprT1, ptr32[&mVU.badBranch]);
if (mVUlow.badBranch) { xMOV(ptr32[&mVU.badBranch], branchAddrN(mVU)); }
if (mVUlow.evilBranch) { xMOV(ptr32[&mVU.evilBranch], branchAddr(mVU));}
xADD(gprT1, 8);
xSHR(gprT1, 3);
mVUallocVIb(mVU, gprT1, _It_);
}
if (mVUlow.badBranch) { xMOV(ptr32[&mVU.badBranch], branchAddr(mVU)); }
if (mVUlow.evilBranch) { if (isEvilBlock) xMOV(ptr32[&mVU.evilevilBranch], branchAddr(mVU)); else xMOV(ptr32[&mVU.evilBranch], branchAddr(mVU)); }
mVU.profiler.EmitOp(opBAL);
}
pass3 { mVUlog("BAL vi%02d [<a href=\"#addr%04x\">%04x</a>]", _Ft_, branchAddr(mVU), branchAddr(mVU)); }
@ -1946,7 +1974,10 @@ void normJumpPass2(mV)
}
else
{
xMOV(ptr32[&mVU.evilBranch], gprT1);
if(isEvilBlock)
xMOV(ptr32[&mVU.evilevilBranch], gprT1);
else
xMOV(ptr32[&mVU.evilBranch], gprT1);
}
//If delay slot is conditional, it uses badBranch to go to its target
if (mVUlow.badBranch)
@ -1983,18 +2014,35 @@ mVUop(mVU_JALR)
}
if (mVUlow.evilBranch)
{
incPC(-2);
if (mVUlow.branch >= 9) // Previous branch is a jump of some type so we need to take the branch address from the register it uses.
if (isEvilBlock)
{
DevCon.Warning("Linking JALR from JALR/JR branch target! - If game broken report to PCSX2 Team");
mVUallocVIa(mVU, gprT1, _Is_);
xMOV(gprT1, ptr32[&mVU.evilBranch]);
xADD(gprT1, 8);
xSHR(gprT1, 3);
incPC(2);
mVUallocVIb(mVU, gprT1, _It_);
}
else
incPC(2);
{
incPC(-2);
if (mVUlow.branch >= 9) // Previous branch is a jump of some type so we need to take the branch address from the register it uses.
{
DevCon.Warning("Linking JALR from JALR/JR branch target! - If game broken report to PCSX2 Team");
mVUallocVIa(mVU, gprT1, _Is_);
xADD(gprT1, 8);
xSHR(gprT1, 3);
incPC(2);
mVUallocVIb(mVU, gprT1, _It_);
}
else // Else we take the branch target of the previous branch
{
DevCon.Warning("Linking JALR from %d branch taken/nottaken target! - If game broken report to PCSX2 Team", branchSTR[mVUlow.branch & 0xf]);
xMOV(gprT1, ptr32[&mVU.badBranch]);
xADD(gprT1, 8);
xSHR(gprT1, 3);
incPC(2);
mVUallocVIb(mVU, gprT1, _It_);
}
}
}
mVU.profiler.EmitOp(opJALR);

View File

@ -229,13 +229,6 @@ static void __fc mVUEBit()
vu1Thread.mtvuInterrupts.fetch_or(VU_Thread::InterruptFlagVUEBit, std::memory_order_release);
}
static inline u32 branchAddrN(const mV)
{
pxAssumeDev(islowerOP, "MicroVU: Expected Lower OP code for valid branch addr.");
return ((((iPC + 4) + (_Imm11_ * 2)) & mVU.progMemMask) * 4);
}
static inline u32 branchAddr(const mV)
{
pxAssumeDev(islowerOP, "MicroVU: Expected Lower OP code for valid branch addr.");