diff --git a/pcsx2/x86/microVU.cpp b/pcsx2/x86/microVU.cpp index 9af86584df..6ca9dfb8b6 100644 --- a/pcsx2/x86/microVU.cpp +++ b/pcsx2/x86/microVU.cpp @@ -34,8 +34,9 @@ microVU microVU1; //------------------------------------------------------------------ // Only run this once! ;) -__forceinline void mVUinit(microVU* mVU, VURegs* vuRegsPtr, const int vuIndex) { +microVUt(void) mVUinit(VURegs* vuRegsPtr) { + microVU* mVU = mVUx; mVU->regs = vuRegsPtr; mVU->index = vuIndex; mVU->microSize = (vuIndex ? 0x4000 : 0x1000); @@ -43,13 +44,14 @@ __forceinline void mVUinit(microVU* mVU, VURegs* vuRegsPtr, const int vuIndex) { mVU->cacheAddr = 0xC0000000 + (vuIndex ? mVU->cacheSize : 0); mVU->cache = NULL; - mVUreset(mVU); + mVUreset(); } // Will Optimize later -__forceinline void mVUreset(microVU* mVU) { +microVUt(void) mVUreset() { - mVUclose(mVU); // Close + microVU* mVU = mVUx; + mVUclose(); // Close // Create Block Managers for (int i; i <= mVU->prog.max; i++) { @@ -71,7 +73,9 @@ __forceinline void mVUreset(microVU* mVU) { } // Free Allocated Resources -__forceinline void mVUclose(microVU* mVU) { +microVUt(void) mVUclose() { + + microVU* mVU = mVUx; if ( mVU->cache ) { SysMunmap( mVU->cache, mVU->cacheSize ); mVU->cache = NULL; } @@ -83,16 +87,16 @@ __forceinline void mVUclose(microVU* mVU) { } } -// Clears Block Data in specified range (Caches current microProgram if a difference has been found) -__forceinline void mVUclear(microVU* mVU, u32 addr, u32 size) { +// Clears Block Data in specified range +microVUt(void) mVUclear(u32 addr, u32 size) { + microVU* mVU = mVUx; int i = addr/8; int end = i+((size+(8-(size&7)))/8); // ToDo: Can be simplified to addr+size if Size is always a multiple of 8 if (!mVU->prog.cleared) { for ( ; i < end; i++) { if ( mVU->prog.prog[mVU->prog.cur].block[i]->clear() ) { - mVUcacheProg(mVU); mVU->prog.cleared = 1; i++; break; @@ -105,8 +109,9 @@ __forceinline void mVUclear(microVU* mVU, u32 addr, u32 size) { } // Executes for number of cycles -void* __fastcall mVUexecuteVU0(u32 startPC, u32 cycles) { -/* Pseudocode: (ToDo: implement # of cycles) +microVUt(void*) __fastcall mVUexecute(u32 startPC, u32 cycles) { +/* + Pseudocode: (ToDo: implement # of cycles) 1) Search for existing program 2) If program not found, goto 5 3) Search for recompiled block @@ -114,38 +119,44 @@ void* __fastcall mVUexecuteVU0(u32 startPC, u32 cycles) { 5) Recompile as much blocks as possible 6) Return start execution address of block */ - if ( mVUsearchProg(µVU0) ) { // Found Program - microBlock* block = microVU0.prog.prog[microVU0.prog.cur].block[startPC]->search(microVU0.prog.lastPipelineState); + microVU* mVU = mVUx; + if ( mVUsearchProg(mVU) ) { // Found Program + microBlock* block = mVU->prog.prog[mVU->prog.cur].block[startPC]->search(mVU->prog.lastPipelineState); if (block) return block->x86ptrStart; } // Recompile code return NULL; } + +void* __fastcall mVUexecuteVU0(u32 startPC, u32 cycles) { + return mVUexecute<0>(startPC, cycles); +} void* __fastcall mVUexecuteVU1(u32 startPC, u32 cycles) { - return NULL; + return mVUexecute<1>(startPC, cycles); } -/* -// Executes till finished -void* mVUexecuteF(microVU* mVU, u32 startPC) { - //if (!mProg.finished) { - // runMicroProgram(startPC); - //} - //if (mProg.cleared && !mProg.finished) { - - //} - return NULL; -} -*/ - //------------------------------------------------------------------ // Micro VU - Private Functions //------------------------------------------------------------------ -// Finds the least used program +// Clears program data (Sets used to 1 because calling this function implies the program will be used at least once) +__forceinline void mVUclearProg(microVU* mVU, int progIndex) { + mVU->prog.prog[progIndex].used = 1; + for (u32 i = 0; i < mVU->progSize; i++) { + mVU->prog.prog[progIndex].block[i]->reset(); + } +} + +// Caches Micro Program +__forceinline void mVUcacheProg(microVU* mVU, int progIndex) { + memcpy_fast(mVU->prog.prog[progIndex].data, mVU->regs->Micro, mVU->microSize); +} + +// Finds the least used program, (if program list full clears and returns an old program; if not-full, returns free program) __forceinline int mVUfindLeastUsedProg(microVU* mVU) { if (mVU->prog.total < mVU->prog.max) { mVU->prog.total++; + mVUcacheProg(mVU, mVU->prog.total); // Cache Micro Program return mVU->prog.total; } else { @@ -157,35 +168,30 @@ __forceinline int mVUfindLeastUsedProg(microVU* mVU) { j = i; } } + mVUclearProg(mVU, j); // Clear old data if overwriting old program + mVUcacheProg(mVU, j); // Cache Micro Program return j; } } -// Caches Micro Program if appropriate -__forceinline void mVUcacheProg(microVU* mVU) { - if (!mVU->prog.prog[mVU->prog.cur].cached) { // If uncached, then cache - memcpy_fast(mVU->prog.prog[mVU->prog.cur].data, mVU->regs->Micro, mVU->microSize); - mVU->prog.prog[mVU->prog.cur].cached = 1; - } -} - // Searches for Cached Micro Program and sets prog.cur to it (returns 1 if program found, else returns 0) __forceinline int mVUsearchProg(microVU* mVU) { if (mVU->prog.cleared) { // If cleared, we need to search for new program for (int i = 0; i <= mVU->prog.total; i++) { if (i == mVU->prog.cur) continue; // We can skip the current program. - if (mVU->prog.prog[i].cached) { - if (!memcmp_mmx(mVU->prog.prog[i].data, mVU->regs->Micro, mVU->microSize)) { - mVU->prog.cur = i; - return 1; - } + if (!memcmp_mmx(mVU->prog.prog[i].data, mVU->regs->Micro, mVU->microSize)) { + mVU->prog.cur = i; + mVU->prog.cleared = 0; + mVU->prog.prog[i].used++; + return 1; } } - mVU->prog.cur = mVUfindLeastUsedProg(mVU); // If cleared and program not cached, make a new program instance - // ToDo: Clear old data if overwriting old program + mVU->prog.cur = mVUfindLeastUsedProg(mVU); // If cleared and program not found, make a new program instance + mVU->prog.cleared = 0; return 0; } - else return 1; // If !cleared, then we're still on the same program as last-time ;) + mVU->prog.prog[mVU->prog.cur].used++; + return 1; // If !cleared, then we're still on the same program as last-time ;) } //------------------------------------------------------------------ @@ -249,29 +255,29 @@ __declspec(naked) void __fastcall endVU0(u32 startPC, u32 cycles) { // Wrapper Functions - Called by other parts of the Emu //------------------------------------------------------------------ -__forceinline void initVUrec(VURegs* vuRegs, int vuIndex) { - if (!vuIndex) mVUinit(µVU0, vuRegs, 0); - else mVUinit(µVU1, vuRegs, 1); +__forceinline void initVUrec(VURegs* vuRegs, const int vuIndex) { + if (!vuIndex) mVUinit<0>(vuRegs); + else mVUinit<1>(vuRegs); } -__forceinline void closeVUrec(int vuIndex) { - if (!vuIndex) mVUclose(µVU0); - else mVUclose(µVU1); +__forceinline void closeVUrec(const int vuIndex) { + if (!vuIndex) mVUclose<0>(); + else mVUclose<1>(); } -__forceinline void resetVUrec(int vuIndex) { - if (!vuIndex) mVUreset(µVU0); - else mVUreset(µVU1); +__forceinline void resetVUrec(const int vuIndex) { + if (!vuIndex) mVUreset<0>(); + else mVUreset<1>(); } -__forceinline void clearVUrec(u32 addr, u32 size, int vuIndex) { - if (!vuIndex) mVUclear(µVU0, addr, size); - else mVUclear(µVU1, addr, size); +__forceinline void clearVUrec(u32 addr, u32 size, const int vuIndex) { + if (!vuIndex) mVUclear<0>(addr, size); + else mVUclear<1>(addr, size); } -__forceinline void runVUrec(u32 startPC, u32 cycles, int vuIndex) { - if (!vuIndex) startVU0(startPC, cycles); - else startVU1(startPC, cycles); +__forceinline void runVUrec(u32 startPC, u32 cycles, const int vuIndex) { + if (!vuIndex) startVU0(startPC, cycles); + else startVU1(startPC, cycles); } #endif // PCSX2_MICROVU diff --git a/pcsx2/x86/microVU.h b/pcsx2/x86/microVU.h index 5244c8000b..541581018a 100644 --- a/pcsx2/x86/microVU.h +++ b/pcsx2/x86/microVU.h @@ -47,8 +47,10 @@ public: void init() { listSize = -1; callerSize = -1; - ZeroMemory(&blockList, sizeof(blockList)); // Can be Omitted? + //ZeroMemory(&blockList, sizeof(blockList)); // Can be Omitted? + //ZeroMemory(&blockList, sizeof(callersList)); // Can be Omitted? } + void reset() { init(); }; void close() {}; // Can be Omitted? void add(u32 pipelineState, u8* x86ptrStart) { if (!search(pipelineState)) { @@ -67,7 +69,7 @@ public: void clearFast() { listSize = -1; for ( ; callerSize >= 0; callerSize--) { - //callerList[callerSize]. // Implement Branch Link Removal Code + //callerList[callerSize]. // ToDo: Implement Branch Link Removal Code } } int clear() { @@ -80,7 +82,7 @@ template struct microProgram { u8 data[progSize]; u32 used; // Number of times its been used - int cached; // Has been Cached? + //int cached; // Has been Cached? (can be omitted because every new program will be cached?) microBlockManager* block[progSize]; }; @@ -92,7 +94,7 @@ struct microProgManager { int cur; // Index to Current MicroProgram thats running (-1 = uncached) int total; // Total Number of valid MicroPrograms minus 1 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 to E-bit Termination + int finished; // Completed MicroProgram by E-bit Termination u32 lastPipelineState; // Pipeline state from where it left off (useful for continuing execution) }; @@ -119,18 +121,23 @@ struct microVU { microProgManager<0x800> prog; // Micro Program Data }; +// Template Stuff +#define mVUx (vuIndex ? µVU1 : µVU0) +#define microVUt(aType) template __forceinline aType + // Opcode Tables extern void (*mVU_UPPER_OPCODE[64])( VURegs* VU, s32 info ); extern void (*mVU_LOWER_OPCODE[128])( VURegs* VU, s32 info ); //void invalidateBlocks(u32 addr, u32 size); // Invalidates Blocks in the range [addr, addr+size) -__forceinline void mVUinit(microVU* mVU, VURegs* vuRegsPtr, const int vuIndex); -__forceinline void mVUreset(microVU* mVU); -__forceinline void mVUclose(microVU* mVU); -__forceinline void mVUclear(microVU* mVU, u32 addr, u32 size); // Clears part of a Micro Program (must use before modifying micro program!) +//__forceinline void mVUinit(microVU* mVU, VURegs* vuRegsPtr, const int vuIndex); +//__forceinline void mVUreset(microVU* mVU); +//__forceinline void mVUclose(microVU* mVU); +//__forceinline void mVUclear(microVU* mVU, u32 addr, u32 size); // Clears part of a Micro Program (must use before modifying micro program!) //void* mVUexecute(microVU* mVU, u32 startPC, u32 cycles); // Recompiles/Executes code for the number of cycles indicated (will always run for >= 'cycles' amount unless 'finished') //void* mVUexecuteF(microVU* mVU, u32 startPC); // Recompiles/Executes code till finished -__forceinline int mVUfindLeastUsedProg(microVU* mVU); -__forceinline int mVUsearchProg(microVU* mVU); -__forceinline void mVUcacheProg(microVU* mVU); +__forceinline void mVUclearProg(microVU* mVU, int progIndex); +__forceinline int mVUfindLeastUsedProg(microVU* mVU); +__forceinline int mVUsearchProg(microVU* mVU); +__forceinline void mVUcacheProg(microVU* mVU, int progIndex);