- Implemented the case where an Unconditional branch has the E-bit Set. This solves a few games from getting stuck in infinite loops. (I still need to handle conditional branches and jumps).
- Max/Mini Opcodes shouldn't set status/mac flags. This should be a minor speedup.
- Minor Changes/Cleanups...

git-svn-id: http://pcsx2.googlecode.com/svn/trunk@1241 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
cottonvibes 2009-05-23 03:27:53 +00:00
parent 3ff7f2f191
commit 995b9d1eaa
5 changed files with 47 additions and 39 deletions

View File

@ -41,6 +41,15 @@
} \
}
#define branchEbit() { \
if (branch == 2) { \
if (!((mVUbranch == 1) || (mVUbranch == 2))) { \
Console::Error("microVU%d Warning: Jump with E-bit not Implemented [%04x]", params vuIndex, xPC); \
} \
else { eBitBranch = 1; } \
} \
}
#define startLoop() { mVUdebug1(); mVUstall = 0; memset(&mVUregsTemp, 0, sizeof(mVUregsTemp)); }
#define calcCycles(reg, x) { reg = ((reg > x) ? (reg - x) : 0); }
#define tCycles(dest, src) { dest = aMax(dest, src); }
@ -163,9 +172,7 @@ microVUt(void) mVUendProgram(int qInst, int pInst, int fStatus, int fMac, int fC
MOV32RtoM((uptr)&mVU->regs->VI[REG_MAC_FLAG].UL, gprT1);
MOV32RtoM((uptr)&mVU->regs->VI[REG_CLIP_FLAG].UL, gprT2);
//memcpy_fast(&pBlock->pStateEnd, &mVUregs, sizeof(microRegInfo));
//MOV32ItoM((uptr)&mVU->prog.lpState, (int)&mVUblock.pState); // Save pipeline state (clipflag instance)
//AND32ItoM((uptr)&microVU0.regs->VI[REG_VPU_STAT].UL, (vuIndex ? ~0x100 : ~0x001)); // VBS0/VBS1 flag
// Clear 'is busy' Flags, Save PC, and Jump to Exit Point
AND32ItoM((uptr)&VU0.VI[REG_VPU_STAT].UL, (vuIndex ? ~0x100 : ~0x001)); // VBS0/VBS1 flag
AND32ItoM((uptr)&mVU->regs->vifRegs->stat, ~0x4); // Clear VU 'is busy' signal for vif
MOV32ItoM((uptr)&mVU->regs->VI[REG_TPC].UL, xPC);
@ -175,7 +182,8 @@ microVUt(void) mVUendProgram(int qInst, int pInst, int fStatus, int fMac, int fC
#define sI ((mVUpBlock->pState.needExactMatch & 0x000f) ? 0 : ((mVUpBlock->pState.flags >> 0) & 3))
#define cI ((mVUpBlock->pState.needExactMatch & 0x0f00) ? 0 : ((mVUpBlock->pState.flags >> 2) & 3))
void mVUwarning() { Console::Error("microVU Warning: Exiting Execution Early (Possible Infinite Loop)"); }
void __fastcall mVUwarning0(u32 PC) { Console::Error("microVU0 Warning: Exiting from Possible Infinite Loop [%04x]", params PC); }
void __fastcall mVUwarning1(u32 PC) { Console::Error("microVU1 Warning: Exiting from Possible Infinite Loop [%04x]", params PC); }
microVUt(void) mVUtestCycles() {
microVU* mVU = mVUx;
@ -183,7 +191,9 @@ microVUt(void) mVUtestCycles() {
CMP32ItoM((uptr)&mVU->cycles, 0);
u8* jmp8 = JG8(0);
PUSH32R(gprR);
CALLFunc((uptr)mVUwarning);
MOV32ItoR(gprT2, xPC);
if (!vuIndex) CALLFunc((uptr)mVUwarning0);
else CALLFunc((uptr)mVUwarning1);
POP32R(gprR);
mVUendProgram<vuIndex>(0, 0, sI, 0, cI);
x86SetJ8(jmp8);
@ -224,9 +234,10 @@ microVUt(void*) __fastcall mVUcompile(u32 startPC, uptr pState) {
memcpy_fast(&mVUregs, (microRegInfo*)pState, sizeof(microRegInfo)); // Loads up Pipeline State Info
mVUblock.x86ptrStart = thisPtr;
pBlock = mVUblocks[startPC/8]->add(&mVUblock); // Add this block to block manager
mVUpBlock = pBlock;
mVUregs.flags = 0;
mVUflagInfo = 0;
mVUpBlock = pBlock;
mVUregs.flags = 0;
mVUflagInfo = 0;
bool eBitBranch = 0; // E-bit Set on Branch
for (int branch = 0; mVUcount < (vuIndex ? (0x3fff/8) : (0xfff/8)); ) {
incPC(1);
@ -235,7 +246,7 @@ microVUt(void*) __fastcall mVUcompile(u32 startPC, uptr pState) {
startLoop();
mVUopU<vuIndex, 0>();
if (curI & _Ebit_) { branch = 1; }
if (curI & _MDTbit_) { branch = 2; }
if (curI & _MDTbit_) { branch = 4; }
if (curI & _Ibit_) { mVUinfo |= _isNOP; }
else { incPC(-1); mVUopL<vuIndex, 0>(); incPC(1); }
mVUsetCycles<vuIndex>();
@ -244,7 +255,7 @@ microVUt(void*) __fastcall mVUcompile(u32 startPC, uptr pState) {
else { mVUinfo |= _writeQ; }
if (branch >= 2) { mVUinfo |= _isEOB | ((branch == 3) ? _isBdelay : 0); mVUcount++; branchWarning(); break; }
else if (branch == 1) { branch = 2; }
if (mVUbranch) { mVUsetFlagInfo<vuIndex>(); branch = 3; mVUbranch = 0; mVUinfo |= _isBranch; }
if (mVUbranch) { mVUsetFlagInfo<vuIndex>(); branchEbit(); branch = 3; mVUbranch = 0; mVUinfo |= _isBranch; }
incPC(1);
mVUcount++;
}
@ -253,10 +264,6 @@ microVUt(void*) __fastcall mVUcompile(u32 startPC, uptr pState) {
int xStatus[4], xMac[4], xClip[4];
int xCycles = mVUsetFlags<vuIndex>(xStatus, xMac, xClip);
mVUtestCycles<vuIndex>();
//SysPrintf("bS[0] = %08x, bS[1] = %08x, bS[2] = %08x, bS[3] = %08x\n", bStatus[0], bStatus[1], bStatus[2], bStatus[3]);
//SysPrintf("bM[0] = %08x, bM[1] = %08x, bM[2] = %08x, bM[3] = %08x\n", bMac[0], bMac[1], bMac[2], bMac[3]);
//SysPrintf("mVUcount = %d\n", mVUcount);
//SysPrintf("mVUflagInfo = %d\n", mVUflagInfo);
// Second Pass
iPC = mVUstartPC;
@ -286,6 +293,8 @@ microVUt(void*) __fastcall mVUcompile(u32 startPC, uptr pState) {
mVUprint("mVUcompile B/BAL");
incPC(-3); // Go back to branch opcode (to get branch imm addr)
if (eBitBranch) { iPC = branchAddr/4; goto eBitTemination; } // E-bit Was Set on Branch
mVUsetupBranch<vuIndex>(xStatus, xMac, xClip, xCycles);
if (mVUblocks[branchAddr/8] == NULL)
@ -347,10 +356,11 @@ microVUt(void*) __fastcall mVUcompile(u32 startPC, uptr pState) {
return thisPtr;
}
}
mVUprint("mVUcompile ebit");
if (x == (vuIndex?(0x3fff/8):(0xfff/8))) { Console::Error("microVU%d: Possible infinite compiling loop!", params vuIndex); }
eBitTemination:
mVUprint("mVUcompile ebit");
incCycles(100); // Ensures Valid P/Q instances (And sets all cycle data to 0)
mVUcycles -= 100;
@ -358,7 +368,7 @@ microVUt(void*) __fastcall mVUcompile(u32 startPC, uptr pState) {
mVUsetupRange<vuIndex>(xPC - 8);
mVUendProgram<vuIndex>(mVU->q, mVU->p, findFlagInst(xStatus, 0x7fffffff), findFlagInst(xMac, 0x7fffffff), findFlagInst(xClip, 0x7fffffff));
return thisPtr; //ToDo: Save pipeline state?
return thisPtr;
}
void* __fastcall mVUcompileVU0(u32 startPC, uptr pState) { return mVUcompile<0>(startPC, pState); }

View File

@ -23,8 +23,6 @@
// Dispatcher Functions
//------------------------------------------------------------------
void testFunction() { mVUprint("microVU: Entered Execution Mode"); }
// Generates the code for entering recompiled blocks
microVUt(void) mVUdispatcherA() {
microVU* mVU = mVUx;
@ -70,11 +68,6 @@ microVUt(void) mVUdispatcherA() {
if (isMMX(i)) { MOVQMtoR(mmVI(i), (uptr)&mVU->regs->VI[i].UL); }
}
//PUSH32R(EAX);
//CALLFunc((uptr)testFunction);
//write8(0xcc);
//POP32R(EAX);
// Jump to Recompiled Code Block
JMPR(EAX);
}

View File

@ -202,7 +202,7 @@ microVUt(void) mVUpass4(int startPC) {
if (mVUbranch) { branch = 3; mVUbranch = 0; }
incPC(1);
}
//if (mVUcount == 4) { mVUflagInfo |= 0xfff; } // Is this Too Slow? 99% of games probably don't need this.
//if (mVUcount < 4) { mVUflagInfo |= 0xfff; } // Is this Too Slow? 99% of games probably don't need this.
iPC = oldPC;
mVUcount = oldCount;
mVUbranch = oldBranch;

View File

@ -590,8 +590,8 @@ microVUf(void) mVU_FSSET() {
int flagReg1, flagReg2;
getFlagReg(flagReg1, fsInstance);
if (!(doStatus||doDivFlag)) { getFlagReg(flagReg2, fpsInstance); MOV32RtoR(flagReg1, flagReg2); } // Get status result from last status setting instruction
AND16ItoR(flagReg1, 0x03f); // Remember not to modify upper 16 bits because of mac flag
OR16ItoR (flagReg1, (_Imm12_ & 0xfc0));
AND32ItoR(flagReg1, 0x03f);
OR32ItoR (flagReg1, (_Imm12_ & 0xfc0));
}
pass3 { mVUlog("FSSET $%x", _Imm12_); }
pass4 { mVUsFlagHack = 0; }

View File

@ -461,6 +461,11 @@ microVUt(void) mVUupdateFlags(int reg, int regT1, int regT2, int xyzw, bool modX
pass3 { mVUlog(OPname); mVUlogACC(); mVUlogQ(); } \
}
// FMAC27~29 - MAX/MINI FMAC Opcodes
#define mVU_FMAC27(operation, OPname) { mVU_FMAC1 (operation, OPname); pass1 { microVU* mVU = mVUx; mVUinfo &= ~_doStatus; } }
#define mVU_FMAC28(operation, OPname) { mVU_FMAC6 (operation, OPname); pass1 { microVU* mVU = mVUx; mVUinfo &= ~_doStatus; } }
#define mVU_FMAC29(operation, OPname) { mVU_FMAC3 (operation, OPname); pass1 { microVU* mVU = mVUx; mVUinfo &= ~_doStatus; } }
//------------------------------------------------------------------
// Micro VU Micromode Upper instructions
//------------------------------------------------------------------
@ -546,21 +551,21 @@ microVUf(void) mVU_MSUBAx() { mVU_FMAC15(SUB, "MSUBAx"); }
microVUf(void) mVU_MSUBAy() { mVU_FMAC15(SUB, "MSUBAy"); }
microVUf(void) mVU_MSUBAz() { mVU_FMAC15(SUB, "MSUBAz"); }
microVUf(void) mVU_MSUBAw() { mVU_FMAC15(SUB, "MSUBAw"); }
microVUf(void) mVU_MAX() { mVU_FMAC1 (MAX2, "MAX"); }
microVUf(void) mVU_MAXi() { mVU_FMAC6 (MAX2, "MAXi"); }
microVUf(void) mVU_MAXx() { mVU_FMAC3 (MAX2, "MAXx"); }
microVUf(void) mVU_MAXy() { mVU_FMAC3 (MAX2, "MAXy"); }
microVUf(void) mVU_MAXz() { mVU_FMAC3 (MAX2, "MAXz"); }
microVUf(void) mVU_MAXw() { mVU_FMAC3 (MAX2, "MAXw"); }
microVUf(void) mVU_MINI() { mVU_FMAC1 (MIN2, "MINI"); }
microVUf(void) mVU_MINIi() { mVU_FMAC6 (MIN2, "MINIi"); }
microVUf(void) mVU_MINIx() { mVU_FMAC3 (MIN2, "MINIx"); }
microVUf(void) mVU_MINIy() { mVU_FMAC3 (MIN2, "MINIy"); }
microVUf(void) mVU_MINIz() { mVU_FMAC3 (MIN2, "MINIz"); }
microVUf(void) mVU_MINIw() { mVU_FMAC3 (MIN2, "MINIw"); }
microVUf(void) mVU_MAX() { mVU_FMAC27(MAX2, "MAX"); }
microVUf(void) mVU_MAXi() { mVU_FMAC28(MAX2, "MAXi"); }
microVUf(void) mVU_MAXx() { mVU_FMAC29(MAX2, "MAXx"); }
microVUf(void) mVU_MAXy() { mVU_FMAC29(MAX2, "MAXy"); }
microVUf(void) mVU_MAXz() { mVU_FMAC29(MAX2, "MAXz"); }
microVUf(void) mVU_MAXw() { mVU_FMAC29(MAX2, "MAXw"); }
microVUf(void) mVU_MINI() { mVU_FMAC27(MIN2, "MINI"); }
microVUf(void) mVU_MINIi() { mVU_FMAC28(MIN2, "MINIi"); }
microVUf(void) mVU_MINIx() { mVU_FMAC29(MIN2, "MINIx"); }
microVUf(void) mVU_MINIy() { mVU_FMAC29(MIN2, "MINIy"); }
microVUf(void) mVU_MINIz() { mVU_FMAC29(MIN2, "MINIz"); }
microVUf(void) mVU_MINIw() { mVU_FMAC29(MIN2, "MINIw"); }
microVUf(void) mVU_OPMULA() { mVU_FMAC18(MUL, "OPMULA"); }
microVUf(void) mVU_OPMSUB() { mVU_FMAC19(SUB, "OPMSUB"); }
microVUf(void) mVU_NOP() { pass3 { mVUlog("NOP"); } }
microVUf(void) mVU_NOP() { pass3 { mVUlog("NOP"); } }
microVUq(void) mVU_FTOIx(uptr addr) {
microVU* mVU = mVUx;
pass1 { mVUanalyzeFMAC2<vuIndex>(_Fs_, _Ft_); }