From 2f186e647e45e5c9da825db26ef5cc5e4421046d Mon Sep 17 00:00:00 2001 From: cottonvibes Date: Sat, 20 Jun 2009 03:45:44 +0000 Subject: [PATCH] microVU: minor changes git-svn-id: http://pcsx2.googlecode.com/svn/trunk@1407 96395faa-99c1-11dd-bbfe-3dabce05a288 --- pcsx2/x86/microVU.cpp | 268 ++++------------------------------ pcsx2/x86/microVU.h | 14 +- pcsx2/x86/microVU_Compile.inl | 186 +++++++++++++++++++++++ pcsx2/x86/microVU_Log.inl | 2 +- pcsx2/x86/microVU_Misc.h | 7 +- 5 files changed, 223 insertions(+), 254 deletions(-) diff --git a/pcsx2/x86/microVU.cpp b/pcsx2/x86/microVU.cpp index b56e266f1b..d6198eebee 100644 --- a/pcsx2/x86/microVU.cpp +++ b/pcsx2/x86/microVU.cpp @@ -35,15 +35,16 @@ declareAllVariables // Declares All Global Variables :D //------------------------------------------------------------------ // Only run this once per VU! ;) -microVUf(void) mVUinit(VURegs* vuRegsPtr) { +microVUt(void) mVUinit(VURegs* vuRegsPtr, int vuIndex) { - microVU* mVU = mVUx; - mVU->regs = vuRegsPtr; - mVU->index = vuIndex; - mVU->microMemSize = (vuIndex ? 0x4000 : 0x1000); - mVU->progMemSize = (vuIndex ? 0x4000 : 0x1000) / 4; - mVU->cache = NULL; - mVU->cacheSize = mVUcacheSize; + microVU* mVU = mVUx; + mVU->regs = vuRegsPtr; + mVU->index = vuIndex; + mVU->vuMemSize = (vuIndex ? 0x4000 : 0x1000); + mVU->microMemSize = (vuIndex ? 0x4000 : 0x1000); + mVU->progSize = (vuIndex ? 0x4000 : 0x1000) / 4; + mVU->cache = NULL; + mVU->cacheSize = mVUcacheSize; memset(&mVU->prog, 0, sizeof(mVU->prog)); mVUprint((vuIndex) ? "microVU1: init" : "microVU0: init"); @@ -51,18 +52,17 @@ microVUf(void) mVUinit(VURegs* vuRegsPtr) { if ( mVU->cache == NULL ) throw Exception::OutOfMemory(fmt_string( "microVU Error: Failed to allocate recompiler memory! (addr: 0x%x)", (u32)mVU->cache)); mVUemitSearch(); - mVUreset(); + mVUreset(mVU); } // Resets Rec Data -microVUx(void) mVUreset() { +microVUt(void) mVUreset(mV) { - microVU* mVU = mVUx; - mVUprint((vuIndex) ? "microVU1: reset" : "microVU0: reset"); + mVUprint((mVU->index) ? "microVU1: reset" : "microVU0: reset"); // Delete Block Managers for (int i = 0; i <= mVU->prog.max; i++) { - for (u32 j = 0; j < (mVU->progMemSize / 2); j++) { + for (u32 j = 0; j < (mVU->progSize / 2); j++) { microBlockManager::Delete( mVU->prog.prog[i].block[j] ); } } @@ -99,16 +99,15 @@ microVUx(void) mVUreset() { } // Free Allocated Resources -microVUf(void) mVUclose() { +microVUt(void) mVUclose(mV) { - microVU* mVU = mVUx; - mVUprint((vuIndex) ? "microVU1: close" : "microVU0: close"); + mVUprint((mVU->index) ? "microVU1: close" : "microVU0: close"); - if ( mVU->cache ) { HostSys::Munmap( mVU->cache, mVU->cacheSize ); mVU->cache = NULL; } + if (mVU->cache) { HostSys::Munmap(mVU->cache, mVU->cacheSize); mVU->cache = NULL; } // Delete Block Managers for (int i = 0; i <= mVU->prog.max; i++) { - for (u32 j = 0; j < (mVU->progMemSize / 2); j++) { + for (u32 j = 0; j < (mVU->progSize / 2); j++) { if (mVU->prog.prog[i].block[j]) { microBlockManager::Delete( mVU->prog.prog[i].block[j] ); } @@ -117,8 +116,7 @@ microVUf(void) mVUclose() { } // Clears Block Data in specified range -microVUf(void) mVUclear(u32 addr, u32 size) { - microVU* mVU = mVUx; +microVUt(void) mVUclear(mV, u32 addr, u32 size) { if (!mVU->prog.cleared) { memset(&mVU->prog.lpState, 0, sizeof(mVU->prog.lpState)); mVU->prog.cleared = 1; // Next execution searches/creates a new microprogram @@ -137,7 +135,7 @@ microVUf(void) mVUclearProg(int progIndex) { mVU->prog.prog[progIndex].range[0] = -1; mVU->prog.prog[progIndex].range[1] = -1; mVU->prog.prog[progIndex].x86ptr = mVU->prog.prog[progIndex].x86start; - for (u32 i = 0; i < (mVU->progMemSize / 2); i++) { + for (u32 i = 0; i < (mVU->progSize / 2); i++) { if (mVU->prog.prog[progIndex].block[i]) mVU->prog.prog[progIndex].block[i]->reset(); } @@ -191,9 +189,8 @@ microVUf(int) mVUfindLeastUsedProg() { // frame-based decrementing system in combination with a program-execution-based incrementing // system. In english: if last_used >= 2 it means the program has been used for the current // or prev frame. if it's 0, the program hasn't been used for a while. -microVUf(void) mVUvsyncUpdate() { +microVUt(void) mVUvsyncUpdate(mV) { - microVU* mVU = mVUx; if (mVU->prog.total < mVU->prog.max) return; for (int i = 0; i <= mVU->prog.total; i++) { @@ -252,232 +249,17 @@ microVUf(int) mVUsearchProg() { return 1; // If !cleared, then we're still on the same program as last-time ;) } -//------------------------------------------------------------------ -// JIT recompiler -- called from recompiled code when register jumps are made. -//------------------------------------------------------------------ - -microVUf(void*) __fastcall mVUcompileJIT(u32 startPC, uptr pState) { - - return mVUblockFetch( mVUx, startPC, pState ); -} - -//------------------------------------------------------------------ -// Recompiler -//------------------------------------------------------------------ - -static void* __fastcall mVUcompile( microVU* mVU, u32 startPC, uptr pState ) -{ - using namespace x86Emitter; - - // Setup Program Bounds/Range - mVUsetupRange(mVU, startPC); - - microBlock* pBlock = NULL; - u8* thisPtr = x86Ptr; - - const u32 microSizeDiv8 = (mVU->microMemSize-1) / 8; - - // First Pass - iPC = startPC / 4; - setCode(); - mVUbranch = 0; - mVUstartPC = iPC; - mVUcount = 0; - mVUcycles = 0; // Skips "M" phase, and starts counting cycles at "T" stage - mVU->p = 0; // All blocks start at p index #0 - mVU->q = 0; // All blocks start at q index #0 - memcpy_fast(&mVUregs, (microRegInfo*)pState, sizeof(microRegInfo)); // Loads up Pipeline State Info - mVUblock.x86ptrStart = thisPtr; - pBlock = mVUblocks[startPC/8]->add(&mVUblock); // Add this block to block manager - mVUpBlock = pBlock; - mVUregs.flags = 0; - mVUflagInfo = 0; - mVUsFlagHack = CHECK_VU_FLAGHACK; - - for (int branch = 0; mVUcount < microSizeDiv8; ) { - incPC(1); - startLoop(); - mVUincCycles(mVU, 1); - mVUopU(mVU, 0); - if (curI & _Ebit_) { branch = 1; mVUup.eBit = 1; } - if (curI & _DTbit_) { branch = 4; } - if (curI & _Mbit_) { mVUup.mBit = 1; } - if (curI & _Ibit_) { mVUlow.isNOP = 1; mVUup.iBit = 1; } - else { incPC(-1); mVUopL(mVU, 0); incPC(1); } - mVUsetCycles(mVU); - mVUinfo.readQ = mVU->q; - mVUinfo.writeQ = !mVU->q; - mVUinfo.readP = mVU->p; - mVUinfo.writeP = !mVU->p; - if (branch >= 2) { mVUinfo.isEOB = 1; if (branch == 3) { mVUinfo.isBdelay = 1; } mVUcount++; branchWarning(); break; } - else if (branch == 1) { branch = 2; } - if (mVUbranch) { mVUsetFlagInfo(mVU); branch = 3; mVUbranch = 0; } - incPC(1); - mVUcount++; - } - - // Sets Up Flag instances - int xStatus[4], xMac[4], xClip[4]; - int xCycles = mVUsetFlags(mVU, xStatus, xMac, xClip); - mVUtestCycles(mVU); - - // Second Pass - iPC = mVUstartPC; - setCode(); - mVUbranch = 0; - uint x; - for (x = 0; x < microSizeDiv8; x++) { - if (mVUinfo.isEOB) { x = 0xffff; } - if (mVUup.mBit) { OR32ItoM((uptr)&mVU->regs->flags, VUFLAG_MFLAGSET); } - if (mVUlow.isNOP) { incPC(1); doUpperOp(); doIbit(); } - else if (!mVUinfo.swapOps) { incPC(1); doUpperOp(); doLowerOp(); } - else { doSwapOp(); } - if (mVUinfo.doXGKICK) { mVU_XGKICK_DELAY(mVU, 1); } - - if (!mVUinfo.isBdelay) { incPC(1); } - else { - microBlock* bBlock = NULL; - s32* ajmp = 0; - mVUsetupRange(mVU, xPC); - mVUdebugNOW(1); - - switch (mVUbranch) { - case 3: branchCase(Jcc_Equal); // IBEQ - case 4: branchCase(Jcc_GreaterOrEqual); // IBGEZ - case 5: branchCase(Jcc_Greater); // IBGTZ - case 6: branchCase(Jcc_LessOrEqual); // IBLEQ - case 7: branchCase(Jcc_Less); // IBLTZ - case 8: branchCase(Jcc_NotEqual); // IBNEQ - case 1: case 2: // B/BAL - - mVUprint("mVUcompile B/BAL"); - incPC(-3); // Go back to branch opcode (to get branch imm addr) - - if (mVUup.eBit) { iPC = branchAddr/4; mVUendProgram(mVU, 1, xStatus, xMac, xClip); } // E-bit Branch - mVUsetupBranch(mVU, xStatus, xMac, xClip, xCycles); - - if (mVUblocks[branchAddr/8] == NULL) - mVUblocks[branchAddr/8] = microBlockManager::AlignedNew(); - - // Check if branch-block has already been compiled - pBlock = mVUblocks[branchAddr/8]->search((microRegInfo*)&mVUregs); - if (pBlock) { xJMP(pBlock->x86ptrStart); } - else { mVUcompile(mVU, branchAddr, (uptr)&mVUregs); } - return thisPtr; - case 9: case 10: // JR/JALR - - mVUprint("mVUcompile JR/JALR"); - incPC(-3); // Go back to jump opcode - - if (mVUup.eBit) { // E-bit Jump - mVUendProgram(mVU, 2, xStatus, xMac, xClip); - MOV32MtoR(gprT1, (uptr)&mVU->branch); - MOV32RtoM((uptr)&mVU->regs->VI[REG_TPC].UL, gprT1); - xJMP(mVU->exitFunct); - return thisPtr; - } - - memcpy_fast(&pBlock->pStateEnd, &mVUregs, sizeof(microRegInfo)); - mVUsetupBranch(mVU, xStatus, xMac, xClip, xCycles); - - mVUbackupRegs(mVU); - MOV32MtoR(gprT2, (uptr)&mVU->branch); // Get startPC (ECX first argument for __fastcall) - MOV32ItoR(gprR, (u32)&pBlock->pStateEnd); // Get pState (EDX second argument for __fastcall) - - if (!mVU->index) xCALL( mVUcompileJIT<0> ); //(u32 startPC, uptr pState) - else xCALL( mVUcompileJIT<1> ); - mVUrestoreRegs(mVU); - JMPR(gprT1); // Jump to rec-code address - return thisPtr; - } - // Conditional Branches - mVUprint("mVUcompile conditional branch"); - if (bBlock) { // Branch non-taken has already been compiled - incPC(-3); // Go back to branch opcode (to get branch imm addr) - - if (mVUblocks[branchAddr/8] == NULL) - mVUblocks[branchAddr/8] = microBlockManager::AlignedNew(); - - // Check if branch-block has already been compiled - pBlock = mVUblocks[branchAddr/8]->search((microRegInfo*)&mVUregs); - if (pBlock) { xJMP( pBlock->x86ptrStart ); } - else if (!mVU->index) { mVUblockFetch(mVU, branchAddr, (uptr)&mVUregs); } - else { mVUblockFetch(mVU, branchAddr, (uptr)&mVUregs); } - } - else { - uptr jumpAddr; - u32 bPC = iPC; // mVUcompile can modify iPC and mVUregs so back them up - memcpy_fast(&pBlock->pStateEnd, &mVUregs, sizeof(microRegInfo)); - - incPC2(1); // Get PC for branch not-taken - mVUcompile(mVU, xPC, (uptr)&mVUregs); - - iPC = bPC; - incPC(-3); // Go back to branch opcode (to get branch imm addr) - if (!mVU->index) jumpAddr = (uptr)mVUblockFetch(mVU, branchAddr, (uptr)&pBlock->pStateEnd); - else jumpAddr = (uptr)mVUblockFetch(mVU, branchAddr, (uptr)&pBlock->pStateEnd); - *ajmp = (jumpAddr - ((uptr)ajmp + 4)); - } - return thisPtr; - } - } - if (x == microSizeDiv8) { Console::Error("microVU%d: Possible infinite compiling loop!", params mVU->index); } - - // E-bit End - mVUendProgram(mVU, 1, xStatus, xMac, xClip); - return thisPtr; -} - - -microVUt(void*) mVUblockFetch( microVU* mVU, u32 startPC, uptr pState ) -{ - using namespace x86Emitter; - - if (startPC > mVU->microMemSize-8) { Console::Error("microVU%d: invalid startPC", params mVU->index); } - startPC &= mVU->microMemSize-8; - - if (mVUblocks[startPC/8] == NULL) { - mVUblocks[startPC/8] = microBlockManager::AlignedNew(); - } - - // Searches for Existing Compiled Block (if found, then returns; else, compile) - microBlock* pBlock = mVUblocks[startPC/8]->search((microRegInfo*)pState); - if (pBlock) { return pBlock->x86ptrStart; } - - return mVUcompile( mVU, startPC, pState ); -} - - //------------------------------------------------------------------ // Wrapper Functions - Called by other parts of the Emu //------------------------------------------------------------------ -void initVUrec(VURegs* vuRegs, const int vuIndex) { - if (!vuIndex) mVUinit<0>(vuRegs); - else mVUinit<1>(vuRegs); -} - -void closeVUrec(const int vuIndex) { - if (!vuIndex) mVUclose<0>(); - else mVUclose<1>(); -} - -void resetVUrec(const int vuIndex) { - if (!vuIndex) mVUreset<0>(); - else mVUreset<1>(); -} - -void clearVUrec(u32 addr, u32 size, const int vuIndex) { - if (!vuIndex) mVUclear<0>(addr, size); - else mVUclear<1>(addr, size); -} +void initVUrec (VURegs* vuRegs, const int vuIndex) { mVUinit(vuRegs, vuIndex); } +void closeVUrec(const int vuIndex) { mVUclose(mVUx); } +void resetVUrec(const int vuIndex) { mVUreset(mVUx); } +void vsyncVUrec(const int vuIndex) { mVUvsyncUpdate(mVUx); } +void clearVUrec(u32 addr, u32 size, const int vuIndex) { mVUclear(mVUx, addr, size); } void runVUrec(u32 startPC, u32 cycles, const int vuIndex) { if (!vuIndex) startVU0(startPC, cycles); else startVU1(startPC, cycles); } - -void vsyncVUrec(const int vuIndex) { - if (!vuIndex) mVUvsyncUpdate<0>(); - else mVUvsyncUpdate<1>(); -} diff --git a/pcsx2/x86/microVU.h b/pcsx2/x86/microVU.h index 0d0cdad2f3..96fd3349f7 100644 --- a/pcsx2/x86/microVU.h +++ b/pcsx2/x86/microVU.h @@ -117,8 +117,9 @@ struct microVU { PCSX2_ALIGNED16(u32 xmmVFb[4]); // Backup for VF regs u32 index; // VU Index (VU0 or VU1) + u32 vuMemSize; // VU Main Memory Size (in bytes) u32 microMemSize; // VU Micro Memory Size (in bytes) - u32 progMemSize; // VU Micro Program Size (microSize/4, because each instruction of a program is 4 bytes) + u32 progSize; // VU Micro Memory Size (in u32's) u32 cacheSize; // VU Cache Size microProgManager<0x4000/4> prog; // Micro Program Data @@ -151,11 +152,12 @@ extern void (*mVU_LOWER_OPCODE[128])( VURegs* VU, s32 info ); extern int mVUdebugNow; // Main Functions -microVUf(void) mVUinit(VURegs*); -microVUx(void) mVUreset(); -microVUf(void) mVUclose(); -microVUf(void) mVUclear(u32, u32); -microVUt(void*) mVUblockFetch( microVU* mVU, u32 startPC, uptr pState ); +microVUt(void) mVUinit(VURegs*, int); +microVUt(void) mVUreset(mV); +microVUt(void) mVUclose(mV); +microVUt(void) mVUclear(mV, u32, u32); +microVUt(void*) mVUblockFetch(microVU* mVU, u32 startPC, uptr pState); +microVUx(void*) __fastcall mVUcompileJIT(u32 startPC, uptr pState); // Prototypes for Linux void __fastcall mVUcleanUpVU0(); diff --git a/pcsx2/x86/microVU_Compile.inl b/pcsx2/x86/microVU_Compile.inl index 01a2095f7b..78e3a5ca0a 100644 --- a/pcsx2/x86/microVU_Compile.inl +++ b/pcsx2/x86/microVU_Compile.inl @@ -282,3 +282,189 @@ microVUt(void) mVUtestCycles(mV) { mVUendProgram(mVU, 0, NULL, NULL, NULL); x86SetJ32(jmp32); } + +//------------------------------------------------------------------ +// Recompiler +//------------------------------------------------------------------ + +static void* __fastcall mVUcompile(microVU* mVU, u32 startPC, uptr pState) { + + using namespace x86Emitter; + microBlock* pBlock = NULL; + u8* thisPtr = x86Ptr; + const u32 endCount = (mVU->microMemSize / 8) - 1; + + // Setup Program Bounds/Range + mVUsetupRange(mVU, startPC); + + // First Pass + iPC = startPC / 4; + setCode(); + mVUbranch = 0; + mVUstartPC = iPC; + mVUcount = 0; + mVUcycles = 0; // Skips "M" phase, and starts counting cycles at "T" stage + mVU->p = 0; // All blocks start at p index #0 + mVU->q = 0; // All blocks start at q index #0 + memcpy_fast(&mVUregs, (microRegInfo*)pState, sizeof(microRegInfo)); // Loads up Pipeline State Info + mVUblock.x86ptrStart = thisPtr; + pBlock = mVUblocks[startPC/8]->add(&mVUblock); // Add this block to block manager + mVUpBlock = pBlock; + mVUregs.flags = 0; + mVUflagInfo = 0; + mVUsFlagHack = CHECK_VU_FLAGHACK; + + for (int branch = 0; mVUcount < endCount; mVUcount++) { + incPC(1); + startLoop(); + mVUincCycles(mVU, 1); + mVUopU(mVU, 0); + if (curI & _Ebit_) { branch = 1; mVUup.eBit = 1; } + if (curI & _DTbit_) { branch = 4; } + if (curI & _Mbit_) { mVUup.mBit = 1; } + if (curI & _Ibit_) { mVUlow.isNOP = 1; mVUup.iBit = 1; } + else { incPC(-1); mVUopL(mVU, 0); incPC(1); } + mVUsetCycles(mVU); + mVUinfo.readQ = mVU->q; + mVUinfo.writeQ = !mVU->q; + mVUinfo.readP = mVU->p; + mVUinfo.writeP = !mVU->p; + if (branch >= 2) { mVUinfo.isEOB = 1; if (branch == 3) { mVUinfo.isBdelay = 1; } mVUcount++; branchWarning(); break; } + else if (branch == 1) { branch = 2; } + if (mVUbranch) { mVUsetFlagInfo(mVU); branch = 3; mVUbranch = 0; } + incPC(1); + } + + // Sets Up Flag instances + int xStatus[4], xMac[4], xClip[4]; + int xCycles = mVUsetFlags(mVU, xStatus, xMac, xClip); + mVUtestCycles(mVU); + + // Second Pass + iPC = mVUstartPC; + setCode(); + mVUbranch = 0; + uint x; + for (x = 0; x < endCount; x++) { + if (mVUinfo.isEOB) { x = 0xffff; } + if (mVUup.mBit) { OR32ItoM((uptr)&mVU->regs->flags, VUFLAG_MFLAGSET); } + if (mVUlow.isNOP) { incPC(1); doUpperOp(); doIbit(); } + else if (!mVUinfo.swapOps) { incPC(1); doUpperOp(); doLowerOp(); } + else { doSwapOp(); } + if (mVUinfo.doXGKICK) { mVU_XGKICK_DELAY(mVU, 1); } + + if (!mVUinfo.isBdelay) { incPC(1); } + else { + microBlock* bBlock = NULL; + s32* ajmp = 0; + mVUsetupRange(mVU, xPC); + mVUdebugNOW(1); + + switch (mVUbranch) { + case 3: branchCase(Jcc_Equal); // IBEQ + case 4: branchCase(Jcc_GreaterOrEqual); // IBGEZ + case 5: branchCase(Jcc_Greater); // IBGTZ + case 6: branchCase(Jcc_LessOrEqual); // IBLEQ + case 7: branchCase(Jcc_Less); // IBLTZ + case 8: branchCase(Jcc_NotEqual); // IBNEQ + case 1: case 2: // B/BAL + + mVUprint("mVUcompile B/BAL"); + incPC(-3); // Go back to branch opcode (to get branch imm addr) + + if (mVUup.eBit) { iPC = branchAddr/4; mVUendProgram(mVU, 1, xStatus, xMac, xClip); } // E-bit Branch + mVUsetupBranch(mVU, xStatus, xMac, xClip, xCycles); + + if (mVUblocks[branchAddr/8] == NULL) + mVUblocks[branchAddr/8] = microBlockManager::AlignedNew(); + + // Check if branch-block has already been compiled + pBlock = mVUblocks[branchAddr/8]->search((microRegInfo*)&mVUregs); + if (pBlock) { xJMP(pBlock->x86ptrStart); } + else { mVUcompile(mVU, branchAddr, (uptr)&mVUregs); } + return thisPtr; + case 9: case 10: // JR/JALR + + mVUprint("mVUcompile JR/JALR"); + incPC(-3); // Go back to jump opcode + + if (mVUup.eBit) { // E-bit Jump + mVUendProgram(mVU, 2, xStatus, xMac, xClip); + MOV32MtoR(gprT1, (uptr)&mVU->branch); + MOV32RtoM((uptr)&mVU->regs->VI[REG_TPC].UL, gprT1); + xJMP(mVU->exitFunct); + return thisPtr; + } + + memcpy_fast(&pBlock->pStateEnd, &mVUregs, sizeof(microRegInfo)); + mVUsetupBranch(mVU, xStatus, xMac, xClip, xCycles); + + mVUbackupRegs(mVU); + MOV32MtoR(gprT2, (uptr)&mVU->branch); // Get startPC (ECX first argument for __fastcall) + MOV32ItoR(gprR, (u32)&pBlock->pStateEnd); // Get pState (EDX second argument for __fastcall) + + if (!mVU->index) xCALL(mVUcompileJIT<0>); //(u32 startPC, uptr pState) + else xCALL(mVUcompileJIT<1>); + mVUrestoreRegs(mVU); + JMPR(gprT1); // Jump to rec-code address + return thisPtr; + } + // Conditional Branches + mVUprint("mVUcompile conditional branch"); + if (bBlock) { // Branch non-taken has already been compiled + incPC(-3); // Go back to branch opcode (to get branch imm addr) + + if (mVUblocks[branchAddr/8] == NULL) + mVUblocks[branchAddr/8] = microBlockManager::AlignedNew(); + + // Check if branch-block has already been compiled + pBlock = mVUblocks[branchAddr/8]->search((microRegInfo*)&mVUregs); + if (pBlock) { xJMP( pBlock->x86ptrStart ); } + else { mVUblockFetch(mVU, branchAddr, (uptr)&mVUregs); } + } + else { + uptr jumpAddr; + u32 bPC = iPC; // mVUcompile can modify iPC and mVUregs so back them up + memcpy_fast(&pBlock->pStateEnd, &mVUregs, sizeof(microRegInfo)); + + incPC2(1); // Get PC for branch not-taken + mVUcompile(mVU, xPC, (uptr)&mVUregs); + + iPC = bPC; + incPC(-3); // Go back to branch opcode (to get branch imm addr) + jumpAddr = (uptr)mVUblockFetch(mVU, branchAddr, (uptr)&pBlock->pStateEnd); + *ajmp = (jumpAddr - ((uptr)ajmp + 4)); + } + return thisPtr; + } + } + if (x == endCount) { Console::Error("microVU%d: Possible infinite compiling loop!", params mVU->index); } + + // E-bit End + mVUendProgram(mVU, 1, xStatus, xMac, xClip); + return thisPtr; +} + + +microVUt(void*) mVUblockFetch(microVU* mVU, u32 startPC, uptr pState) { + + using namespace x86Emitter; + + if (startPC > mVU->microMemSize-8) { DevCon::Error("microVU%d: invalid startPC", params mVU->index); } + startPC &= mVU->microMemSize-8; + + if (mVUblocks[startPC/8] == NULL) { + mVUblocks[startPC/8] = microBlockManager::AlignedNew(); + } + + // Searches for Existing Compiled Block (if found, then returns; else, compile) + microBlock* pBlock = mVUblocks[startPC/8]->search((microRegInfo*)pState); + if (pBlock) { return pBlock->x86ptrStart; } + else { return mVUcompile(mVU, startPC, pState); } +} + +// Called By JR/JALR +microVUx(void*) __fastcall mVUcompileJIT(u32 startPC, uptr pState) { + return mVUblockFetch(mVUx, startPC, pState); +} + diff --git a/pcsx2/x86/microVU_Log.inl b/pcsx2/x86/microVU_Log.inl index a721642b01..4b84ab61cc 100644 --- a/pcsx2/x86/microVU_Log.inl +++ b/pcsx2/x86/microVU_Log.inl @@ -62,7 +62,7 @@ microVUx(void) __mVUdumpProgram(int progIndex) { mVUlog("*********************\n\n

