- Implemented some bizarre behavior where conditional branches will read old VI-reg values if the previous instructions continuously read+write to the VI reg.

example from zerorec's comments:
SQI vi5++
SQI vi5++
IBNE vi4, vi5

vi5's value in the branch should be the value before all the SQI's...
more examples in iVUzerorec.cpp

git-svn-id: http://pcsx2.googlecode.com/svn/trunk@1304 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
cottonvibes 2009-06-02 00:50:37 +00:00
parent a8266a48d8
commit 8c5b6ae749
2 changed files with 34 additions and 32 deletions

View File

@ -29,6 +29,7 @@
#define aReg(x) mVUregs.VF[x] #define aReg(x) mVUregs.VF[x]
#define bReg(x, y) mVUregsTemp.VFreg[y] = x; mVUregsTemp.VF[y] #define bReg(x, y) mVUregsTemp.VFreg[y] = x; mVUregsTemp.VF[y]
#define aMax(x, y) ((x > y) ? x : y) #define aMax(x, y) ((x > y) ? x : y)
#define aMin(x, y) ((x < y) ? x : y)
// Read a VF reg by upper op // Read a VF reg by upper op
#define analyzeReg1(xReg, vfRead) { \ #define analyzeReg1(xReg, vfRead) { \
@ -128,18 +129,6 @@
// Writing to a VI reg // Writing to a VI reg
#define analyzeVIreg2(xReg, viWrite, aCycles) { \ #define analyzeVIreg2(xReg, viWrite, aCycles) { \
if (xReg) { \
mVUregsTemp.VIreg = xReg; \
mVUregsTemp.VI = aCycles; \
mVUlow.writesVI = 1; \
mVU->VIbackup[0] = xReg; \
viWrite.reg = xReg; \
viWrite.used = aCycles; \
} \
}
// Writing to a VI reg (FSxxx, FMxxx, FCxxx opcodes)
#define analyzeVIreg3(xReg, viWrite, aCycles) { \
if (xReg) { \ if (xReg) { \
mVUregsTemp.VIreg = xReg; \ mVUregsTemp.VIreg = xReg; \
mVUregsTemp.VI = aCycles; \ mVUregsTemp.VI = aCycles; \
@ -319,16 +308,13 @@ microVUt(void) mVUanalyzeSflag(mV, int It) {
// Do to stalls, it can only be set one instruction prior to the status flag read instruction // Do to stalls, it can only be set one instruction prior to the status flag read instruction
// if we were guaranteed no-stalls were to happen, it could be set 4 instruction prior. // if we were guaranteed no-stalls were to happen, it could be set 4 instruction prior.
} }
analyzeVIreg3(It, mVUlow.VI_write, 1); mVUlow.readFlags = 1;
analyzeVIreg2(It, mVUlow.VI_write, 1);
} }
microVUt(void) mVUanalyzeFSSET(mV) { microVUt(void) mVUanalyzeFSSET(mV) {
mVUlow.isFSSET = 1; mVUlow.isFSSET = 1;
// mVUinfo &= ~_doStatus; mVUlow.readFlags = 1;
// Note: I'm not entirely sure if the non-sticky flags
// should be taken from the current upper instruction
// or if they should be taken from the previous instruction
// Uncomment the above line if the latter-case is true
} }
//------------------------------------------------------------------ //------------------------------------------------------------------
@ -347,8 +333,9 @@ microVUt(void) mVUanalyzeMflag(mV, int Is, int It) {
} }
iPC = curPC; iPC = curPC;
} }
mVUlow.readFlags = 1;
analyzeVIreg1(Is, mVUlow.VI_read[0]); analyzeVIreg1(Is, mVUlow.VI_read[0]);
analyzeVIreg3(It, mVUlow.VI_write, 1); analyzeVIreg2(It, mVUlow.VI_write, 1);
} }
//------------------------------------------------------------------ //------------------------------------------------------------------
@ -357,8 +344,9 @@ microVUt(void) mVUanalyzeMflag(mV, int Is, int It) {
microVUt(void) mVUanalyzeCflag(mV, int It) { microVUt(void) mVUanalyzeCflag(mV, int It) {
mVUinfo.swapOps = 1; mVUinfo.swapOps = 1;
mVUlow.readFlags = 1;
if (mVUcount < 4) { mVUpBlock->pState.needExactMatch |= 0xf << (/*mVUcount +*/ 8); } if (mVUcount < 4) { mVUpBlock->pState.needExactMatch |= 0xf << (/*mVUcount +*/ 8); }
analyzeVIreg3(It, mVUlow.VI_write, 1); analyzeVIreg2(It, mVUlow.VI_write, 1);
} }
//------------------------------------------------------------------ //------------------------------------------------------------------
@ -381,18 +369,31 @@ microVUt(void) mVUanalyzeXGkick(mV, int Fs, int xCycles) {
// Branches - Branch Opcodes // Branches - Branch Opcodes
//------------------------------------------------------------------ //------------------------------------------------------------------
#define analyzeBranchVI(reg, infoVar) { \ #define analyzeBranchVI(xReg, infoVar) { \
/* First ensure branch is not first opcode in block */ \ if (xReg) { \
if (reg && (mVUcount > 0)) { \ int i; \
incPC2(-2); \ int iEnd = aMin(4, mVUcount); \
/* Check if prev Op modified VI reg */ \ int bPC = iPC; \
if (mVUlow.writesVI && (reg == mVU->VIbackup[0])) { \ for (i = 0; i < iEnd; i++) { \
mVUlow.backupVI = 1; \ incPC2(-2) \
incPC2(2); \ if ((mVUlow.VI_write.reg == xReg) && mVUlow.VI_write.used) { \
infoVar = 1; \ if (mVUlow.readFlags) break; \
} \ if (i == 0) continue; \
else { incPC2(2); } \ if (((mVUlow.VI_read[0].reg == xReg) && (mVUlow.VI_read[0].used)) \
} \ || ((mVUlow.VI_read[1].reg == xReg) && (mVUlow.VI_read[1].used))) \
{ continue; } \
} \
break; \
} \
if (i) { \
DevCon::Status("microVU%d: Branch VI-Delay (%d)", params getIndex, i); \
incPC2(2); \
mVUlow.backupVI = 1; \
iPC = bPC; \
infoVar = 1; \
} \
iPC = bPC; \
} \
} }
microVUt(void) mVUanalyzeBranch1(mV, int Is) { microVUt(void) mVUanalyzeBranch1(mV, int Is) {

View File

@ -99,6 +99,7 @@ struct microLowerOp {
bool memReadIs; // Read Is (VI reg) from memory (used by branches) bool memReadIs; // Read Is (VI reg) from memory (used by branches)
bool memReadIt; // Read If (VI reg) from memory (used by branches) bool memReadIt; // Read If (VI reg) from memory (used by branches)
bool writesVI; // Current Instruction writes to VI (used by branches; note that flag-modifying opcodes shouldn't set this) bool writesVI; // Current Instruction writes to VI (used by branches; note that flag-modifying opcodes shouldn't set this)
bool readFlags; // Current Instruction reads Status, Mac, or Clip flags
}; };
struct microFlagInst { struct microFlagInst {