mirror of https://github.com/PCSX2/pcsx2.git
microVU: Now properly supports E-bit set on branch delay slot instructions.
(Gets rid of "Unknown Micro VU opcode called" errors in Dark Cloud 2, and possibly fixes some other games) git-svn-id: http://pcsx2.googlecode.com/svn/trunk@1647 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
parent
4509e085c6
commit
9da4a53929
|
@ -89,6 +89,7 @@ public:
|
|||
&& (linkI->block->pState.flags == pState->flags)
|
||||
&& (linkI->block->pState.xgkick == pState->xgkick)
|
||||
&& (linkI->block->pState.viBackUp == pState->viBackUp)
|
||||
&& (linkI->block->pState.blockType == pState->blockType)
|
||||
&& !(linkI->block->pState.needExactMatch & 5)) { return linkI->block; }
|
||||
linkI = linkI->next;
|
||||
}
|
||||
|
|
|
@ -108,7 +108,7 @@ void normBranch(mV, microFlagCycles& mFC) {
|
|||
normBranchCompile(mVU, branchAddr);
|
||||
}
|
||||
|
||||
void condBranch(mV, microFlagCycles& mFC, microBlock* &pBlock, int JMPcc) {
|
||||
void condBranch(mV, microFlagCycles& mFC, int JMPcc) {
|
||||
using namespace x86Emitter;
|
||||
mVUsetupBranch(mVU, mFC);
|
||||
xCMP(ptr16[&mVU->branch], 0);
|
||||
|
@ -138,8 +138,8 @@ void condBranch(mV, microFlagCycles& mFC, microBlock* &pBlock, int JMPcc) {
|
|||
}
|
||||
else {
|
||||
s32* ajmp = xJcc32((JccComparisonType)JMPcc);
|
||||
uptr jumpAddr;
|
||||
u32 bPC = iPC; // mVUcompile can modify iPC and mVUregs so back them up
|
||||
u32 bPC = iPC; // mVUcompile can modify iPC, mVUpBlock, and mVUregs so back them up
|
||||
microBlock* pBlock = mVUpBlock;
|
||||
memcpy_fast(&pBlock->pStateEnd, &mVUregs, sizeof(microRegInfo));
|
||||
|
||||
incPC2(1); // Get PC for branch not-taken
|
||||
|
@ -147,13 +147,13 @@ void condBranch(mV, microFlagCycles& mFC, microBlock* &pBlock, int JMPcc) {
|
|||
|
||||
iPC = bPC;
|
||||
incPC(-3); // Go back to branch opcode (to get branch imm addr)
|
||||
jumpAddr = (uptr)mVUblockFetch(mVU, branchAddr, (uptr)&pBlock->pStateEnd);
|
||||
uptr jumpAddr = (uptr)mVUblockFetch(mVU, branchAddr, (uptr)&pBlock->pStateEnd);
|
||||
*ajmp = (jumpAddr - ((uptr)ajmp + 4));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void normJump(mV, microFlagCycles& mFC, microBlock* &pBlock) {
|
||||
void normJump(mV, microFlagCycles& mFC) {
|
||||
using namespace x86Emitter;
|
||||
mVUprint("mVUcompile JR/JALR");
|
||||
incPC(-3); // Go back to jump opcode
|
||||
|
@ -178,12 +178,12 @@ void normJump(mV, microFlagCycles& mFC, microBlock* &pBlock) {
|
|||
return;
|
||||
}
|
||||
|
||||
memcpy_fast(&pBlock->pStateEnd, &mVUregs, sizeof(microRegInfo));
|
||||
memcpy_fast(&mVUpBlock->pStateEnd, &mVUregs, sizeof(microRegInfo));
|
||||
mVUsetupBranch(mVU, mFC);
|
||||
|
||||
mVUbackupRegs(mVU);
|
||||
MOV32MtoR(gprT2, (uptr)&mVU->branch); // Get startPC (ECX 1st argument for __fastcall)
|
||||
MOV32ItoR(gprR, (u32)&pBlock->pStateEnd); // Get pState (EDX 2nd argument for __fastcall)
|
||||
MOV32ItoR(gprR, (u32)&mVUpBlock->pStateEnd); // Get pState (EDX 2nd argument for __fastcall)
|
||||
|
||||
if (!mVU->index) xCALL(mVUcompileJIT<0>); //(u32 startPC, uptr pState)
|
||||
else xCALL(mVUcompileJIT<1>);
|
||||
|
|
|
@ -170,10 +170,19 @@ microVUt(void) branchWarning(mV) {
|
|||
}
|
||||
}
|
||||
|
||||
microVUt(void) eBitWarning(mV) {
|
||||
microVUt(void) eBitPass1(mV, int& branch) {
|
||||
if (!mVUregs.blockType) {
|
||||
branch = 1;
|
||||
mVUup.eBit = 1;
|
||||
}
|
||||
}
|
||||
|
||||
microVUt(void) eBitWarning(mV, u32 endCount) {
|
||||
if (endCount == 1) Console::Error("microVU%d Warning: Branch, E-bit, Branch! [%04x]", params mVU->index, xPC);
|
||||
incPC(2);
|
||||
if (curI & _Ebit_) {
|
||||
Console::Error("microVU%d Warning: E-bit in Branch delay slot! [%04x]", params mVU->index, xPC);
|
||||
DevCon::Status("microVU%d: E-bit in Branch delay slot! [%04x]", params mVU->index, xPC);
|
||||
mVUregs.blockType = 1;
|
||||
}
|
||||
incPC(-2);
|
||||
}
|
||||
|
@ -297,7 +306,7 @@ microVUt(void) mVUinitConstValues(microVU* mVU) {
|
|||
}
|
||||
|
||||
// Initialize Variables
|
||||
microVUt(void) mVUinitFirstPass(microVU* mVU, microBlock* &pBlock, uptr pState, u8* thisPtr) {
|
||||
microVUt(void) mVUinitFirstPass(microVU* mVU, uptr pState, u8* thisPtr) {
|
||||
mVUstartPC = iPC; // Block Start PC
|
||||
mVUbranch = 0; // Branch Type
|
||||
mVUcount = 0; // Number of instructions ran
|
||||
|
@ -306,11 +315,11 @@ microVUt(void) mVUinitFirstPass(microVU* mVU, microBlock* &pBlock, uptr pState,
|
|||
mVU->q = 0; // All blocks start at q index #0
|
||||
memcpy_fast(&mVUregs, (microRegInfo*)pState, sizeof(microRegInfo)); // Loads up Pipeline State Info
|
||||
mVUblock.x86ptrStart = thisPtr;
|
||||
pBlock = mVUblocks[mVUstartPC/2]->add(&mVUblock); // Add this block to block manager
|
||||
mVUpBlock = pBlock;
|
||||
mVUpBlock = mVUblocks[mVUstartPC/2]->add(&mVUblock); // Add this block to block manager
|
||||
mVUregs.blockType = 0;
|
||||
mVUregs.viBackUp = 0;
|
||||
mVUregs.flags = 0;
|
||||
mVUflagInfo = 0;
|
||||
mVUregs.needExactMatch = 0;
|
||||
mVUsFlagHack = CHECK_VU_FLAGHACK;
|
||||
mVUinitConstValues(mVU);
|
||||
}
|
||||
|
@ -323,22 +332,21 @@ microVUr(void*) mVUcompile(microVU* mVU, u32 startPC, uptr pState) {
|
|||
|
||||
using namespace x86Emitter;
|
||||
microFlagCycles mFC;
|
||||
microBlock* pBlock = NULL;
|
||||
u8* thisPtr = x86Ptr;
|
||||
const u32 endCount = (mVU->microMemSize / 8) - 1;
|
||||
const u32 endCount = (((microRegInfo*)pState)->blockType) ? 1 : (mVU->microMemSize / 8);
|
||||
|
||||
// First Pass
|
||||
iPC = startPC / 4;
|
||||
mVUsetupRange(mVU, startPC, 1); // Setup Program Bounds/Range
|
||||
mVU->regAlloc->reset(); // Reset regAlloc
|
||||
mVUinitFirstPass(mVU, pBlock, pState, thisPtr);
|
||||
mVUinitFirstPass(mVU, pState, thisPtr);
|
||||
|
||||
for (int branch = 0; mVUcount < endCount; mVUcount++) {
|
||||
incPC(1);
|
||||
startLoop(mVU);
|
||||
mVUincCycles(mVU, 1);
|
||||
mVUopU(mVU, 0);
|
||||
if (curI & _Ebit_) { branch = 1; mVUup.eBit = 1; }
|
||||
if (curI & _Ebit_) { eBitPass1(mVU, branch); }
|
||||
if (curI & _DTbit_) { branch = 4; }
|
||||
if (curI & _Mbit_) { mVUup.mBit = 1; }
|
||||
if (curI & _Ibit_) { mVUlow.isNOP = 1; mVUup.iBit = 1; }
|
||||
|
@ -350,7 +358,7 @@ microVUr(void*) mVUcompile(microVU* mVU, u32 startPC, uptr pState) {
|
|||
mVUinfo.writeP = !mVU->p;
|
||||
if (branch >= 2) { mVUinfo.isEOB = 1; if (branch == 3) { mVUinfo.isBdelay = 1; } mVUcount++; branchWarning(mVU); break; }
|
||||
else if (branch == 1) { branch = 2; }
|
||||
if (mVUbranch) { mVUsetFlagInfo(mVU); eBitWarning(mVU); branch = 3; mVUbranch = 0; }
|
||||
if (mVUbranch) { mVUsetFlagInfo(mVU); eBitWarning(mVU, endCount); branch = 3; mVUbranch = 0; }
|
||||
incPC(1);
|
||||
}
|
||||
|
||||
|
@ -379,18 +387,18 @@ microVUr(void*) mVUcompile(microVU* mVU, u32 startPC, uptr pState) {
|
|||
mVUsetupRange(mVU, xPC, 0);
|
||||
mVUdebugNOW(1);
|
||||
switch (mVUbranch) {
|
||||
case 3: condBranch(mVU, mFC, pBlock, Jcc_Equal); return thisPtr; // IBEQ
|
||||
case 4: condBranch(mVU, mFC, pBlock, Jcc_GreaterOrEqual); return thisPtr; // IBGEZ
|
||||
case 5: condBranch(mVU, mFC, pBlock, Jcc_Greater); return thisPtr; // IBGTZ
|
||||
case 6: condBranch(mVU, mFC, pBlock, Jcc_LessOrEqual); return thisPtr; // IBLEQ
|
||||
case 7: condBranch(mVU, mFC, pBlock, Jcc_Less); return thisPtr; // IBLTZ
|
||||
case 8: condBranch(mVU, mFC, pBlock, Jcc_NotEqual); return thisPtr; // IBNEQ
|
||||
case 1: case 2: normBranch(mVU, mFC); return thisPtr; // B/BAL
|
||||
case 9: case 10: normJump (mVU, mFC, pBlock); return thisPtr; // JR/JALR
|
||||
case 9: case 10: normJump (mVU, mFC); return thisPtr; // JR/JALR
|
||||
case 3: condBranch(mVU, mFC, Jcc_Equal); return thisPtr; // IBEQ
|
||||
case 4: condBranch(mVU, mFC, Jcc_GreaterOrEqual); return thisPtr; // IBGEZ
|
||||
case 5: condBranch(mVU, mFC, Jcc_Greater); return thisPtr; // IBGTZ
|
||||
case 6: condBranch(mVU, mFC, Jcc_LessOrEqual); return thisPtr; // IBLEQ
|
||||
case 7: condBranch(mVU, mFC, Jcc_Less); return thisPtr; // IBLTZ
|
||||
case 8: condBranch(mVU, mFC, Jcc_NotEqual); return thisPtr; // IBNEQ
|
||||
}
|
||||
}
|
||||
}
|
||||
if (x == endCount) { Console::Error("microVU%d: Possible infinite compiling loop!", params mVU->index); }
|
||||
if ((x == endCount) && (x!=1)) { Console::Error("microVU%d: Possible infinite compiling loop!", params mVU->index); }
|
||||
|
||||
// E-bit End
|
||||
mVUsetupRange(mVU, xPC-8, 0);
|
||||
|
|
|
@ -248,7 +248,7 @@ void mVUflagPass(mV, u32 startPC, u32 xCount) {
|
|||
if (mVUbranch) { branch = ((mVUbranch>8)?(5):((mVUbranch<3)?3:4)); aBranchAddr = branchAddr; mVUbranch = 0; }
|
||||
incPC(1);
|
||||
}
|
||||
if (mVUcount < 4) { mVUflagInfo |= 0x7; }
|
||||
if (mVUcount < 4) { mVUregs.needExactMatch |= 0x7; }
|
||||
iPC = oldPC;
|
||||
mVUcount = oldCount;
|
||||
mVUbranch = oldBranch;
|
||||
|
@ -263,18 +263,18 @@ void mVUflagPass(mV, u32 startPC, u32 xCount) {
|
|||
microVUt(void) mVUsetFlagInfo(mV) {
|
||||
branchType1 { incPC(-1); mVUflagPass(mVU, branchAddr, 4); incPC(1); }
|
||||
branchType2 {
|
||||
if (!mVUlow.constJump.isValid) { mVUflagInfo |= 0x7; }
|
||||
if (!mVUlow.constJump.isValid) { mVUregs.needExactMatch |= 0x7; }
|
||||
else { mVUflagPass(mVU, (mVUlow.constJump.regValue*8)&(mVU->microMemSize-8), 4); }
|
||||
}
|
||||
branchType3 {
|
||||
incPC(-1);
|
||||
mVUflagPass(mVU, branchAddr, 4);
|
||||
int backupFlagInfo = mVUflagInfo;
|
||||
mVUflagInfo = 0;
|
||||
int backupFlagInfo = mVUregs.needExactMatch;
|
||||
mVUregs.needExactMatch = 0;
|
||||
incPC(4); // Branch Not Taken
|
||||
mVUflagPass(mVU, xPC, 4);
|
||||
incPC(-3);
|
||||
mVUflagInfo |= backupFlagInfo;
|
||||
mVUregs.needExactMatch |= backupFlagInfo;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -44,7 +44,8 @@ __declspec(align(16)) struct microRegInfo { // Ordered for Faster Compares
|
|||
u8 VI[16];
|
||||
regInfo VF[32];
|
||||
u8 flags; // clip x2 :: status x2
|
||||
u8 padding[6]; // 160 bytes
|
||||
u8 blockType; // 0 = Normal; 1 = Compile one instruction with E-bit termination
|
||||
u8 padding[5]; // 160 bytes
|
||||
#if defined(_MSC_VER)
|
||||
};
|
||||
#else
|
||||
|
|
|
@ -458,7 +458,7 @@ mVUop(mVU_FCAND) {
|
|||
mVUallocVIb(mVU, gprT1, 1);
|
||||
}
|
||||
pass3 { mVUlog("FCAND vi01, $%x", _Imm24_); }
|
||||
pass4 { mVUflagInfo |= 4; }
|
||||
pass4 { mVUregs.needExactMatch |= 4; }
|
||||
}
|
||||
|
||||
mVUop(mVU_FCEQ) {
|
||||
|
@ -471,7 +471,7 @@ mVUop(mVU_FCEQ) {
|
|||
mVUallocVIb(mVU, gprT1, 1);
|
||||
}
|
||||
pass3 { mVUlog("FCEQ vi01, $%x", _Imm24_); }
|
||||
pass4 { mVUflagInfo |= 4; }
|
||||
pass4 { mVUregs.needExactMatch |= 4; }
|
||||
}
|
||||
|
||||
mVUop(mVU_FCGET) {
|
||||
|
@ -482,7 +482,7 @@ mVUop(mVU_FCGET) {
|
|||
mVUallocVIb(mVU, gprT1, _It_);
|
||||
}
|
||||
pass3 { mVUlog("FCGET vi%02d", _Ft_); }
|
||||
pass4 { mVUflagInfo |= 4; }
|
||||
pass4 { mVUregs.needExactMatch |= 4; }
|
||||
}
|
||||
|
||||
mVUop(mVU_FCOR) {
|
||||
|
@ -495,7 +495,7 @@ mVUop(mVU_FCOR) {
|
|||
mVUallocVIb(mVU, gprT1, 1);
|
||||
}
|
||||
pass3 { mVUlog("FCOR vi01, $%x", _Imm24_); }
|
||||
pass4 { mVUflagInfo |= 4; }
|
||||
pass4 { mVUregs.needExactMatch |= 4; }
|
||||
}
|
||||
|
||||
mVUop(mVU_FCSET) {
|
||||
|
@ -520,7 +520,7 @@ mVUop(mVU_FMAND) {
|
|||
mVUallocVIb(mVU, gprT1, _It_);
|
||||
}
|
||||
pass3 { mVUlog("FMAND vi%02d, vi%02d", _Ft_, _Fs_); }
|
||||
pass4 { mVUflagInfo |= 2; }
|
||||
pass4 { mVUregs.needExactMatch |= 2; }
|
||||
}
|
||||
|
||||
mVUop(mVU_FMEQ) {
|
||||
|
@ -534,7 +534,7 @@ mVUop(mVU_FMEQ) {
|
|||
mVUallocVIb(mVU, gprT1, _It_);
|
||||
}
|
||||
pass3 { mVUlog("FMEQ vi%02d, vi%02d", _Ft_, _Fs_); }
|
||||
pass4 { mVUflagInfo |= 2; }
|
||||
pass4 { mVUregs.needExactMatch |= 2; }
|
||||
}
|
||||
|
||||
mVUop(mVU_FMOR) {
|
||||
|
@ -546,7 +546,7 @@ mVUop(mVU_FMOR) {
|
|||
mVUallocVIb(mVU, gprT1, _It_);
|
||||
}
|
||||
pass3 { mVUlog("FMOR vi%02d, vi%02d", _Ft_, _Fs_); }
|
||||
pass4 { mVUflagInfo |= 2; }
|
||||
pass4 { mVUregs.needExactMatch |= 2; }
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------
|
||||
|
@ -561,7 +561,7 @@ mVUop(mVU_FSAND) {
|
|||
mVUallocVIb(mVU, gprT1, _It_);
|
||||
}
|
||||
pass3 { mVUlog("FSAND vi%02d, $%x", _Ft_, _Imm12_); }
|
||||
pass4 { mVUflagInfo |= 1; }
|
||||
pass4 { mVUregs.needExactMatch |= 1; }
|
||||
}
|
||||
|
||||
mVUop(mVU_FSOR) {
|
||||
|
@ -572,7 +572,7 @@ mVUop(mVU_FSOR) {
|
|||
mVUallocVIb(mVU, gprT1, _It_);
|
||||
}
|
||||
pass3 { mVUlog("FSOR vi%02d, $%x", _Ft_, _Imm12_); }
|
||||
pass4 { mVUflagInfo |= 1; }
|
||||
pass4 { mVUregs.needExactMatch |= 1; }
|
||||
}
|
||||
|
||||
mVUop(mVU_FSEQ) {
|
||||
|
@ -604,7 +604,7 @@ mVUop(mVU_FSEQ) {
|
|||
mVUallocVIb(mVU, gprT1, _It_);
|
||||
}
|
||||
pass3 { mVUlog("FSEQ vi%02d, $%x", _Ft_, _Imm12_); }
|
||||
pass4 { mVUflagInfo |= 1; }
|
||||
pass4 { mVUregs.needExactMatch |= 1; }
|
||||
}
|
||||
|
||||
mVUop(mVU_FSSET) {
|
||||
|
|
|
@ -205,7 +205,6 @@ typedef u32 (__fastcall *mVUCall)(void*, void*);
|
|||
#define sFLAG mVUinfo.sFlag
|
||||
#define mFLAG mVUinfo.mFlag
|
||||
#define cFLAG mVUinfo.cFlag
|
||||
#define mVUflagInfo mVUregs.needExactMatch
|
||||
#define mVUrange mVUcurProg.ranges.range[mVUcurProg.ranges.total]
|
||||
#define xPC ((iPC / 2) * 8)
|
||||
#define curI ((u32*)mVU->regs->Micro)[iPC] //mVUcurProg.data[iPC]
|
||||
|
@ -222,9 +221,9 @@ typedef u32 (__fastcall *mVUCall)(void*, void*);
|
|||
#define shuffleSS(x) ((x==1)?(0x27):((x==2)?(0xc6):((x==4)?(0xe1):(0xe4))))
|
||||
|
||||
// Flag Info
|
||||
#define __Status (mVUflagInfo & 1)
|
||||
#define __Mac (mVUflagInfo & 2)
|
||||
#define __Clip (mVUflagInfo & 4)
|
||||
#define __Status (mVUregs.needExactMatch & 1)
|
||||
#define __Mac (mVUregs.needExactMatch & 2)
|
||||
#define __Clip (mVUregs.needExactMatch & 4)
|
||||
|
||||
// Pass 3 Helper Macros
|
||||
#define _Fsf_String ((_Fsf_ == 3) ? "w" : ((_Fsf_ == 2) ? "z" : ((_Fsf_ == 1) ? "y" : "x")))
|
||||
|
|
Loading…
Reference in New Issue