mirror of https://github.com/PCSX2/pcsx2.git
microVU:
- 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:
parent
9d38252d0e
commit
2c3043862d
|
@ -53,7 +53,7 @@ microVUt(void) mVUinit(VURegs* vuRegsPtr) {
|
|||
mVUreset<vuIndex>();
|
||||
}
|
||||
|
||||
// Will Optimize later
|
||||
// Resets Rec Data
|
||||
microVUt(void) mVUreset() {
|
||||
|
||||
microVU* mVU = mVUx;
|
||||
|
@ -86,7 +86,6 @@ microVUt(void) mVUreset() {
|
|||
}*/
|
||||
|
||||
// Program Variables
|
||||
mVU->prog.finished = 1;
|
||||
mVU->prog.cleared = 1;
|
||||
mVU->prog.cur = -1;
|
||||
mVU->prog.total = -1;
|
||||
|
@ -125,8 +124,10 @@ microVUt(void) mVUclose() {
|
|||
microVUt(void) mVUclear(u32 addr, u32 size) {
|
||||
|
||||
microVU* mVU = mVUx;
|
||||
memset(&mVU->prog.lpState, 0, sizeof(mVU->prog.lpState));
|
||||
mVU->prog.cleared = 1; // Next execution searches/creates a new microprogram
|
||||
if (!mVU->prog.cleared) {
|
||||
memset(&mVU->prog.lpState, 0, sizeof(mVU->prog.lpState));
|
||||
mVU->prog.cleared = 1; // Next execution searches/creates a new microprogram
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------
|
||||
|
@ -198,30 +199,36 @@ microVUt(int) mVUfindLeastUsedProg() {
|
|||
microVUt(void) __mVUvsyncUpdate() {
|
||||
|
||||
microVU* mVU = mVUx;
|
||||
|
||||
if (mVU->prog.total < mVU->prog.max) return;
|
||||
|
||||
for (int i = 0; i <= mVU->prog.total; i++) {
|
||||
if( mVU->prog.prog[i].last_used != 0 )
|
||||
{
|
||||
if( mVU->prog.prog[i].last_used >= 3 )
|
||||
{
|
||||
// program has been used recently. Give it's program execution counter a
|
||||
// 'weighted' bonus signifying it's importance:
|
||||
if( mVU->prog.prog[i].used < 0x4fffffff )
|
||||
mVU->prog.prog[i].used += 0x200;
|
||||
if (mVU->prog.prog[i].last_used != 0) {
|
||||
if (mVU->prog.prog[i].last_used >= 3) {
|
||||
|
||||
if (mVU->prog.prog[i].used < 0x4fffffff) // program has been used recently. Give it a
|
||||
mVU->prog.prog[i].used += 0x200; // 'weighted' bonus signifying it's importance
|
||||
}
|
||||
mVU->prog.prog[i].last_used--;
|
||||
}
|
||||
else
|
||||
mVU->prog.prog[i].used /= 2; // penalize unused programs.
|
||||
else mVU->prog.prog[i].used /= 2; // penalize unused programs.
|
||||
}
|
||||
}
|
||||
|
||||
void mVUvsyncUpdate()
|
||||
{
|
||||
__mVUvsyncUpdate<0>();
|
||||
__mVUvsyncUpdate<1>();
|
||||
microVUt(int) mVUcmpProg(int progIndex, bool progUsed, bool needOverflowCheck) {
|
||||
microVU* mVU = mVUx;
|
||||
|
||||
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)
|
||||
|
@ -230,15 +237,12 @@ microVUt(int) mVUsearchProg() {
|
|||
|
||||
if (mVU->prog.cleared) { // If cleared, we need to search for new program
|
||||
for (int i = 0; i <= mVU->prog.total; i++) {
|
||||
if (!memcmp_mmx(mVU->prog.prog[i].data, mVU->regs->Micro, mVU->microSize)) {
|
||||
mVU->prog.cur = i;
|
||||
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;
|
||||
}
|
||||
if (mVUcmpProg<vuIndex>(i, !!mVU->prog.prog[i].used, 1))
|
||||
return 1; // Check Recently Used Programs
|
||||
}
|
||||
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.cleared = 0;
|
||||
|
@ -297,4 +301,9 @@ void runVUrec(u32 startPC, u32 cycles, const int vuIndex) {
|
|||
else startVU1(startPC, cycles);
|
||||
}
|
||||
|
||||
void mVUvsyncUpdate() {
|
||||
__mVUvsyncUpdate<0>();
|
||||
__mVUvsyncUpdate<1>();
|
||||
}
|
||||
|
||||
#endif // PCSX2_MICROVU
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
#include "microVU_Alloc.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 {
|
||||
private:
|
||||
static const int MaxBlocks = mMaxBlocks - 1;
|
||||
|
@ -42,7 +42,7 @@ public:
|
|||
microBlock* thisBlock = search(&pBlock->pState);
|
||||
if (!thisBlock) {
|
||||
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));
|
||||
thisBlock = &blockList[listSize];
|
||||
}
|
||||
|
@ -57,8 +57,10 @@ public:
|
|||
}
|
||||
else { // Can do Simple Search (Only Matches the Important Pipeline Stuff)
|
||||
for (int i = 0; i <= listSize; i++) {
|
||||
if ((blockList[i].pState.q == pState->q) && (blockList[i].pState.p == pState->p)
|
||||
&& (blockList[i].pState.flags == pState->flags)) { return &blockList[i]; }
|
||||
if ((blockList[i].pState.q == pState->q)
|
||||
&& (blockList[i].pState.p == pState->p)
|
||||
&& (blockList[i].pState.flags == pState->flags)
|
||||
&& !(blockList[i].pState.needExactMatch & 0xf0f)) { return &blockList[i]; }
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
|
@ -69,8 +71,9 @@ template<u32 progSize> // progSize = VU program memory size / 4
|
|||
struct microProgram {
|
||||
u32 data[progSize];
|
||||
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
|
||||
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* x86start; // Start 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;
|
||||
int cur; // Index to Current MicroProgram thats running (-1 = uncached)
|
||||
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 finished; // Completed MicroProgram by E-bit Termination
|
||||
microRegInfo lpState; // Pipeline state from where program left off (useful for continuing execution)
|
||||
};
|
||||
|
||||
|
|
|
@ -108,7 +108,7 @@ microVUt(void) mVUdispatcherB() {
|
|||
if (isMMX(1)) EMMS();
|
||||
RET();
|
||||
|
||||
mVUcacheCheck(x86Ptr, mVU->cache, 512);
|
||||
mVUcacheCheck(x86Ptr, mVU->cache, 0x1000);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------
|
||||
|
|
Loading…
Reference in New Issue