mirror of https://github.com/PCSX2/pcsx2.git
microVU:
- 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:
parent
3ff7f2f191
commit
995b9d1eaa
|
@ -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)µVU0.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); }
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -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_); }
|
||||
|
|
Loading…
Reference in New Issue