From fb4fcc7d29486c3779b0b5be52ace6d2b43faa28 Mon Sep 17 00:00:00 2001 From: "Jake.Stine" Date: Tue, 16 Jun 2009 22:49:06 +0000 Subject: [PATCH] Changed some code around in microVU that was causing 10+ minute link times in Release builds (LTCG mode), also added some new x86Emitter cleanups along the way. :) git-svn-id: http://pcsx2.googlecode.com/svn/trunk@1374 96395faa-99c1-11dd-bbfe-3dabce05a288 --- pcsx2/x86/ix86/ix86_inlines.inl | 11 ++ pcsx2/x86/microVU.cpp | 196 +++++++++++++++++++++++++++++++ pcsx2/x86/microVU.h | 4 +- pcsx2/x86/microVU_Compile.inl | 201 ++------------------------------ pcsx2/x86/microVU_Execute.inl | 3 +- pcsx2/x86/microVU_Misc.h | 4 +- 6 files changed, 222 insertions(+), 197 deletions(-) diff --git a/pcsx2/x86/ix86/ix86_inlines.inl b/pcsx2/x86/ix86/ix86_inlines.inl index 4462aecd0b..45c9b75d75 100644 --- a/pcsx2/x86/ix86/ix86_inlines.inl +++ b/pcsx2/x86/ix86/ix86_inlines.inl @@ -231,4 +231,15 @@ namespace x86Emitter } } + // ------------------------------------------------------------------------ + // returns the inverted conditional type for this Jcc condition. Ie, JNS will become JS. + // + static __forceinline JccComparisonType xInvertCond( JccComparisonType src ) + { + jASSUME( src != Jcc_Unknown ); + if( Jcc_Unconditional == src ) return Jcc_Unconditional; + + // x86 conditionals are clever! To invert conditional types, just invert the lower bit: + return (JccComparisonType)((int)src ^ 1); + } } diff --git a/pcsx2/x86/microVU.cpp b/pcsx2/x86/microVU.cpp index a2f65ed38f..f3403d6455 100644 --- a/pcsx2/x86/microVU.cpp +++ b/pcsx2/x86/microVU.cpp @@ -252,6 +252,202 @@ 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->microSize-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->microSize-1) { Console::Error("microVU%d: invalid startPC", params mVU->index); } + startPC &= ~7; + + 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 //------------------------------------------------------------------ diff --git a/pcsx2/x86/microVU.h b/pcsx2/x86/microVU.h index 0dab141a4b..c722b0e5f8 100644 --- a/pcsx2/x86/microVU.h +++ b/pcsx2/x86/microVU.h @@ -155,17 +155,15 @@ microVUf(void) mVUinit(VURegs*); microVUx(void) mVUreset(); microVUf(void) mVUclose(); microVUf(void) mVUclear(u32, u32); +microVUt(void*) mVUblockFetch( microVU* mVU, u32 startPC, uptr pState ); // Prototypes for Linux void __fastcall mVUcleanUpVU0(); void __fastcall mVUcleanUpVU1(); -void* __fastcall mVUcompileVU0(u32 startPC, uptr pState); -void* __fastcall mVUcompileVU1(u32 startPC, uptr pState); mVUop(mVUopU); mVUop(mVUopL); // Private Functions -microVUf(void) mVUclearProg(microVU* mVU, int progIndex); microVUf(int) mVUfindLeastUsedProg(microVU* mVU); microVUf(int) mVUsearchProg(); microVUf(void) mVUcacheProg(int progIndex); diff --git a/pcsx2/x86/microVU_Compile.inl b/pcsx2/x86/microVU_Compile.inl index 30ac835a2b..6b713e24a9 100644 --- a/pcsx2/x86/microVU_Compile.inl +++ b/pcsx2/x86/microVU_Compile.inl @@ -22,20 +22,20 @@ // Helper Macros //------------------------------------------------------------------ -#define branchCase(JMPcc, nJMPcc, ebitJMP) \ +#define branchCase(JMPcc) \ mVUsetupBranch(mVU, xStatus, xMac, xClip, xCycles); \ - CMP16ItoM((uptr)&mVU->branch, 0); \ + xCMP( ptr16[&mVU->branch], 0); \ if (mVUup.eBit) { /* Conditional Branch With E-Bit Set */ \ mVUendProgram(mVU, 2, xStatus, xMac, xClip); \ - u8* eJMP = ebitJMP(0); \ + xForwardJump8 eJMP( JMPcc ); \ incPC(1); /* Set PC to First instruction of Non-Taken Side */ \ - MOV32ItoM((uptr)&mVU->regs->VI[REG_TPC].UL, xPC); \ - JMP32((uptr)mVU->exitFunct - ((uptr)x86Ptr + 5)); \ - x86SetJ8(eJMP); \ + xMOV( ptr32[&mVU->regs->VI[REG_TPC].UL], xPC); \ + xJMP( mVU->exitFunct ); \ + eJMP.SetTarget(); \ incPC(-4); /* Go Back to Branch Opcode to get branchAddr */ \ iPC = branchAddr/4; \ - MOV32ItoM((uptr)&mVU->regs->VI[REG_TPC].UL, xPC); \ - JMP32((uptr)mVU->exitFunct - ((uptr)x86Ptr + 5)); \ + xMOV( ptr32[&mVU->regs->VI[REG_TPC].UL], xPC); \ + xJMP( mVU->exitFunct ); \ return thisPtr; \ } \ else { /* Normal Conditional Branch */ \ @@ -43,14 +43,14 @@ if (!mVUblocks[iPC/2]) { mVUblocks[iPC/2] = microBlockManager::AlignedNew(); } \ bBlock = mVUblocks[iPC/2]->search((microRegInfo*)&mVUregs); \ incPC2(-1); \ - if (bBlock) { nJMPcc((uptr)bBlock->x86ptrStart - ((uptr)x86Ptr + 6)); } \ - else { ajmp = JMPcc((uptr)0); } \ + if (bBlock) { xJcc( xInvertCond( JMPcc ), bBlock->x86ptrStart ); } \ + else { ajmp = xJcc32( JMPcc ); } \ } \ break #define branchWarning() { \ if (mVUbranch) { \ - Console::Error("microVU%d Warning: Branch in E-bit/Branch delay slot! [%04x]", params vuIndex, xPC); \ + Console::Error("microVU%d Warning: Branch in E-bit/Branch delay slot! [%04x]", params mVU->index, xPC); \ mVUlow.isNOP = 1; \ } \ } @@ -282,182 +282,3 @@ microVUt(void) mVUtestCycles(mV) { mVUendProgram(mVU, 0, NULL, NULL, NULL); x86SetJ32(jmp32); } - -//------------------------------------------------------------------ -// Recompiler -//------------------------------------------------------------------ - -microVUf(void*) __fastcall mVUcompile(u32 startPC, uptr pState) { - microVU* mVU = mVUx; - u8* thisPtr = x86Ptr; - - if (startPC > ((vuIndex) ? 0x3fff : 0xfff)) { Console::Error("microVU%d: invalid startPC", params vuIndex); } - startPC &= (vuIndex ? 0x3ff8 : 0xff8); - - 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; } - - // 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 < (vuIndex ? (0x3fff/8) : (0xfff/8)); ) { - 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; - int x; - for (x = 0; x < (vuIndex ? (0x3fff/8) : (0xfff/8)); 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; - u32* ajmp = 0; - mVUsetupRange(mVU, xPC); - mVUdebugNOW(1); - - switch (mVUbranch) { - case 3: branchCase(JE32, JNE32, JE8); // IBEQ - case 4: branchCase(JGE32, JNGE32, JGE8); // IBGEZ - case 5: branchCase(JG32, JNG32, JG8); // IBGTZ - case 6: branchCase(JLE32, JNLE32, JLE8); // IBLEQ - case 7: branchCase(JL32, JNL32, JL8); // IBLTZ - case 8: branchCase(JNE32, JE32, JNE8); // 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) { JMP32((uptr)pBlock->x86ptrStart - ((uptr)x86Ptr + 5)); } - else if (!vuIndex) { mVUcompileVU0(branchAddr, (uptr)&mVUregs); } - else { mVUcompileVU1(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); - JMP32((uptr)mVU->exitFunct - ((uptr)x86Ptr + 5)); - 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 (!vuIndex) CALLFunc((uptr)mVUcompileVU0); //(u32 startPC, uptr pState) - else CALLFunc((uptr)mVUcompileVU1); - 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) { JMP32((uptr)pBlock->x86ptrStart - ((uptr)x86Ptr + 5)); } - else if (!vuIndex) { mVUcompileVU0(branchAddr, (uptr)&mVUregs); } - else { mVUcompileVU1(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 - if (!vuIndex) mVUcompileVU0(xPC, (uptr)&mVUregs); - else mVUcompileVU1(xPC, (uptr)&mVUregs); - - iPC = bPC; - incPC(-3); // Go back to branch opcode (to get branch imm addr) - if (!vuIndex) jumpAddr = (uptr)mVUcompileVU0(branchAddr, (uptr)&pBlock->pStateEnd); - else jumpAddr = (uptr)mVUcompileVU1(branchAddr, (uptr)&pBlock->pStateEnd); - *ajmp = (jumpAddr - ((uptr)ajmp + 4)); - } - return thisPtr; - } - } - if (x == (vuIndex?(0x3fff/8):(0xfff/8))) { Console::Error("microVU%d: Possible infinite compiling loop!", params vuIndex); } - - // E-bit End - mVUendProgram(mVU, 1, xStatus, xMac, xClip); - return thisPtr; -} - -void* __fastcall mVUcompileVU0(u32 startPC, uptr pState) { return mVUcompile<0>(startPC, pState); } -void* __fastcall mVUcompileVU1(u32 startPC, uptr pState) { return mVUcompile<1>(startPC, pState); } - diff --git a/pcsx2/x86/microVU_Execute.inl b/pcsx2/x86/microVU_Execute.inl index 39d1c85e3a..1ca593aac8 100644 --- a/pcsx2/x86/microVU_Execute.inl +++ b/pcsx2/x86/microVU_Execute.inl @@ -128,8 +128,7 @@ microVUx(void*) __fastcall mVUexecute(u32 startPC, u32 cycles) { mVU->totalCycles = cycles; x86SetPtr(mVUcurProg.x86ptr); // Set x86ptr to where program left off - if (!vuIndex) return mVUcompileVU0(startPC, (uptr)&mVU->prog.lpState); - else return mVUcompileVU1(startPC, (uptr)&mVU->prog.lpState); + return mVUblockFetch(mVU, startPC, (uptr)&mVU->prog.lpState); } //------------------------------------------------------------------ diff --git a/pcsx2/x86/microVU_Misc.h b/pcsx2/x86/microVU_Misc.h index 4196d35e33..66690240e7 100644 --- a/pcsx2/x86/microVU_Misc.h +++ b/pcsx2/x86/microVU_Misc.h @@ -94,7 +94,7 @@ declareAllVariables #define _Ftf_ ((mVU->code >> 23) & 0x03) #define _Imm5_ (s16)(((mVU->code & 0x400) ? 0xfff0 : 0) | ((mVU->code >> 6) & 0xf)) -#define _Imm11_ (s32)((mVU->code & 0x400) ? (0xfffffc00 | (mVU->code & 0x3ff)) : mVU->code & 0x3ff) +#define _Imm11_ (s32)((mVU->code & 0x400) ? (0xfffffc00 | (mVU->code & 0x3ff)) : (mVU->code & 0x3ff)) #define _Imm12_ (((mVU->code >> 21) & 0x1) << 11) | (mVU->code & 0x7ff) #define _Imm15_ (((mVU->code >> 10) & 0x7800) | (mVU->code & 0x7ff)) #define _Imm24_ (u32)(mVU->code & 0xffffff) @@ -204,7 +204,7 @@ typedef u32 (__fastcall *mVUCall)(void*, void*); #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)) & ((isVU1) ? 0x3ff8 : 0xff8)) +#define branchAddr ((xPC + 8 + (_Imm11_ * 8)) & (mVU->microSize-8)) #define shufflePQ (((mVU->p) ? 0xb0 : 0xe0) | ((mVU->q) ? 0x01 : 0x04)) #define Rmem (uptr)&mVU->regs->VI[REG_R].UL #define Roffset (uptr)&mVU->regs->VI[9].UL