", progIndex); mVUlog(""); - for (u32 i = 0; i < mVU->progMemSize; i+=2) { + for (u32 i = 0; i < mVU->progSize; i+=2) { if (delay) { delay--; mVUlog(""); if (!delay) mVUlog("
"); } if (mVUbranch) { delay = 1; mVUbranch = 0; } diff --git a/pcsx2/x86/microVU_Misc.h b/pcsx2/x86/microVU_Misc.h index 32089b006b..b91f9e74a9 100644 --- a/pcsx2/x86/microVU_Misc.h +++ b/pcsx2/x86/microVU_Misc.h @@ -201,8 +201,8 @@ typedef u32 (__fastcall *mVUCall)(void*, void*); #define xPC ((iPC / 2) * 8) #define curI ((u32*)mVU->regs->Micro)[iPC] //mVUcurProg.data[iPC] #define setCode() { mVU->code = curI; } -#define incPC(x) { iPC = ((iPC + x) & (mVU->progMemSize-1)); setCode(); } -#define incPC2(x) { iPC = ((iPC + x) & (mVU->progMemSize-1)); } +#define incPC(x) { iPC = ((iPC + x) & (mVU->progSize-1)); setCode(); } +#define incPC2(x) { iPC = ((iPC + x) & (mVU->progSize-1)); } #define bSaveAddr (((xPC + (2 * 8)) & ((isVU1) ? 0x3ff8:0xff8)) / 8) #define branchAddr ((xPC + 8 + (_Imm11_ * 8)) & (mVU->microMemSize-8)) #define shufflePQ (((mVU->p) ? 0xb0 : 0xe0) | ((mVU->q) ? 0x01 : 0x04)) @@ -274,8 +274,7 @@ typedef u32 (__fastcall *mVUCall)(void*, void*); uptr diff = ptr - start; \ if (diff >= limit) { \ Console::Error("microVU Error: Program went over its cache limit. Size = 0x%x", params diff); \ - if (!isVU1) mVUreset<0>(); \ - else mVUreset<1>(); \ + mVUreset(mVU); \ } \ }