mirror of https://github.com/PCSX2/pcsx2.git
microVU:
- 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:
parent
a8266a48d8
commit
8c5b6ae749
|
@ -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) {
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
Loading…
Reference in New Issue