mirror of https://github.com/PCSX2/pcsx2.git
mVU: Clean up branch chain handling
This commit is contained in:
parent
59ab303c5c
commit
bcade5bb9d
|
@ -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.needExactMatch |= 7; // This might not be necessary, but w/e...
|
||||
mVUregs.flagInfo = 0;
|
||||
|
@ -678,6 +666,7 @@ __fi void mVUanalyzeNormBranch(mV, int It, bool isBAL)
|
|||
if (isBAL)
|
||||
{
|
||||
analyzeVIreg2(mVU, It, mVUlow.VI_write, 1);
|
||||
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);
|
||||
if (!mVUlow.evilBranch)
|
||||
setConstReg(It, bSaveAddr);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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);
|
||||
|
@ -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,26 +2023,15 @@ 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);
|
||||
DevCon.Warning("Linking JALR from %s branch taken/not taken target! - If game broken report to PCSX2 Team", branchSTR[mVUlow.branch & 0xf]);
|
||||
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);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue