- Cached Program search is faster/smarter thanks to an idea Jake had to search recently used blocks first.
- Fixed a problem with block searching.
- Minor changes.

git-svn-id: http://pcsx2.googlecode.com/svn/trunk@1203 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
cottonvibes 2009-05-16 08:43:56 +00:00
parent 9d38252d0e
commit 2c3043862d
3 changed files with 47 additions and 35 deletions

View File

@ -53,7 +53,7 @@ microVUt(void) mVUinit(VURegs* vuRegsPtr) {
mVUreset<vuIndex>(); mVUreset<vuIndex>();
} }
// Will Optimize later // Resets Rec Data
microVUt(void) mVUreset() { microVUt(void) mVUreset() {
microVU* mVU = mVUx; microVU* mVU = mVUx;
@ -86,7 +86,6 @@ microVUt(void) mVUreset() {
}*/ }*/
// Program Variables // Program Variables
mVU->prog.finished = 1;
mVU->prog.cleared = 1; mVU->prog.cleared = 1;
mVU->prog.cur = -1; mVU->prog.cur = -1;
mVU->prog.total = -1; mVU->prog.total = -1;
@ -125,8 +124,10 @@ microVUt(void) mVUclose() {
microVUt(void) mVUclear(u32 addr, u32 size) { microVUt(void) mVUclear(u32 addr, u32 size) {
microVU* mVU = mVUx; microVU* mVU = mVUx;
if (!mVU->prog.cleared) {
memset(&mVU->prog.lpState, 0, sizeof(mVU->prog.lpState)); memset(&mVU->prog.lpState, 0, sizeof(mVU->prog.lpState));
mVU->prog.cleared = 1; // Next execution searches/creates a new microprogram mVU->prog.cleared = 1; // Next execution searches/creates a new microprogram
}
} }
//------------------------------------------------------------------ //------------------------------------------------------------------
@ -198,30 +199,36 @@ microVUt(int) mVUfindLeastUsedProg() {
microVUt(void) __mVUvsyncUpdate() { microVUt(void) __mVUvsyncUpdate() {
microVU* mVU = mVUx; microVU* mVU = mVUx;
if (mVU->prog.total < mVU->prog.max) return; if (mVU->prog.total < mVU->prog.max) return;
for (int i = 0; i <= mVU->prog.total; i++) { for (int i = 0; i <= mVU->prog.total; i++) {
if( mVU->prog.prog[i].last_used != 0 ) if (mVU->prog.prog[i].last_used != 0) {
{ if (mVU->prog.prog[i].last_used >= 3) {
if( mVU->prog.prog[i].last_used >= 3 )
{ if (mVU->prog.prog[i].used < 0x4fffffff) // program has been used recently. Give it a
// program has been used recently. Give it's program execution counter a mVU->prog.prog[i].used += 0x200; // 'weighted' bonus signifying it's importance
// 'weighted' bonus signifying it's importance:
if( mVU->prog.prog[i].used < 0x4fffffff )
mVU->prog.prog[i].used += 0x200;
} }
mVU->prog.prog[i].last_used--; mVU->prog.prog[i].last_used--;
} }
else else mVU->prog.prog[i].used /= 2; // penalize unused programs.
mVU->prog.prog[i].used /= 2; // penalize unused programs.
} }
} }
void mVUvsyncUpdate() microVUt(int) mVUcmpProg(int progIndex, bool progUsed, bool needOverflowCheck) {
{ microVU* mVU = mVUx;
__mVUvsyncUpdate<0>();
__mVUvsyncUpdate<1>(); if (progUsed) {
if (!memcmp_mmx(mVU->prog.prog[progIndex].data, mVU->regs->Micro, mVU->microSize)) {
mVU->prog.cur = progIndex;
mVU->prog.cleared = 0;
mVU->prog.prog[progIndex].last_used = 3;
if (!needOverflowCheck || mVU->prog.prog[progIndex].used < 0x7fffffff) {
mVU->prog.prog[progIndex].used++; // increment 'used' (avoiding overflows if necessary)
}
return 1;
}
}
return 0;
} }
// Searches for Cached Micro Program and sets prog.cur to it (returns 1 if program found, else returns 0) // Searches for Cached Micro Program and sets prog.cur to it (returns 1 if program found, else returns 0)
@ -230,15 +237,12 @@ microVUt(int) mVUsearchProg() {
if (mVU->prog.cleared) { // If cleared, we need to search for new program if (mVU->prog.cleared) { // If cleared, we need to search for new program
for (int i = 0; i <= mVU->prog.total; i++) { for (int i = 0; i <= mVU->prog.total; i++) {
if (!memcmp_mmx(mVU->prog.prog[i].data, mVU->regs->Micro, mVU->microSize)) { if (mVUcmpProg<vuIndex>(i, !!mVU->prog.prog[i].used, 1))
mVU->prog.cur = i; return 1; // Check Recently Used Programs
mVU->prog.cleared = 0;
if( mVU->prog.prog[i].used < 0x7fffffff ) // avoid overflows on well-used programs
mVU->prog.prog[i].used++;
mVU->prog.prog[i].last_used = 3; // add me to the mVU structs
return 1;
} }
for (int i = 0; i <= mVU->prog.total; i++) {
if (mVUcmpProg<vuIndex>(i, !mVU->prog.prog[i].used, 0))
return 1; // Check Older Programs
} }
mVU->prog.cur = mVUfindLeastUsedProg<vuIndex>(); // If cleared and program not found, make a new program instance mVU->prog.cur = mVUfindLeastUsedProg<vuIndex>(); // If cleared and program not found, make a new program instance
mVU->prog.cleared = 0; mVU->prog.cleared = 0;
@ -297,4 +301,9 @@ void runVUrec(u32 startPC, u32 cycles, const int vuIndex) {
else startVU1(startPC, cycles); else startVU1(startPC, cycles);
} }
void mVUvsyncUpdate() {
__mVUvsyncUpdate<0>();
__mVUvsyncUpdate<1>();
}
#endif // PCSX2_MICROVU #endif // PCSX2_MICROVU

View File

@ -27,7 +27,7 @@
#include "microVU_Alloc.h" #include "microVU_Alloc.h"
#include "microVU_Misc.h" #include "microVU_Misc.h"
#define mMaxBlocks 32 // Max Blocks With Different Pipeline States (For n = 1, 2, 4, 8, 16, etc...) #define mMaxBlocks 32 // Max Blocks With Different Pipeline States
class microBlockManager { class microBlockManager {
private: private:
static const int MaxBlocks = mMaxBlocks - 1; static const int MaxBlocks = mMaxBlocks - 1;
@ -42,7 +42,7 @@ public:
microBlock* thisBlock = search(&pBlock->pState); microBlock* thisBlock = search(&pBlock->pState);
if (!thisBlock) { if (!thisBlock) {
listSize++; listSize++;
if (listSize > MaxBlocks) { Console::Error("microVU Warning: Block List Overflow"); listSize &= MaxBlocks; } if (listSize > MaxBlocks) { Console::Error("microVU Warning: Block List Overflow"); listSize = 0; }
memcpy_fast(&blockList[listSize], pBlock, sizeof(microBlock)); memcpy_fast(&blockList[listSize], pBlock, sizeof(microBlock));
thisBlock = &blockList[listSize]; thisBlock = &blockList[listSize];
} }
@ -57,8 +57,10 @@ public:
} }
else { // Can do Simple Search (Only Matches the Important Pipeline Stuff) else { // Can do Simple Search (Only Matches the Important Pipeline Stuff)
for (int i = 0; i <= listSize; i++) { for (int i = 0; i <= listSize; i++) {
if ((blockList[i].pState.q == pState->q) && (blockList[i].pState.p == pState->p) if ((blockList[i].pState.q == pState->q)
&& (blockList[i].pState.flags == pState->flags)) { return &blockList[i]; } && (blockList[i].pState.p == pState->p)
&& (blockList[i].pState.flags == pState->flags)
&& !(blockList[i].pState.needExactMatch & 0xf0f)) { return &blockList[i]; }
} }
} }
return NULL; return NULL;
@ -69,8 +71,9 @@ template<u32 progSize> // progSize = VU program memory size / 4
struct microProgram { struct microProgram {
u32 data[progSize]; u32 data[progSize];
u32 used; // Number of times its been used u32 used; // Number of times its been used
u32 last_used; // counters # of frames since last use (starts at 3 and counts backwards to 0 for each 30fps vsync) u32 last_used; // Counters # of frames since last use (starts at 3 and counts backwards to 0 for each 30fps vSync)
u32 sFlagHack; // Optimize out Status Flag Updates if Program doesn't use Status Flags u32 sFlagHack; // Optimize out Status Flag Updates if Program doesn't use Status Flags
s32 range[2]; // The range of microMemory that has already been recompiled for the current program
u8* x86ptr; // Pointer to program's recompilation code u8* x86ptr; // Pointer to program's recompilation code
u8* x86start; // Start of program's rec-cache u8* x86start; // Start of program's rec-cache
u8* x86end; // Limit of program's rec-cache u8* x86end; // Limit of program's rec-cache
@ -85,8 +88,8 @@ struct microProgManager {
static const int max = mMaxProg - 1; static const int max = mMaxProg - 1;
int cur; // Index to Current MicroProgram thats running (-1 = uncached) int cur; // Index to Current MicroProgram thats running (-1 = uncached)
int total; // Total Number of valid MicroPrograms minus 1 int total; // Total Number of valid MicroPrograms minus 1
int isSame; // Current cached microProgram is Exact Same program as mVU->regs->Micro
int cleared; // Micro Program is Indeterminate so must be searched for (and if no matches are found then recompile a new one) int cleared; // Micro Program is Indeterminate so must be searched for (and if no matches are found then recompile a new one)
int finished; // Completed MicroProgram by E-bit Termination
microRegInfo lpState; // Pipeline state from where program left off (useful for continuing execution) microRegInfo lpState; // Pipeline state from where program left off (useful for continuing execution)
}; };

View File

@ -108,7 +108,7 @@ microVUt(void) mVUdispatcherB() {
if (isMMX(1)) EMMS(); if (isMMX(1)) EMMS();
RET(); RET();
mVUcacheCheck(x86Ptr, mVU->cache, 512); mVUcacheCheck(x86Ptr, mVU->cache, 0x1000);
} }
//------------------------------------------------------------------ //------------------------------------------------------------------