mirror of https://github.com/PCSX2/pcsx2.git
microVU: New improved flag speedhack.
- Now does Mac Flags as well pretty safely - Speedup is anywhere from nothing to ~30fps (latter is DQ8 + MTVU)
This commit is contained in:
parent
31ffdd8c53
commit
d8343cea2a
|
@ -291,7 +291,7 @@ __ri void flagSet(mV, bool setMacFlag) {
|
|||
for (int i = mVUcount, j = 0; i > 0; i--, j++) {
|
||||
j += mVUstall;
|
||||
incPC2(-2);
|
||||
if (sFLAG.doFlag && (j >= 3)) {
|
||||
if (sFLAG.doFlag && (j >= 3) && sFLAG.skipWrite != 1) {
|
||||
if (setMacFlag) { mFLAG.doFlag = 1; }
|
||||
else { sFLAG.doNonSticky = 1; }
|
||||
break;
|
||||
|
@ -317,7 +317,7 @@ __ri void mVUanalyzeSflag(mV, int It) {
|
|||
|
||||
__ri void mVUanalyzeFSSET(mV) {
|
||||
mVUlow.isFSSET = 1;
|
||||
mVUlow.readFlags = 1;
|
||||
mVUlow.readFlags = 2;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------
|
||||
|
@ -345,7 +345,7 @@ __ri void mVUanalyzeMflag(mV, int Is, int It) {
|
|||
|
||||
__fi void mVUanalyzeCflag(mV, int It) {
|
||||
mVUinfo.swapOps = 1;
|
||||
mVUlow.readFlags = 1;
|
||||
mVUlow.readFlags = 2;
|
||||
if (mVUcount < 4) {
|
||||
if (!(mVUpBlock->pState.needExactMatch & 4)) // The only time this should happen is on the first program block
|
||||
DevCon.WriteLn(Color_Green, "microVU%d: pState's cFlag Info was expected to be set [%04x]", getIndex, xPC);
|
||||
|
|
|
@ -31,7 +31,7 @@ __fi void mVUstatusFlagOp(mV) {
|
|||
int i = mVUcount;
|
||||
bool runLoop = true;
|
||||
|
||||
if (sFLAG.doFlag) {
|
||||
if (sFLAG.doFlag && sFLAG.skipWrite != 1) {
|
||||
sFLAG.doNonSticky = true;
|
||||
}
|
||||
else {
|
||||
|
@ -41,7 +41,7 @@ __fi void mVUstatusFlagOp(mV) {
|
|||
runLoop = false;
|
||||
break;
|
||||
}
|
||||
else if (sFLAG.doFlag) {
|
||||
else if (sFLAG.doFlag && sFLAG.skipWrite != 1) {
|
||||
sFLAG.doNonSticky = true;
|
||||
break;
|
||||
}
|
||||
|
@ -92,30 +92,128 @@ void sortFullFlag(int* fFlag, int* bFlag) {
|
|||
}
|
||||
}
|
||||
|
||||
#define sFlagCond (sFLAG.doFlag || mVUlow.isFSSET || mVUinfo.doDivFlag)
|
||||
#define sFlagCond ((sFLAG.doFlag && sFLAG.skipWrite != 1) || mVUlow.isFSSET || mVUinfo.doDivFlag )
|
||||
#define sHackCond (mVUsFlagHack && !sFLAG.doNonSticky)
|
||||
|
||||
// Note: Flag handling is 'very' complex, it requires full knowledge of how microVU recs work, so don't touch!
|
||||
__fi void mVUsetFlags(mV, microFlagCycles& mFC) {
|
||||
|
||||
int endPC = iPC;
|
||||
u32 aCount = 1; // Amount of instructions needed to get valid mac flag instances for block linking
|
||||
u32 aCount = 0; // Amount of instructions needed to get valid mac flag instances for block linking
|
||||
bool writeProtect = false;
|
||||
|
||||
// Ensure last ~4+ instructions update mac/status flags (if next block's first 4 instructions will read them)
|
||||
for(int i = mVUcount; i > 0; i--, aCount++) {
|
||||
if (sFLAG.doFlag) {
|
||||
if (__Mac)
|
||||
|
||||
if (__Mac) {
|
||||
mFLAG.doFlag = true;
|
||||
writeProtect = true;
|
||||
}
|
||||
|
||||
if (__Status)
|
||||
if (__Status) {
|
||||
sFLAG.doNonSticky = true;
|
||||
writeProtect = true;
|
||||
}
|
||||
if (writeProtect == true)
|
||||
|
||||
if (aCount >= 4)
|
||||
if (aCount >= 3){
|
||||
break;
|
||||
}
|
||||
}
|
||||
incPC2(-2);
|
||||
}
|
||||
|
||||
if (mVUsFlagHack){
|
||||
bool flagReadFound = false;
|
||||
bool updateCalcFound = false;
|
||||
int flagReadptr = 0;
|
||||
incPC2((aCount * 2));
|
||||
int instanceCycles = 0;
|
||||
|
||||
// Go through checking flags if they need to be written back or not, ignoring the last 4ish of course
|
||||
for (int i = mVUcount; i > 0; i--) {
|
||||
if (sFLAG.doFlag) {
|
||||
if (writeProtect && (mVUcount - i) <= aCount) { //Don't actually clear any of the last ops in the block, just check for reads
|
||||
//DevCon.Warning("aCnt %d, mVUcnt %d mVUcnt-i %d", aCount, mVUcount, (mVUcount - i));
|
||||
sFLAG.skipWrite = 2;
|
||||
}
|
||||
|
||||
if (flagReadFound) {
|
||||
if (instanceCycles >= 4) {
|
||||
if (mVUinfo.uOp.VF_write.reg != 0) { //Keep going because this is a mac/status calculation op only
|
||||
if (updateCalcFound == false)
|
||||
sFLAG.skipWrite = 2;
|
||||
//DevCon.Warning("Flag read mac found at %d and %d cycles, rolling back to %d", i, instanceCycles, i + (flagReadptr - 1) * 2);
|
||||
flagReadFound = false;
|
||||
updateCalcFound = false;
|
||||
instanceCycles = 0;
|
||||
//Roll back in case there was other flag reads
|
||||
|
||||
incPC2((flagReadptr - 1) * 2);
|
||||
i += flagReadptr - 1;
|
||||
flagReadptr = 0;
|
||||
}
|
||||
else {
|
||||
//DevCon.Warning("Calculation found!");
|
||||
updateCalcFound = true;
|
||||
sFLAG.skipWrite = 2;
|
||||
}
|
||||
}
|
||||
//else DevCon.Warning("waiting On %d cycles, flagptr %d pos %d", instanceCycles, flagReadptr, i);
|
||||
//Else do nothing, we will come back to this one
|
||||
}
|
||||
else {
|
||||
if (sFLAG.skipWrite != 2) { //Kill only non-write protected flag updates
|
||||
|
||||
sFLAG.skipWrite = 1;
|
||||
//DevCon.Warning("ignoring at %d", i);
|
||||
}
|
||||
//else DevCon.Warning("Write protected at %d", i);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (flagReadFound) {
|
||||
if (i == 1) {
|
||||
//Nothing found by the end of the block
|
||||
flagReadFound = false;
|
||||
|
||||
//Roll back in case there was other flag reads
|
||||
if (flagReadptr > 0) {
|
||||
incPC2((flagReadptr)* 2);
|
||||
i += flagReadptr - 1;
|
||||
flagReadptr = 0;
|
||||
}
|
||||
}
|
||||
else { //Relevant flag update instructions not yet found, keep checking the stalls to get the right one
|
||||
if (flagReadptr > 0){
|
||||
//DevCon.Warning("adding cycles Swap ops %d", mVUinfo.swapOps);
|
||||
instanceCycles += mVUstall;
|
||||
if (mVUstall == 0)
|
||||
instanceCycles += 1;
|
||||
|
||||
}
|
||||
flagReadptr++;
|
||||
}
|
||||
}
|
||||
if (mVUlow.readFlags == 1 && !flagReadFound) {
|
||||
flagReadFound = true;
|
||||
flagReadptr = 0;
|
||||
instanceCycles = 0;
|
||||
//DevCon.Warning("Found Flag on %d Stall = %d swapops = %d", i, mVUstall, mVUinfo.swapOps);
|
||||
|
||||
if (mVUinfo.swapOps)
|
||||
instanceCycles += mVUstall;
|
||||
|
||||
instanceCycles += 1;
|
||||
//DevCon.Warning("%d cycles on flag read", instanceCycles);
|
||||
flagReadptr++;
|
||||
}
|
||||
incPC2(-2);
|
||||
}
|
||||
}
|
||||
|
||||
// Status/Mac Flags Setup Code
|
||||
int xS = 0, xM = 0, xC = 0;
|
||||
u32 ff0=0, ff1=0, ffOn=0, fInfo=0;
|
||||
|
|
|
@ -133,7 +133,7 @@ struct microLowerOp {
|
|||
bool backupVI; // Backup VI reg to memory if modified before branch (branch uses old VI value unless opcode is ILW or ILWR)
|
||||
bool memReadIs; // Read Is (VI reg) from memory (used by branches)
|
||||
bool memReadIt; // Read If (VI reg) from memory (used by branches)
|
||||
bool readFlags; // Current Instruction reads Status, Mac, or Clip flags
|
||||
u8 readFlags; // Current Instruction reads Status, Mac, or Clip flags
|
||||
};
|
||||
|
||||
struct microFlagInst {
|
||||
|
@ -142,6 +142,7 @@ struct microFlagInst {
|
|||
u8 write; // Points to the instance that should be written to (s-stage write)
|
||||
u8 lastWrite; // Points to the instance that was last written to (most up-to-date flag)
|
||||
u8 read; // Points to the instance that should be read by a lower instruction (t-stage read)
|
||||
u8 skipWrite; // Makes sure the flags dont written (MAC Flag hack)
|
||||
};
|
||||
|
||||
struct microFlagCycles {
|
||||
|
|
|
@ -31,7 +31,7 @@ static void mVUupdateFlags(mV, const xmm& reg, const xmm& regT1in = xEmptyReg, c
|
|||
static const u16 flipMask[16] = {0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15};
|
||||
|
||||
//SysPrintf("Status = %d; Mac = %d\n", sFLAG.doFlag, mFLAG.doFlag);
|
||||
if (!sFLAG.doFlag && !mFLAG.doFlag) { return; }
|
||||
if ((!sFLAG.doFlag && !mFLAG.doFlag) || sFLAG.skipWrite == 1) { return; }
|
||||
|
||||
const xmm& regT1 = regT1b ? mVU.regAlloc->allocReg() : regT1in;
|
||||
|
||||
|
@ -125,7 +125,7 @@ static void setupPass1(microVU& mVU, int opCase, bool isACC, bool noFlagUpdate)
|
|||
opCase3 { mVUanalyzeFMAC1(mVU, ((isACC) ? 0 : _Fd_), _Fs_, 0); }
|
||||
opCase4 { mVUanalyzeFMAC1(mVU, ((isACC) ? 0 : _Fd_), _Fs_, 0); }
|
||||
|
||||
if (noFlagUpdate) {
|
||||
if (noFlagUpdate) { //Max/Min Ops
|
||||
sFLAG.doFlag = false;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue