From 0c8c01494ff33acb0b375ae407e7610da4dd4ea1 Mon Sep 17 00:00:00 2001 From: cottonvibes Date: Tue, 2 Mar 2010 04:36:09 +0000 Subject: [PATCH] Minor vif/vu changes... git-svn-id: http://pcsx2.googlecode.com/svn/trunk@2654 96395faa-99c1-11dd-bbfe-3dabce05a288 --- pcsx2/VU1micro.cpp | 13 +++++--- pcsx2/VUmicro.h | 1 + pcsx2/Vif0_Dma.cpp | 7 ++-- pcsx2/Vif1_Dma.cpp | 15 +++------ pcsx2/x86/microVU.cpp | 63 ++++++++++++++++++----------------- pcsx2/x86/microVU.h | 10 ++++-- pcsx2/x86/microVU_Compile.inl | 33 ++++++++++++++++-- pcsx2/x86/microVU_Misc.h | 1 + 8 files changed, 90 insertions(+), 53 deletions(-) diff --git a/pcsx2/VU1micro.cpp b/pcsx2/VU1micro.cpp index e2cf46b51d..de5f9dae8c 100644 --- a/pcsx2/VU1micro.cpp +++ b/pcsx2/VU1micro.cpp @@ -40,14 +40,17 @@ void vu1ResetRegs() vif1Regs->stat.VEW = false; } -static int count; - -void __fastcall vu1ExecMicro(u32 addr) -{ - while(VU0.VI[REG_VPU_STAT].UL & 0x100) { +void vu1Finish() { + while (VU0.VI[REG_VPU_STAT].UL & 0x100) { VUM_LOG("vu1ExecMicro > Stalling until current microprogram finishes"); CpuVU1->Execute(vu1RunCycles); } +} + +void __fastcall vu1ExecMicro(u32 addr) +{ + static int count = 0; + vu1Finish(); VUM_LOG("vu1ExecMicro %x", addr); VUM_LOG("vu1ExecMicro %x (count=%d)", addr, count++); diff --git a/pcsx2/VUmicro.h b/pcsx2/VUmicro.h index db3ea4cb69..15f01bb3bc 100644 --- a/pcsx2/VUmicro.h +++ b/pcsx2/VUmicro.h @@ -294,6 +294,7 @@ extern void vu0Finish(); extern void recResetVU0( void ); // VU1 +extern void vu1Finish(); extern void vu1ResetRegs(); extern void __fastcall vu1ExecMicro(u32 addr); extern void vu1Exec(VURegs* VU); diff --git a/pcsx2/Vif0_Dma.cpp b/pcsx2/Vif0_Dma.cpp index 8685a8aeb3..89ce47b277 100644 --- a/pcsx2/Vif0_Dma.cpp +++ b/pcsx2/Vif0_Dma.cpp @@ -19,11 +19,12 @@ #include "VUmicro.h" #include "newVif.h" -__forceinline void vif0FLUSH() +// Run VU0 until finish, don't add cycles to EE +// because its vif stalling not the EE core... +__forceinline void vif0FLUSH() { + if (!(VU0.VI[REG_VPU_STAT].UL & 1)) return; int _cycles = VU0.cycle; - // Run VU0 until finish, don't add cycles to EE - // because its vif stalling not the EE core... vu0Finish(); g_vifCycles += (VU0.cycle - _cycles) * BIAS; } diff --git a/pcsx2/Vif1_Dma.cpp b/pcsx2/Vif1_Dma.cpp index dfc8564dc7..ca3e60b23d 100644 --- a/pcsx2/Vif1_Dma.cpp +++ b/pcsx2/Vif1_Dma.cpp @@ -21,17 +21,12 @@ #include "VUmicro.h" #include "newVif.h" -__forceinline void vif1FLUSH() +__forceinline void vif1FLUSH() { - if (VU0.VI[REG_VPU_STAT].UL & 0x100) - { - int _cycles = VU1.cycle; - - do { CpuVU1->Execute(vu1RunCycles); } - while (VU0.VI[REG_VPU_STAT].UL & 0x100); - - g_vifCycles += (VU1.cycle - _cycles) * BIAS; - } + if (!(VU0.VI[REG_VPU_STAT].UL & 0x100)) return; + int _cycles = VU1.cycle; + vu1Finish(); + g_vifCycles += (VU1.cycle - _cycles) * BIAS; } void vif1TransferFromMemory() diff --git a/pcsx2/x86/microVU.cpp b/pcsx2/x86/microVU.cpp index e3a35ddd69..3aa4d43144 100644 --- a/pcsx2/x86/microVU.cpp +++ b/pcsx2/x86/microVU.cpp @@ -184,8 +184,7 @@ _mVUt _f void mVUclearProg(int progIndex) { microProgram& program = mVU->prog.prog[progIndex]; program.used = 0; - program.isDead = 1; - program.isOld = 1; + program.age = isDead; program.frame = mVU->prog.curFrame; for (int j = 0; j <= program.ranges.max; j++) { program.ranges.range[j][0] = -1; // Set range to @@ -209,7 +208,7 @@ _mVUt _f void mVUcacheProg(int progIndex) { _f void mVUsortProg(mV, int progIndex) { int* temp = new int[mVU->prog.max+1]; int offset = 0; - for (int i = 0; i <= (mVU->prog.max-1); i++) { + for (int i = 0; i <=(mVU->prog.max-1); i++) { if (progIndex == mVU->prog.progList[i]) offset = 1; temp[i+1] = mVU->prog.progList[i+offset]; } @@ -223,14 +222,13 @@ _mVUt _f int mVUfindLeastUsedProg() { microVU* mVU = mVUx; for (int i = 0; i <= mVU->prog.max; i++) { - if (mVU->prog.prog[i].isDead) { + if (mVU->prog.prog[i].age == isDead) { mVU->prog.total++; mVUcacheProg(i); // Cache Micro Program - mVU->prog.prog[i].isDead = 0; - mVU->prog.prog[i].isOld = 0; - mVU->prog.prog[i].used = 1; + mVU->prog.prog[i].age = isYoung; + mVU->prog.prog[i].used = 1; mVUsortProg(mVU, i); - Console.WriteLn( Color_Orange, "microVU%d: Cached MicroPrograms = [%03d] [%03d]", vuIndex, i+1, mVU->prog.total+1); + Console.WriteLn(Color_Orange, "microVU%d: Cached MicroPrograms = [%03d] [%03d]", vuIndex, i+1, mVU->prog.total+1); return i; } } @@ -243,31 +241,32 @@ _mVUt _f int mVUfindLeastUsedProg() { } mVU->prog.total -= ((mVU->prog.max+1)/4)-1; mVUcacheProg(pIdx); // Cache Micro Program - mVU->prog.prog[pIdx].isDead = 0; - mVU->prog.prog[pIdx].isOld = 0; - mVU->prog.prog[pIdx].used = 1; + mVU->prog.prog[pIdx].age = isYoung; + mVU->prog.prog[pIdx].used = 1; mVUsortProg(mVU, pIdx); - Console.WriteLn( Color_Orange, "microVU%d: Cached MicroPrograms = [%03d] [%03d]", vuIndex, pIdx+1, mVU->prog.total+1); + Console.WriteLn(Color_Orange, "microVU%d: Cached MicroPrograms = [%03d] [%03d]", vuIndex, pIdx+1, mVU->prog.total+1); return pIdx; } // Finds and Ages/Kills Programs if they haven't been used in a while. _f void mVUvsyncUpdate(mV) { for (int i = 0; i <= mVU->prog.max; i++) { - if (mVU->prog.prog[i].isDead) continue; + if (mVU->prog.prog[i].age == isDead) continue; if (mVU->prog.prog[i].used) { mVU->prog.prog[i].used = 0; mVU->prog.prog[i].frame = mVU->prog.curFrame; } - else if (((mVU->prog.curFrame - mVU->prog.prog[i].frame) >= (360 * 10)) && (i != mVU->prog.cur)) { - mVU->prog.total--; - if (!mVU->index) mVUclearProg<0>(i); - else mVUclearProg<1>(i); - DevCon.WriteLn("microVU%d: Killing Dead Program [%03d]", mVU->index, i+1); - } - else if (((mVU->prog.curFrame - mVU->prog.prog[i].frame) >= (30 * 1)) && !mVU->prog.prog[i].isOld) { - mVU->prog.prog[i].isOld = 1; - //DevCon.Status("microVU%d: Aging Old Program [%03d]", mVU->index, i+1); + else { // Age Micro Program that wasn't used + s32 diff = mVU->prog.curFrame - mVU->prog.prog[i].frame; + if (diff >= (360 * 10)) { + if (i == mVU->prog.cur) continue; // Don't Age/Kill last used program + mVU->prog.total--; + if (!mVU->index) mVUclearProg<0>(i); + else mVUclearProg<1>(i); + DevCon.WriteLn("microVU%d: Killing Dead Program [%03d]", mVU->index, i+1); + } + elif(diff >= (60 * 1)) { mVU->prog.prog[i].age = isOld; } + elif(diff >= (20 * 1)) { mVU->prog.prog[i].age = isAged; } } } mVU->prog.curFrame++; @@ -286,16 +285,16 @@ _mVUt _f bool mVUcmpPartial(int progIndex) { } // Compare Cached microProgram to mVU->regs->Micro -_mVUt _f bool mVUcmpProg(int progIndex, const bool checkOld, const bool cmpWholeProg) { - microVU* mVU = mVUx; - if (!mVUprogI.isDead && (checkOld == mVUprogI.isOld)) { +_mVUt _f bool mVUcmpProg(int progIndex, const int checkAge, const bool cmpWholeProg) { + microVU* mVU = mVUx; + if (checkAge == mVUprogI.age) { if ((cmpWholeProg && !memcmp_mmx((u8*)mVUprogI.data, mVU->regs->Micro, mVU->microMemSize)) || (!cmpWholeProg && mVUcmpPartial(progIndex))) { mVU->prog.cur = progIndex; mVU->prog.cleared = 0; mVU->prog.isSame = cmpWholeProg ? 1 : -1; - mVU->prog.prog[progIndex].used = 1; - mVU->prog.prog[progIndex].isOld = 0; + mVU->prog.prog[progIndex].used = 1; + mVU->prog.prog[progIndex].age = isYoung; return 1; } } @@ -311,7 +310,11 @@ _mVUt _f int mVUsearchProg() { return 1; // Check Young Programs } for (int i = mVU->prog.max; i >= 0; i--) { - if (mVUcmpProg(mVU->prog.progList[i], 1, 0)) + if (mVUcmpProg(mVU->prog.progList[i], 1, 0)) + return 1; // Check Aged Programs + } + for (int i = mVU->prog.max; i >= 0; i--) { + if (mVUcmpProg(mVU->prog.progList[i], 2, 0)) return 1; // Check Old Programs } mVU->prog.cur = mVUfindLeastUsedProg(); // If cleared and program not found, make a new program instance @@ -319,8 +322,8 @@ _mVUt _f int mVUsearchProg() { mVU->prog.isSame = 1; return 0; } - mVU->prog.prog[mVU->prog.cur].used = 1; - mVU->prog.prog[mVU->prog.cur].isOld = 0; + mVU->prog.prog[mVU->prog.cur].used = 1; + mVU->prog.prog[mVU->prog.cur].age = isYoung; return 1; // If !cleared, then we're still on the same program as last-time ;) } diff --git a/pcsx2/x86/microVU.h b/pcsx2/x86/microVU.h index 26d4300281..cef0b63f9e 100644 --- a/pcsx2/x86/microVU.h +++ b/pcsx2/x86/microVU.h @@ -111,6 +111,13 @@ struct microRange { s32 range[mMaxRanges][2]; }; +enum microProgramAge { + isYoung = 0, + isAged = 1, + isOld = 2, + isDead = 3 +}; + #define mProgSize (0x4000/4) struct microProgram { u32 data [mProgSize]; // Holds a copy of the VU microProgram @@ -118,8 +125,7 @@ struct microProgram { microRange ranges; // The ranges of the microProgram that have already been recompiled u32 frame; // Frame # the program was last used on u32 used; // Program was used this frame? - bool isDead; // Program is Dead? - bool isOld; // Program is Old? (Program hasn't been used in a while) + int age; // Program age... Young, Aged, Old, or Dead... }; #define mMaxProg ((mVU->index)?400:8) // The amount of Micro Programs Recs will 'remember' diff --git a/pcsx2/x86/microVU_Compile.inl b/pcsx2/x86/microVU_Compile.inl index 821b7d51ba..3e1612056c 100644 --- a/pcsx2/x86/microVU_Compile.inl +++ b/pcsx2/x86/microVU_Compile.inl @@ -31,9 +31,36 @@ // Helper Functions //------------------------------------------------------------------ +// Used by checkIfSibling below... +bool cmpSibling(mV, int progIndex) { + if (mVUprogI.age == isDead) return 0; + for (int i = 0; i <= mVUprogI.ranges.total; i++) { + if ((mVUprogI.ranges.range[i][0] < 0) + || (mVUprogI.ranges.range[i][1] < 0)) { DevCon.Error("microVU%d: Negative Range![%d][%d]", mVU->index, i, mVUprogI.ranges.total); } + if (memcmp_mmx(cmpOffset(mVUprogI.data), cmpOffset(mVU->regs->Micro), ((mVUprogI.ranges.range[i][1] + 8) - mVUprogI.ranges.range[i][0]))) { + return 0; + } + } + return 1; +} + +// Since we use partial-program comparisons to search cached microPrograms, +// it is possible that another cached microProgram we have also would've +// passed the comparison check. This function checks how often this happens... +_f void checkIfSibling(mV) { + if (mVU->prog.isSame != -1) return; + for (int i = mVU->prog.max; i >= 0; i--) { + if (i != mVU->prog.cur && cmpSibling(mVU, i)) { + if (mVU->prog.prog[i].block[iPC/2] != NULL) { + DevCon.WriteLn("mVU: microProgram Sibling Detected! [%d][%d]", mVU->prog.cur, i); + } + } + } +} + // Used by mVUsetupRange _f void mVUcheckIsSame(mV) { - + if (0) checkIfSibling(mVU); if (mVU->prog.isSame == -1) { mVU->prog.isSame = !memcmp_mmx((u8*)mVUcurProg.data, mVU->regs->Micro, mVU->microMemSize); } @@ -65,7 +92,7 @@ _f void mVUsetupRange(mV, s32 pc, bool isStartPC) { mVUcurProg.ranges.total = 0; mVUrange[0] = 0; mVUrange[1] = mVU->microMemSize - 8; - DevCon.WriteLn( Color_StrongBlack, "microVU%d: Prog Range List Full", mVU->index); + DevCon.Warning("microVU%d: Prog Range List Full", mVU->index); } } else { @@ -100,7 +127,7 @@ _f void mVUsetupRange(mV, s32 pc, bool isStartPC) { mVUcurProg.ranges.total = 0; mVUrange[0] = 0; mVUrange[1] = mVU->microMemSize - 8; - DevCon.WriteLn( Color_StrongBlack, "microVU%d: Prog Range List Full", mVU->index); + DevCon.Warning("microVU%d: Prog Range List Full", mVU->index); } } } diff --git a/pcsx2/x86/microVU_Misc.h b/pcsx2/x86/microVU_Misc.h index 28d8ec3977..e61713c73d 100644 --- a/pcsx2/x86/microVU_Misc.h +++ b/pcsx2/x86/microVU_Misc.h @@ -196,6 +196,7 @@ typedef u32 (__fastcall *mVUCall)(void*, void*); #define shuffleSS(x) ((x==1)?(0x27):((x==2)?(0xc6):((x==4)?(0xe1):(0xe4)))) #define _1mb (0x100000) #define clampE CHECK_VU_EXTRA_OVERFLOW +#define elif else if // Flag Info #define __Status (mVUregs.needExactMatch & 1)