From bda80fc748037d708a7efb26d11087bfc0865309 Mon Sep 17 00:00:00 2001 From: refractionpcsx2 Date: Tue, 31 Aug 2021 20:51:14 +0100 Subject: [PATCH] Clang Format VU files --- pcsx2/VU.h | 122 +++--- pcsx2/VUmicro.cpp | 37 +- pcsx2/x86/microVU.cpp | 310 ++++++++------ pcsx2/x86/microVU_Branch.inl | 383 +++++++++++------- pcsx2/x86/microVU_Macro.inl | 753 ++++++++++++++++++++++++----------- 5 files changed, 1033 insertions(+), 572 deletions(-) diff --git a/pcsx2/VU.h b/pcsx2/VU.h index ce960f6c58..caef1a9519 100644 --- a/pcsx2/VU.h +++ b/pcsx2/VU.h @@ -18,72 +18,79 @@ enum VURegFlags { - REG_STATUS_FLAG = 16, - REG_MAC_FLAG = 17, - REG_CLIP_FLAG = 18, - REG_ACC_FLAG = 19, // dummy flag that indicates that VFACC is written/read (nothing to do with VI[19]) - REG_R = 20, - REG_I = 21, - REG_Q = 22, - REG_P = 23, // only exists in micromode - REG_VF0_FLAG = 24, // dummy flag that indicates VF0 is read (nothing to do with VI[24]) - REG_TPC = 26, - REG_CMSAR0 = 27, - REG_FBRST = 28, - REG_VPU_STAT = 29, - REG_CMSAR1 = 31 + REG_STATUS_FLAG = 16, + REG_MAC_FLAG = 17, + REG_CLIP_FLAG = 18, + REG_ACC_FLAG = 19, // dummy flag that indicates that VFACC is written/read (nothing to do with VI[19]) + REG_R = 20, + REG_I = 21, + REG_Q = 22, + REG_P = 23, // only exists in micromode + REG_VF0_FLAG = 24, // dummy flag that indicates VF0 is read (nothing to do with VI[24]) + REG_TPC = 26, + REG_CMSAR0 = 27, + REG_FBRST = 28, + REG_VPU_STAT = 29, + REG_CMSAR1 = 31 }; //interpreter hacks, WIP //#define INT_VUSTALLHACK //some games work without those, big speedup //#define INT_VUDOUBLEHACK -enum VUStatus { +enum VUStatus +{ VU_Ready = 0, - VU_Run = 1, - VU_Stop = 2, + VU_Run = 1, + VU_Stop = 2, }; -union VECTOR { - struct { - float x,y,z,w; +union VECTOR +{ + struct + { + float x, y, z, w; } f; - struct { - u32 x,y,z,w; + struct + { + u32 x, y, z, w; } i; float F[4]; u128 UQ; s128 SQ; - u64 UD[2]; //128 bits + u64 UD[2]; //128 bits s64 SD[2]; u32 UL[4]; s32 SL[4]; u16 US[8]; s16 SS[8]; - u8 UC[16]; - s8 SC[16]; + u8 UC[16]; + s8 SC[16]; }; -struct REG_VI { - union { +struct REG_VI +{ + union + { float F; - s32 SL; - u32 UL; - s16 SS[2]; - u16 US[2]; - s8 SC[4]; - u8 UC[4]; + s32 SL; + u32 UL; + s16 SS[2]; + u16 US[2]; + s8 SC[4]; + u8 UC[4]; }; u32 padding[3]; // needs padding to make them 128bit; VU0 maps VU1's VI regs as 128bits to addr 0x4xx0 in - // VU0 mem, with only lower 16 bits valid, and the upper 112bits are hardwired to 0 (cottonvibes) + // VU0 mem, with only lower 16 bits valid, and the upper 112bits are hardwired to 0 (cottonvibes) }; //#define VUFLAG_BREAKONMFLAG 0x00000001 -#define VUFLAG_MFLAGSET 0x00000002 -#define VUFLAG_INTCINTERRUPT 0x00000004 -struct fdivPipe { +#define VUFLAG_MFLAGSET 0x00000002 +#define VUFLAG_INTCINTERRUPT 0x00000004 +struct fdivPipe +{ int enable; REG_VI reg; u32 sCycle; @@ -91,14 +98,16 @@ struct fdivPipe { u32 statusflag; }; -struct efuPipe { +struct efuPipe +{ int enable; REG_VI reg; u32 sCycle; u32 Cycle; }; -struct fmacPipe { +struct fmacPipe +{ int enable; int reg; int xyzw; @@ -109,22 +118,24 @@ struct fmacPipe { u32 clipflag; }; -struct ialuPipe { +struct ialuPipe +{ int enable; int reg; u32 sCycle; u32 Cycle; }; -struct __aligned16 VURegs { - VECTOR VF[32]; // VF and VI need to be first in this struct for proper mapping - REG_VI VI[32]; // needs to be 128bit x 32 (cottonvibes) +struct __aligned16 VURegs +{ + VECTOR VF[32]; // VF and VI need to be first in this struct for proper mapping + REG_VI VI[32]; // needs to be 128bit x 32 (cottonvibes) VECTOR ACC; REG_VI q; REG_VI p; - uint idx; // VU index (0 or 1) + uint idx; // VU index (0 or 1) // flags/cycle are needed by VIF dma code, so they have to be here (for now) // We may replace these by accessors in the future, if merited. @@ -157,8 +168,8 @@ struct __aligned16 VURegs { s32 nextBlockCycles; - u8 *Mem; - u8 *Micro; + u8* Mem; + u8* Micro; u32 ebit; @@ -188,13 +199,13 @@ struct __aligned16 VURegs { enum VUPipeState { - VUPIPE_NONE = 0, - VUPIPE_FMAC, - VUPIPE_FDIV, - VUPIPE_EFU, - VUPIPE_IALU, - VUPIPE_BRANCH, - VUPIPE_XGKICK + VUPIPE_NONE = 0, + VUPIPE_FMAC, + VUPIPE_FDIV, + VUPIPE_EFU, + VUPIPE_IALU, + VUPIPE_BRANCH, + VUPIPE_XGKICK }; extern __aligned16 VURegs vuRegs[2]; @@ -205,8 +216,7 @@ static VURegs& VU0 = vuRegs[0]; static VURegs& VU1 = vuRegs[1]; // Do not use __fi here because it fires 'multiple definition' error in GCC -inline bool VURegs::IsVU1() const { return this == &vuRegs[1]; } -inline bool VURegs::IsVU0() const { return this == &vuRegs[0]; } +inline bool VURegs::IsVU1() const { return this == &vuRegs[1]; } +inline bool VURegs::IsVU0() const { return this == &vuRegs[0]; } extern u32* GET_VU_MEM(VURegs* VU, u32 addr); - diff --git a/pcsx2/VUmicro.cpp b/pcsx2/VUmicro.cpp index cc2c287720..4f8d6abb6c 100644 --- a/pcsx2/VUmicro.cpp +++ b/pcsx2/VUmicro.cpp @@ -19,10 +19,11 @@ #include "MTVU.h" // Executes a Block based on EE delta time -void BaseVUmicroCPU::ExecuteBlock(bool startUp) { - const u32& stat = VU0.VI[REG_VPU_STAT].UL; - const int test = m_Idx ? 0x100 : 1; - const int s = EmuConfig.Gamefixes.VUKickstartHack ? 16 : 0; // Kick Start Cycles (Jak needs at least 4 due to writing values after they're read +void BaseVUmicroCPU::ExecuteBlock(bool startUp) +{ + const u32& stat = VU0.VI[REG_VPU_STAT].UL; + const int test = m_Idx ? 0x100 : 1; + const int s = EmuConfig.Gamefixes.VUKickstartHack ? 16 : 0; // Kick Start Cycles (Jak needs at least 4 due to writing values after they're read if (m_Idx && THREAD_VU1) { @@ -30,12 +31,15 @@ void BaseVUmicroCPU::ExecuteBlock(bool startUp) { return; } - if (!(stat & test)) return; + if (!(stat & test)) + return; - if (startUp && s) { // Start Executing a microprogram + if (startUp && s) + { // Start Executing a microprogram Execute(s); // Kick start VU } - else { // Continue Executing + else + { // Continue Executing u32 cycle = m_Idx ? VU1.cycle : VU0.cycle; s32 delta = (s32)(u32)(cpuRegs.cycle - cycle); s32 nextblockcycles = m_Idx ? VU1.nextBlockCycles : VU0.nextBlockCycles; @@ -43,8 +47,8 @@ void BaseVUmicroCPU::ExecuteBlock(bool startUp) { if (delta < nextblockcycles) return; - if (delta > 0) // Enough time has passed - Execute(delta); // Execute the time since the last call + if (delta > 0) // Enough time has passed + Execute(delta); // Execute the time since the last call } } @@ -52,15 +56,18 @@ void BaseVUmicroCPU::ExecuteBlock(bool startUp) { // EE data to VU0's registers. We want to run VU0 Micro right after this // to ensure that the register is used at the correct time. // This fixes spinning/hanging in some games like Ratchet and Clank's Intro. -void BaseVUmicroCPU::ExecuteBlockJIT(BaseVUmicroCPU* cpu) { - const u32& stat = VU0.VI[REG_VPU_STAT].UL; - const int test = 1; +void BaseVUmicroCPU::ExecuteBlockJIT(BaseVUmicroCPU* cpu) +{ + const u32& stat = VU0.VI[REG_VPU_STAT].UL; + const int test = 1; - if (stat & test) { // VU is running + if (stat & test) + { // VU is running s32 delta = (s32)(u32)(cpuRegs.cycle - VU0.cycle); - if (delta > 0) { // Enough time has passed - cpu->Execute(delta); // Execute the time since the last call + if (delta > 0) + { // Enough time has passed + cpu->Execute(delta); // Execute the time since the last call } } } diff --git a/pcsx2/x86/microVU.cpp b/pcsx2/x86/microVU.cpp index 9946903a11..31fbe5db0d 100644 --- a/pcsx2/x86/microVU.cpp +++ b/pcsx2/x86/microVU.cpp @@ -26,53 +26,60 @@ static u8 __pagealigned vu0_RecDispatchers[mVUdispCacheSize]; static u8 __pagealigned vu1_RecDispatchers[mVUdispCacheSize]; -static __fi void mVUthrowHardwareDeficiency(const wxChar* extFail, int vuIndex) { +static __fi void mVUthrowHardwareDeficiency(const wxChar* extFail, int vuIndex) +{ throw Exception::HardwareDeficiency() .SetDiagMsg(pxsFmt(L"microVU%d recompiler init failed: %s is not available.", vuIndex, extFail)) .SetUserMsg(pxsFmt(_("%s Extensions not found. microVU requires a host CPU with SSE2 extensions."), extFail)); } -void mVUreserveCache(microVU& mVU) { +void mVUreserveCache(microVU& mVU) +{ mVU.cache_reserve = new RecompiledCodeReserve(pxsFmt("Micro VU%u Recompiler Cache", mVU.index), _16mb); mVU.cache_reserve->SetProfilerName(pxsFmt("mVU%urec", mVU.index)); - + mVU.cache = mVU.index ? - (u8*)mVU.cache_reserve->Reserve(GetVmMemory().MainMemory(), HostMemoryMap::mVU1recOffset, mVU.cacheSize * _1mb): - (u8*)mVU.cache_reserve->Reserve(GetVmMemory().MainMemory(), HostMemoryMap::mVU0recOffset, mVU.cacheSize * _1mb); + (u8*)mVU.cache_reserve->Reserve(GetVmMemory().MainMemory(), HostMemoryMap::mVU1recOffset, mVU.cacheSize * _1mb) : + (u8*)mVU.cache_reserve->Reserve(GetVmMemory().MainMemory(), HostMemoryMap::mVU0recOffset, mVU.cacheSize * _1mb); mVU.cache_reserve->ThrowIfNotOk(); } // Only run this once per VU! ;) -void mVUinit(microVU& mVU, uint vuIndex) { +void mVUinit(microVU& mVU, uint vuIndex) +{ - if(!x86caps.hasStreamingSIMD4Extensions) mVUthrowHardwareDeficiency( L"SSE4", vuIndex ); + if (!x86caps.hasStreamingSIMD4Extensions) + mVUthrowHardwareDeficiency(L"SSE4", vuIndex); memzero(mVU.prog); - mVU.index = vuIndex; - mVU.cop2 = 0; - mVU.vuMemSize = (mVU.index ? 0x4000 : 0x1000); - mVU.microMemSize = (mVU.index ? 0x4000 : 0x1000); - mVU.progSize = (mVU.index ? 0x4000 : 0x1000) / 4; - mVU.progMemMask = mVU.progSize-1; - mVU.cacheSize = vuIndex ? mVU1cacheReserve : mVU0cacheReserve; - mVU.cache = NULL; - mVU.dispCache = NULL; - mVU.startFunct = NULL; - mVU.exitFunct = NULL; + mVU.index = vuIndex; + mVU.cop2 = 0; + mVU.vuMemSize = (mVU.index ? 0x4000 : 0x1000); + mVU.microMemSize = (mVU.index ? 0x4000 : 0x1000); + mVU.progSize = (mVU.index ? 0x4000 : 0x1000) / 4; + mVU.progMemMask = mVU.progSize - 1; + mVU.cacheSize = vuIndex ? mVU1cacheReserve : mVU0cacheReserve; + mVU.cache = NULL; + mVU.dispCache = NULL; + mVU.startFunct = NULL; + mVU.exitFunct = NULL; mVUreserveCache(mVU); - if (vuIndex) mVU.dispCache = vu1_RecDispatchers; - else mVU.dispCache = vu0_RecDispatchers; + if (vuIndex) + mVU.dispCache = vu1_RecDispatchers; + else + mVU.dispCache = vu0_RecDispatchers; mVU.regAlloc.reset(new microRegAlloc(mVU.index)); } // Resets Rec Data -void mVUreset(microVU& mVU, bool resetReserve) { +void mVUreset(microVU& mVU, bool resetReserve) +{ if (THREAD_VU1) { @@ -85,7 +92,8 @@ void mVUreset(microVU& mVU, bool resetReserve) { VU0.VI[REG_VPU_STAT].UL &= ~0x100; } // Restore reserve to uncommitted state - if (resetReserve) mVU.cache_reserve->Reset(); + if (resetReserve) + mVU.cache_reserve->Reset(); HostSys::MemProtect(mVU.dispCache, mVUdispCacheSize, PageAccess_ReadWrite()); memset(mVU.dispCache, 0xcc, mVUdispCacheSize); @@ -102,49 +110,58 @@ void mVUreset(microVU& mVU, bool resetReserve) { mVU.profiler.Reset(mVU.index); // Program Variables - mVU.prog.cleared = 1; - mVU.prog.isSame = -1; - mVU.prog.cur = NULL; - mVU.prog.total = 0; - mVU.prog.curFrame = 0; + mVU.prog.cleared = 1; + mVU.prog.isSame = -1; + mVU.prog.cur = NULL; + mVU.prog.total = 0; + mVU.prog.curFrame = 0; // Setup Dynarec Cache Limits for Each Program u8* z = mVU.cache; - mVU.prog.x86start = z; - mVU.prog.x86ptr = z; - mVU.prog.x86end = z + ((mVU.cacheSize - mVUcacheSafeZone) * _1mb); + mVU.prog.x86start = z; + mVU.prog.x86ptr = z; + mVU.prog.x86end = z + ((mVU.cacheSize - mVUcacheSafeZone) * _1mb); //memset(mVU.prog.x86start, 0xcc, mVU.cacheSize*_1mb); - for(u32 i = 0; i < (mVU.progSize / 2); i++) { - if(!mVU.prog.prog[i]) { + for (u32 i = 0; i < (mVU.progSize / 2); i++) + { + if (!mVU.prog.prog[i]) + { mVU.prog.prog[i] = new std::deque(); continue; } std::deque::iterator it(mVU.prog.prog[i]->begin()); - for ( ; it != mVU.prog.prog[i]->end(); ++it) { + for (; it != mVU.prog.prog[i]->end(); ++it) + { mVUdeleteProg(mVU, it[0]); } mVU.prog.prog[i]->clear(); mVU.prog.quick[i].block = NULL; - mVU.prog.quick[i].prog = NULL; + mVU.prog.quick[i].prog = NULL; } HostSys::MemProtect(mVU.dispCache, mVUdispCacheSize, PageAccess_ExecOnly()); - if (mVU.index) Perf::any.map((uptr)&mVU.dispCache, mVUdispCacheSize, "mVU1 Dispatcher"); - else Perf::any.map((uptr)&mVU.dispCache, mVUdispCacheSize, "mVU0 Dispatcher"); + if (mVU.index) + Perf::any.map((uptr)&mVU.dispCache, mVUdispCacheSize, "mVU1 Dispatcher"); + else + Perf::any.map((uptr)&mVU.dispCache, mVUdispCacheSize, "mVU0 Dispatcher"); } // Free Allocated Resources -void mVUclose(microVU& mVU) { +void mVUclose(microVU& mVU) +{ - safe_delete (mVU.cache_reserve); + safe_delete(mVU.cache_reserve); // Delete Programs and Block Managers - for (u32 i = 0; i < (mVU.progSize / 2); i++) { - if (!mVU.prog.prog[i]) continue; + for (u32 i = 0; i < (mVU.progSize / 2); i++) + { + if (!mVU.prog.prog[i]) + continue; std::deque::iterator it(mVU.prog.prog[i]->begin()); - for ( ; it != mVU.prog.prog[i]->end(); ++it) { + for (; it != mVU.prog.prog[i]->end(); ++it) + { mVUdeleteProg(mVU, it[0]); } safe_delete(mVU.prog.prog[i]); @@ -152,13 +169,16 @@ void mVUclose(microVU& mVU) { } // Clears Block Data in specified range -__fi void mVUclear(mV, u32 addr, u32 size) { - if(!mVU.prog.cleared) { - mVU.prog.cleared = 1; // Next execution searches/creates a new microprogram +__fi void mVUclear(mV, u32 addr, u32 size) +{ + if (!mVU.prog.cleared) + { + mVU.prog.cleared = 1; // Next execution searches/creates a new microprogram memzero(mVU.prog.lpState); // Clear pipeline state - for(u32 i = 0; i < (mVU.progSize / 2); i++) { + for (u32 i = 0; i < (mVU.progSize / 2); i++) + { mVU.prog.quick[i].block = NULL; // Clear current quick-reference block - mVU.prog.quick[i].prog = NULL; // Clear current quick-reference prog + mVU.prog.quick[i].prog = NULL; // Clear current quick-reference prog } } } @@ -168,13 +188,16 @@ __fi void mVUclear(mV, u32 addr, u32 size) { //------------------------------------------------------------------ // Finds and Ages/Kills Programs if they haven't been used in a while. -__ri void mVUvsyncUpdate(mV) { +__ri void mVUvsyncUpdate(mV) +{ //mVU.prog.curFrame++; } // Deletes a program -__ri void mVUdeleteProg(microVU& mVU, microProgram*& prog) { - for (u32 i = 0; i < (mVU.progSize / 2); i++) { +__ri void mVUdeleteProg(microVU& mVU, microProgram*& prog) +{ + for (u32 i = 0; i < (mVU.progSize / 2); i++) + { safe_delete(prog->block[i]); } safe_delete(prog->ranges); @@ -182,40 +205,51 @@ __ri void mVUdeleteProg(microVU& mVU, microProgram*& prog) { } // Creates a new Micro Program -__ri microProgram* mVUcreateProg(microVU& mVU, int startPC) { +__ri microProgram* mVUcreateProg(microVU& mVU, int startPC) +{ microProgram* prog = (microProgram*)_aligned_malloc(sizeof(microProgram), 64); memset(prog, 0, sizeof(microProgram)); - prog->idx = mVU.prog.total++; - prog->ranges = new std::deque(); + prog->idx = mVU.prog.total++; + prog->ranges = new std::deque(); prog->startPC = startPC; mVUcacheProg(mVU, *prog); // Cache Micro Program double cacheSize = (double)((uptr)mVU.prog.x86end - (uptr)mVU.prog.x86start); - double cacheUsed =((double)((uptr)mVU.prog.x86ptr - (uptr)mVU.prog.x86start)) / (double)_1mb; - double cachePerc =((double)((uptr)mVU.prog.x86ptr - (uptr)mVU.prog.x86start)) / cacheSize * 100; + double cacheUsed = ((double)((uptr)mVU.prog.x86ptr - (uptr)mVU.prog.x86start)) / (double)_1mb; + double cachePerc = ((double)((uptr)mVU.prog.x86ptr - (uptr)mVU.prog.x86start)) / cacheSize * 100; ConsoleColors c = mVU.index ? Color_Orange : Color_Magenta; DevCon.WriteLn(c, "microVU%d: Cached Prog = [%03d] [PC=%04x] [List=%02d] (Cache=%3.3f%%) [%3.1fmb]", - mVU.index, prog->idx, startPC*8, mVU.prog.prog[startPC]->size()+1, cachePerc, cacheUsed); + mVU.index, prog->idx, startPC * 8, mVU.prog.prog[startPC]->size() + 1, cachePerc, cacheUsed); return prog; } // Caches Micro Program -__ri void mVUcacheProg(microVU& mVU, microProgram& prog) { - if (!mVU.index) memcpy(prog.data, mVU.regs().Micro, 0x1000); - else memcpy(prog.data, mVU.regs().Micro, 0x4000); +__ri void mVUcacheProg(microVU& mVU, microProgram& prog) +{ + if (!mVU.index) + memcpy(prog.data, mVU.regs().Micro, 0x1000); + else + memcpy(prog.data, mVU.regs().Micro, 0x4000); mVUdumpProg(mVU, prog); } // Generate Hash for partial program based on compiled ranges... -u64 mVUrangesHash(microVU& mVU, microProgram& prog) { - union { +u64 mVUrangesHash(microVU& mVU, microProgram& prog) +{ + union + { u64 v64; u32 v32[2]; } hash = {0}; std::deque::const_iterator it(prog.ranges->begin()); - for ( ; it != prog.ranges->end(); ++it) { - if((it[0].start<0)||(it[0].end<0)) { DevCon.Error("microVU%d: Negative Range![%d][%d]", mVU.index, it[0].start, it[0].end); } - for(int i = it[0].start/4; i < it[0].end/4; i++) { + for (; it != prog.ranges->end(); ++it) + { + if ((it[0].start < 0) || (it[0].end < 0)) + { + DevCon.Error("microVU%d: Negative Range![%d][%d]", mVU.index, it[0].start, it[0].end); + } + for (int i = it[0].start / 4; i < it[0].end / 4; i++) + { hash.v32[0] -= prog.data[i]; hash.v32[1] ^= prog.data[i]; } @@ -224,25 +258,31 @@ u64 mVUrangesHash(microVU& mVU, microProgram& prog) { } // Prints the ratio of unique programs to total programs -void mVUprintUniqueRatio(microVU& mVU) { +void mVUprintUniqueRatio(microVU& mVU) +{ std::vector v; - for(u32 pc = 0; pc < mProgSize/2; pc++) { + for (u32 pc = 0; pc < mProgSize / 2; pc++) + { microProgramList* list = mVU.prog.prog[pc]; - if (!list) continue; + if (!list) + continue; std::deque::iterator it(list->begin()); - for ( ; it != list->end(); ++it) { + for (; it != list->end(); ++it) + { v.push_back(mVUrangesHash(mVU, *it[0])); } } u32 total = v.size(); sortVector(v); makeUnique(v); - if (!total) return; - DevCon.WriteLn("%d / %d [%3.1f%%]", v.size(), total, 100.-(double)v.size()/(double)total*100.); + if (!total) + return; + DevCon.WriteLn("%d / %d [%3.1f%%]", v.size(), total, 100. - (double)v.size() / (double)total * 100.); } // Compare Cached microProgram to mVU.regs().Micro -__fi bool mVUcmpProg(microVU& mVU, microProgram& prog, const bool cmpWholeProg) { +__fi bool mVUcmpProg(microVU& mVU, microProgram& prog, const bool cmpWholeProg) +{ if (cmpWholeProg) { if (memcmp_mmx((u8*)prog.data, mVU.regs().Micro, mVU.microMemSize)) @@ -250,10 +290,15 @@ __fi bool mVUcmpProg(microVU& mVU, microProgram& prog, const bool cmpWholeProg) } else { - for (const auto& range : *prog.ranges) { + for (const auto& range : *prog.ranges) + { auto cmpOffset = [&](void* x) { return (u8*)x + range.start; }; - if ((range.start < 0) || (range.end < 0)) { DevCon.Error("microVU%d: Negative Range![%d][%d]", mVU.index, range.start, range.end); } - if (memcmp_mmx(cmpOffset(prog.data), cmpOffset(mVU.regs().Micro), (range.end - range.start))) { + if ((range.start < 0) || (range.end < 0)) + { + DevCon.Error("microVU%d: Negative Range![%d][%d]", mVU.index, range.start, range.end); + } + if (memcmp_mmx(cmpOffset(prog.data), cmpOffset(mVU.regs().Micro), (range.end - range.start))) + { return false; } } @@ -265,19 +310,23 @@ __fi bool mVUcmpProg(microVU& mVU, microProgram& prog, const bool cmpWholeProg) } // Searches for Cached Micro Program and sets prog.cur to it (returns entry-point to program) -_mVUt __fi void* mVUsearchProg(u32 startPC, uptr pState) { +_mVUt __fi void* mVUsearchProg(u32 startPC, uptr pState) +{ microVU& mVU = mVUx; - microProgramQuick& quick = mVU.prog.quick[mVU.regs().start_pc/8]; - microProgramList* list = mVU.prog.prog [mVU.regs().start_pc/8]; + microProgramQuick& quick = mVU.prog.quick[mVU.regs().start_pc / 8]; + microProgramList* list = mVU.prog.prog[mVU.regs().start_pc / 8]; - if(!quick.prog) { // If null, we need to search for new program + if (!quick.prog) + { // If null, we need to search for new program std::deque::iterator it(list->begin()); - for ( ; it != list->end(); ++it) { + for (; it != list->end(); ++it) + { bool b = mVUcmpProg(mVU, *it[0], 0); - - if (b) { - quick.block = it[0]->block[startPC/8]; - quick.prog = it[0]; + + if (b) + { + quick.block = it[0]->block[startPC / 8]; + quick.prog = it[0]; list->erase(it); list->push_front(quick.prog); @@ -292,12 +341,12 @@ _mVUt __fi void* mVUsearchProg(u32 startPC, uptr pState) { } // If cleared and program not found, make a new program instance - mVU.prog.cleared = 0; - mVU.prog.isSame = 1; - mVU.prog.cur = mVUcreateProg(mVU, mVU.regs().start_pc/8); - void* entryPoint = mVUblockFetch(mVU, startPC, pState); - quick.block = mVU.prog.cur->block[startPC/8]; - quick.prog = mVU.prog.cur; + mVU.prog.cleared = 0; + mVU.prog.isSame = 1; + mVU.prog.cur = mVUcreateProg(mVU, mVU.regs().start_pc / 8); + void* entryPoint = mVUblockFetch(mVU, startPC, pState); + quick.block = mVU.prog.cur->block[startPC / 8]; + quick.prog = mVU.prog.cur; list->push_front(mVU.prog.cur); //mVUprintUniqueRatio(mVU); return entryPoint; @@ -322,39 +371,57 @@ _mVUt __fi void* mVUsearchProg(u32 startPC, uptr pState) { //------------------------------------------------------------------ // recMicroVU0 / recMicroVU1 //------------------------------------------------------------------ -recMicroVU0::recMicroVU0() { m_Idx = 0; IsInterpreter = false; } -recMicroVU1::recMicroVU1() { m_Idx = 1; IsInterpreter = false; } +recMicroVU0::recMicroVU0() +{ + m_Idx = 0; + IsInterpreter = false; +} +recMicroVU1::recMicroVU1() +{ + m_Idx = 1; + IsInterpreter = false; +} void recMicroVU0::Vsync() noexcept { mVUvsyncUpdate(microVU0); } void recMicroVU1::Vsync() noexcept { mVUvsyncUpdate(microVU1); } -void recMicroVU0::Reserve() { +void recMicroVU0::Reserve() +{ if (m_Reserved.exchange(1) == 0) mVUinit(microVU0, 0); } -void recMicroVU1::Reserve() { - if (m_Reserved.exchange(1) == 0) { +void recMicroVU1::Reserve() +{ + if (m_Reserved.exchange(1) == 0) + { mVUinit(microVU1, 1); vu1Thread.Start(); } } -void recMicroVU0::Shutdown() noexcept { +void recMicroVU0::Shutdown() noexcept +{ if (m_Reserved.exchange(0) == 1) mVUclose(microVU0); } -void recMicroVU1::Shutdown() noexcept { - if (m_Reserved.exchange(0) == 1) { +void recMicroVU1::Shutdown() noexcept +{ + if (m_Reserved.exchange(0) == 1) + { vu1Thread.WaitVU(); mVUclose(microVU1); } } -void recMicroVU0::Reset() { - if(!pxAssertDev(m_Reserved, "MicroVU0 CPU Provider has not been reserved prior to reset!")) return; +void recMicroVU0::Reset() +{ + if (!pxAssertDev(m_Reserved, "MicroVU0 CPU Provider has not been reserved prior to reset!")) + return; mVUreset(microVU0, true); } -void recMicroVU1::Reset() { - if(!pxAssertDev(m_Reserved, "MicroVU1 CPU Provider has not been reserved prior to reset!")) return; +void recMicroVU1::Reset() +{ + if (!pxAssertDev(m_Reserved, "MicroVU1 CPU Provider has not been reserved prior to reset!")) + return; vu1Thread.WaitVU(); vu1Thread.Get_MTVUChanges(); mVUreset(microVU1, true); @@ -365,12 +432,14 @@ void recMicroVU0::SetStartPC(u32 startPC) VU0.start_pc = startPC; } -void recMicroVU0::Execute(u32 cycles) { +void recMicroVU0::Execute(u32 cycles) +{ pxAssert(m_Reserved); // please allocate me first! :| VU0.flags &= ~VUFLAG_MFLAGSET; - if(!(VU0.VI[REG_VPU_STAT].UL & 1)) return; + if (!(VU0.VI[REG_VPU_STAT].UL & 1)) + return; VU0.VI[REG_TPC].UL <<= 3; // Sometimes games spin on vu0, so be careful with this value @@ -378,7 +447,7 @@ void recMicroVU0::Execute(u32 cycles) { // Edit: Need to test this again, if anyone ever has a "Woody" game :p ((mVUrecCall)microVU0.startFunct)(VU0.VI[REG_TPC].UL, cycles); VU0.VI[REG_TPC].UL >>= 3; - if(microVU0.regs().flags & 0x4) + if (microVU0.regs().flags & 0x4) { microVU0.regs().flags &= ~0x4; hwIntcIrq(6); @@ -390,54 +459,65 @@ void recMicroVU1::SetStartPC(u32 startPC) VU1.start_pc = startPC; } -void recMicroVU1::Execute(u32 cycles) { +void recMicroVU1::Execute(u32 cycles) +{ pxAssert(m_Reserved); // please allocate me first! :| - if (!THREAD_VU1) { - if(!(VU0.VI[REG_VPU_STAT].UL & 0x100)) return; + if (!THREAD_VU1) + { + if (!(VU0.VI[REG_VPU_STAT].UL & 0x100)) + return; } VU1.VI[REG_TPC].UL <<= 3; ((mVUrecCall)microVU1.startFunct)(VU1.VI[REG_TPC].UL, cycles); VU1.VI[REG_TPC].UL >>= 3; - if(microVU1.regs().flags & 0x4 && !THREAD_VU1) + if (microVU1.regs().flags & 0x4 && !THREAD_VU1) { microVU1.regs().flags &= ~0x4; hwIntcIrq(7); } } -void recMicroVU0::Clear(u32 addr, u32 size) { +void recMicroVU0::Clear(u32 addr, u32 size) +{ pxAssert(m_Reserved); // please allocate me first! :| mVUclear(microVU0, addr, size); } -void recMicroVU1::Clear(u32 addr, u32 size) { +void recMicroVU1::Clear(u32 addr, u32 size) +{ pxAssert(m_Reserved); // please allocate me first! :| mVUclear(microVU1, addr, size); } -uint recMicroVU0::GetCacheReserve() const { +uint recMicroVU0::GetCacheReserve() const +{ return microVU0.cacheSize; } -uint recMicroVU1::GetCacheReserve() const { +uint recMicroVU1::GetCacheReserve() const +{ return microVU1.cacheSize; } -void recMicroVU0::SetCacheReserve(uint reserveInMegs) const { +void recMicroVU0::SetCacheReserve(uint reserveInMegs) const +{ DevCon.WriteLn("microVU0: Changing cache size [%dmb]", reserveInMegs); microVU0.cacheSize = std::min(reserveInMegs, mVU0cacheReserve); safe_delete(microVU0.cache_reserve); // I assume this unmaps the memory mVUreserveCache(microVU0); // Need rec-reset after this } -void recMicroVU1::SetCacheReserve(uint reserveInMegs) const { +void recMicroVU1::SetCacheReserve(uint reserveInMegs) const +{ DevCon.WriteLn("microVU1: Changing cache size [%dmb]", reserveInMegs); microVU1.cacheSize = std::min(reserveInMegs, mVU1cacheReserve); safe_delete(microVU1.cache_reserve); // I assume this unmaps the memory mVUreserveCache(microVU1); // Need rec-reset after this } -void recMicroVU1::ResumeXGkick() { +void recMicroVU1::ResumeXGkick() +{ pxAssert(m_Reserved); // please allocate me first! :| - if(!(VU0.VI[REG_VPU_STAT].UL & 0x100)) return; + if (!(VU0.VI[REG_VPU_STAT].UL & 0x100)) + return; ((mVUrecCallXG)microVU1.startFunctXG)(); } diff --git a/pcsx2/x86/microVU_Branch.inl b/pcsx2/x86/microVU_Branch.inl index 31a39d3a3d..91755b7a2e 100644 --- a/pcsx2/x86/microVU_Branch.inl +++ b/pcsx2/x86/microVU_Branch.inl @@ -15,59 +15,83 @@ #pragma once -extern void mVUincCycles(microVU& mVU, int x); -extern void* mVUcompile (microVU& mVU, u32 startPC, uptr pState); +extern void mVUincCycles(microVU& mVU, int x); +extern void* mVUcompile(microVU& mVU, u32 startPC, uptr pState); extern void* mVUcompileSingleInstruction(microVU& mVU, u32 startPC, uptr pState, microFlagCycles& mFC); -__fi int getLastFlagInst(microRegInfo& pState, int* xFlag, int flagType, int isEbit) { - if (isEbit) return findFlagInst(xFlag, 0x7fffffff); - if (pState.needExactMatch & (1<> (2*flagType+2)) & 3) - 1) & 3; +__fi int getLastFlagInst(microRegInfo& pState, int* xFlag, int flagType, int isEbit) +{ + if (isEbit) + return findFlagInst(xFlag, 0x7fffffff); + if (pState.needExactMatch & (1 << flagType)) + return 3; + return (((pState.flagInfo >> (2 * flagType + 2)) & 3) - 1) & 3; } -void mVU0clearlpStateJIT() { if (!microVU0.prog.cleared) memzero(microVU0.prog.lpState); } -void mVU1clearlpStateJIT() { if (!microVU1.prog.cleared) memzero(microVU1.prog.lpState); } +void mVU0clearlpStateJIT() +{ + if (!microVU0.prog.cleared) + memzero(microVU0.prog.lpState); +} +void mVU1clearlpStateJIT() +{ + if (!microVU1.prog.cleared) + memzero(microVU1.prog.lpState); +} -void mVUDTendProgram(mV, microFlagCycles* mFC, int isEbit) { +void mVUDTendProgram(mV, microFlagCycles* mFC, int isEbit) +{ int fStatus = getLastFlagInst(mVUpBlock->pState, mFC->xStatus, 0, isEbit); - int fMac = getLastFlagInst(mVUpBlock->pState, mFC->xMac, 1, isEbit); - int fClip = getLastFlagInst(mVUpBlock->pState, mFC->xClip, 2, isEbit); - int qInst = 0; - int pInst = 0; + int fMac = getLastFlagInst(mVUpBlock->pState, mFC->xMac, 1, isEbit); + int fClip = getLastFlagInst(mVUpBlock->pState, mFC->xClip, 2, isEbit); + int qInst = 0; + int pInst = 0; microBlock stateBackup; memcpy(&stateBackup, &mVUregs, sizeof(mVUregs)); //backup the state, it's about to get screwed with. mVU.regAlloc->TDwritebackAll(); //Writing back ok, invalidating early kills the rec, so don't do it :P - if (isEbit) { + if (isEbit) + { /*memzero(mVUinfo); memzero(mVUregsTemp);*/ mVUincCycles(mVU, 100); // Ensures Valid P/Q instances (And sets all cycle data to 0) mVUcycles -= 100; qInst = mVU.q; pInst = mVU.p; - if (mVUinfo.doDivFlag) { + if (mVUinfo.doDivFlag) + { sFLAG.doFlag = true; - sFLAG.write = fStatus; + sFLAG.write = fStatus; mVUdivSet(mVU); } //Run any pending XGKick, providing we've got to it. - if (mVUinfo.doXGKICK && xPC >= mVUinfo.XGKICKPC) { + if (mVUinfo.doXGKICK && xPC >= mVUinfo.XGKICKPC) + { mVU_XGKICK_DELAY(mVU); } - if (!isVU1) xFastCall((void*)mVU0clearlpStateJIT); - else xFastCall((void*)mVU1clearlpStateJIT); + if (!isVU1) + xFastCall((void*)mVU0clearlpStateJIT); + else + xFastCall((void*)mVU1clearlpStateJIT); } // Save P/Q Regs - if (qInst) { xPSHUF.D(xmmPQ, xmmPQ, 0xe1); } + if (qInst) + { + xPSHUF.D(xmmPQ, xmmPQ, 0xe1); + } xMOVSS(ptr32[&mVU.regs().VI[REG_Q].UL], xmmPQ); xPSHUF.D(xmmPQ, xmmPQ, 0xe1); xMOVSS(ptr32[&mVU.regs().pending_q], xmmPQ); xPSHUF.D(xmmPQ, xmmPQ, 0xe1); - if (isVU1) { - if (pInst) { xPSHUF.D(xmmPQ, xmmPQ, 0xb4); } // Swap Pending/Active P + if (isVU1) + { + if (pInst) + { + xPSHUF.D(xmmPQ, xmmPQ, 0xb4); + } // Swap Pending/Active P xPSHUF.D(xmmPQ, xmmPQ, 0xC6); // 3 0 1 2 xMOVSS(ptr32[&mVU.regs().VI[REG_P].UL], xmmPQ); xPSHUF.D(xmmPQ, xmmPQ, 0x87); // 0 2 1 3 @@ -83,7 +107,8 @@ void mVUDTendProgram(mV, microFlagCycles* mFC, int isEbit) { xMOV(ptr32[&mVU.regs().VI[REG_MAC_FLAG].UL], gprT1); xMOV(ptr32[&mVU.regs().VI[REG_CLIP_FLAG].UL], gprT2); - if (!isEbit) { // Backup flag instances + if (!isEbit) + { // Backup flag instances xMOVAPS(xmmT1, ptr128[mVU.macFlag]); xMOVAPS(ptr128[&mVU.regs().micro_macflags], xmmT1); xMOVAPS(xmmT1, ptr128[mVU.clipFlag]); @@ -93,7 +118,9 @@ void mVUDTendProgram(mV, microFlagCycles* mFC, int isEbit) { xMOV(ptr32[&mVU.regs().micro_statusflags[1]], gprF1); xMOV(ptr32[&mVU.regs().micro_statusflags[2]], gprF2); xMOV(ptr32[&mVU.regs().micro_statusflags[3]], gprF3); - } else { // Flush flag instances + } + else + { // Flush flag instances xMOVDZX(xmmT1, ptr32[&mVU.regs().VI[REG_CLIP_FLAG].UL]); xSHUF.PS(xmmT1, xmmT1, 0); xMOVAPS(ptr128[&mVU.regs().micro_clipflags], xmmT1); @@ -107,9 +134,11 @@ void mVUDTendProgram(mV, microFlagCycles* mFC, int isEbit) { xMOVAPS(ptr128[&mVU.regs().micro_statusflags], xmmT1); } - if (isEbit) { // Clear 'is busy' Flags + if (isEbit) + { // Clear 'is busy' Flags xMOV(ptr32[&mVU.regs().nextBlockCycles], 0); - if (!mVU.index || !THREAD_VU1) { + if (!mVU.index || !THREAD_VU1) + { xAND(ptr32[&VU0.VI[REG_VPU_STAT].UL], (isVU1 ? ~0x100 : ~0x001)); // VBS0/VBS1 flag } else @@ -117,41 +146,46 @@ void mVUDTendProgram(mV, microFlagCycles* mFC, int isEbit) { } else xMOV(ptr32[&mVU.regs().nextBlockCycles], mVUcycles); - - if (isEbit != 2) { // Save PC, and Jump to Exit Point + + if (isEbit != 2) + { // Save PC, and Jump to Exit Point xMOV(ptr32[&mVU.regs().VI[REG_TPC].UL], xPC); xJMP(mVU.exitFunct); } memcpy(&mVUregs, &stateBackup, sizeof(mVUregs)); //Restore the state for the rest of the recompile } -void mVUendProgram(mV, microFlagCycles* mFC, int isEbit) { +void mVUendProgram(mV, microFlagCycles* mFC, int isEbit) +{ int fStatus = getLastFlagInst(mVUpBlock->pState, mFC->xStatus, 0, isEbit && isEbit != 3); - int fMac = getLastFlagInst(mVUpBlock->pState, mFC->xMac, 1, isEbit && isEbit != 3); - int fClip = getLastFlagInst(mVUpBlock->pState, mFC->xClip, 2, isEbit && isEbit != 3); - int qInst = 0; - int pInst = 0; + int fMac = getLastFlagInst(mVUpBlock->pState, mFC->xMac, 1, isEbit && isEbit != 3); + int fClip = getLastFlagInst(mVUpBlock->pState, mFC->xClip, 2, isEbit && isEbit != 3); + int qInst = 0; + int pInst = 0; microBlock stateBackup; memcpy(&stateBackup, &mVUregs, sizeof(mVUregs)); //backup the state, it's about to get screwed with. - if(!isEbit || isEbit == 3) + if (!isEbit || isEbit == 3) mVU.regAlloc->TDwritebackAll(); //Writing back ok, invalidating early kills the rec, so don't do it :P else mVU.regAlloc->flushAll(); - if (isEbit && isEbit != 3) { + if (isEbit && isEbit != 3) + { memzero(mVUinfo); memzero(mVUregsTemp); mVUincCycles(mVU, 100); // Ensures Valid P/Q instances (And sets all cycle data to 0) mVUcycles -= 100; qInst = mVU.q; pInst = mVU.p; - if (mVUinfo.doDivFlag) { + if (mVUinfo.doDivFlag) + { sFLAG.doFlag = true; - sFLAG.write = fStatus; + sFLAG.write = fStatus; mVUdivSet(mVU); } - if (mVUinfo.doXGKICK) { + if (mVUinfo.doXGKICK) + { mVU_XGKICK_DELAY(mVU); } if (!isVU1) @@ -161,14 +195,21 @@ void mVUendProgram(mV, microFlagCycles* mFC, int isEbit) { } // Save P/Q Regs - if (qInst) { xPSHUF.D(xmmPQ, xmmPQ, 0xe1); } + if (qInst) + { + xPSHUF.D(xmmPQ, xmmPQ, 0xe1); + } xMOVSS(ptr32[&mVU.regs().VI[REG_Q].UL], xmmPQ); xPSHUF.D(xmmPQ, xmmPQ, 0xe1); xMOVSS(ptr32[&mVU.regs().pending_q], xmmPQ); xPSHUF.D(xmmPQ, xmmPQ, 0xe1); - if (isVU1) { - if (pInst) { xPSHUF.D(xmmPQ, xmmPQ, 0xb4); } // Swap Pending/Active P + if (isVU1) + { + if (pInst) + { + xPSHUF.D(xmmPQ, xmmPQ, 0xb4); + } // Swap Pending/Active P xPSHUF.D(xmmPQ, xmmPQ, 0xC6); // 3 0 1 2 xMOVSS(ptr32[&mVU.regs().VI[REG_P].UL], xmmPQ); xPSHUF.D(xmmPQ, xmmPQ, 0x87); // 0 2 1 3 @@ -181,10 +222,11 @@ void mVUendProgram(mV, microFlagCycles* mFC, int isEbit) { xMOV(ptr32[&mVU.regs().VI[REG_STATUS_FLAG].UL], gprT1); mVUallocMFLAGa(mVU, gprT1, fMac); mVUallocCFLAGa(mVU, gprT2, fClip); - xMOV(ptr32[&mVU.regs().VI[REG_MAC_FLAG].UL], gprT1); - xMOV(ptr32[&mVU.regs().VI[REG_CLIP_FLAG].UL], gprT2); + xMOV(ptr32[&mVU.regs().VI[REG_MAC_FLAG].UL], gprT1); + xMOV(ptr32[&mVU.regs().VI[REG_CLIP_FLAG].UL], gprT2); - if (!isEbit || isEbit == 3) { // Backup flag instances + if (!isEbit || isEbit == 3) + { // Backup flag instances xMOVAPS(xmmT1, ptr128[mVU.macFlag]); xMOVAPS(ptr128[&mVU.regs().micro_macflags], xmmT1); xMOVAPS(xmmT1, ptr128[mVU.clipFlag]); @@ -195,7 +237,8 @@ void mVUendProgram(mV, microFlagCycles* mFC, int isEbit) { xMOV(ptr32[&mVU.regs().micro_statusflags[2]], gprF2); xMOV(ptr32[&mVU.regs().micro_statusflags[3]], gprF3); } - else { // Flush flag instances + else + { // Flush flag instances xMOVDZX(xmmT1, ptr32[&mVU.regs().VI[REG_CLIP_FLAG].UL]); xSHUF.PS(xmmT1, xmmT1, 0); xMOVAPS(ptr128[&mVU.regs().micro_clipflags], xmmT1); @@ -210,9 +253,11 @@ void mVUendProgram(mV, microFlagCycles* mFC, int isEbit) { } - if ((isEbit && isEbit != 3)) { // Clear 'is busy' Flags + if ((isEbit && isEbit != 3)) + { // Clear 'is busy' Flags xMOV(ptr32[&mVU.regs().nextBlockCycles], 0); - if (!mVU.index || !THREAD_VU1) { + if (!mVU.index || !THREAD_VU1) + { xAND(ptr32[&VU0.VI[REG_VPU_STAT].UL], (isVU1 ? ~0x100 : ~0x001)); // VBS0/VBS1 flag } else @@ -221,7 +266,8 @@ void mVUendProgram(mV, microFlagCycles* mFC, int isEbit) { else xMOV(ptr32[&mVU.regs().nextBlockCycles], mVUcycles); - if (isEbit != 2 && isEbit != 3) { // Save PC, and Jump to Exit Point + if (isEbit != 2 && isEbit != 3) + { // Save PC, and Jump to Exit Point xMOV(ptr32[&mVU.regs().VI[REG_TPC].UL], xPC); xJMP(mVU.exitFunct); } @@ -229,39 +275,56 @@ void mVUendProgram(mV, microFlagCycles* mFC, int isEbit) { } // Recompiles Code for Proper Flags and Q/P regs on Block Linkings -void mVUsetupBranch(mV, microFlagCycles& mFC) { - - mVU.regAlloc->flushAll(); // Flush Allocated Regs - mVUsetupFlags(mVU, mFC); // Shuffle Flag Instances +void mVUsetupBranch(mV, microFlagCycles& mFC) +{ + + mVU.regAlloc->flushAll(); // Flush Allocated Regs + mVUsetupFlags(mVU, mFC); // Shuffle Flag Instances // Shuffle P/Q regs since every block starts at instance #0 - if (mVU.p || mVU.q) { xPSHUF.D(xmmPQ, xmmPQ, shufflePQ); } + if (mVU.p || mVU.q) + { + xPSHUF.D(xmmPQ, xmmPQ, shufflePQ); + } mVU.p = 0, mVU.q = 0; } -void normBranchCompile(microVU& mVU, u32 branchPC) { +void normBranchCompile(microVU& mVU, u32 branchPC) +{ microBlock* pBlock; - blockCreate(branchPC/8); - pBlock = mVUblocks[branchPC/8]->search((microRegInfo*)&mVUregs); - if (pBlock) { xJMP(pBlock->x86ptrStart); } - else { mVUcompile(mVU, branchPC, (uptr)&mVUregs); } + blockCreate(branchPC / 8); + pBlock = mVUblocks[branchPC / 8]->search((microRegInfo*)&mVUregs); + if (pBlock) + { + xJMP(pBlock->x86ptrStart); + } + else + { + mVUcompile(mVU, branchPC, (uptr)&mVUregs); + } } -void normJumpCompile(mV, microFlagCycles& mFC, bool isEvilJump) { +void normJumpCompile(mV, microFlagCycles& mFC, bool isEvilJump) +{ memcpy(&mVUpBlock->pStateEnd, &mVUregs, sizeof(microRegInfo)); mVUsetupBranch(mVU, mFC); mVUbackupRegs(mVU); - if(!mVUpBlock->jumpCache) { // Create the jump cache for this block - mVUpBlock->jumpCache = new microJumpCache[mProgSize/2]; + if (!mVUpBlock->jumpCache) + { // Create the jump cache for this block + mVUpBlock->jumpCache = new microJumpCache[mProgSize / 2]; } - if (isEvilJump) xMOV(arg1regd, ptr32[&mVU.evilBranch]); - else xMOV(arg1regd, ptr32[&mVU.branch]); - if (doJumpCaching) xLoadFarAddr(arg2reg, mVUpBlock); - else xLoadFarAddr(arg2reg, &mVUpBlock->pStateEnd); + if (isEvilJump) + xMOV(arg1regd, ptr32[&mVU.evilBranch]); + else + xMOV(arg1regd, ptr32[&mVU.branch]); + if (doJumpCaching) + xLoadFarAddr(arg2reg, mVUpBlock); + else + xLoadFarAddr(arg2reg, &mVUpBlock->pStateEnd); - if(mVUup.eBit && isEvilJump)// E-bit EvilJump + if (mVUup.eBit && isEvilJump) // E-bit EvilJump { //Xtreme G 3 does 2 conditional jumps, the first contains an E Bit on the first instruction //So if it is taken, you need to end the program, else you get infinite loops. @@ -269,44 +332,49 @@ void normJumpCompile(mV, microFlagCycles& mFC, bool isEvilJump) { xMOV(ptr32[&mVU.regs().VI[REG_TPC].UL], arg1regd); xJMP(mVU.exitFunct); } - - if (!mVU.index) xFastCall((void*)(void(*)())mVUcompileJIT<0>, arg1reg, arg2reg); //(u32 startPC, uptr pState) - else xFastCall((void*)(void(*)())mVUcompileJIT<1>, arg1reg, arg2reg); + + if (!mVU.index) + xFastCall((void*)(void (*)())mVUcompileJIT<0>, arg1reg, arg2reg); //(u32 startPC, uptr pState) + else + xFastCall((void*)(void (*)())mVUcompileJIT<1>, arg1reg, arg2reg); mVUrestoreRegs(mVU); - xJMP(gprT1q); // Jump to rec-code address + xJMP(gprT1q); // Jump to rec-code address } -void normBranch(mV, microFlagCycles& mFC) { +void normBranch(mV, microFlagCycles& mFC) +{ // E-bit or T-Bit or D-Bit Branch - if (mVUup.dBit && doDBitHandling) + if (mVUup.dBit && doDBitHandling) { u32 tempPC = iPC; xTEST(ptr32[&VU0.VI[REG_FBRST].UL], (isVU1 ? 0x400 : 0x4)); xForwardJump32 eJMP(Jcc_Zero); - if (!mVU.index || !THREAD_VU1) { + if (!mVU.index || !THREAD_VU1) + { xOR(ptr32[&VU0.VI[REG_VPU_STAT].UL], (isVU1 ? 0x200 : 0x2)); xOR(ptr32[&mVU.regs().flags], VUFLAG_INTCINTERRUPT); } - iPC = branchAddr(mVU)/4; + iPC = branchAddr(mVU) / 4; mVUDTendProgram(mVU, &mFC, 1); eJMP.SetTarget(); - iPC = tempPC; + iPC = tempPC; } if (mVUup.tBit) { u32 tempPC = iPC; xTEST(ptr32[&VU0.VI[REG_FBRST].UL], (isVU1 ? 0x800 : 0x8)); xForwardJump32 eJMP(Jcc_Zero); - if (!mVU.index || !THREAD_VU1) { + if (!mVU.index || !THREAD_VU1) + { xOR(ptr32[&VU0.VI[REG_VPU_STAT].UL], (isVU1 ? 0x400 : 0x4)); xOR(ptr32[&mVU.regs().flags], VUFLAG_INTCINTERRUPT); } - iPC = branchAddr(mVU)/4; + iPC = branchAddr(mVU) / 4; mVUDTendProgram(mVU, &mFC, 1); eJMP.SetTarget(); - iPC = tempPC; + iPC = tempPC; } if (mVUup.mBit) { @@ -314,7 +382,8 @@ void normBranch(mV, microFlagCycles& mFC) { u32 tempPC = iPC; u32* cpS = (u32*)&mVUregs; u32* lpS = (u32*)&mVU.prog.lpState; - for (size_t i = 0; i < (sizeof(microRegInfo) - 4) / 4; i++, lpS++, cpS++) { + for (size_t i = 0; i < (sizeof(microRegInfo) - 4) / 4; i++, lpS++, cpS++) + { xMOV(ptr32[lpS], cpS[0]); } mVUsetupBranch(mVU, mFC); @@ -324,30 +393,30 @@ void normBranch(mV, microFlagCycles& mFC) { xJMP(mVU.exitFunct); iPC = tempPC; } - if (mVUup.eBit) { - if(mVUlow.badBranch) - DevCon.Warning("End on evil Unconditional branch! - Not implemented! - If game broken report to PCSX2 Team"); - - iPC = branchAddr(mVU)/4; - mVUendProgram(mVU, &mFC, 1); - return; - } - - if(mVUlow.badBranch) + if (mVUup.eBit) { - u32 badBranchAddr = branchAddr(mVU)+8; + if (mVUlow.badBranch) + DevCon.Warning("End on evil Unconditional branch! - Not implemented! - If game broken report to PCSX2 Team"); + + iPC = branchAddr(mVU) / 4; + mVUendProgram(mVU, &mFC, 1); + return; + } + + if (mVUlow.badBranch) + { + u32 badBranchAddr = branchAddr(mVU) + 8; incPC(3); - if(mVUlow.branch == 2 || mVUlow.branch == 10) //Delay slot branch needs linking + if (mVUlow.branch == 2 || mVUlow.branch == 10) //Delay slot branch needs linking { DevCon.Warning("Found %s in delay slot, linking - If game broken report to PCSX2 Team", mVUlow.branch == 2 ? "BAL" : "JALR"); xMOV(gprT3, badBranchAddr); xSHR(gprT3, 3); mVUallocVIb(mVU, gprT3, _It_); - } incPC(-3); } - + // Normal Branch mVUsetupBranch(mVU, mFC); normBranchCompile(mVU, branchAddr(mVU)); @@ -357,31 +426,32 @@ void normBranch(mV, microFlagCycles& mFC) { //This handles JALR/BAL in the delay slot of a conditional branch. We do this because the normal handling //Doesn't seem to work properly, even if the link is made to the correct address, so we do it manually instead. //Normally EvilBlock handles all this stuff, but something to do with conditionals and links don't quite work right :/ -void condJumpProcessingEvil(mV, microFlagCycles& mFC, int JMPcc) { +void condJumpProcessingEvil(mV, microFlagCycles& mFC, int JMPcc) +{ - u32 bPC = iPC-1; // mVUcompile can modify iPC, mVUpBlock, and mVUregs so back them up + u32 bPC = iPC - 1; // mVUcompile can modify iPC, mVUpBlock, and mVUregs so back them up u32 badBranchAddr; - iPC = bPC-2; + iPC = bPC - 2; setCode(); badBranchAddr = branchAddr(mVU); xCMP(ptr16[&mVU.branch], 0); - + xForwardJump32 eJMP(xInvertCond((JccComparisonType)JMPcc)); mVUcompileSingleInstruction(mVU, badBranchAddr, (uptr)&mVUregs, mFC); - xMOV(gprT3, badBranchAddr+8); + xMOV(gprT3, badBranchAddr + 8); iPC = bPC; setCode(); xSHR(gprT3, 3); mVUallocVIb(mVU, gprT3, _It_); //Link to branch addr + 8 - + normJumpCompile(mVU, mFC, true); //Compile evil branch, just in time! - + eJMP.SetTarget(); - - incPC(2); // Point to delay slot of evil Branch (as the original branch isn't taken) + + incPC(2); // Point to delay slot of evil Branch (as the original branch isn't taken) mVUcompileSingleInstruction(mVU, xPC, (uptr)&mVUregs, mFC); xMOV(gprT3, xPC); @@ -389,55 +459,57 @@ void condJumpProcessingEvil(mV, microFlagCycles& mFC, int JMPcc) { setCode(); xSHR(gprT3, 3); mVUallocVIb(mVU, gprT3, _It_); - - normJumpCompile(mVU, mFC, true); //Compile evil branch, just in time! + normJumpCompile(mVU, mFC, true); //Compile evil branch, just in time! } -void condBranch(mV, microFlagCycles& mFC, int JMPcc) { +void condBranch(mV, microFlagCycles& mFC, int JMPcc) +{ mVUsetupBranch(mVU, mFC); - + if (mVUup.tBit) { DevCon.Warning("T-Bit on branch, please report if broken"); u32 tempPC = iPC; xTEST(ptr32[&VU0.VI[REG_FBRST].UL], (isVU1 ? 0x800 : 0x8)); xForwardJump32 eJMP(Jcc_Zero); - if (!mVU.index || !THREAD_VU1) { + if (!mVU.index || !THREAD_VU1) + { xOR(ptr32[&VU0.VI[REG_VPU_STAT].UL], (isVU1 ? 0x400 : 0x4)); xOR(ptr32[&mVU.regs().flags], VUFLAG_INTCINTERRUPT); } mVUDTendProgram(mVU, &mFC, 2); xCMP(ptr16[&mVU.branch], 0); xForwardJump32 tJMP(xInvertCond((JccComparisonType)JMPcc)); - incPC(4); // Set PC to First instruction of Non-Taken Side - xMOV(ptr32[&mVU.regs().VI[REG_TPC].UL], xPC); - xJMP(mVU.exitFunct); + incPC(4); // Set PC to First instruction of Non-Taken Side + xMOV(ptr32[&mVU.regs().VI[REG_TPC].UL], xPC); + xJMP(mVU.exitFunct); tJMP.SetTarget(); incPC(-4); // Go Back to Branch Opcode to get branchAddr - iPC = branchAddr(mVU)/4; + iPC = branchAddr(mVU) / 4; xMOV(ptr32[&mVU.regs().VI[REG_TPC].UL], xPC); xJMP(mVU.exitFunct); eJMP.SetTarget(); - iPC = tempPC; + iPC = tempPC; } - if (mVUup.dBit && doDBitHandling) + if (mVUup.dBit && doDBitHandling) { u32 tempPC = iPC; xTEST(ptr32[&VU0.VI[REG_FBRST].UL], (isVU1 ? 0x400 : 0x4)); xForwardJump32 eJMP(Jcc_Zero); - if (!mVU.index || !THREAD_VU1) { + if (!mVU.index || !THREAD_VU1) + { xOR(ptr32[&VU0.VI[REG_VPU_STAT].UL], (isVU1 ? 0x200 : 0x2)); xOR(ptr32[&mVU.regs().flags], VUFLAG_INTCINTERRUPT); } mVUDTendProgram(mVU, &mFC, 2); xCMP(ptr16[&mVU.branch], 0); xForwardJump32 dJMP(xInvertCond((JccComparisonType)JMPcc)); - incPC(4); // Set PC to First instruction of Non-Taken Side - xMOV(ptr32[&mVU.regs().VI[REG_TPC].UL], xPC); - xJMP(mVU.exitFunct); + incPC(4); // Set PC to First instruction of Non-Taken Side + xMOV(ptr32[&mVU.regs().VI[REG_TPC].UL], xPC); + xJMP(mVU.exitFunct); dJMP.SetTarget(); incPC(-4); // Go Back to Branch Opcode to get branchAddr - iPC = branchAddr(mVU)/4; + iPC = branchAddr(mVU) / 4; xMOV(ptr32[&mVU.regs().VI[REG_TPC].UL], xPC); xJMP(mVU.exitFunct); eJMP.SetTarget(); @@ -448,7 +520,8 @@ void condBranch(mV, microFlagCycles& mFC, int JMPcc) { u32 tempPC = iPC; u32* cpS = (u32*)&mVUregs; u32* lpS = (u32*)&mVU.prog.lpState; - for (size_t i = 0; i < (sizeof(microRegInfo) - 4) / 4; i++, lpS++, cpS++) { + for (size_t i = 0; i < (sizeof(microRegInfo) - 4) / 4; i++, lpS++, cpS++) + { xMOV(ptr32[lpS], cpS[0]); } mVUendProgram(mVU, &mFC, 3); @@ -464,8 +537,9 @@ void condBranch(mV, microFlagCycles& mFC, int JMPcc) { xJMP(mVU.exitFunct); iPC = tempPC; } - if (mVUup.eBit) { // Conditional Branch With E-Bit Set - if(mVUlow.evilBranch) + if (mVUup.eBit) + { // Conditional Branch With E-Bit Set + if (mVUlow.evilBranch) DevCon.Warning("End on evil branch! - Not implemented! - If game broken report to PCSX2 Team"); mVUendProgram(mVU, &mFC, 2); @@ -473,25 +547,26 @@ void condBranch(mV, microFlagCycles& mFC, int JMPcc) { incPC(3); xForwardJump32 eJMP(((JccComparisonType)JMPcc)); - incPC(1); // Set PC to First instruction of Non-Taken Side - xMOV(ptr32[&mVU.regs().VI[REG_TPC].UL], xPC); - xJMP(mVU.exitFunct); + incPC(1); // Set PC to First instruction of Non-Taken Side + 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(mVU)/4; + iPC = branchAddr(mVU) / 4; xMOV(ptr32[&mVU.regs().VI[REG_TPC].UL], xPC); xJMP(mVU.exitFunct); return; } - else { // Normal Conditional Branch + else + { // Normal Conditional Branch xCMP(ptr16[&mVU.branch], 0); incPC(3); - if(mVUlow.evilBranch) //We are dealing with an evil evil block, so we need to process this slightly differently + if (mVUlow.evilBranch) //We are dealing with an evil evil block, so we need to process this slightly differently { - - if(mVUlow.branch == 10 || mVUlow.branch == 2) //Evil branch is a jump of some measure + + if (mVUlow.branch == 10 || mVUlow.branch == 2) //Evil branch is a jump of some measure { //Because of how it is linked, we need to make sure the target is recompiled if taken condJumpProcessingEvil(mVU, mFC, JMPcc); @@ -500,21 +575,23 @@ void condBranch(mV, microFlagCycles& mFC, int JMPcc) { } microBlock* bBlock; incPC2(1); // Check if Branch Non-Taken Side has already been recompiled - blockCreate(iPC/2); - bBlock = mVUblocks[iPC/2]->search((microRegInfo*)&mVUregs); + blockCreate(iPC / 2); + bBlock = mVUblocks[iPC / 2]->search((microRegInfo*)&mVUregs); incPC2(-1); - if (bBlock) { // Branch non-taken has already been compiled + if (bBlock) + { // Branch non-taken has already been compiled xJcc(xInvertCond((JccComparisonType)JMPcc), bBlock->x86ptrStart); incPC(-3); // Go back to branch opcode (to get branch imm addr) normBranchCompile(mVU, branchAddr(mVU)); } - else { - s32* ajmp = xJcc32((JccComparisonType)JMPcc); + else + { + s32* ajmp = xJcc32((JccComparisonType)JMPcc); u32 bPC = iPC; // mVUcompile can modify iPC, mVUpBlock, and mVUregs so back them up microBlock* pBlock = mVUpBlock; memcpy(&pBlock->pStateEnd, &mVUregs, sizeof(microRegInfo)); - incPC2(1); // Get PC for branch not-taken + incPC2(1); // Get PC for branch not-taken mVUcompile(mVU, xPC, (uptr)&mVUregs); iPC = bPC; @@ -525,26 +602,29 @@ void condBranch(mV, microFlagCycles& mFC, int JMPcc) { } } -void normJump(mV, microFlagCycles& mFC) { +void normJump(mV, microFlagCycles& mFC) +{ if (mVUup.mBit) { DevCon.Warning("M-Bit on Jump! Please report if broken"); } - if (mVUlow.constJump.isValid) { // Jump Address is Constant - if (mVUup.eBit) { // E-bit Jump - iPC = (mVUlow.constJump.regValue*2) & (mVU.progMemMask); + if (mVUlow.constJump.isValid) + { // Jump Address is Constant + if (mVUup.eBit) + { // E-bit Jump + iPC = (mVUlow.constJump.regValue * 2) & (mVU.progMemMask); mVUendProgram(mVU, &mFC, 1); return; } - int jumpAddr = (mVUlow.constJump.regValue*8)&(mVU.microMemSize-8); + int jumpAddr = (mVUlow.constJump.regValue * 8) & (mVU.microMemSize - 8); mVUsetupBranch(mVU, mFC); normBranchCompile(mVU, jumpAddr); return; } - if(mVUlow.badBranch) - { + if (mVUlow.badBranch) + { incPC(3); - if(mVUlow.branch == 2 || mVUlow.branch == 10) //Delay slot BAL needs linking, only need to do BAL here, JALR done earlier + if (mVUlow.branch == 2 || mVUlow.branch == 10) //Delay slot BAL needs linking, only need to do BAL here, JALR done earlier { DevCon.Warning("Found %x in delay slot, linking - If game broken report to PCSX2 Team", mVUlow.branch == 2 ? "BAL" : "JALR"); incPC(-2); @@ -553,15 +633,15 @@ void normJump(mV, microFlagCycles& mFC) { xSHR(gprT1, 3); incPC(2); mVUallocVIb(mVU, gprT1, _It_); - } incPC(-3); } - if (mVUup.dBit && doDBitHandling) + if (mVUup.dBit && doDBitHandling) { xTEST(ptr32[&VU0.VI[REG_FBRST].UL], (isVU1 ? 0x400 : 0x4)); xForwardJump32 eJMP(Jcc_Zero); - if (!mVU.index || !THREAD_VU1) { + if (!mVU.index || !THREAD_VU1) + { xOR(ptr32[&VU0.VI[REG_VPU_STAT].UL], (isVU1 ? 0x200 : 0x2)); xOR(ptr32[&mVU.regs().flags], VUFLAG_INTCINTERRUPT); } @@ -569,13 +649,14 @@ void normJump(mV, microFlagCycles& mFC) { xMOV(gprT1, ptr32[&mVU.branch]); xMOV(ptr32[&mVU.regs().VI[REG_TPC].UL], gprT1); xJMP(mVU.exitFunct); - eJMP.SetTarget(); + eJMP.SetTarget(); } if (mVUup.tBit) { xTEST(ptr32[&VU0.VI[REG_FBRST].UL], (isVU1 ? 0x800 : 0x8)); xForwardJump32 eJMP(Jcc_Zero); - if (!mVU.index || !THREAD_VU1) { + if (!mVU.index || !THREAD_VU1) + { xOR(ptr32[&VU0.VI[REG_VPU_STAT].UL], (isVU1 ? 0x400 : 0x4)); xOR(ptr32[&mVU.regs().flags], VUFLAG_INTCINTERRUPT); } @@ -585,13 +666,15 @@ void normJump(mV, microFlagCycles& mFC) { xJMP(mVU.exitFunct); eJMP.SetTarget(); } - if (mVUup.eBit) { // E-bit Jump + if (mVUup.eBit) + { // E-bit Jump mVUendProgram(mVU, &mFC, 2); xMOV(gprT1, ptr32[&mVU.branch]); xMOV(ptr32[&mVU.regs().VI[REG_TPC].UL], gprT1); xJMP(mVU.exitFunct); } - else { + else + { normJumpCompile(mVU, mFC, false); } } diff --git a/pcsx2/x86/microVU_Macro.inl b/pcsx2/x86/microVU_Macro.inl index f96c142744..eeb62d06a7 100644 --- a/pcsx2/x86/microVU_Macro.inl +++ b/pcsx2/x86/microVU_Macro.inl @@ -29,7 +29,8 @@ using namespace R5900::Dynarec; #define printCOP2(...) (void)0 //#define printCOP2 DevCon.Status -void setupMacroOp(int mode, const char* opName) { +void setupMacroOp(int mode, const char* opName) +{ printCOP2(opName); microVU0.cop2 = 1; microVU0.prog.IRinfo.curPC = 0; @@ -37,20 +38,23 @@ void setupMacroOp(int mode, const char* opName) { memset(µVU0.prog.IRinfo.info[0], 0, sizeof(microVU0.prog.IRinfo.info[0])); iFlushCall(FLUSH_EVERYTHING); microVU0.regAlloc->reset(); - if (mode & 0x01) { // Q-Reg will be Read + if (mode & 0x01) + { // Q-Reg will be Read xMOVSSZX(xmmPQ, ptr32[&vu0Regs.VI[REG_Q].UL]); } - if (mode & 0x08) { // Clip Instruction - microVU0.prog.IRinfo.info[0].cFlag.write = 0xff; + if (mode & 0x08) + { // Clip Instruction + microVU0.prog.IRinfo.info[0].cFlag.write = 0xff; microVU0.prog.IRinfo.info[0].cFlag.lastWrite = 0xff; } - if (mode & 0x10) { // Update Status/Mac Flags - microVU0.prog.IRinfo.info[0].sFlag.doFlag = true; + if (mode & 0x10) + { // Update Status/Mac Flags + microVU0.prog.IRinfo.info[0].sFlag.doFlag = true; microVU0.prog.IRinfo.info[0].sFlag.doNonSticky = true; - microVU0.prog.IRinfo.info[0].sFlag.write = 0; - microVU0.prog.IRinfo.info[0].sFlag.lastWrite = 0; - microVU0.prog.IRinfo.info[0].mFlag.doFlag = true; - microVU0.prog.IRinfo.info[0].mFlag.write = 0xff; + microVU0.prog.IRinfo.info[0].sFlag.write = 0; + microVU0.prog.IRinfo.info[0].sFlag.lastWrite = 0; + microVU0.prog.IRinfo.info[0].mFlag.doFlag = true; + microVU0.prog.IRinfo.info[0].mFlag.write = 0xff; //Denormalize mVUallocSFLAGd(&vu0Regs.VI[REG_STATUS_FLAG].UL); @@ -58,18 +62,22 @@ void setupMacroOp(int mode, const char* opName) { } } -void endMacroOp(int mode) { - if (mode & 0x02) { // Q-Reg was Written To +void endMacroOp(int mode) +{ + if (mode & 0x02) + { // Q-Reg was Written To xMOVSS(ptr32[&vu0Regs.VI[REG_Q].UL], xmmPQ); } - if (mode & 0x10) { // Status/Mac Flags were Updated + if (mode & 0x10) + { // Status/Mac Flags were Updated // Normalize mVUallocSFLAGc(eax, gprF0, 0); xMOV(ptr32[&vu0Regs.VI[REG_STATUS_FLAG].UL], eax); } microVU0.regAlloc->flushAll(); - if (mode & 0x10) { // Update VU0 Status/Mac instances after flush to avoid corrupting anything + if (mode & 0x10) + { // Update VU0 Status/Mac instances after flush to avoid corrupting anything mVUallocSFLAGd(&vu0Regs.VI[REG_STATUS_FLAG].UL); xMOVDZX(xmmT1, eax); xSHUF.PS(xmmT1, xmmT1, 0); @@ -82,23 +90,30 @@ void endMacroOp(int mode) { microVU0.cop2 = 0; } -#define REC_COP2_mVU0(f, opName, mode) \ - void recV##f() { \ - setupMacroOp(mode, opName); \ - if (mode & 4) { \ - mVU_##f(microVU0, 0); \ - if (!microVU0.prog.IRinfo.info[0].lOp.isNOP) { \ - mVU_##f(microVU0, 1); \ - } \ - } \ - else { mVU_##f(microVU0, 1); } \ - endMacroOp(mode); \ +#define REC_COP2_mVU0(f, opName, mode) \ + void recV##f() \ + { \ + setupMacroOp(mode, opName); \ + if (mode & 4) \ + { \ + mVU_##f(microVU0, 0); \ + if (!microVU0.prog.IRinfo.info[0].lOp.isNOP) \ + { \ + mVU_##f(microVU0, 1); \ + } \ + } \ + else \ + { \ + mVU_##f(microVU0, 1); \ + } \ + endMacroOp(mode); \ } -#define INTERPRETATE_COP2_FUNC(f) \ - void recV##f() { \ - recCall(V##f); \ - _freeX86regs(); \ +#define INTERPRETATE_COP2_FUNC(f) \ + void recV##f() \ + { \ + recCall(V##f); \ + _freeX86regs(); \ } //------------------------------------------------------------------ @@ -109,134 +124,134 @@ void endMacroOp(int mode) { // Macro VU - Redirect Upper Instructions //------------------------------------------------------------------ -REC_COP2_mVU0(ABS, "ABS", 0x00); -REC_COP2_mVU0(ITOF0, "ITOF0", 0x00); -REC_COP2_mVU0(ITOF4, "ITOF4", 0x00); -REC_COP2_mVU0(ITOF12, "ITOF12", 0x00); -REC_COP2_mVU0(ITOF15, "ITOF15", 0x00); -REC_COP2_mVU0(FTOI0, "FTOI0", 0x00); -REC_COP2_mVU0(FTOI4, "FTOI4", 0x00); -REC_COP2_mVU0(FTOI12, "FTOI12", 0x00); -REC_COP2_mVU0(FTOI15, "FTOI15", 0x00); -REC_COP2_mVU0(ADD, "ADD", 0x10); -REC_COP2_mVU0(ADDi, "ADDi", 0x10); -REC_COP2_mVU0(ADDq, "ADDq", 0x11); -REC_COP2_mVU0(ADDx, "ADDx", 0x10); -REC_COP2_mVU0(ADDy, "ADDy", 0x10); -REC_COP2_mVU0(ADDz, "ADDz", 0x10); -REC_COP2_mVU0(ADDw, "ADDw", 0x10); -REC_COP2_mVU0(ADDA, "ADDA", 0x10); -REC_COP2_mVU0(ADDAi, "ADDAi", 0x10); -REC_COP2_mVU0(ADDAq, "ADDAq", 0x11); -REC_COP2_mVU0(ADDAx, "ADDAx", 0x10); -REC_COP2_mVU0(ADDAy, "ADDAy", 0x10); -REC_COP2_mVU0(ADDAz, "ADDAz", 0x10); -REC_COP2_mVU0(ADDAw, "ADDAw", 0x10); -REC_COP2_mVU0(SUB, "SUB", 0x10); -REC_COP2_mVU0(SUBi, "SUBi", 0x10); -REC_COP2_mVU0(SUBq, "SUBq", 0x11); -REC_COP2_mVU0(SUBx, "SUBx", 0x10); -REC_COP2_mVU0(SUBy, "SUBy", 0x10); -REC_COP2_mVU0(SUBz, "SUBz", 0x10); -REC_COP2_mVU0(SUBw, "SUBw", 0x10); -REC_COP2_mVU0(SUBA, "SUBA", 0x10); -REC_COP2_mVU0(SUBAi, "SUBAi", 0x10); -REC_COP2_mVU0(SUBAq, "SUBAq", 0x11); -REC_COP2_mVU0(SUBAx, "SUBAx", 0x10); -REC_COP2_mVU0(SUBAy, "SUBAy", 0x10); -REC_COP2_mVU0(SUBAz, "SUBAz", 0x10); -REC_COP2_mVU0(SUBAw, "SUBAw", 0x10); -REC_COP2_mVU0(MUL, "MUL", 0x10); -REC_COP2_mVU0(MULi, "MULi", 0x10); -REC_COP2_mVU0(MULq, "MULq", 0x11); -REC_COP2_mVU0(MULx, "MULx", 0x10); -REC_COP2_mVU0(MULy, "MULy", 0x10); -REC_COP2_mVU0(MULz, "MULz", 0x10); -REC_COP2_mVU0(MULw, "MULw", 0x10); -REC_COP2_mVU0(MULA, "MULA", 0x10); -REC_COP2_mVU0(MULAi, "MULAi", 0x10); -REC_COP2_mVU0(MULAq, "MULAq", 0x11); -REC_COP2_mVU0(MULAx, "MULAx", 0x10); -REC_COP2_mVU0(MULAy, "MULAy", 0x10); -REC_COP2_mVU0(MULAz, "MULAz", 0x10); -REC_COP2_mVU0(MULAw, "MULAw", 0x10); -REC_COP2_mVU0(MAX, "MAX", 0x00); -REC_COP2_mVU0(MAXi, "MAXi", 0x00); -REC_COP2_mVU0(MAXx, "MAXx", 0x00); -REC_COP2_mVU0(MAXy, "MAXy", 0x00); -REC_COP2_mVU0(MAXz, "MAXz", 0x00); -REC_COP2_mVU0(MAXw, "MAXw", 0x00); -REC_COP2_mVU0(MINI, "MINI", 0x00); -REC_COP2_mVU0(MINIi, "MINIi", 0x00); -REC_COP2_mVU0(MINIx, "MINIx", 0x00); -REC_COP2_mVU0(MINIy, "MINIy", 0x00); -REC_COP2_mVU0(MINIz, "MINIz", 0x00); -REC_COP2_mVU0(MINIw, "MINIw", 0x00); -REC_COP2_mVU0(MADD, "MADD", 0x10); -REC_COP2_mVU0(MADDi, "MADDi", 0x10); -REC_COP2_mVU0(MADDq, "MADDq", 0x11); -REC_COP2_mVU0(MADDx, "MADDx", 0x10); -REC_COP2_mVU0(MADDy, "MADDy", 0x10); -REC_COP2_mVU0(MADDz, "MADDz", 0x10); -REC_COP2_mVU0(MADDw, "MADDw", 0x10); -REC_COP2_mVU0(MADDA, "MADDA", 0x10); -REC_COP2_mVU0(MADDAi, "MADDAi", 0x10); -REC_COP2_mVU0(MADDAq, "MADDAq", 0x11); -REC_COP2_mVU0(MADDAx, "MADDAx", 0x10); -REC_COP2_mVU0(MADDAy, "MADDAy", 0x10); -REC_COP2_mVU0(MADDAz, "MADDAz", 0x10); -REC_COP2_mVU0(MADDAw, "MADDAw", 0x10); -REC_COP2_mVU0(MSUB, "MSUB", 0x10); -REC_COP2_mVU0(MSUBi, "MSUBi", 0x10); -REC_COP2_mVU0(MSUBq, "MSUBq", 0x11); -REC_COP2_mVU0(MSUBx, "MSUBx", 0x10); -REC_COP2_mVU0(MSUBy, "MSUBy", 0x10); -REC_COP2_mVU0(MSUBz, "MSUBz", 0x10); -REC_COP2_mVU0(MSUBw, "MSUBw", 0x10); -REC_COP2_mVU0(MSUBA, "MSUBA", 0x10); -REC_COP2_mVU0(MSUBAi, "MSUBAi", 0x10); -REC_COP2_mVU0(MSUBAq, "MSUBAq", 0x11); -REC_COP2_mVU0(MSUBAx, "MSUBAx", 0x10); -REC_COP2_mVU0(MSUBAy, "MSUBAy", 0x10); -REC_COP2_mVU0(MSUBAz, "MSUBAz", 0x10); -REC_COP2_mVU0(MSUBAw, "MSUBAw", 0x10); -REC_COP2_mVU0(OPMULA, "OPMULA", 0x10); -REC_COP2_mVU0(OPMSUB, "OPMSUB", 0x10); -REC_COP2_mVU0(CLIP, "CLIP", 0x08); +REC_COP2_mVU0(ABS, "ABS", 0x00); +REC_COP2_mVU0(ITOF0, "ITOF0", 0x00); +REC_COP2_mVU0(ITOF4, "ITOF4", 0x00); +REC_COP2_mVU0(ITOF12, "ITOF12", 0x00); +REC_COP2_mVU0(ITOF15, "ITOF15", 0x00); +REC_COP2_mVU0(FTOI0, "FTOI0", 0x00); +REC_COP2_mVU0(FTOI4, "FTOI4", 0x00); +REC_COP2_mVU0(FTOI12, "FTOI12", 0x00); +REC_COP2_mVU0(FTOI15, "FTOI15", 0x00); +REC_COP2_mVU0(ADD, "ADD", 0x10); +REC_COP2_mVU0(ADDi, "ADDi", 0x10); +REC_COP2_mVU0(ADDq, "ADDq", 0x11); +REC_COP2_mVU0(ADDx, "ADDx", 0x10); +REC_COP2_mVU0(ADDy, "ADDy", 0x10); +REC_COP2_mVU0(ADDz, "ADDz", 0x10); +REC_COP2_mVU0(ADDw, "ADDw", 0x10); +REC_COP2_mVU0(ADDA, "ADDA", 0x10); +REC_COP2_mVU0(ADDAi, "ADDAi", 0x10); +REC_COP2_mVU0(ADDAq, "ADDAq", 0x11); +REC_COP2_mVU0(ADDAx, "ADDAx", 0x10); +REC_COP2_mVU0(ADDAy, "ADDAy", 0x10); +REC_COP2_mVU0(ADDAz, "ADDAz", 0x10); +REC_COP2_mVU0(ADDAw, "ADDAw", 0x10); +REC_COP2_mVU0(SUB, "SUB", 0x10); +REC_COP2_mVU0(SUBi, "SUBi", 0x10); +REC_COP2_mVU0(SUBq, "SUBq", 0x11); +REC_COP2_mVU0(SUBx, "SUBx", 0x10); +REC_COP2_mVU0(SUBy, "SUBy", 0x10); +REC_COP2_mVU0(SUBz, "SUBz", 0x10); +REC_COP2_mVU0(SUBw, "SUBw", 0x10); +REC_COP2_mVU0(SUBA, "SUBA", 0x10); +REC_COP2_mVU0(SUBAi, "SUBAi", 0x10); +REC_COP2_mVU0(SUBAq, "SUBAq", 0x11); +REC_COP2_mVU0(SUBAx, "SUBAx", 0x10); +REC_COP2_mVU0(SUBAy, "SUBAy", 0x10); +REC_COP2_mVU0(SUBAz, "SUBAz", 0x10); +REC_COP2_mVU0(SUBAw, "SUBAw", 0x10); +REC_COP2_mVU0(MUL, "MUL", 0x10); +REC_COP2_mVU0(MULi, "MULi", 0x10); +REC_COP2_mVU0(MULq, "MULq", 0x11); +REC_COP2_mVU0(MULx, "MULx", 0x10); +REC_COP2_mVU0(MULy, "MULy", 0x10); +REC_COP2_mVU0(MULz, "MULz", 0x10); +REC_COP2_mVU0(MULw, "MULw", 0x10); +REC_COP2_mVU0(MULA, "MULA", 0x10); +REC_COP2_mVU0(MULAi, "MULAi", 0x10); +REC_COP2_mVU0(MULAq, "MULAq", 0x11); +REC_COP2_mVU0(MULAx, "MULAx", 0x10); +REC_COP2_mVU0(MULAy, "MULAy", 0x10); +REC_COP2_mVU0(MULAz, "MULAz", 0x10); +REC_COP2_mVU0(MULAw, "MULAw", 0x10); +REC_COP2_mVU0(MAX, "MAX", 0x00); +REC_COP2_mVU0(MAXi, "MAXi", 0x00); +REC_COP2_mVU0(MAXx, "MAXx", 0x00); +REC_COP2_mVU0(MAXy, "MAXy", 0x00); +REC_COP2_mVU0(MAXz, "MAXz", 0x00); +REC_COP2_mVU0(MAXw, "MAXw", 0x00); +REC_COP2_mVU0(MINI, "MINI", 0x00); +REC_COP2_mVU0(MINIi, "MINIi", 0x00); +REC_COP2_mVU0(MINIx, "MINIx", 0x00); +REC_COP2_mVU0(MINIy, "MINIy", 0x00); +REC_COP2_mVU0(MINIz, "MINIz", 0x00); +REC_COP2_mVU0(MINIw, "MINIw", 0x00); +REC_COP2_mVU0(MADD, "MADD", 0x10); +REC_COP2_mVU0(MADDi, "MADDi", 0x10); +REC_COP2_mVU0(MADDq, "MADDq", 0x11); +REC_COP2_mVU0(MADDx, "MADDx", 0x10); +REC_COP2_mVU0(MADDy, "MADDy", 0x10); +REC_COP2_mVU0(MADDz, "MADDz", 0x10); +REC_COP2_mVU0(MADDw, "MADDw", 0x10); +REC_COP2_mVU0(MADDA, "MADDA", 0x10); +REC_COP2_mVU0(MADDAi, "MADDAi", 0x10); +REC_COP2_mVU0(MADDAq, "MADDAq", 0x11); +REC_COP2_mVU0(MADDAx, "MADDAx", 0x10); +REC_COP2_mVU0(MADDAy, "MADDAy", 0x10); +REC_COP2_mVU0(MADDAz, "MADDAz", 0x10); +REC_COP2_mVU0(MADDAw, "MADDAw", 0x10); +REC_COP2_mVU0(MSUB, "MSUB", 0x10); +REC_COP2_mVU0(MSUBi, "MSUBi", 0x10); +REC_COP2_mVU0(MSUBq, "MSUBq", 0x11); +REC_COP2_mVU0(MSUBx, "MSUBx", 0x10); +REC_COP2_mVU0(MSUBy, "MSUBy", 0x10); +REC_COP2_mVU0(MSUBz, "MSUBz", 0x10); +REC_COP2_mVU0(MSUBw, "MSUBw", 0x10); +REC_COP2_mVU0(MSUBA, "MSUBA", 0x10); +REC_COP2_mVU0(MSUBAi, "MSUBAi", 0x10); +REC_COP2_mVU0(MSUBAq, "MSUBAq", 0x11); +REC_COP2_mVU0(MSUBAx, "MSUBAx", 0x10); +REC_COP2_mVU0(MSUBAy, "MSUBAy", 0x10); +REC_COP2_mVU0(MSUBAz, "MSUBAz", 0x10); +REC_COP2_mVU0(MSUBAw, "MSUBAw", 0x10); +REC_COP2_mVU0(OPMULA, "OPMULA", 0x10); +REC_COP2_mVU0(OPMSUB, "OPMSUB", 0x10); +REC_COP2_mVU0(CLIP, "CLIP", 0x08); //------------------------------------------------------------------ // Macro VU - Redirect Lower Instructions //------------------------------------------------------------------ -REC_COP2_mVU0(DIV, "DIV", 0x12); -REC_COP2_mVU0(SQRT, "SQRT", 0x12); -REC_COP2_mVU0(RSQRT, "RSQRT", 0x12); -REC_COP2_mVU0(IADD, "IADD", 0x04); -REC_COP2_mVU0(IADDI, "IADDI", 0x04); -REC_COP2_mVU0(IAND, "IAND", 0x04); -REC_COP2_mVU0(IOR, "IOR", 0x04); -REC_COP2_mVU0(ISUB, "ISUB", 0x04); -REC_COP2_mVU0(ILWR, "ILWR", 0x04); -REC_COP2_mVU0(ISWR, "ISWR", 0x00); -REC_COP2_mVU0(LQI, "LQI", 0x04); -REC_COP2_mVU0(LQD, "LQD", 0x04); -REC_COP2_mVU0(SQI, "SQI", 0x00); -REC_COP2_mVU0(SQD, "SQD", 0x00); -REC_COP2_mVU0(MFIR, "MFIR", 0x04); -REC_COP2_mVU0(MTIR, "MTIR", 0x04); -REC_COP2_mVU0(MOVE, "MOVE", 0x00); -REC_COP2_mVU0(MR32, "MR32", 0x00); -REC_COP2_mVU0(RINIT, "RINIT", 0x00); -REC_COP2_mVU0(RGET, "RGET", 0x04); -REC_COP2_mVU0(RNEXT, "RNEXT", 0x04); -REC_COP2_mVU0(RXOR, "RXOR", 0x00); +REC_COP2_mVU0(DIV, "DIV", 0x12); +REC_COP2_mVU0(SQRT, "SQRT", 0x12); +REC_COP2_mVU0(RSQRT, "RSQRT", 0x12); +REC_COP2_mVU0(IADD, "IADD", 0x04); +REC_COP2_mVU0(IADDI, "IADDI", 0x04); +REC_COP2_mVU0(IAND, "IAND", 0x04); +REC_COP2_mVU0(IOR, "IOR", 0x04); +REC_COP2_mVU0(ISUB, "ISUB", 0x04); +REC_COP2_mVU0(ILWR, "ILWR", 0x04); +REC_COP2_mVU0(ISWR, "ISWR", 0x00); +REC_COP2_mVU0(LQI, "LQI", 0x04); +REC_COP2_mVU0(LQD, "LQD", 0x04); +REC_COP2_mVU0(SQI, "SQI", 0x00); +REC_COP2_mVU0(SQD, "SQD", 0x00); +REC_COP2_mVU0(MFIR, "MFIR", 0x04); +REC_COP2_mVU0(MTIR, "MTIR", 0x04); +REC_COP2_mVU0(MOVE, "MOVE", 0x00); +REC_COP2_mVU0(MR32, "MR32", 0x00); +REC_COP2_mVU0(RINIT, "RINIT", 0x00); +REC_COP2_mVU0(RGET, "RGET", 0x04); +REC_COP2_mVU0(RNEXT, "RNEXT", 0x04); +REC_COP2_mVU0(RXOR, "RXOR", 0x00); //------------------------------------------------------------------ // Macro VU - Misc... //------------------------------------------------------------------ -void recVNOP() {} -void recVWAITQ(){} +void recVNOP() {} +void recVWAITQ() {} INTERPRETATE_COP2_FUNC(CALLMS); INTERPRETATE_COP2_FUNC(CALLMSR); @@ -244,7 +259,8 @@ INTERPRETATE_COP2_FUNC(CALLMSR); // Macro VU - Branches //------------------------------------------------------------------ -void _setupBranchTest(u32*(jmpType)(u32), bool isLikely) { +void _setupBranchTest(u32*(jmpType)(u32), bool isLikely) +{ printCOP2("COP2 Branch"); _eeFlushAllUnused(); //xTEST(ptr32[&vif1Regs.stat._u32], 0x4); @@ -252,18 +268,20 @@ void _setupBranchTest(u32*(jmpType)(u32), bool isLikely) { recDoBranchImm(jmpType(0), isLikely); } -void recBC2F() { _setupBranchTest(JNZ32, false); } -void recBC2T() { _setupBranchTest(JZ32, false); } -void recBC2FL() { _setupBranchTest(JNZ32, true); } -void recBC2TL() { _setupBranchTest(JZ32, true); } +void recBC2F() { _setupBranchTest(JNZ32, false); } +void recBC2T() { _setupBranchTest(JZ32, false); } +void recBC2FL() { _setupBranchTest(JNZ32, true); } +void recBC2TL() { _setupBranchTest(JZ32, true); } //------------------------------------------------------------------ // Macro VU - COP2 Transfer Instructions //------------------------------------------------------------------ -void COP2_Interlock(bool mBitSync) { +void COP2_Interlock(bool mBitSync) +{ - if (cpuRegs.code & 1) { + if (cpuRegs.code & 1) + { iFlushCall(FLUSH_EVERYTHING); xTEST(ptr32[&VU0.VI[REG_VPU_STAT].UL], 0x1); xForwardJZ32 skipvuidle; @@ -272,30 +290,36 @@ void COP2_Interlock(bool mBitSync) { xMOV(ptr[&cpuRegs.cycle], eax); // update cycles xLoadFarAddr(arg1reg, CpuVU0); xFastCall((void*)BaseVUmicroCPU::ExecuteBlockJIT, arg1reg); - if (mBitSync) xFastCall((void*)_vu0WaitMicro); - else xFastCall((void*)_vu0FinishMicro); + if (mBitSync) + xFastCall((void*)_vu0WaitMicro); + else + xFastCall((void*)_vu0FinishMicro); skipvuidle.SetTarget(); } } -void TEST_FBRST_RESET(FnType_Void* resetFunct, int vuIndex) { +void TEST_FBRST_RESET(FnType_Void* resetFunct, int vuIndex) +{ xTEST(eax, (vuIndex) ? 0x200 : 0x002); xForwardJZ8 skip; - xFastCall((void*)resetFunct); - xMOV(eax, ptr32[&cpuRegs.GPR.r[_Rt_].UL[0]]); + xFastCall((void*)resetFunct); + xMOV(eax, ptr32[&cpuRegs.GPR.r[_Rt_].UL[0]]); skip.SetTarget(); } -static void recCFC2() { +static void recCFC2() +{ printCOP2("CFC2"); COP2_Interlock(false); - if (!_Rt_) return; + if (!_Rt_) + return; iFlushCall(FLUSH_EVERYTHING); - if (!(cpuRegs.code & 1)) { + if (!(cpuRegs.code & 1)) + { xTEST(ptr32[&VU0.VI[REG_VPU_STAT].UL], 0x1); xForwardJZ32 skipvuidle; xMOV(eax, ptr32[&cpuRegs.cycle]); @@ -311,24 +335,27 @@ static void recCFC2() { skipvuidle.SetTarget(); } - if (_Rd_ == REG_STATUS_FLAG) { // Normalize Status Flag + if (_Rd_ == REG_STATUS_FLAG) + { // Normalize Status Flag xMOV(eax, ptr32[&vu0Regs.VI[REG_STATUS_FLAG].UL]); } - else xMOV(eax, ptr32[&vu0Regs.VI[_Rd_].UL]); + else + xMOV(eax, ptr32[&vu0Regs.VI[_Rd_].UL]); - if (_Rd_ == REG_TPC) { // Divide TPC register value by 8 during copying + if (_Rd_ == REG_TPC) + { // Divide TPC register value by 8 during copying // Ok, this deserves an explanation. // Accoring to the official PS2 VU0 coding manual there are 3 ways to execute a micro subroutine on VU0 // one of which is using the VCALLMSR intruction. // The manual requires putting the address of the micro subroutine // into the CMSAR0 register divided by 8 using the CTC2 command before executing VCALLMSR. - // Many games (for instance, 24: The Game, GTA LCS, GTA VCS and FFXII) do in fact use this way, + // Many games (for instance, 24: The Game, GTA LCS, GTA VCS and FFXII) do in fact use this way, // they diligently put the address of the micro subroutine into a separate register (v0, v1 etc), divide it by 8 // and move it to CMSAR0 by calling the CTC2 command. - - // However, there are also at least 2 confirmed games (R Racing Evolution, Street Fighter EX3) + + // However, there are also at least 2 confirmed games (R Racing Evolution, Street Fighter EX3) // that execute a piece of code to run a micro subroutine on VU0 like this: - // + // // ... // cfc2 t4, TPC // ctc2 t4, CMSAR0 @@ -342,10 +369,10 @@ static void recCFC2() { // There are 2 possibilities: either the CFC2 instruction divides the value of the TPC (which is the Program Counter register // for micro subroutines) by 8 itself during copying or the TPC register always works with addresses already divided by 8. // The latter seems less possible because the Program Counter register by definition holds the memory address of the instruction. - // In addition, PCSX2 already implements TPC as an instruction pointer so we'll assume that division by 8 + // In addition, PCSX2 already implements TPC as an instruction pointer so we'll assume that division by 8 // is done by CFC2 while working with the TPC register. // (fixes R Racing Evolution and Street Fighter EX3) - + //xSHR(eax, 3); //Update Refraction - Don't need to do this anymore as addresses are fed in divided by 8 always. @@ -356,25 +383,31 @@ static void recCFC2() { // FixMe: Should R-Reg have upper 9 bits 0? xMOV(ptr32[&cpuRegs.GPR.r[_Rt_].UL[0]], eax); - if (_Rd_ >= 16) { + if (_Rd_ >= 16) + { xCDQ(); // Sign Extend xMOV(ptr32[&cpuRegs.GPR.r[_Rt_].UL[1]], edx); } - else xMOV(ptr32[&cpuRegs.GPR.r[_Rt_].UL[1]], 0); + else + xMOV(ptr32[&cpuRegs.GPR.r[_Rt_].UL[1]], 0); // FixMe: I think this is needed, but not sure how it works _eeOnWriteReg(_Rt_, 1); } -static void recCTC2() { +static void recCTC2() +{ printCOP2("CTC2"); COP2_Interlock(1); - if (!_Rd_) return; + if (!_Rd_) + return; iFlushCall(FLUSH_EVERYTHING); - if (!(cpuRegs.code & 1)) {; + if (!(cpuRegs.code & 1)) + { + ; xTEST(ptr32[&VU0.VI[REG_VPU_STAT].UL], 0x1); xForwardJZ32 skipvuidle; xMOV(eax, ptr32[&cpuRegs.cycle]); @@ -390,24 +423,28 @@ static void recCTC2() { skipvuidle.SetTarget(); } - switch(_Rd_) { - case REG_MAC_FLAG: case REG_TPC: - case REG_VPU_STAT: break; // Read Only Regs + switch (_Rd_) + { + case REG_MAC_FLAG: + case REG_TPC: + case REG_VPU_STAT: + break; // Read Only Regs case REG_R: xMOV(eax, ptr32[&cpuRegs.GPR.r[_Rt_].UL[0]]); - xOR (eax, 0x3f800000); + xOR(eax, 0x3f800000); xMOV(ptr32[&vu0Regs.VI[REG_R].UL], eax); break; case REG_STATUS_FLAG: { - if (_Rt_) { + if (_Rt_) + { xMOV(eax, ptr32[&cpuRegs.GPR.r[_Rt_].UL[0]]); xAND(eax, 0xFC0); xAND(ptr32[&vu0Regs.VI[REG_STATUS_FLAG].UL], 0x3F); xOR(ptr32[&vu0Regs.VI[REG_STATUS_FLAG].UL], eax); - } - else xAND(ptr32[&vu0Regs.VI[REG_STATUS_FLAG].UL], 0x3F); + else + xAND(ptr32[&vu0Regs.VI[REG_STATUS_FLAG].UL], 0x3F); //Need to update the sticky flags for microVU mVUallocSFLAGd(&vu0Regs.VI[REG_STATUS_FLAG].UL); @@ -417,21 +454,25 @@ static void recCTC2() { xMOVAPS(ptr128[&vu0Regs.micro_statusflags], xmmT1); break; } - case REG_CMSAR1: // Execute VU1 Micro SubRoutine + case REG_CMSAR1: // Execute VU1 Micro SubRoutine xMOV(ecx, 1); xFastCall((void*)vu1Finish, ecx); - if (_Rt_) { + if (_Rt_) + { xMOV(ecx, ptr32[&cpuRegs.GPR.r[_Rt_].UL[0]]); } - else xXOR(ecx, ecx); + else + xXOR(ecx, ecx); xFastCall((void*)vu1ExecMicro, ecx); break; case REG_FBRST: - if (!_Rt_) { + if (!_Rt_) + { xMOV(ptr32[&vu0Regs.VI[REG_FBRST].UL], 0); return; } - else xMOV(eax, ptr32[&cpuRegs.GPR.r[_Rt_].UL[0]]); + else + xMOV(eax, ptr32[&cpuRegs.GPR.r[_Rt_].UL[0]]); TEST_FBRST_RESET(vu0ResetRegs, 0); TEST_FBRST_RESET(vu1ResetRegs, 1); @@ -442,20 +483,24 @@ static void recCTC2() { default: // Executing vu0 block here fixes the intro of Ratchet and Clank // sVU's COP2 has a comment that "Donald Duck" needs this too... - if (_Rd_) _eeMoveGPRtoM((uptr)&vu0Regs.VI[_Rd_].UL, _Rt_); + if (_Rd_) + _eeMoveGPRtoM((uptr)&vu0Regs.VI[_Rd_].UL, _Rt_); break; } } -static void recQMFC2() { +static void recQMFC2() +{ printCOP2("QMFC2"); COP2_Interlock(false); - if (!_Rt_) return; + if (!_Rt_) + return; iFlushCall(FLUSH_EVERYTHING); - if (!(cpuRegs.code & 1)) { + if (!(cpuRegs.code & 1)) + { xTEST(ptr32[&VU0.VI[REG_VPU_STAT].UL], 0x1); xForwardJZ32 skipvuidle; xMOV(eax, ptr32[&cpuRegs.cycle]); @@ -478,15 +523,18 @@ static void recQMFC2() { xMOVAPS(ptr128[&cpuRegs.GPR.r[_Rt_]], xmmT1); } -static void recQMTC2() { +static void recQMTC2() +{ printCOP2("QMTC2"); COP2_Interlock(true); - if (!_Rd_) return; + if (!_Rd_) + return; iFlushCall(FLUSH_EVERYTHING); - if (!(cpuRegs.code & 1)) { + if (!(cpuRegs.code & 1)) + { xTEST(ptr32[&VU0.VI[REG_VPU_STAT].UL], 0x1); xForwardJZ32 skipvuidle; xMOV(eax, ptr32[&cpuRegs.cycle]); @@ -513,7 +561,8 @@ void recCOP2(); void recCOP2_BC2(); void recCOP2_SPEC1(); void recCOP2_SPEC2(); -void rec_C2UNK() { +void rec_C2UNK() +{ Console.Error("Cop2 bad opcode: %x", cpuRegs.code); } @@ -522,54 +571,286 @@ void _vuRegsCOP22(VURegs* VU, _VURegsNum* VUregsn) {} // Recompilation void (*recCOP2t[32])() = { - rec_C2UNK, recQMFC2, recCFC2, rec_C2UNK, rec_C2UNK, recQMTC2, recCTC2, rec_C2UNK, - recCOP2_BC2, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, - recCOP2_SPEC1, recCOP2_SPEC1, recCOP2_SPEC1, recCOP2_SPEC1, recCOP2_SPEC1, recCOP2_SPEC1, recCOP2_SPEC1, recCOP2_SPEC1, - recCOP2_SPEC1, recCOP2_SPEC1, recCOP2_SPEC1, recCOP2_SPEC1, recCOP2_SPEC1, recCOP2_SPEC1, recCOP2_SPEC1, recCOP2_SPEC1, + rec_C2UNK, + recQMFC2, + recCFC2, + rec_C2UNK, + rec_C2UNK, + recQMTC2, + recCTC2, + rec_C2UNK, + recCOP2_BC2, + rec_C2UNK, + rec_C2UNK, + rec_C2UNK, + rec_C2UNK, + rec_C2UNK, + rec_C2UNK, + rec_C2UNK, + recCOP2_SPEC1, + recCOP2_SPEC1, + recCOP2_SPEC1, + recCOP2_SPEC1, + recCOP2_SPEC1, + recCOP2_SPEC1, + recCOP2_SPEC1, + recCOP2_SPEC1, + recCOP2_SPEC1, + recCOP2_SPEC1, + recCOP2_SPEC1, + recCOP2_SPEC1, + recCOP2_SPEC1, + recCOP2_SPEC1, + recCOP2_SPEC1, + recCOP2_SPEC1, }; void (*recCOP2_BC2t[32])() = { - recBC2F, recBC2T, recBC2FL, recBC2TL, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, - rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, - rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, - rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, -}; + recBC2F, + recBC2T, + recBC2FL, + recBC2TL, + rec_C2UNK, + rec_C2UNK, + rec_C2UNK, + rec_C2UNK, + rec_C2UNK, + rec_C2UNK, + rec_C2UNK, + rec_C2UNK, + rec_C2UNK, + rec_C2UNK, + rec_C2UNK, + rec_C2UNK, + rec_C2UNK, + rec_C2UNK, + rec_C2UNK, + rec_C2UNK, + rec_C2UNK, + rec_C2UNK, + rec_C2UNK, + rec_C2UNK, + rec_C2UNK, + rec_C2UNK, + rec_C2UNK, + rec_C2UNK, + rec_C2UNK, + rec_C2UNK, + rec_C2UNK, + rec_C2UNK, +}; -void (*recCOP2SPECIAL1t[64])() = { - recVADDx, recVADDy, recVADDz, recVADDw, recVSUBx, recVSUBy, recVSUBz, recVSUBw, - recVMADDx, recVMADDy, recVMADDz, recVMADDw, recVMSUBx, recVMSUBy, recVMSUBz, recVMSUBw, - recVMAXx, recVMAXy, recVMAXz, recVMAXw, recVMINIx, recVMINIy, recVMINIz, recVMINIw, - recVMULx, recVMULy, recVMULz, recVMULw, recVMULq, recVMAXi, recVMULi, recVMINIi, - recVADDq, recVMADDq, recVADDi, recVMADDi, recVSUBq, recVMSUBq, recVSUBi, recVMSUBi, - recVADD, recVMADD, recVMUL, recVMAX, recVSUB, recVMSUB, recVOPMSUB, recVMINI, - recVIADD, recVISUB, recVIADDI, rec_C2UNK, recVIAND, recVIOR, rec_C2UNK, rec_C2UNK, - recVCALLMS, recVCALLMSR,rec_C2UNK, rec_C2UNK, recCOP2_SPEC2, recCOP2_SPEC2, recCOP2_SPEC2, recCOP2_SPEC2, +void (*recCOP2SPECIAL1t[64])() = { + recVADDx, + recVADDy, + recVADDz, + recVADDw, + recVSUBx, + recVSUBy, + recVSUBz, + recVSUBw, + recVMADDx, + recVMADDy, + recVMADDz, + recVMADDw, + recVMSUBx, + recVMSUBy, + recVMSUBz, + recVMSUBw, + recVMAXx, + recVMAXy, + recVMAXz, + recVMAXw, + recVMINIx, + recVMINIy, + recVMINIz, + recVMINIw, + recVMULx, + recVMULy, + recVMULz, + recVMULw, + recVMULq, + recVMAXi, + recVMULi, + recVMINIi, + recVADDq, + recVMADDq, + recVADDi, + recVMADDi, + recVSUBq, + recVMSUBq, + recVSUBi, + recVMSUBi, + recVADD, + recVMADD, + recVMUL, + recVMAX, + recVSUB, + recVMSUB, + recVOPMSUB, + recVMINI, + recVIADD, + recVISUB, + recVIADDI, + rec_C2UNK, + recVIAND, + recVIOR, + rec_C2UNK, + rec_C2UNK, + recVCALLMS, + recVCALLMSR, + rec_C2UNK, + rec_C2UNK, + recCOP2_SPEC2, + recCOP2_SPEC2, + recCOP2_SPEC2, + recCOP2_SPEC2, }; void (*recCOP2SPECIAL2t[128])() = { - recVADDAx, recVADDAy, recVADDAz, recVADDAw, recVSUBAx, recVSUBAy, recVSUBAz, recVSUBAw, - recVMADDAx,recVMADDAy, recVMADDAz, recVMADDAw, recVMSUBAx, recVMSUBAy, recVMSUBAz, recVMSUBAw, - recVITOF0, recVITOF4, recVITOF12, recVITOF15, recVFTOI0, recVFTOI4, recVFTOI12, recVFTOI15, - recVMULAx, recVMULAy, recVMULAz, recVMULAw, recVMULAq, recVABS, recVMULAi, recVCLIP, - recVADDAq, recVMADDAq, recVADDAi, recVMADDAi, recVSUBAq, recVMSUBAq, recVSUBAi, recVMSUBAi, - recVADDA, recVMADDA, recVMULA, rec_C2UNK, recVSUBA, recVMSUBA, recVOPMULA, recVNOP, - recVMOVE, recVMR32, rec_C2UNK, rec_C2UNK, recVLQI, recVSQI, recVLQD, recVSQD, - recVDIV, recVSQRT, recVRSQRT, recVWAITQ, recVMTIR, recVMFIR, recVILWR, recVISWR, - recVRNEXT, recVRGET, recVRINIT, recVRXOR, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, - rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, - rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, - rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, - rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, - rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, - rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, - rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, + recVADDAx, + recVADDAy, + recVADDAz, + recVADDAw, + recVSUBAx, + recVSUBAy, + recVSUBAz, + recVSUBAw, + recVMADDAx, + recVMADDAy, + recVMADDAz, + recVMADDAw, + recVMSUBAx, + recVMSUBAy, + recVMSUBAz, + recVMSUBAw, + recVITOF0, + recVITOF4, + recVITOF12, + recVITOF15, + recVFTOI0, + recVFTOI4, + recVFTOI12, + recVFTOI15, + recVMULAx, + recVMULAy, + recVMULAz, + recVMULAw, + recVMULAq, + recVABS, + recVMULAi, + recVCLIP, + recVADDAq, + recVMADDAq, + recVADDAi, + recVMADDAi, + recVSUBAq, + recVMSUBAq, + recVSUBAi, + recVMSUBAi, + recVADDA, + recVMADDA, + recVMULA, + rec_C2UNK, + recVSUBA, + recVMSUBA, + recVOPMULA, + recVNOP, + recVMOVE, + recVMR32, + rec_C2UNK, + rec_C2UNK, + recVLQI, + recVSQI, + recVLQD, + recVSQD, + recVDIV, + recVSQRT, + recVRSQRT, + recVWAITQ, + recVMTIR, + recVMFIR, + recVILWR, + recVISWR, + recVRNEXT, + recVRGET, + recVRINIT, + recVRXOR, + rec_C2UNK, + rec_C2UNK, + rec_C2UNK, + rec_C2UNK, + rec_C2UNK, + rec_C2UNK, + rec_C2UNK, + rec_C2UNK, + rec_C2UNK, + rec_C2UNK, + rec_C2UNK, + rec_C2UNK, + rec_C2UNK, + rec_C2UNK, + rec_C2UNK, + rec_C2UNK, + rec_C2UNK, + rec_C2UNK, + rec_C2UNK, + rec_C2UNK, + rec_C2UNK, + rec_C2UNK, + rec_C2UNK, + rec_C2UNK, + rec_C2UNK, + rec_C2UNK, + rec_C2UNK, + rec_C2UNK, + rec_C2UNK, + rec_C2UNK, + rec_C2UNK, + rec_C2UNK, + rec_C2UNK, + rec_C2UNK, + rec_C2UNK, + rec_C2UNK, + rec_C2UNK, + rec_C2UNK, + rec_C2UNK, + rec_C2UNK, + rec_C2UNK, + rec_C2UNK, + rec_C2UNK, + rec_C2UNK, + rec_C2UNK, + rec_C2UNK, + rec_C2UNK, + rec_C2UNK, + rec_C2UNK, + rec_C2UNK, + rec_C2UNK, + rec_C2UNK, + rec_C2UNK, + rec_C2UNK, + rec_C2UNK, + rec_C2UNK, + rec_C2UNK, + rec_C2UNK, + rec_C2UNK, + rec_C2UNK, }; -namespace R5900 { -namespace Dynarec { -namespace OpcodeImpl { void recCOP2() { recCOP2t[_Rs_](); }}}} -void recCOP2_BC2 () { recCOP2_BC2t[_Rt_](); } -void recCOP2_SPEC1() { +namespace R5900 +{ + namespace Dynarec + { + namespace OpcodeImpl + { + void recCOP2() { recCOP2t[_Rs_](); } + } // namespace OpcodeImpl + } // namespace Dynarec +} // namespace R5900 +void recCOP2_BC2() { recCOP2_BC2t[_Rt_](); } +void recCOP2_SPEC1() +{ iFlushCall(FLUSH_EVERYTHING); xTEST(ptr32[&VU0.VI[REG_VPU_STAT].UL], 0x1); xForwardJZ32 skipvuidle; @@ -578,4 +859,4 @@ void recCOP2_SPEC1() { recCOP2SPECIAL1t[_Funct_](); } -void recCOP2_SPEC2() { recCOP2SPECIAL2t[(cpuRegs.code&3)|((cpuRegs.code>>4)&0x7c)](); } \ No newline at end of file +void recCOP2_SPEC2() { recCOP2SPECIAL2t[(cpuRegs.code & 3) | ((cpuRegs.code >> 4) & 0x7c)](); }