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);
|
incPC(2);
|
||||||
mVUlow.evilBranch = true;
|
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.needExactMatch |= 7; // This might not be necessary, but w/e...
|
||||||
mVUregs.flagInfo = 0;
|
mVUregs.flagInfo = 0;
|
||||||
|
@ -678,6 +666,7 @@ __fi void mVUanalyzeNormBranch(mV, int It, bool isBAL)
|
||||||
if (isBAL)
|
if (isBAL)
|
||||||
{
|
{
|
||||||
analyzeVIreg2(mVU, It, mVUlow.VI_write, 1);
|
analyzeVIreg2(mVU, It, mVUlow.VI_write, 1);
|
||||||
|
if(!mVUlow.evilBranch)
|
||||||
setConstReg(It, bSaveAddr);
|
setConstReg(It, bSaveAddr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -695,6 +684,7 @@ __ri void mVUanalyzeJump(mV, int Is, int It, bool isJALR)
|
||||||
if (isJALR)
|
if (isJALR)
|
||||||
{
|
{
|
||||||
analyzeVIreg2(mVU, It, mVUlow.VI_write, 1);
|
analyzeVIreg2(mVU, It, mVUlow.VI_write, 1);
|
||||||
|
if (!mVUlow.evilBranch)
|
||||||
setConstReg(It, bSaveAddr);
|
setConstReg(It, bSaveAddr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,6 @@
|
||||||
|
|
||||||
extern void mVUincCycles(microVU& mVU, int x);
|
extern void mVUincCycles(microVU& mVU, int x);
|
||||||
extern void* mVUcompile(microVU& mVU, u32 startPC, uptr pState);
|
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)
|
__fi int getLastFlagInst(microRegInfo& pState, int* xFlag, int flagType, int isEbit)
|
||||||
{
|
{
|
||||||
if (isEbit)
|
if (isEbit)
|
||||||
|
@ -395,65 +394,11 @@ void normBranch(mV, microFlagCycles& mFC)
|
||||||
return;
|
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
|
// Normal Branch
|
||||||
mVUsetupBranch(mVU, mFC);
|
mVUsetupBranch(mVU, mFC);
|
||||||
normBranchCompile(mVU, branchAddr(mVU));
|
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)
|
void condBranch(mV, microFlagCycles& mFC, int JMPcc)
|
||||||
{
|
{
|
||||||
mVUsetupBranch(mVU, mFC);
|
mVUsetupBranch(mVU, mFC);
|
||||||
|
@ -555,15 +500,6 @@ void condBranch(mV, microFlagCycles& mFC, int JMPcc)
|
||||||
xCMP(ptr16[&mVU.branch], 0);
|
xCMP(ptr16[&mVU.branch], 0);
|
||||||
|
|
||||||
incPC(3);
|
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;
|
microBlock* bBlock;
|
||||||
incPC2(1); // Check if Branch Non-Taken Side has already been recompiled
|
incPC2(1); // Check if Branch Non-Taken Side has already been recompiled
|
||||||
blockCreate(iPC / 2);
|
blockCreate(iPC / 2);
|
||||||
|
@ -612,21 +548,6 @@ void normJump(mV, microFlagCycles& mFC)
|
||||||
normBranchCompile(mVU, jumpAddr);
|
normBranchCompile(mVU, jumpAddr);
|
||||||
return;
|
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)
|
if (mVUup.dBit && doDBitHandling)
|
||||||
{
|
{
|
||||||
xTEST(ptr32[&VU0.VI[REG_FBRST].UL], (isVU1 ? 0x400 : 0x4));
|
xTEST(ptr32[&VU0.VI[REG_FBRST].UL], (isVU1 ? 0x400 : 0x4));
|
||||||
|
|
|
@ -295,7 +295,7 @@ __ri void eBitWarning(mV)
|
||||||
if (mVUpBlock->pState.blockType == 1)
|
if (mVUpBlock->pState.blockType == 1)
|
||||||
Console.Error("microVU%d Warning: Branch, E-bit, Branch! [%04x]", mVU.index, xPC);
|
Console.Error("microVU%d Warning: Branch, E-bit, Branch! [%04x]", mVU.index, xPC);
|
||||||
if (mVUpBlock->pState.blockType == 2)
|
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);
|
incPC(2);
|
||||||
if (curI & _Ebit_)
|
if (curI & _Ebit_)
|
||||||
{
|
{
|
||||||
|
@ -547,107 +547,6 @@ __fi void mVUinitFirstPass(microVU& mVU, uptr pState, u8* thisPtr)
|
||||||
// Recompiler
|
// 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)
|
void mVUDoDBit(microVU& mVU, microFlagCycles* mFC)
|
||||||
{
|
{
|
||||||
xTEST(ptr32[&VU0.VI[REG_FBRST].UL], (isVU1 ? 0x400 : 0x4));
|
xTEST(ptr32[&VU0.VI[REG_FBRST].UL], (isVU1 ? 0x400 : 0x4));
|
||||||
|
|
|
@ -1746,13 +1746,13 @@ void condEvilBranch(mV, int JMPcc)
|
||||||
if (mVUlow.badBranch)
|
if (mVUlow.badBranch)
|
||||||
{
|
{
|
||||||
xMOV(ptr32[&mVU.branch], gprT1);
|
xMOV(ptr32[&mVU.branch], gprT1);
|
||||||
xMOV(ptr32[&mVU.badBranch], branchAddrN(mVU));
|
xMOV(ptr32[&mVU.badBranch], branchAddr(mVU));
|
||||||
|
|
||||||
xCMP(gprT1b, 0);
|
xCMP(gprT1b, 0);
|
||||||
xForwardJump8 cJMP((JccComparisonType)JMPcc);
|
xForwardJump8 cJMP((JccComparisonType)JMPcc);
|
||||||
incPC(6); // Branch Not Taken Addr + 8
|
incPC(4); // Branch Not Taken Addr
|
||||||
xMOV(ptr32[&mVU.badBranch], xPC);
|
xMOV(ptr32[&mVU.badBranch], xPC);
|
||||||
incPC(-6);
|
incPC(-4);
|
||||||
cJMP.SetTarget();
|
cJMP.SetTarget();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1772,7 +1772,7 @@ void condEvilBranch(mV, int JMPcc)
|
||||||
xCMP(gprT1b, 0);
|
xCMP(gprT1b, 0);
|
||||||
xForwardJump8 cJMP((JccComparisonType)JMPcc);
|
xForwardJump8 cJMP((JccComparisonType)JMPcc);
|
||||||
xMOV(gprT1, ptr32[&mVU.badBranch]); // Branch Not Taken
|
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);
|
xMOV(ptr32[&mVU.evilBranch], gprT1);
|
||||||
cJMP.SetTarget();
|
cJMP.SetTarget();
|
||||||
incPC(-2);
|
incPC(-2);
|
||||||
|
@ -1809,7 +1809,7 @@ mVUop(mVU_BAL)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
incPC(-2);
|
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);
|
incPC(2);
|
||||||
if (isEvilBlock)
|
if (isEvilBlock)
|
||||||
xMOV(gprT1, ptr32[&mVU.evilBranch]);
|
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 delay slot is conditional, it uses badBranch to go to its target
|
||||||
if (mVUlow.badBranch)
|
if (mVUlow.badBranch)
|
||||||
{
|
{
|
||||||
xADD(gprT1, 8);
|
|
||||||
xMOV(ptr32[&mVU.badBranch], gprT1);
|
xMOV(ptr32[&mVU.badBranch], gprT1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2024,26 +2023,15 @@ mVUop(mVU_JALR)
|
||||||
else
|
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 %s branch taken/not taken target! - If game broken report to PCSX2 Team", branchSTR[mVUlow.branch & 0xf]);
|
||||||
{
|
|
||||||
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);
|
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]);
|
xMOV(gprT1, ptr32[&mVU.badBranch]);
|
||||||
xADD(gprT1, 8);
|
xADD(gprT1, 8);
|
||||||
xSHR(gprT1, 3);
|
xSHR(gprT1, 3);
|
||||||
incPC(2);
|
|
||||||
mVUallocVIb(mVU, gprT1, _It_);
|
mVUallocVIb(mVU, gprT1, _It_);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
mVU.profiler.EmitOp(opJALR);
|
mVU.profiler.EmitOp(opJALR);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue