microVU: Finished properly supporting branch in branch delay slots.

git-svn-id: http://pcsx2.googlecode.com/svn/trunk@1654 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
cottonvibes 2009-08-20 00:49:13 +00:00
parent 490d996abc
commit 3c458affad
6 changed files with 56 additions and 36 deletions

View File

@ -159,6 +159,7 @@ struct microVU {
u32 VIbackup; // Holds a backup of a VI reg if modified before a branch u32 VIbackup; // Holds a backup of a VI reg if modified before a branch
u32 VIxgkick; // Holds a backup of a VI reg used for xgkick-delays u32 VIxgkick; // Holds a backup of a VI reg used for xgkick-delays
u32 branch; // Holds branch compare result (IBxx) OR Holds address to Jump to (JALR/JR) 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 evilBranch; // For Branches in Branch Delay Slots, holds Address to Jump to
u32 p; // Holds current P instance index u32 p; // Holds current P instance index
u32 q; // Holds current Q instance index u32 q; // Holds current Q instance index

View File

@ -393,6 +393,7 @@ microVUt(int) mVUbranchCheck(mV) {
if (!mVUcount) return 0; if (!mVUcount) return 0;
incPC(-2); incPC(-2);
if (mVUlow.branch) { if (mVUlow.branch) {
mVUlow.badBranch = 1;
incPC(2); incPC(2);
mVUlow.evilBranch = 1; mVUlow.evilBranch = 1;
mVUregs.blockType = 2; mVUregs.blockType = 2;

View File

@ -386,7 +386,7 @@ microVUr(void*) mVUcompile(microVU* mVU, u32 startPC, uptr pState) {
else { doSwapOp(mVU); } else { doSwapOp(mVU); }
if (mVUinfo.doXGKICK) { mVU_XGKICK_DELAY(mVU, 1); } if (mVUinfo.doXGKICK) { mVU_XGKICK_DELAY(mVU, 1); }
if (!doRegAlloc) { mVU->regAlloc->flushAll(); } if (!doRegAlloc) { mVU->regAlloc->flushAll(); }
if (_isBlock2) { mVUsetupRange(mVU, xPC, 0); normJumpCompile(mVU, mFC, 1); return thisPtr; } if (isEvilBlock) { mVUsetupRange(mVU, xPC, 0); normJumpCompile(mVU, mFC, 1); return thisPtr; }
else if (!mVUinfo.isBdelay) { incPC(1); } else if (!mVUinfo.isBdelay) { incPC(1); }
else { else {
mVUsetupRange(mVU, xPC, 0); mVUsetupRange(mVU, xPC, 0);

View File

@ -44,7 +44,7 @@ __declspec(align(16)) struct microRegInfo { // Ordered for Faster Compares
u8 VI[16]; u8 VI[16];
regInfo VF[32]; regInfo VF[32];
u8 flags; // clip x2 :: status x2 u8 flags; // clip x2 :: status x2
u8 blockType; // 0 = Normal; 1 = Compile one instruction (E-bit End); 2 = Compile one instruction (Branch End) u8 blockType; // 0 = Normal; 1,2 = Compile one instruction (E-bit/Branch Ending)
u8 padding[5]; // 160 bytes u8 padding[5]; // 160 bytes
#if defined(_MSC_VER) #if defined(_MSC_VER)
}; };
@ -107,7 +107,8 @@ struct microLowerOp {
microVIreg VI_read[2]; // VI regs read by this instruction microVIreg VI_read[2]; // VI regs read by this instruction
microConstInfo constJump; // Constant Reg Info for JR/JARL instructions microConstInfo constJump; // Constant Reg Info for JR/JARL instructions
u32 branch; // Branch Type (0 = Not a Branch, 1 = B. 2 = BAL, 3~8 = Conditional Branches, 9 = JALR, 10 = JR) u32 branch; // Branch Type (0 = Not a Branch, 1 = B. 2 = BAL, 3~8 = Conditional Branches, 9 = JALR, 10 = JR)
bool evilBranch;// This instruction is a Branch in a Branch Delay Slot bool badBranch; // This instruction is a Branch who has another branch in its Delay Slot
bool evilBranch;// This instruction is a Branch in a Branch Delay Slot (Instruction after badBranch)
bool isNOP; // This instruction is a NOP bool isNOP; // This instruction is a NOP
bool isFSSET; // This instruction is a FSSET bool isFSSET; // This instruction is a FSSET
bool noWriteVF; // Don't write back the result of a lower op to VF reg if upper op writes to same reg (or if VF = 0) bool noWriteVF; // Don't write back the result of a lower op to VF reg if upper op writes to same reg (or if VF = 0)

View File

@ -1166,19 +1166,32 @@ void setBranchA(mP, int x, int _x_) {
void condEvilBranch(mV, int JMPcc) { void condEvilBranch(mV, int JMPcc) {
using namespace x86Emitter; using namespace x86Emitter;
if (mVUlow.badBranch) {
xMOV(ptr32[&mVU->branch], eax);
xMOV(ptr32[&mVU->badBranch], branchAddrN);
xCMP(ax, 0); xCMP(ax, 0);
xMOV(ptr32[&mVU->evilBranch], branchAddr);
xForwardJump8 cJMP((JccComparisonType)JMPcc); xForwardJump8 cJMP((JccComparisonType)JMPcc);
incPC(-2); // Branch Not Taken incPC(4); // Branch Not Taken
xMOV(ptr32[&mVU->evilBranch], ((branchAddr+8) & (mVU->microMemSize-8))); xMOV(ptr32[&mVU->badBranch], xPC);
incPC(2); incPC(-4);
cJMP.SetTarget();
return;
}
xMOV(ptr32[&mVU->evilBranch], branchAddr);
xCMP(ax, 0);
xForwardJump8 cJMP((JccComparisonType)JMPcc);
xMOV(eax, ptr32[&mVU->badBranch]); // Branch Not Taken
xMOV(ptr32[&mVU->evilBranch], eax);
cJMP.SetTarget(); cJMP.SetTarget();
} }
mVUop(mVU_B) { mVUop(mVU_B) {
setBranchA(mX, 1, 0); setBranchA(mX, 1, 0);
pass1 { mVUanalyzeNormBranch(mVU, 0, 0); } pass1 { mVUanalyzeNormBranch(mVU, 0, 0); }
pass2 { if (mVUlow.evilBranch) { MOV32ItoM((uptr)&mVU->evilBranch, branchAddr); } } pass2 {
if (mVUlow.badBranch) { MOV32ItoM((uptr)&mVU->badBranch, branchAddrN); }
if (mVUlow.evilBranch) { MOV32ItoM((uptr)&mVU->evilBranch, branchAddr); }
}
pass3 { mVUlog("B [<a href=\"#addr%04x\">%04x</a>]", branchAddr, branchAddr); } pass3 { mVUlog("B [<a href=\"#addr%04x\">%04x</a>]", branchAddr, branchAddr); }
} }
@ -1188,6 +1201,7 @@ mVUop(mVU_BAL) {
pass2 { pass2 {
MOV32ItoR(gprT1, bSaveAddr); MOV32ItoR(gprT1, bSaveAddr);
mVUallocVIb(mVU, gprT1, _It_); mVUallocVIb(mVU, gprT1, _It_);
if (mVUlow.badBranch) { MOV32ItoM((uptr)&mVU->badBranch, branchAddrN); }
if (mVUlow.evilBranch) { MOV32ItoM((uptr)&mVU->evilBranch, branchAddr); } if (mVUlow.evilBranch) { MOV32ItoM((uptr)&mVU->evilBranch, branchAddr); }
} }
pass3 { mVUlog("BAL vi%02d [<a href=\"#addr%04x\">%04x</a>]", _Ft_, branchAddr, branchAddr); } pass3 { mVUlog("BAL vi%02d [<a href=\"#addr%04x\">%04x</a>]", _Ft_, branchAddr, branchAddr); }
@ -1204,8 +1218,8 @@ mVUop(mVU_IBEQ) {
if (mVUlow.memReadIt) XOR32MtoR(gprT1, (uptr)&mVU->VIbackup); if (mVUlow.memReadIt) XOR32MtoR(gprT1, (uptr)&mVU->VIbackup);
else { mVUallocVIa(mVU, gprT2, _It_); XOR32RtoR(gprT1, gprT2); } else { mVUallocVIa(mVU, gprT2, _It_); XOR32RtoR(gprT1, gprT2); }
if (!mVUlow.evilBranch) { MOV32RtoM((uptr)&mVU->branch, gprT1); } if (!(isBadOrEvil)) MOV32RtoM((uptr)&mVU->branch, gprT1);
else { condEvilBranch(mVU, Jcc_Equal); } else condEvilBranch(mVU, Jcc_Equal);
} }
pass3 { mVUlog("IBEQ vi%02d, vi%02d [<a href=\"#addr%04x\">%04x</a>]", _Ft_, _Fs_, branchAddr, branchAddr); } pass3 { mVUlog("IBEQ vi%02d, vi%02d [<a href=\"#addr%04x\">%04x</a>]", _Ft_, _Fs_, branchAddr, branchAddr); }
} }
@ -1217,7 +1231,7 @@ mVUop(mVU_IBGEZ) {
pass2 { pass2 {
if (mVUlow.memReadIs) MOV32MtoR(gprT1, (uptr)&mVU->VIbackup); if (mVUlow.memReadIs) MOV32MtoR(gprT1, (uptr)&mVU->VIbackup);
else mVUallocVIa(mVU, gprT1, _Is_); else mVUallocVIa(mVU, gprT1, _Is_);
if (!mVUlow.evilBranch) MOV32RtoM((uptr)&mVU->branch, gprT1); if (!(isBadOrEvil)) MOV32RtoM((uptr)&mVU->branch, gprT1);
else condEvilBranch(mVU, Jcc_GreaterOrEqual); else condEvilBranch(mVU, Jcc_GreaterOrEqual);
} }
pass3 { mVUlog("IBGEZ vi%02d [<a href=\"#addr%04x\">%04x</a>]", _Fs_, branchAddr, branchAddr); } pass3 { mVUlog("IBGEZ vi%02d [<a href=\"#addr%04x\">%04x</a>]", _Fs_, branchAddr, branchAddr); }
@ -1230,7 +1244,7 @@ mVUop(mVU_IBGTZ) {
pass2 { pass2 {
if (mVUlow.memReadIs) MOV32MtoR(gprT1, (uptr)&mVU->VIbackup); if (mVUlow.memReadIs) MOV32MtoR(gprT1, (uptr)&mVU->VIbackup);
else mVUallocVIa(mVU, gprT1, _Is_); else mVUallocVIa(mVU, gprT1, _Is_);
if (!mVUlow.evilBranch) MOV32RtoM((uptr)&mVU->branch, gprT1); if (!(isBadOrEvil)) MOV32RtoM((uptr)&mVU->branch, gprT1);
else condEvilBranch(mVU, Jcc_Greater); else condEvilBranch(mVU, Jcc_Greater);
} }
pass3 { mVUlog("IBGTZ vi%02d [<a href=\"#addr%04x\">%04x</a>]", _Fs_, branchAddr, branchAddr); } pass3 { mVUlog("IBGTZ vi%02d [<a href=\"#addr%04x\">%04x</a>]", _Fs_, branchAddr, branchAddr); }
@ -1243,7 +1257,7 @@ mVUop(mVU_IBLEZ) {
pass2 { pass2 {
if (mVUlow.memReadIs) MOV32MtoR(gprT1, (uptr)&mVU->VIbackup); if (mVUlow.memReadIs) MOV32MtoR(gprT1, (uptr)&mVU->VIbackup);
else mVUallocVIa(mVU, gprT1, _Is_); else mVUallocVIa(mVU, gprT1, _Is_);
if (!mVUlow.evilBranch) MOV32RtoM((uptr)&mVU->branch, gprT1); if (!(isBadOrEvil)) MOV32RtoM((uptr)&mVU->branch, gprT1);
else condEvilBranch(mVU, Jcc_LessOrEqual); else condEvilBranch(mVU, Jcc_LessOrEqual);
} }
pass3 { mVUlog("IBLEZ vi%02d [<a href=\"#addr%04x\">%04x</a>]", _Fs_, branchAddr, branchAddr); } pass3 { mVUlog("IBLEZ vi%02d [<a href=\"#addr%04x\">%04x</a>]", _Fs_, branchAddr, branchAddr); }
@ -1256,7 +1270,7 @@ mVUop(mVU_IBLTZ) {
pass2 { pass2 {
if (mVUlow.memReadIs) MOV32MtoR(gprT1, (uptr)&mVU->VIbackup); if (mVUlow.memReadIs) MOV32MtoR(gprT1, (uptr)&mVU->VIbackup);
else mVUallocVIa(mVU, gprT1, _Is_); else mVUallocVIa(mVU, gprT1, _Is_);
if (!mVUlow.evilBranch) MOV32RtoM((uptr)&mVU->branch, gprT1); if (!(isBadOrEvil)) MOV32RtoM((uptr)&mVU->branch, gprT1);
else condEvilBranch(mVU, Jcc_Less); else condEvilBranch(mVU, Jcc_Less);
} }
pass3 { mVUlog("IBLTZ vi%02d [<a href=\"#addr%04x\">%04x</a>]", _Fs_, branchAddr, branchAddr); } pass3 { mVUlog("IBLTZ vi%02d [<a href=\"#addr%04x\">%04x</a>]", _Fs_, branchAddr, branchAddr); }
@ -1273,31 +1287,13 @@ mVUop(mVU_IBNE) {
if (mVUlow.memReadIt) XOR32MtoR(gprT1, (uptr)&mVU->VIbackup); if (mVUlow.memReadIt) XOR32MtoR(gprT1, (uptr)&mVU->VIbackup);
else { mVUallocVIa(mVU, gprT2, _It_); XOR32RtoR(gprT1, gprT2); } else { mVUallocVIa(mVU, gprT2, _It_); XOR32RtoR(gprT1, gprT2); }
if (!mVUlow.evilBranch) { MOV32RtoM((uptr)&mVU->branch, gprT1); } if (!(isBadOrEvil)) MOV32RtoM((uptr)&mVU->branch, gprT1);
else { condEvilBranch(mVU, Jcc_NotEqual); } else condEvilBranch(mVU, Jcc_NotEqual);
} }
pass3 { mVUlog("IBNE vi%02d, vi%02d [<a href=\"#addr%04x\">%04x</a>]", _Ft_, _Fs_, branchAddr, branchAddr); } pass3 { mVUlog("IBNE vi%02d, vi%02d [<a href=\"#addr%04x\">%04x</a>]", _Ft_, _Fs_, branchAddr, branchAddr); }
} }
mVUop(mVU_JR) { void normJumpPass2(mV) {
mVUbranch = 9;
pass1 { mVUanalyzeJump(mVU, _Is_, 0, 0); }
pass2 {
if (!mVUlow.constJump.isValid || mVUlow.evilBranch) {
mVUallocVIa(mVU, gprT1, _Is_);
SHL32ItoR(gprT1, 3);
AND32ItoR(gprT1, mVU->microMemSize - 8);
if (!mVUlow.evilBranch) MOV32RtoM((uptr)&mVU->branch, gprT1);
else MOV32RtoM((uptr)&mVU->evilBranch, gprT1);
}
}
pass3 { mVUlog("JR [vi%02d]", _Fs_); }
}
mVUop(mVU_JALR) {
mVUbranch = 10;
pass1 { mVUanalyzeJump(mVU, _Is_, _It_, 1); }
pass2 {
if (!mVUlow.constJump.isValid || mVUlow.evilBranch) { if (!mVUlow.constJump.isValid || mVUlow.evilBranch) {
mVUallocVIa(mVU, gprT1, _Is_); mVUallocVIa(mVU, gprT1, _Is_);
SHL32ItoR(gprT1, 3); SHL32ItoR(gprT1, 3);
@ -1305,7 +1301,26 @@ mVUop(mVU_JALR) {
MOV32RtoM((uptr)&mVU->branch, gprT1); MOV32RtoM((uptr)&mVU->branch, gprT1);
if (!mVUlow.evilBranch) MOV32RtoM((uptr)&mVU->branch, gprT1); if (!mVUlow.evilBranch) MOV32RtoM((uptr)&mVU->branch, gprT1);
else MOV32RtoM((uptr)&mVU->evilBranch, gprT1); else MOV32RtoM((uptr)&mVU->evilBranch, gprT1);
if (mVUlow.badBranch) {
ADD32ItoR(gprT1, 8);
AND32ItoR(gprT1, mVU->microMemSize - 8);
MOV32RtoM((uptr)&mVU->badBranch, gprT1);
} }
}
}
mVUop(mVU_JR) {
mVUbranch = 9;
pass1 { mVUanalyzeJump(mVU, _Is_, 0, 0); }
pass2 { normJumpPass2(mVU); }
pass3 { mVUlog("JR [vi%02d]", _Fs_); }
}
mVUop(mVU_JALR) {
mVUbranch = 10;
pass1 { mVUanalyzeJump(mVU, _Is_, _It_, 1); }
pass2 {
normJumpPass2(mVU);
MOV32ItoR(gprT1, bSaveAddr); MOV32ItoR(gprT1, bSaveAddr);
mVUallocVIb(mVU, gprT1, _It_); mVUallocVIb(mVU, gprT1, _It_);
} }

View File

@ -206,7 +206,8 @@ typedef u32 (__fastcall *mVUCall)(void*, void*);
#define mFLAG mVUinfo.mFlag #define mFLAG mVUinfo.mFlag
#define cFLAG mVUinfo.cFlag #define cFLAG mVUinfo.cFlag
#define mVUrange mVUcurProg.ranges.range[mVUcurProg.ranges.total] #define mVUrange mVUcurProg.ranges.range[mVUcurProg.ranges.total]
#define _isBlock2 (mVUpBlock->pState.blockType == 2) #define isEvilBlock (mVUpBlock->pState.blockType == 2)
#define isBadOrEvil (mVUlow.badBranch || mVUlow.evilBranch)
#define xPC ((iPC / 2) * 8) #define xPC ((iPC / 2) * 8)
#define curI ((u32*)mVU->regs->Micro)[iPC] //mVUcurProg.data[iPC] #define curI ((u32*)mVU->regs->Micro)[iPC] //mVUcurProg.data[iPC]
#define setCode() { mVU->code = curI; } #define setCode() { mVU->code = curI; }
@ -214,6 +215,7 @@ typedef u32 (__fastcall *mVUCall)(void*, void*);
#define incPC2(x) { iPC = ((iPC + x) & (mVU->progSize-1)); } #define incPC2(x) { iPC = ((iPC + x) & (mVU->progSize-1)); }
#define bSaveAddr (((xPC + 16) & (mVU->microMemSize-8)) / 8) #define bSaveAddr (((xPC + 16) & (mVU->microMemSize-8)) / 8)
#define branchAddr ((xPC + 8 + (_Imm11_ * 8)) & (mVU->microMemSize-8)) #define branchAddr ((xPC + 8 + (_Imm11_ * 8)) & (mVU->microMemSize-8))
#define branchAddrN ((xPC + 16 + (_Imm11_ * 8)) & (mVU->microMemSize-8))
#define shufflePQ (((mVU->p) ? 0xb0 : 0xe0) | ((mVU->q) ? 0x01 : 0x04)) #define shufflePQ (((mVU->p) ? 0xb0 : 0xe0) | ((mVU->q) ? 0x01 : 0x04))
#define cmpOffset(x) ((u8*)&(((u8*)x)[mVUprogI.ranges.range[i][0]])) #define cmpOffset(x) ((u8*)&(((u8*)x)[mVUprogI.ranges.range[i][0]]))
#define Rmem (uptr)&mVU->regs->VI[REG_R].UL #define Rmem (uptr)&mVU->regs->VI[REG_R].UL