mVU: Clean up branch chain handling

This commit is contained in:
refractionpcsx2 2022-01-23 15:49:08 +00:00
parent 59ab303c5c
commit bcade5bb9d
4 changed files with 18 additions and 220 deletions

View File

@ -619,19 +619,7 @@ __ri int mVUbranchCheck(mV)
incPC(2);
mVUlow.evilBranch = true;
if (mVUlow.branch == 2 || mVUlow.branch == 10) // Needs linking, we can only guess this if the next is not conditional
{
// First branch is not conditional so we know what the link will be
// So we can let the existing evil block do its thing! We know where to get the addr :)
if (branchType <= 2 || branchType >= 9)
{
mVUregs.blockType = 2;
} // Else it is conditional, so we need to do some nasty processing later in microVU_Branch.inl
}
else
{
mVUregs.blockType = 2; // Second branch doesn't need linking, so can let it run its evil block course (MGS2 for testing)
}
mVUregs.blockType = 2; // Second branch doesn't need linking, so can let it run its evil block course (MGS2 for testing)
mVUregs.needExactMatch |= 7; // This might not be necessary, but w/e...
mVUregs.flagInfo = 0;
@ -678,7 +666,8 @@ __fi void mVUanalyzeNormBranch(mV, int It, bool isBAL)
if (isBAL)
{
analyzeVIreg2(mVU, It, mVUlow.VI_write, 1);
setConstReg(It, bSaveAddr);
if(!mVUlow.evilBranch)
setConstReg(It, bSaveAddr);
}
}
@ -695,6 +684,7 @@ __ri void mVUanalyzeJump(mV, int Is, int It, bool isJALR)
if (isJALR)
{
analyzeVIreg2(mVU, It, mVUlow.VI_write, 1);
setConstReg(It, bSaveAddr);
if (!mVUlow.evilBranch)
setConstReg(It, bSaveAddr);
}
}

View File

@ -17,7 +17,6 @@
extern void mVUincCycles(microVU& mVU, int x);
extern void* mVUcompile(microVU& mVU, u32 startPC, uptr pState);
extern void* mVUcompileSingleInstruction(microVU& mVU, u32 startPC, uptr pState, microFlagCycles& mFC);
__fi int getLastFlagInst(microRegInfo& pState, int* xFlag, int flagType, int isEbit)
{
if (isEbit)
@ -395,65 +394,11 @@ void normBranch(mV, microFlagCycles& mFC)
return;
}
if (mVUlow.badBranch)
{
u32 badBranchAddr = branchAddr(mVU) + 8;
incPC(3);
if (mVUlow.branch == 2 || mVUlow.branch == 10) //Delay slot branch needs linking
{
DevCon.Warning("Found %s in delay slot, linking - If game broken report to PCSX2 Team", mVUlow.branch == 2 ? "BAL" : "JALR");
xMOV(gprT3, badBranchAddr);
xSHR(gprT3, 3);
mVUallocVIb(mVU, gprT3, _It_);
}
incPC(-3);
}
// Normal Branch
mVUsetupBranch(mVU, mFC);
normBranchCompile(mVU, branchAddr(mVU));
}
//Messy handler warning!!
//This handles JALR/BAL in the delay slot of a conditional branch. We do this because the normal handling
//Doesn't seem to work properly, even if the link is made to the correct address, so we do it manually instead.
//Normally EvilBlock handles all this stuff, but something to do with conditionals and links don't quite work right :/
void condJumpProcessingEvil(mV, microFlagCycles& mFC, int JMPcc)
{
u32 bPC = iPC - 1; // mVUcompile can modify iPC, mVUpBlock, and mVUregs so back them up
u32 badBranchAddr;
iPC = bPC - 2;
setCode();
badBranchAddr = branchAddr(mVU);
xCMP(ptr16[&mVU.branch], 0);
xForwardJump32 eJMP(xInvertCond((JccComparisonType)JMPcc));
mVUcompileSingleInstruction(mVU, badBranchAddr, (uptr)&mVUregs, mFC);
xMOV(gprT3, badBranchAddr + 8);
iPC = bPC;
setCode();
xSHR(gprT3, 3);
mVUallocVIb(mVU, gprT3, _It_); //Link to branch addr + 8
normJumpCompile(mVU, mFC, true); //Compile evil branch, just in time!
eJMP.SetTarget();
incPC(2); // Point to delay slot of evil Branch (as the original branch isn't taken)
mVUcompileSingleInstruction(mVU, xPC, (uptr)&mVUregs, mFC);
xMOV(gprT3, xPC);
iPC = bPC;
setCode();
xSHR(gprT3, 3);
mVUallocVIb(mVU, gprT3, _It_);
normJumpCompile(mVU, mFC, true); //Compile evil branch, just in time!
}
void condBranch(mV, microFlagCycles& mFC, int JMPcc)
{
mVUsetupBranch(mVU, mFC);
@ -555,15 +500,6 @@ void condBranch(mV, microFlagCycles& mFC, int JMPcc)
xCMP(ptr16[&mVU.branch], 0);
incPC(3);
if (mVUlow.evilBranch) // We are dealing with an evil evil block, so we need to process this slightly differently
{
if (mVUlow.branch == 10 || mVUlow.branch == 2) // Evil branch is a jump of some measure
{
//Because of how it is linked, we need to make sure the target is recompiled if taken
condJumpProcessingEvil(mVU, mFC, JMPcc);
return;
}
}
microBlock* bBlock;
incPC2(1); // Check if Branch Non-Taken Side has already been recompiled
blockCreate(iPC / 2);
@ -612,21 +548,6 @@ void normJump(mV, microFlagCycles& mFC)
normBranchCompile(mVU, jumpAddr);
return;
}
if (mVUlow.badBranch)
{
incPC(3);
if (mVUlow.branch == 2 || mVUlow.branch == 10) //Delay slot BAL needs linking, only need to do BAL here, JALR done earlier
{
DevCon.Warning("Found %x in delay slot, linking - If game broken report to PCSX2 Team", mVUlow.branch == 2 ? "BAL" : "JALR");
incPC(-2);
mVUallocVIa(mVU, gprT1, _Is_);
xADD(gprT1, 8);
xSHR(gprT1, 3);
incPC(2);
mVUallocVIb(mVU, gprT1, _It_);
}
incPC(-3);
}
if (mVUup.dBit && doDBitHandling)
{
xTEST(ptr32[&VU0.VI[REG_FBRST].UL], (isVU1 ? 0x400 : 0x4));

View File

@ -295,7 +295,7 @@ __ri void eBitWarning(mV)
if (mVUpBlock->pState.blockType == 1)
Console.Error("microVU%d Warning: Branch, E-bit, Branch! [%04x]", mVU.index, xPC);
if (mVUpBlock->pState.blockType == 2)
Console.Error("microVU%d Warning: Branch, Branch, Branch! [%04x]", mVU.index, xPC);
DevCon.Warning("microVU%d Warning: Branch, Branch, Branch! [%04x]", mVU.index, xPC);
incPC(2);
if (curI & _Ebit_)
{
@ -547,107 +547,6 @@ __fi void mVUinitFirstPass(microVU& mVU, uptr pState, u8* thisPtr)
// Recompiler
//------------------------------------------------------------------
//This bastardized function is used when a linked branch is in a conditional delay slot. It's messy, it's horrible, but it works.
//Unfortunately linking the reg manually and using the normal evil block method seems to suck at this :/
//If this is removed, test Evil Dead: Fistful of Boomstick (hangs going ingame), Mark of Kri (collision detection)
//and Tony Hawks Project 8 (graphics are half missing, requires Negative rounding when working)
void* mVUcompileSingleInstruction(microVU& mVU, u32 startPC, uptr pState, microFlagCycles& mFC)
{
u8* thisPtr = x86Ptr;
// First Pass
iPC = startPC / 4;
mVUbranch = 0;
incPC(1);
startLoop(mVU);
mVUincCycles(mVU, 1);
mVUopU(mVU, 0);
mVUcheckBadOp(mVU);
if (curI & _Ebit_)
{
eBitPass1(mVU, g_branch);
DevCon.Warning("E Bit on single instruction");
}
if (curI & _Dbit_)
{
mVUup.dBit = true;
}
if (curI & _Tbit_)
{
mVUup.tBit = true;
}
if (curI & _Mbit_)
{
mVUup.mBit = true;
DevCon.Warning("M Bit on single instruction");
}
if (curI & _Ibit_)
{
mVUlow.isNOP = true;
mVUup.iBit = true;
DevCon.Warning("I Bit on single instruction");
}
else
{
incPC(-1);
mVUopL(mVU, 0);
incPC(1);
}
if (!mVUlow.isKick)
{
mVUlow.kickcycles = 1 + mVUstall;
mVUregs.xgkickcycles = 0;
}
else
{
mVUregs.xgkickcycles = 0;
mVUlow.kickcycles = 0;
}
mVUsetCycles(mVU);
mVUinfo.readQ = mVU.q;
mVUinfo.writeQ = !mVU.q;
mVUinfo.readP = mVU.p && isVU1;
mVUinfo.writeP = !mVU.p && isVU1;
mVUcount++;
mVUsetFlagInfo(mVU);
incPC(1);
mVUsetFlags(mVU, mFC); // Sets Up Flag instances
mVUoptimizePipeState(mVU); // Optimize the End Pipeline State for nicer Block Linking
mVUdebugPrintBlocks(mVU, false); // Prints Start/End PC of blocks executed, for debugging...
// Second Pass
iPC = startPC / 4;
setCode();
if (mVUup.mBit)
{
xOR(ptr32[&mVU.regs().flags], VUFLAG_MFLAGSET);
}
mVUexecuteInstruction(mVU);
if (isVU1 && mVUlow.kickcycles && CHECK_XGKICKHACK)
{
mVU_XGKICK_SYNC(mVU, false);
}
mVUincCycles(mVU, 1); //Just incase the is XGKick
if (mVUinfo.doXGKICK)
{
mVU_XGKICK_DELAY(mVU);
}
mVUregs.xgkickcycles = 0;
return thisPtr;
}
void mVUDoDBit(microVU& mVU, microFlagCycles* mFC)
{
xTEST(ptr32[&VU0.VI[REG_FBRST].UL], (isVU1 ? 0x400 : 0x4));

View File

@ -1746,13 +1746,13 @@ void condEvilBranch(mV, int JMPcc)
if (mVUlow.badBranch)
{
xMOV(ptr32[&mVU.branch], gprT1);
xMOV(ptr32[&mVU.badBranch], branchAddrN(mVU));
xMOV(ptr32[&mVU.badBranch], branchAddr(mVU));
xCMP(gprT1b, 0);
xForwardJump8 cJMP((JccComparisonType)JMPcc);
incPC(6); // Branch Not Taken Addr + 8
incPC(4); // Branch Not Taken Addr
xMOV(ptr32[&mVU.badBranch], xPC);
incPC(-6);
incPC(-4);
cJMP.SetTarget();
return;
}
@ -1772,7 +1772,7 @@ void condEvilBranch(mV, int JMPcc)
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
xADD(gprT1, 8); // We have already executed 1 instruction from the original branch
xMOV(ptr32[&mVU.evilBranch], gprT1);
cJMP.SetTarget();
incPC(-2);
@ -1809,7 +1809,7 @@ mVUop(mVU_BAL)
else
{
incPC(-2);
DevCon.Warning("Linking BAL from %s branch taken/nottaken target! - If game broken report to PCSX2 Team", branchSTR[mVUlow.branch & 0xf]);
DevCon.Warning("Linking BAL from %s branch taken/not taken target! - If game broken report to PCSX2 Team", branchSTR[mVUlow.branch & 0xf]);
incPC(2);
if (isEvilBlock)
xMOV(gprT1, ptr32[&mVU.evilBranch]);
@ -1982,7 +1982,6 @@ void normJumpPass2(mV)
//If delay slot is conditional, it uses badBranch to go to its target
if (mVUlow.badBranch)
{
xADD(gprT1, 8);
xMOV(ptr32[&mVU.badBranch], gprT1);
}
}
@ -2024,24 +2023,13 @@ mVUop(mVU_JALR)
else
{
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_);
}
DevCon.Warning("Linking JALR from %s branch taken/not taken target! - If game broken report to PCSX2 Team", branchSTR[mVUlow.branch & 0xf]);
incPC(2);
xMOV(gprT1, ptr32[&mVU.badBranch]);
xADD(gprT1, 8);
xSHR(gprT1, 3);
mVUallocVIb(mVU, gprT1, _It_);
}
}