diff --git a/pcsx2/windows/VCprojects/pcsx2.vcxproj b/pcsx2/windows/VCprojects/pcsx2.vcxproj index c861950ca7..90045dce9e 100644 --- a/pcsx2/windows/VCprojects/pcsx2.vcxproj +++ b/pcsx2/windows/VCprojects/pcsx2.vcxproj @@ -715,11 +715,12 @@ - + + diff --git a/pcsx2/windows/VCprojects/pcsx2.vcxproj.filters b/pcsx2/windows/VCprojects/pcsx2.vcxproj.filters index 5ebed0d702..843c3c1a72 100644 --- a/pcsx2/windows/VCprojects/pcsx2.vcxproj.filters +++ b/pcsx2/windows/VCprojects/pcsx2.vcxproj.filters @@ -1201,6 +1201,9 @@ System\Ps2\GS + + System\Ps2\EmotionEngine\VU\Dynarec\microVU + diff --git a/pcsx2/x86/microVU.cpp b/pcsx2/x86/microVU.cpp index f2b83a7e94..b953e65679 100644 --- a/pcsx2/x86/microVU.cpp +++ b/pcsx2/x86/microVU.cpp @@ -86,6 +86,7 @@ void mVUreset(microVU& mVU, bool resetReserve) { // Clear All Program Data //memset(&mVU.prog, 0, sizeof(mVU.prog)); memset(&mVU.prog.lpState, 0, sizeof(mVU.prog.lpState)); + mVU.profiler.Reset(mVU.index); // Program Variables mVU.prog.cleared = 1; diff --git a/pcsx2/x86/microVU.h b/pcsx2/x86/microVU.h index 30c76a9f55..76c7713496 100644 --- a/pcsx2/x86/microVU.h +++ b/pcsx2/x86/microVU.h @@ -15,6 +15,7 @@ #pragma once //#define mVUlogProg // Dumps MicroPrograms to \logs\*.html +//#define mVUprofileProg // Shows opcode statistics in console class AsciiFile; using namespace std; @@ -33,6 +34,7 @@ using namespace x86Emitter; #include "x86emitter/x86emitter.h" #include "microVU_Misc.h" #include "microVU_IR.h" +#include "microVU_Profiler.h" struct microBlockLink { microBlock block; @@ -192,6 +194,7 @@ struct microVU { u32 cacheSize; // VU Cache Size microProgManager prog; // Micro Program Data + microProfiler profiler; // Opcode Profiler ScopedPtr regAlloc; // Reg Alloc Class ScopedPtr logFile; // Log File Pointer diff --git a/pcsx2/x86/microVU_Alloc.inl b/pcsx2/x86/microVU_Alloc.inl index 7fea7e4eb6..9bc2ea2dd5 100644 --- a/pcsx2/x86/microVU_Alloc.inl +++ b/pcsx2/x86/microVU_Alloc.inl @@ -71,31 +71,34 @@ __ri void mVUallocSFLAGc(const x32& reg, const x32& regT, int fInstance) } // Denormalizes Status Flag +// If setAllflags is false, then returns result in eax (gprT1) +// else all microVU flag regs (gprF0..F3) get the result. __ri void mVUallocSFLAGd(u32* memAddr, bool setAllflags) { - // Cannot use EBP (gprF1) here; as this function is used by mVU0 macro and - // the EErec needs EBP preserved. + // When this function is used by mVU0 macro the EErec + // needs EBP (gprF1) and ESI (gprF2) to be preserved. + const xAddressReg& t0 = setAllflags ? gprT1 : gprF3; + const xAddressReg& t1 = setAllflags ? gprT2 : gprF2; + const xAddressReg& t2 = setAllflags ? gprT3 : gprF0; - xMOV(gprF0, ptr32[memAddr]); - xMOV(gprF3, gprF0); - xSHR(gprF3, 3); - xAND(gprF3, 0x18); + xMOV(t2, ptr32[memAddr]); + xMOV(t0, t2); + xSHR(t0, 3); + xAND(t0, 0x18); - xMOV(gprF2, gprF0); - xSHL(gprF2, 11); - xAND(gprF2, 0x1800); - xOR (gprF3, gprF2); + xMOV(t1, t2); + xSHL(t1, 11); + xAND(t1, 0x1800); + xOR (t0, t1); - xSHL(gprF0, 14); - xAND(gprF0, 0x3cf0000); - xOR (gprF3, gprF0); + xSHL(t2, 14); + xAND(t2, 0x3cf0000); + xOR (t0, t2); if (setAllflags) { - // this code should be run in mVU micro mode only, so writing to - // EBP (gprF1) is ok (and needed for vuMicro optimizations). - - xMOV(gprF0, gprF3); + // EBP (gprF1) and ESI (gprF2) is ok (and needed for vuMicro). + xMOV(gprF0, gprF3); // gprF3 is t0 xMOV(gprF1, gprF3); xMOV(gprF2, gprF3); } diff --git a/pcsx2/x86/microVU_Execute.inl b/pcsx2/x86/microVU_Execute.inl index 02d39a7812..e65dc9f8f4 100644 --- a/pcsx2/x86/microVU_Execute.inl +++ b/pcsx2/x86/microVU_Execute.inl @@ -203,6 +203,7 @@ _mVUt void mVUcleanUp() { if (!vuIndex || !THREAD_VU1) { cpuRegs.cycle += std::min(mVU.cycles, 3000u) * EmuConfig.Speedhacks.VUCycleSteal; } + mVU.profiler.Print(); //static int ax = 0; ax++; //if (!(ax % 100000)) { // for (u32 i = 0; i < (mVU.progSize / 2); i++) { diff --git a/pcsx2/x86/microVU_Lower.inl b/pcsx2/x86/microVU_Lower.inl index 9a9c0288ca..6f337914ad 100644 --- a/pcsx2/x86/microVU_Lower.inl +++ b/pcsx2/x86/microVU_Lower.inl @@ -82,6 +82,7 @@ mVUop(mVU_DIV) { mVU.regAlloc->clearNeeded(Fs); mVU.regAlloc->clearNeeded(Ft); mVU.regAlloc->clearNeeded(t1); + mVU.profiler.EmitOp(opDIV); } pass3 { mVUlog("DIV Q, vf%02d%s, vf%02d%s", _Fs_, _Fsf_String, _Ft_, _Ftf_String); } } @@ -99,6 +100,7 @@ mVUop(mVU_SQRT) { writeQreg(Ft, mVUinfo.writeQ); mVU.regAlloc->clearNeeded(Ft); + mVU.profiler.EmitOp(opSQRT); } pass3 { mVUlog("SQRT Q, vf%02d%s", _Ft_, _Ftf_String); } } @@ -139,6 +141,7 @@ mVUop(mVU_RSQRT) { mVU.regAlloc->clearNeeded(Fs); mVU.regAlloc->clearNeeded(Ft); mVU.regAlloc->clearNeeded(t1); + mVU.profiler.EmitOp(opRSQRT); } pass3 { mVUlog("RSQRT Q, vf%02d%s, vf%02d%s", _Fs_, _Fsf_String, _Ft_, _Ftf_String); } } @@ -186,6 +189,7 @@ mVUop(mVU_EATAN) { mVU.regAlloc->clearNeeded(Fs); mVU.regAlloc->clearNeeded(t1); mVU.regAlloc->clearNeeded(t2); + mVU.profiler.EmitOp(opEATAN); } pass3 { mVUlog("EATAN P"); } } @@ -206,6 +210,7 @@ mVUop(mVU_EATANxy) { mVU.regAlloc->clearNeeded(Fs); mVU.regAlloc->clearNeeded(t1); mVU.regAlloc->clearNeeded(t2); + mVU.profiler.EmitOp(opEATANxy); } pass3 { mVUlog("EATANxy P"); } } @@ -226,6 +231,7 @@ mVUop(mVU_EATANxz) { mVU.regAlloc->clearNeeded(Fs); mVU.regAlloc->clearNeeded(t1); mVU.regAlloc->clearNeeded(t2); + mVU.profiler.EmitOp(opEATANxz); } pass3 { mVUlog("EATANxz P"); } } @@ -267,6 +273,7 @@ mVUop(mVU_EEXP) { mVU.regAlloc->clearNeeded(Fs); mVU.regAlloc->clearNeeded(t1); mVU.regAlloc->clearNeeded(t2); + mVU.profiler.EmitOp(opEEXP); } pass3 { mVUlog("EEXP P"); } } @@ -296,6 +303,7 @@ mVUop(mVU_ELENG) { xSQRT.SS (xmmPQ, xmmPQ); xPSHUF.D (xmmPQ, xmmPQ, mVUinfo.writeP ? 0x27 : 0xC6); // Flip back mVU.regAlloc->clearNeeded(Fs); + mVU.profiler.EmitOp(opELENG); } pass3 { mVUlog("ELENG P"); } } @@ -311,6 +319,7 @@ mVUop(mVU_ERCPR) { xMOVSS (xmmPQ, Fs); xPSHUF.D (xmmPQ, xmmPQ, mVUinfo.writeP ? 0x27 : 0xC6); // Flip back mVU.regAlloc->clearNeeded(Fs); + mVU.profiler.EmitOp(opERCPR); } pass3 { mVUlog("ERCPR P"); } } @@ -327,6 +336,7 @@ mVUop(mVU_ERLENG) { xMOVSS (xmmPQ, Fs); xPSHUF.D (xmmPQ, xmmPQ, mVUinfo.writeP ? 0x27 : 0xC6); // Flip back mVU.regAlloc->clearNeeded(Fs); + mVU.profiler.EmitOp(opERLENG); } pass3 { mVUlog("ERLENG P"); } } @@ -342,6 +352,7 @@ mVUop(mVU_ERSADD) { xMOVSS (xmmPQ, Fs); xPSHUF.D (xmmPQ, xmmPQ, mVUinfo.writeP ? 0x27 : 0xC6); // Flip back mVU.regAlloc->clearNeeded(Fs); + mVU.profiler.EmitOp(opERSADD); } pass3 { mVUlog("ERSADD P"); } } @@ -358,6 +369,7 @@ mVUop(mVU_ERSQRT) { xMOVSS (xmmPQ, Fs); xPSHUF.D (xmmPQ, xmmPQ, mVUinfo.writeP ? 0x27 : 0xC6); // Flip back mVU.regAlloc->clearNeeded(Fs); + mVU.profiler.EmitOp(opERSQRT); } pass3 { mVUlog("ERSQRT P"); } } @@ -370,6 +382,7 @@ mVUop(mVU_ESADD) { mVU_sumXYZ(mVU, xmmPQ, Fs); xPSHUF.D(xmmPQ, xmmPQ, mVUinfo.writeP ? 0x27 : 0xC6); // Flip back mVU.regAlloc->clearNeeded(Fs); + mVU.profiler.EmitOp(opESADD); } pass3 { mVUlog("ESADD P"); } } @@ -406,6 +419,7 @@ mVUop(mVU_ESIN) { mVU.regAlloc->clearNeeded(Fs); mVU.regAlloc->clearNeeded(t1); mVU.regAlloc->clearNeeded(t2); + mVU.profiler.EmitOp(opESIN); } pass3 { mVUlog("ESIN P"); } } @@ -419,6 +433,7 @@ mVUop(mVU_ESQRT) { xSQRT.SS(xmmPQ, Fs); xPSHUF.D(xmmPQ, xmmPQ, mVUinfo.writeP ? 0x27 : 0xC6); // Flip back mVU.regAlloc->clearNeeded(Fs); + mVU.profiler.EmitOp(opESQRT); } pass3 { mVUlog("ESQRT P"); } } @@ -437,6 +452,7 @@ mVUop(mVU_ESUM) { xPSHUF.D (xmmPQ, xmmPQ, mVUinfo.writeP ? 0x27 : 0xC6); // Flip back mVU.regAlloc->clearNeeded(Fs); mVU.regAlloc->clearNeeded(t1); + mVU.profiler.EmitOp(opESUM); } pass3 { mVUlog("ESUM P"); } } @@ -453,6 +469,7 @@ mVUop(mVU_FCAND) { xADD(gprT1, 0xffffff); xSHR(gprT1, 24); mVUallocVIb(mVU, gprT1, 1); + mVU.profiler.EmitOp(opFCAND); } pass3 { mVUlog("FCAND vi01, $%x", _Imm24_); } pass4 { mVUregs.needExactMatch |= 4; } @@ -466,6 +483,7 @@ mVUop(mVU_FCEQ) { xSUB(gprT1, 1); xSHR(gprT1, 31); mVUallocVIb(mVU, gprT1, 1); + mVU.profiler.EmitOp(opFCEQ); } pass3 { mVUlog("FCEQ vi01, $%x", _Imm24_); } pass4 { mVUregs.needExactMatch |= 4; } @@ -477,6 +495,7 @@ mVUop(mVU_FCGET) { mVUallocCFLAGa(mVU, gprT1, cFLAG.read); xAND(gprT1, 0xfff); mVUallocVIb(mVU, gprT1, _It_); + mVU.profiler.EmitOp(opFCGET); } pass3 { mVUlog("FCGET vi%02d", _Ft_); } pass4 { mVUregs.needExactMatch |= 4; } @@ -490,6 +509,7 @@ mVUop(mVU_FCOR) { xADD(gprT1, 1); // If 24 1's will make 25th bit 1, else 0 xSHR(gprT1, 24); // Get the 25th bit (also clears the rest of the garbage in the reg) mVUallocVIb(mVU, gprT1, 1); + mVU.profiler.EmitOp(opFCOR); } pass3 { mVUlog("FCOR vi01, $%x", _Imm24_); } pass4 { mVUregs.needExactMatch |= 4; } @@ -500,6 +520,7 @@ mVUop(mVU_FCSET) { pass2 { xMOV(gprT1, _Imm24_); mVUallocCFLAGb(mVU, gprT1, cFLAG.write); + mVU.profiler.EmitOp(opFCSET); } pass3 { mVUlog("FCSET $%x", _Imm24_); } } @@ -515,6 +536,7 @@ mVUop(mVU_FMAND) { mVUallocVIa(mVU, gprT2, _Is_); xAND(gprT1b, gprT2b); mVUallocVIb(mVU, gprT1, _It_); + mVU.profiler.EmitOp(opFMAND); } pass3 { mVUlog("FMAND vi%02d, vi%02d", _Ft_, _Fs_); } pass4 { mVUregs.needExactMatch |= 2; } @@ -529,6 +551,7 @@ mVUop(mVU_FMEQ) { xSUB(gprT1, 1); xSHR(gprT1, 31); mVUallocVIb(mVU, gprT1, _It_); + mVU.profiler.EmitOp(opFMEQ); } pass3 { mVUlog("FMEQ vi%02d, vi%02d", _Ft_, _Fs_); } pass4 { mVUregs.needExactMatch |= 2; } @@ -541,6 +564,7 @@ mVUop(mVU_FMOR) { mVUallocVIa(mVU, gprT2, _Is_); xOR(gprT1b, gprT2b); mVUallocVIb(mVU, gprT1, _It_); + mVU.profiler.EmitOp(opFMOR); } pass3 { mVUlog("FMOR vi%02d, vi%02d", _Ft_, _Fs_); } pass4 { mVUregs.needExactMatch |= 2; } @@ -558,6 +582,7 @@ mVUop(mVU_FSAND) { mVUallocSFLAGc(gprT1, gprT2, sFLAG.read); xAND(gprT1, _Imm12_); mVUallocVIb(mVU, gprT1, _It_); + mVU.profiler.EmitOp(opFSAND); } pass3 { mVUlog("FSAND vi%02d, $%x", _Ft_, _Imm12_); } pass4 { mVUregs.needExactMatch |= 1; } @@ -569,6 +594,7 @@ mVUop(mVU_FSOR) { mVUallocSFLAGc(gprT1, gprT2, sFLAG.read); xOR(gprT1, _Imm12_); mVUallocVIb(mVU, gprT1, _It_); + mVU.profiler.EmitOp(opFSOR); } pass3 { mVUlog("FSOR vi%02d, $%x", _Ft_, _Imm12_); } pass4 { mVUregs.needExactMatch |= 1; } @@ -602,6 +628,7 @@ mVUop(mVU_FSEQ) { xSUB(gprT1, 1); xSHR(gprT1, 31); mVUallocVIb(mVU, gprT1, _It_); + mVU.profiler.EmitOp(opFSEQ); } pass3 { mVUlog("FSEQ vi%02d, $%x", _Ft_, _Imm12_); } pass4 { mVUregs.needExactMatch |= 1; } @@ -622,6 +649,7 @@ mVUop(mVU_FSSET) { } xAND(getFlagReg(sFLAG.write), 0xfff00); // Keep Non-Sticky Bits if (imm) xOR(getFlagReg(sFLAG.write), imm); + mVU.profiler.EmitOp(opFSSET); } pass3 { mVUlog("FSSET $%x", _Imm12_); } } @@ -640,6 +668,7 @@ mVUop(mVU_IADD) { } else xADD(gprT1b, gprT1b); mVUallocVIb(mVU, gprT1, _Id_); + mVU.profiler.EmitOp(opIADD); } pass3 { mVUlog("IADD vi%02d, vi%02d, vi%02d", _Fd_, _Fs_, _Ft_); } } @@ -650,6 +679,7 @@ mVUop(mVU_IADDI) { mVUallocVIa(mVU, gprT1, _Is_); xADD(gprT1b, _Imm5_); mVUallocVIb(mVU, gprT1, _It_); + mVU.profiler.EmitOp(opIADDI); } pass3 { mVUlog("IADDI vi%02d, vi%02d, %d", _Ft_, _Fs_, _Imm5_); } } @@ -660,6 +690,7 @@ mVUop(mVU_IADDIU) { mVUallocVIa(mVU, gprT1, _Is_); xADD(gprT1b, _Imm15_); mVUallocVIb(mVU, gprT1, _It_); + mVU.profiler.EmitOp(opIADDIU); } pass3 { mVUlog("IADDIU vi%02d, vi%02d, %d", _Ft_, _Fs_, _Imm15_); } } @@ -673,6 +704,7 @@ mVUop(mVU_IAND) { xAND(gprT1, gprT2); } mVUallocVIb(mVU, gprT1, _Id_); + mVU.profiler.EmitOp(opIAND); } pass3 { mVUlog("IAND vi%02d, vi%02d, vi%02d", _Fd_, _Fs_, _Ft_); } } @@ -686,6 +718,7 @@ mVUop(mVU_IOR) { xOR(gprT1, gprT2); } mVUallocVIb(mVU, gprT1, _Id_); + mVU.profiler.EmitOp(opIOR); } pass3 { mVUlog("IOR vi%02d, vi%02d, vi%02d", _Fd_, _Fs_, _Ft_); } } @@ -703,6 +736,7 @@ mVUop(mVU_ISUB) { xXOR(gprT1, gprT1); mVUallocVIb(mVU, gprT1, _Id_); } + mVU.profiler.EmitOp(opISUB); } pass3 { mVUlog("ISUB vi%02d, vi%02d, vi%02d", _Fd_, _Fs_, _Ft_); } } @@ -713,6 +747,7 @@ mVUop(mVU_ISUBIU) { mVUallocVIa(mVU, gprT1, _Is_); xSUB(gprT1b, _Imm15_); mVUallocVIb(mVU, gprT1, _It_); + mVU.profiler.EmitOp(opISUBIU); } pass3 { mVUlog("ISUBIU vi%02d, vi%02d, %d", _Ft_, _Fs_, _Imm15_); } } @@ -733,6 +768,7 @@ mVUop(mVU_MFIR) { xMOVDZX(Ft, gprT1); if (!_XYZW_SS) { mVUunpack_xyzw(Ft, Ft, 0); } mVU.regAlloc->clearNeeded(Ft); + mVU.profiler.EmitOp(opMFIR); } pass3 { mVUlog("MFIR.%s vf%02d, vi%02d", _XYZW_String, _Ft_, _Fs_); } } @@ -743,6 +779,7 @@ mVUop(mVU_MFP) { const xmm& Ft = mVU.regAlloc->allocReg(-1, _Ft_, _X_Y_Z_W); getPreg(mVU, Ft); mVU.regAlloc->clearNeeded(Ft); + mVU.profiler.EmitOp(opMFP); } pass3 { mVUlog("MFP.%s vf%02d, P", _XYZW_String, _Ft_); } } @@ -752,6 +789,7 @@ mVUop(mVU_MOVE) { pass2 { const xmm& Fs = mVU.regAlloc->allocReg(_Fs_, _Ft_, _X_Y_Z_W); mVU.regAlloc->clearNeeded(Fs); + mVU.profiler.EmitOp(opMOVE); } pass3 { mVUlog("MOVE.%s vf%02d, vf%02d", _XYZW_String, _Ft_, _Fs_); } } @@ -765,6 +803,7 @@ mVUop(mVU_MR32) { else xPSHUF.D(Ft, Fs, 0x39); mVU.regAlloc->clearNeeded(Ft); mVU.regAlloc->clearNeeded(Fs); + mVU.profiler.EmitOp(opMR32); } pass3 { mVUlog("MR32.%s vf%02d, vf%02d", _XYZW_String, _Ft_, _Fs_); } } @@ -780,6 +819,7 @@ mVUop(mVU_MTIR) { xMOVD(gprT1, Fs); mVUallocVIb(mVU, gprT1, _It_); mVU.regAlloc->clearNeeded(Fs); + mVU.profiler.EmitOp(opMTIR); } pass3 { mVUlog("MTIR vi%02d, vf%02d%s", _Ft_, _Fs_, _Fsf_String); } } @@ -806,6 +846,7 @@ mVUop(mVU_ILW) { ptr += getVUmem(_Imm11_); xMOVZX(gprT1, ptr16[ptr]); mVUallocVIb(mVU, gprT1, _It_); + mVU.profiler.EmitOp(opILW); } pass3 { mVUlog("ILW.%s vi%02d, vi%02d + %d", _XYZW_String, _Ft_, _Fs_, _Imm11_); } } @@ -825,6 +866,7 @@ mVUop(mVU_ILWR) { } xMOVZX(gprT1, ptr16[ptr]); mVUallocVIb(mVU, gprT1, _It_); + mVU.profiler.EmitOp(opILWR); } pass3 { mVUlog("ILWR.%s vi%02d, vi%02d", _XYZW_String, _Ft_, _Fs_); } } @@ -853,6 +895,7 @@ mVUop(mVU_ISW) { if (_Y) xMOV(ptr32[ptr+4], gprT1); if (_Z) xMOV(ptr32[ptr+8], gprT1); if (_W) xMOV(ptr32[ptr+12], gprT1); + mVU.profiler.EmitOp(opISW); } pass3 { mVUlog("ISW.%s vi%02d, vi%02d + %d", _XYZW_String, _Ft_, _Fs_, _Imm11_); } } @@ -873,6 +916,7 @@ mVUop(mVU_ISWR) { if (_Y) xMOV(ptr32[ptr+4], gprT1); if (_Z) xMOV(ptr32[ptr+8], gprT1); if (_W) xMOV(ptr32[ptr+12], gprT1); + mVU.profiler.EmitOp(opISWR); } pass3 { mVUlog("ISWR.%s vi%02d, vi%02d", _XYZW_String, _Ft_, _Fs_); } } @@ -896,6 +940,7 @@ mVUop(mVU_LQ) { const xmm& Ft = mVU.regAlloc->allocReg(-1, _Ft_, _X_Y_Z_W); mVUloadReg(Ft, ptr, _X_Y_Z_W); mVU.regAlloc->clearNeeded(Ft); + mVU.profiler.EmitOp(opLQ); } pass3 { mVUlog("LQ.%s vf%02d, vi%02d + %d", _XYZW_String, _Ft_, _Fs_, _Imm11_); } } @@ -916,6 +961,7 @@ mVUop(mVU_LQD) { mVUloadReg(Ft, ptr, _X_Y_Z_W); mVU.regAlloc->clearNeeded(Ft); } + mVU.profiler.EmitOp(opLQD); } pass3 { mVUlog("LQD.%s vf%02d, --vi%02d", _XYZW_String, _Ft_, _Is_); } } @@ -937,6 +983,7 @@ mVUop(mVU_LQI) { mVUloadReg(Ft, ptr, _X_Y_Z_W); mVU.regAlloc->clearNeeded(Ft); } + mVU.profiler.EmitOp(opLQI); } pass3 { mVUlog("LQI.%s vf%02d, vi%02d++", _XYZW_String, _Ft_, _Fs_); } } @@ -960,6 +1007,7 @@ mVUop(mVU_SQ) { const xmm& Fs = mVU.regAlloc->allocReg(_Fs_, 0, _X_Y_Z_W); mVUsaveReg(Fs, ptr, _X_Y_Z_W, 1); mVU.regAlloc->clearNeeded(Fs); + mVU.profiler.EmitOp(opSQ); } pass3 { mVUlog("SQ.%s vf%02d, vi%02d + %d", _XYZW_String, _Fs_, _Ft_, _Imm11_); } } @@ -978,6 +1026,7 @@ mVUop(mVU_SQD) { const xmm& Fs = mVU.regAlloc->allocReg(_Fs_, 0, _X_Y_Z_W); mVUsaveReg(Fs, ptr, _X_Y_Z_W, 1); mVU.regAlloc->clearNeeded(Fs); + mVU.profiler.EmitOp(opSQD); } pass3 { mVUlog("SQD.%s vf%02d, --vi%02d", _XYZW_String, _Fs_, _Ft_); } } @@ -997,6 +1046,7 @@ mVUop(mVU_SQI) { const xmm& Fs = mVU.regAlloc->allocReg(_Fs_, 0, _X_Y_Z_W); mVUsaveReg(Fs, ptr, _X_Y_Z_W, 1); mVU.regAlloc->clearNeeded(Fs); + mVU.profiler.EmitOp(opSQI); } pass3 { mVUlog("SQI.%s vf%02d, vi%02d++", _XYZW_String, _Fs_, _Ft_); } } @@ -1017,6 +1067,7 @@ mVUop(mVU_RINIT) { mVU.regAlloc->clearNeeded(Fs); } else xMOV(ptr32[Rmem], 0x3f800000); + mVU.profiler.EmitOp(opRINIT); } pass3 { mVUlog("RINIT R, vf%02d%s", _Fs_, _Fsf_String); } } @@ -1032,7 +1083,11 @@ static __fi void mVU_RGET_(mV, const x32& Rreg) { mVUop(mVU_RGET) { pass1 { mVUanalyzeR2(mVU, _Ft_, 1); } - pass2 { xMOV(gprT1, ptr32[Rmem]); mVU_RGET_(mVU, gprT1); } + pass2 { + xMOV(gprT1, ptr32[Rmem]); + mVU_RGET_(mVU, gprT1); + mVU.profiler.EmitOp(opRGET); + } pass3 { mVUlog("RGET.%s vf%02d, R", _XYZW_String, _Ft_); } } @@ -1056,6 +1111,7 @@ mVUop(mVU_RNEXT) { xOR (gprT3, 0x3f800000); xMOV(ptr32[Rmem], gprT3); mVU_RGET_(mVU, gprT3); + mVU.profiler.EmitOp(opRNEXT); } pass3 { mVUlog("RNEXT.%s vf%02d, R", _XYZW_String, _Ft_); } } @@ -1070,6 +1126,7 @@ mVUop(mVU_RXOR) { xXOR(ptr32[Rmem], gprT1); mVU.regAlloc->clearNeeded(Fs); } + mVU.profiler.EmitOp(opRXOR); } pass3 { mVUlog("RXOR R, vf%02d%s", _Fs_, _Fsf_String); } } @@ -1080,11 +1137,13 @@ mVUop(mVU_RXOR) { mVUop(mVU_WAITP) { pass1 { mVUstall = max(mVUstall, (u8)((mVUregs.p) ? (mVUregs.p - 1) : 0)); } + pass2 { mVU.profiler.EmitOp(opWAITP); } pass3 { mVUlog("WAITP"); } } mVUop(mVU_WAITQ) { pass1 { mVUstall = max(mVUstall, mVUregs.q); } + pass2 { mVU.profiler.EmitOp(opWAITQ); } pass3 { mVUlog("WAITQ"); } } @@ -1100,6 +1159,7 @@ mVUop(mVU_XTOP) { pass2 { xMOVZX(gprT1, ptr16[&mVU.getVifRegs().top]); mVUallocVIb(mVU, gprT1, _It_); + mVU.profiler.EmitOp(opXTOP); } pass3 { mVUlog("XTOP vi%02d", _Ft_); } } @@ -1112,6 +1172,7 @@ mVUop(mVU_XITOP) { xMOVZX(gprT1, ptr16[&mVU.getVifRegs().itop]); xAND (gprT1, isVU1 ? 0x3ff : 0xff); mVUallocVIb(mVU, gprT1, _It_); + mVU.profiler.EmitOp(opXITOP); } pass3 { mVUlog("XITOP vi%02d", _Ft_); } } @@ -1155,6 +1216,7 @@ mVUop(mVU_XGKICK) { elif (mVUinfo.doXGKICK) { mVU_XGKICK_DELAY(mVU, 1); mVUinfo.doXGKICK = 0; } mVUallocVIa(mVU, gprT1, _Is_); xMOV(ptr32[&mVU.VIxgkick], gprT1); + mVU.profiler.EmitOp(opXGKICK); } pass3 { mVUlog("XGKICK vi%02d", _Fs_); } } @@ -1204,6 +1266,7 @@ mVUop(mVU_B) { pass2 { if (mVUlow.badBranch) { xMOV(ptr32[&mVU.badBranch], branchAddrN); } if (mVUlow.evilBranch) { xMOV(ptr32[&mVU.evilBranch], branchAddr); } + mVU.profiler.EmitOp(opB); } pass3 { mVUlog("B [%04x]", branchAddr, branchAddr); } } @@ -1216,6 +1279,7 @@ mVUop(mVU_BAL) { mVUallocVIb(mVU, gprT1, _It_); if (mVUlow.badBranch) { xMOV(ptr32[&mVU.badBranch], branchAddrN); } if (mVUlow.evilBranch) { xMOV(ptr32[&mVU.evilBranch], branchAddr); } + mVU.profiler.EmitOp(opBAL); } pass3 { mVUlog("BAL vi%02d [%04x]", _Ft_, branchAddr, branchAddr); } } @@ -1232,6 +1296,7 @@ mVUop(mVU_IBEQ) { if (!(isBadOrEvil)) xMOV(ptr32[&mVU.branch], gprT1); else condEvilBranch(mVU, Jcc_Equal); + mVU.profiler.EmitOp(opIBEQ); } pass3 { mVUlog("IBEQ vi%02d, vi%02d [%04x]", _Ft_, _Fs_, branchAddr, branchAddr); } } @@ -1244,6 +1309,7 @@ mVUop(mVU_IBGEZ) { else mVUallocVIa(mVU, gprT1, _Is_); if (!(isBadOrEvil)) xMOV(ptr32[&mVU.branch], gprT1); else condEvilBranch(mVU, Jcc_GreaterOrEqual); + mVU.profiler.EmitOp(opIBGEZ); } pass3 { mVUlog("IBGEZ vi%02d [%04x]", _Fs_, branchAddr, branchAddr); } } @@ -1256,6 +1322,7 @@ mVUop(mVU_IBGTZ) { else mVUallocVIa(mVU, gprT1, _Is_); if (!(isBadOrEvil)) xMOV(ptr32[&mVU.branch], gprT1); else condEvilBranch(mVU, Jcc_Greater); + mVU.profiler.EmitOp(opIBGTZ); } pass3 { mVUlog("IBGTZ vi%02d [%04x]", _Fs_, branchAddr, branchAddr); } } @@ -1268,6 +1335,7 @@ mVUop(mVU_IBLEZ) { else mVUallocVIa(mVU, gprT1, _Is_); if (!(isBadOrEvil)) xMOV(ptr32[&mVU.branch], gprT1); else condEvilBranch(mVU, Jcc_LessOrEqual); + mVU.profiler.EmitOp(opIBLEZ); } pass3 { mVUlog("IBLEZ vi%02d [%04x]", _Fs_, branchAddr, branchAddr); } } @@ -1280,6 +1348,7 @@ mVUop(mVU_IBLTZ) { else mVUallocVIa(mVU, gprT1, _Is_); if (!(isBadOrEvil)) xMOV(ptr32[&mVU.branch], gprT1); else condEvilBranch(mVU, Jcc_Less); + mVU.profiler.EmitOp(opIBLTZ); } pass3 { mVUlog("IBLTZ vi%02d [%04x]", _Fs_, branchAddr, branchAddr); } } @@ -1296,6 +1365,7 @@ mVUop(mVU_IBNE) { if (!(isBadOrEvil)) xMOV(ptr32[&mVU.branch], gprT1); else condEvilBranch(mVU, Jcc_NotEqual); + mVU.profiler.EmitOp(opIBNE); } pass3 { mVUlog("IBNE vi%02d, vi%02d [%04x]", _Ft_, _Fs_, branchAddr, branchAddr); } } @@ -1318,7 +1388,7 @@ void normJumpPass2(mV) { mVUop(mVU_JR) { mVUbranch = 9; pass1 { mVUanalyzeJump(mVU, _Is_, 0, 0); } - pass2 { normJumpPass2(mVU); } + pass2 { normJumpPass2(mVU); mVU.profiler.EmitOp(opJR); } pass3 { mVUlog("JR [vi%02d]", _Fs_); } } @@ -1329,7 +1399,7 @@ mVUop(mVU_JALR) { normJumpPass2(mVU); xMOV(gprT1, bSaveAddr); mVUallocVIb(mVU, gprT1, _It_); + mVU.profiler.EmitOp(opJALR); } pass3 { mVUlog("JALR vi%02d, [vi%02d]", _Ft_, _Fs_); } } - diff --git a/pcsx2/x86/microVU_Macro.inl b/pcsx2/x86/microVU_Macro.inl index 9e8a6019c4..ffba4bde6e 100644 --- a/pcsx2/x86/microVU_Macro.inl +++ b/pcsx2/x86/microVU_Macro.inl @@ -45,14 +45,14 @@ void setupMacroOp(int mode, const char* opName) { microVU0.prog.IRinfo.info[0].cFlag.lastWrite = 0xff; } if (mode & 0x10) { // Update Status/Mac Flags - microVU0.prog.IRinfo.info[0].sFlag.doFlag = 1; - microVU0.prog.IRinfo.info[0].sFlag.doNonSticky = 1; - microVU0.prog.IRinfo.info[0].sFlag.write = 0; - microVU0.prog.IRinfo.info[0].sFlag.lastWrite = 0; - microVU0.prog.IRinfo.info[0].mFlag.doFlag = 1; - microVU0.prog.IRinfo.info[0].mFlag.write = 0xff; + microVU0.prog.IRinfo.info[0].sFlag.doFlag = 1; + microVU0.prog.IRinfo.info[0].sFlag.doNonSticky = 1; + microVU0.prog.IRinfo.info[0].sFlag.write = 0; + microVU0.prog.IRinfo.info[0].sFlag.lastWrite = 0; + microVU0.prog.IRinfo.info[0].mFlag.doFlag = 1; + microVU0.prog.IRinfo.info[0].mFlag.write = 0xff; - xMOV(gprF0, ptr32[&vu0Regs.VI[REG_STATUS_FLAG].UL]); + xMOV(gprF0, ptr32[&vu0Regs.VI[REG_STATUS_FLAG].UL]); } } @@ -304,9 +304,9 @@ static void recCTC2() { xMOV(ptr32[&vu0Regs.VI[REG_R].UL], eax); break; case REG_STATUS_FLAG: - if (_Rt_) { // Denormalizes flag into gprF3 + if (_Rt_) { // Denormalizes flag into eax (gprT1) mVUallocSFLAGd(&cpuRegs.GPR.r[_Rt_].UL[0], 0); - xMOV(ptr32[&vu0Regs.VI[_Rd_].UL], gprF3); + xMOV(ptr32[&vu0Regs.VI[_Rd_].UL], eax); } else xMOV(ptr32[&vu0Regs.VI[_Rd_].UL], 0); break; diff --git a/pcsx2/x86/microVU_Misc.h b/pcsx2/x86/microVU_Misc.h index f3f966e5f3..17aed5ed79 100644 --- a/pcsx2/x86/microVU_Misc.h +++ b/pcsx2/x86/microVU_Misc.h @@ -170,10 +170,10 @@ typedef Fntype_mVUrecInst* Fnptr_mVUrecInst; #define _mVUt template // Define Passes -#define pass1 if (recPass == 0) -#define pass2 if (recPass == 1) -#define pass3 if (recPass == 2) -#define pass4 if (recPass == 3) +#define pass1 if (recPass == 0) // Analyze +#define pass2 if (recPass == 1) // Recompile +#define pass3 if (recPass == 2) // Logging +#define pass4 if (recPass == 3) // Flag stuff // Upper Opcode Cases #define opCase1 if (opCase == 1) // Normal Opcodes diff --git a/pcsx2/x86/microVU_Profiler.h b/pcsx2/x86/microVU_Profiler.h new file mode 100644 index 0000000000..0930bbc2a1 --- /dev/null +++ b/pcsx2/x86/microVU_Profiler.h @@ -0,0 +1,143 @@ +/* PCSX2 - PS2 Emulator for PCs + * Copyright (C) 2002-2010 PCSX2 Dev Team + * + * PCSX2 is free software: you can redistribute it and/or modify it under the terms + * of the GNU Lesser General Public License as published by the Free Software Found- + * ation, either version 3 of the License, or (at your option) any later version. + * + * PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with PCSX2. + * If not, see . + */ + +#pragma once + +enum microOpcode { + // Upper Instructions + opABS, opCLIP, opOPMULA, opOPMSUB, opNOP, + opADD, opADDi, opADDq, opADDx, opADDy, opADDz, opADDw, + opADDA, opADDAi, opADDAq, opADDAx, opADDAy, opADDAz, opADDAw, + opSUB, opSUBi, opSUBq, opSUBx, opSUBy, opSUBz, opSUBw, + opSUBA, opSUBAi, opSUBAq, opSUBAx, opSUBAy, opSUBAz, opSUBAw, + opMUL, opMULi, opMULq, opMULx, opMULy, opMULz, opMULw, + opMULA, opMULAi, opMULAq, opMULAx, opMULAy, opMULAz, opMULAw, + opMADD, opMADDi, opMADDq, opMADDx, opMADDy, opMADDz, opMADDw, + opMADDA, opMADDAi, opMADDAq, opMADDAx, opMADDAy, opMADDAz, opMADDAw, + opMSUB, opMSUBi, opMSUBq, opMSUBx, opMSUBy, opMSUBz, opMSUBw, + opMSUBA, opMSUBAi, opMSUBAq, opMSUBAx, opMSUBAy, opMSUBAz, opMSUBAw, + opMAX, opMAXi, opMAXx, opMAXy, opMAXz, opMAXw, + opMINI, opMINIi, opMINIx, opMINIy, opMINIz, opMINIw, + opFTOI0, opFTOI4, opFTOI12, opFTOI15, + opITOF0, opITOF4, opITOF12, opITOF15, + // Lower Instructions + opDIV, opSQRT, opRSQRT, + opIADD, opIADDI, opIADDIU, + opIAND, opIOR, + opISUB, opISUBIU, + opMOVE, opMFIR, opMTIR, opMR32, opMFP, + opLQ, opLQD, opLQI, + opSQ, opSQD, opSQI, + opILW, opISW, opILWR, opISWR, + opRINIT, opRGET, opRNEXT, opRXOR, + opWAITQ, opWAITP, + opFSAND, opFSEQ, opFSOR, opFSSET, + opFMAND, opFMEQ, opFMOR, + opFCAND, opFCEQ, opFCOR, opFCSET, opFCGET, + opIBEQ, opIBGEZ, opIBGTZ, opIBLTZ, opIBLEZ, opIBNE, + opB, opBAL, opJR, opJALR, + opESADD, opERSADD, opELENG, opERLENG, + opEATANxy, opEATANxz, opESUM, opERCPR, + opESQRT, opERSQRT, opESIN, opEATAN, + opEEXP, opXITOP, opXTOP, opXGKICK, + opLastOpcode +}; + +static const char microOpcodeName[][16] = { + // Upper Instructions + "ABS", "CLIP", "OPMULA", "OPMSUB", "NOP", + "ADD", "ADDi", "ADDq", "ADDx", "ADDy", "ADDz", "ADDw", + "ADDA", "ADDAi", "ADDAq", "ADDAx", "ADDAy", "ADDAz", "ADDAw", + "SUB", "SUBi", "SUBq", "SUBx", "SUBy", "SUBz", "SUBw", + "SUBA", "SUBAi", "SUBAq", "SUBAx", "SUBAy", "SUBAz", "SUBAw", + "MUL", "MULi", "MULq", "MULx", "MULy", "MULz", "MULw", + "MULA", "MULAi", "MULAq", "MULAx", "MULAy", "MULAz", "MULAw", + "MADD", "MADDi", "MADDq", "MADDx", "MADDy", "MADDz", "MADDw", + "MADDA", "MADDAi", "MADDAq", "MADDAx", "MADDAy", "MADDAz", "MADDAw", + "MSUB", "MSUBi", "MSUBq", "MSUBx", "MSUBy", "MSUBz", "MSUBw", + "MSUBA", "MSUBAi", "MSUBAq", "MSUBAx", "MSUBAy", "MSUBAz", "MSUBAw", + "MAX", "MAXi", "MAXx", "MAXy", "MAXz", "MAXw", + "MINI", "MINIi", "MINIx", "MINIy", "MINIz", "MINIw", + "FTOI0", "FTOI4", "FTOI12", "FTOI15", + "ITOF0", "ITOF4", "ITOF12", "ITOF15", + // Lower Instructions + "DIV", "SQRT", "RSQRT", + "IADD", "IADDI", "IADDIU", + "IAND", "IOR", + "ISUB", "ISUBIU", + "MOVE", "MFIR", "MTIR", "MR32", "MFP", + "LQ", "LQD", "LQI", + "SQ", "SQD", "SQI", + "ILW", "ISW", "ILWR", "ISWR", + "RINIT", "RGET", "RNEXT", "RXOR", + "WAITQ", "WAITP", + "FSAND", "FSEQ", "FSOR", "FSSET", + "FMAND", "FMEQ", "FMOR", + "FCAND", "FCEQ", "FCOR", "FCSET", "FCGET", + "IBEQ", "IBGEZ", "IBGTZ", "IBLTZ", "IBLEZ", "IBNE", + "B", "BAL", "JR", "JALR", + "ESADD", "ERSADD", "ELENG", "ERLENG", + "EATANxy", "EATANxz", "ESUM", "ERCPR", + "ESQRT", "ERSQRT", "ESIN", "EATAN", + "EEXP", "XITOP", "XTOP", "XGKICK" +}; + +#ifdef mVUprofileProg +#include +#include +#include + +struct microProfiler { + static const u32 progLimit = 10000; + u64 opStats[opLastOpcode]; + u32 progCount; + int index; + void Reset(int _index) { memzero(*this); index = _index; } + void EmitOp(microOpcode op) { + xADD(ptr32[&(((u32*)opStats)[op*2+0])], 1); + xADC(ptr32[&(((u32*)opStats)[op*2+1])], 0); + } + void Print() { + progCount++; + if ((progCount % progLimit) == 0) { + u64 total = 0; + vector< pair > v; + for(int i = 0; i < opLastOpcode; i++) { + total += opStats[i]; + v.push_back(make_pair(opStats[i], i)); + } + std::sort (v.begin(), v.end()); + std::reverse(v.begin(), v.end()); + double dTotal = (double)total; + DevCon.WriteLn("microVU%d Profiler:", index); + for(u32 i = 0; i < v.size(); i++) { + u64 count = v[i].first; + double stat = (double)count / dTotal * 100.0; + string str = microOpcodeName[v[i].second]; + str.resize(8, ' '); + DevCon.WriteLn("%s - [%3.4f%%][count=%u]", + str.c_str(), stat, (u32)count); + } + DevCon.WriteLn("Total = 0x%x%x\n\n", (u32)(u64)(total>>32),(u32)total); + } + } +}; +#else +struct microProfiler { + __fi void Reset(int _index) {} + __fi void EmitOp(microOpcode op) {} + __fi void Print() {} +}; +#endif diff --git a/pcsx2/x86/microVU_Upper.inl b/pcsx2/x86/microVU_Upper.inl index 9f97a059f8..5b655fa114 100644 --- a/pcsx2/x86/microVU_Upper.inl +++ b/pcsx2/x86/microVU_Upper.inl @@ -110,8 +110,8 @@ enum clampModes { }; // Prints Opcode to MicroProgram Logs -static void mVU_printOP(microVU& mVU, int opCase, const char* opName, bool isACC) { - mVUlog(opName); +static void mVU_printOP(microVU& mVU, int opCase, microOpcode opEnum, bool isACC) { + mVUlog(microOpcodeName[opEnum]); opCase1 { if (isACC) { mVUlogACC(); } else { mVUlogFd(); } mVUlogFt(); } opCase2 { if (isACC) { mVUlogACC(); } else { mVUlogFd(); } mVUlogBC(); } opCase3 { if (isACC) { mVUlogACC(); } else { mVUlogFd(); } mVUlogI(); } @@ -163,7 +163,7 @@ static void setupFtReg(microVU& mVU, xmm& Ft, xmm& tempFt, int opCase) { } // Normal FMAC Opcodes -static void mVU_FMACa(microVU& mVU, int recPass, int opCase, int opType, bool isACC, const char* opName, int clampType) { +static void mVU_FMACa(microVU& mVU, int recPass, int opCase, int opType, bool isACC, microOpcode opEnum, int clampType) { pass1 { setupPass1(mVU, opCase, isACC, ((opType == 3) || (opType == 4))); } pass2 { if (doSafeSub(mVU, opCase, opType, isACC)) return; @@ -195,13 +195,14 @@ static void mVU_FMACa(microVU& mVU, int recPass, int opCase, int opType, bool is mVU.regAlloc->clearNeeded(Fs); // Always Clear Written Reg First mVU.regAlloc->clearNeeded(Ft); + mVU.profiler.EmitOp(opEnum); } - pass3 { mVU_printOP(mVU, opCase, opName, isACC); } + pass3 { mVU_printOP(mVU, opCase, opEnum, isACC); } pass4 { if ((opType != 3) && (opType != 4)) mVUregs.needExactMatch |= 8; } } // MADDA/MSUBA Opcodes -static void mVU_FMACb(microVU& mVU, int recPass, int opCase, int opType, const char* opName, int clampType) { +static void mVU_FMACb(microVU& mVU, int recPass, int opCase, int opType, microOpcode opEnum, int clampType) { pass1 { setupPass1(mVU, opCase, 1, 0); } pass2 { xmm Fs, Ft, ACC, tempFt; @@ -236,13 +237,14 @@ static void mVU_FMACb(microVU& mVU, int recPass, int opCase, int opType, const c mVU.regAlloc->clearNeeded(ACC); mVU.regAlloc->clearNeeded(Fs); mVU.regAlloc->clearNeeded(Ft); + mVU.profiler.EmitOp(opEnum); } - pass3 { mVU_printOP(mVU, opCase, opName, 1); } + pass3 { mVU_printOP(mVU, opCase, opEnum, 1); } pass4 { mVUregs.needExactMatch |= 8; } } // MADD Opcodes -static void mVU_FMACc(microVU& mVU, int recPass, int opCase, const char* opName, int clampType) { +static void mVU_FMACc(microVU& mVU, int recPass, int opCase, microOpcode opEnum, int clampType) { pass1 { setupPass1(mVU, opCase, 0, 0); } pass2 { xmm Fs, Ft, ACC, tempFt; @@ -267,13 +269,14 @@ static void mVU_FMACc(microVU& mVU, int recPass, int opCase, const char* opName, mVU.regAlloc->clearNeeded(Fs); // Always Clear Written Reg First mVU.regAlloc->clearNeeded(Ft); mVU.regAlloc->clearNeeded(ACC); + mVU.profiler.EmitOp(opEnum); } - pass3 { mVU_printOP(mVU, opCase, opName, 0); } + pass3 { mVU_printOP(mVU, opCase, opEnum, 0); } pass4 { mVUregs.needExactMatch |= 8; } } // MSUB Opcodes -static void mVU_FMACd(microVU& mVU, int recPass, int opCase, const char* opName, int clampType) { +static void mVU_FMACd(microVU& mVU, int recPass, int opCase, microOpcode opEnum, int clampType) { pass1 { setupPass1(mVU, opCase, 0, 0); } pass2 { xmm Fs, Ft, Fd, tempFt; @@ -294,8 +297,9 @@ static void mVU_FMACd(microVU& mVU, int recPass, int opCase, const char* opName, mVU.regAlloc->clearNeeded(Fd); // Always Clear Written Reg First mVU.regAlloc->clearNeeded(Ft); mVU.regAlloc->clearNeeded(Fs); + mVU.profiler.EmitOp(opEnum); } - pass3 { mVU_printOP(mVU, opCase, opName, 0); } + pass3 { mVU_printOP(mVU, opCase, opEnum, 0); } pass4 { mVUregs.needExactMatch |= 8; } } @@ -307,6 +311,7 @@ mVUop(mVU_ABS) { const xmm& Fs = mVU.regAlloc->allocReg(_Fs_, _Ft_, _X_Y_Z_W, !((_Fs_ == _Ft_) && (_X_Y_Z_W == 0xf))); xAND.PS(Fs, ptr128[mVUglob.absclip]); mVU.regAlloc->clearNeeded(Fs); + mVU.profiler.EmitOp(opABS); } pass3 { mVUlog("ABS"); mVUlogFtFs(); } } @@ -324,6 +329,7 @@ mVUop(mVU_OPMULA) { mVU.regAlloc->clearNeeded(Ft); mVUupdateFlags(mVU, Fs); mVU.regAlloc->clearNeeded(Fs); + mVU.profiler.EmitOp(opOPMULA); } pass3 { mVUlog("OPMULA"); mVUlogACC(); mVUlogFt(); } pass4 { mVUregs.needExactMatch |= 8; } @@ -345,14 +351,14 @@ mVUop(mVU_OPMSUB) { mVU.regAlloc->clearNeeded(Ft); mVUupdateFlags(mVU, ACC); mVU.regAlloc->clearNeeded(ACC); - + mVU.profiler.EmitOp(opOPMSUB); } pass3 { mVUlog("OPMSUB"); mVUlogFd(); mVUlogFt(); } pass4 { mVUregs.needExactMatch |= 8; } } // FTOI0/FTIO4/FTIO12/FTIO15 Opcodes -static void mVU_FTOIx(mP, const float* addr, const char* opName) { +static void mVU_FTOIx(mP, const float* addr, microOpcode opEnum) { pass1 { mVUanalyzeFMAC2(mVU, _Fs_, _Ft_); } pass2 { if (!_Ft_) return; @@ -374,12 +380,13 @@ static void mVU_FTOIx(mP, const float* addr, const char* opName) { mVU.regAlloc->clearNeeded(Fs); mVU.regAlloc->clearNeeded(t1); mVU.regAlloc->clearNeeded(t2); + mVU.profiler.EmitOp(opEnum); } - pass3 { mVUlog(opName); mVUlogFtFs(); } + pass3 { mVUlog(microOpcodeName[opEnum]); mVUlogFtFs(); } } // ITOF0/ITOF4/ITOF12/ITOF15 Opcodes -static void mVU_ITOFx(mP, const float* addr, const char* opName) { +static void mVU_ITOFx(mP, const float* addr, microOpcode opEnum) { pass1 { mVUanalyzeFMAC2(mVU, _Fs_, _Ft_); } pass2 { if (!_Ft_) return; @@ -390,8 +397,9 @@ static void mVU_ITOFx(mP, const float* addr, const char* opName) { //mVUclamp2(Fs, xmmT1, 15); // Clamp (not sure if this is needed) mVU.regAlloc->clearNeeded(Fs); + mVU.profiler.EmitOp(opEnum); } - pass3 { mVUlog(opName); mVUlogFtFs(); } + pass3 { mVUlog(microOpcodeName[opEnum]); mVUlogFtFs(); } } // Clip Opcode @@ -431,6 +439,7 @@ mVUop(mVU_CLIP) { mVU.regAlloc->clearNeeded(Fs); mVU.regAlloc->clearNeeded(Ft); mVU.regAlloc->clearNeeded(t1); + mVU.profiler.EmitOp(opCLIP); } pass3 { mVUlog("CLIP"); mVUlogCLIP(); } } @@ -439,94 +448,94 @@ mVUop(mVU_CLIP) { // Micro VU Micromode Upper instructions //------------------------------------------------------------------ -mVUop(mVU_ADD) { mVU_FMACa(mVU, recPass, 1, 0, 0, "ADD", 0); } -mVUop(mVU_ADDi) { mVU_FMACa(mVU, recPass, 3, 5, 0, "ADDi", 0); } -mVUop(mVU_ADDq) { mVU_FMACa(mVU, recPass, 4, 0, 0, "ADDq", 0); } -mVUop(mVU_ADDx) { mVU_FMACa(mVU, recPass, 2, 0, 0, "ADDx", 0); } -mVUop(mVU_ADDy) { mVU_FMACa(mVU, recPass, 2, 0, 0, "ADDy", 0); } -mVUop(mVU_ADDz) { mVU_FMACa(mVU, recPass, 2, 0, 0, "ADDz", 0); } -mVUop(mVU_ADDw) { mVU_FMACa(mVU, recPass, 2, 0, 0, "ADDw", 0); } -mVUop(mVU_ADDA) { mVU_FMACa(mVU, recPass, 1, 0, 1, "ADDA", 0); } -mVUop(mVU_ADDAi) { mVU_FMACa(mVU, recPass, 3, 0, 1, "ADDAi", 0); } -mVUop(mVU_ADDAq) { mVU_FMACa(mVU, recPass, 4, 0, 1, "ADDAq", 0); } -mVUop(mVU_ADDAx) { mVU_FMACa(mVU, recPass, 2, 0, 1, "ADDAx", 0); } -mVUop(mVU_ADDAy) { mVU_FMACa(mVU, recPass, 2, 0, 1, "ADDAy", 0); } -mVUop(mVU_ADDAz) { mVU_FMACa(mVU, recPass, 2, 0, 1, "ADDAz", 0); } -mVUop(mVU_ADDAw) { mVU_FMACa(mVU, recPass, 2, 0, 1, "ADDAw", 0); } -mVUop(mVU_SUB) { mVU_FMACa(mVU, recPass, 1, 1, 0, "SUB", (_XYZW_PS)?(cFs|cFt):0); } // Clamp (Kingdom Hearts I (VU0)) -mVUop(mVU_SUBi) { mVU_FMACa(mVU, recPass, 3, 1, 0, "SUBi", (_XYZW_PS)?(cFs|cFt):0); } // Clamp (Kingdom Hearts I (VU0)) -mVUop(mVU_SUBq) { mVU_FMACa(mVU, recPass, 4, 1, 0, "SUBq", (_XYZW_PS)?(cFs|cFt):0); } // Clamp (Kingdom Hearts I (VU0)) -mVUop(mVU_SUBx) { mVU_FMACa(mVU, recPass, 2, 1, 0, "SUBx", (_XYZW_PS)?(cFs|cFt):0); } // Clamp (Kingdom Hearts I (VU0)) -mVUop(mVU_SUBy) { mVU_FMACa(mVU, recPass, 2, 1, 0, "SUBy", (_XYZW_PS)?(cFs|cFt):0); } // Clamp (Kingdom Hearts I (VU0)) -mVUop(mVU_SUBz) { mVU_FMACa(mVU, recPass, 2, 1, 0, "SUBz", (_XYZW_PS)?(cFs|cFt):0); } // Clamp (Kingdom Hearts I (VU0)) -mVUop(mVU_SUBw) { mVU_FMACa(mVU, recPass, 2, 1, 0, "SUBw", (_XYZW_PS)?(cFs|cFt):0); } // Clamp (Kingdom Hearts I (VU0)) -mVUop(mVU_SUBA) { mVU_FMACa(mVU, recPass, 1, 1, 1, "SUBA", 0); } -mVUop(mVU_SUBAi) { mVU_FMACa(mVU, recPass, 3, 1, 1, "SUBAi", 0); } -mVUop(mVU_SUBAq) { mVU_FMACa(mVU, recPass, 4, 1, 1, "SUBAq", 0); } -mVUop(mVU_SUBAx) { mVU_FMACa(mVU, recPass, 2, 1, 1, "SUBAx", 0); } -mVUop(mVU_SUBAy) { mVU_FMACa(mVU, recPass, 2, 1, 1, "SUBAy", 0); } -mVUop(mVU_SUBAz) { mVU_FMACa(mVU, recPass, 2, 1, 1, "SUBAz", 0); } -mVUop(mVU_SUBAw) { mVU_FMACa(mVU, recPass, 2, 1, 1, "SUBAw", 0); } -mVUop(mVU_MUL) { mVU_FMACa(mVU, recPass, 1, 2, 0, "MUL", (_XYZW_PS)?(cFs|cFt):cFs); } // Clamp (TOTA, DoM, Ice Age (VU0)) -mVUop(mVU_MULi) { mVU_FMACa(mVU, recPass, 3, 2, 0, "MULi", (_XYZW_PS)?(cFs|cFt):cFs); } // Clamp (TOTA, DoM, Ice Age (VU0)) -mVUop(mVU_MULq) { mVU_FMACa(mVU, recPass, 4, 2, 0, "MULq", (_XYZW_PS)?(cFs|cFt):cFs); } // Clamp (TOTA, DoM, Ice Age (VU0)) -mVUop(mVU_MULx) { mVU_FMACa(mVU, recPass, 2, 2, 0, "MULx", (_XYZW_PS)?(cFs|cFt):cFs); } // Clamp (TOTA, DoM, Ice Age (vu0)) -mVUop(mVU_MULy) { mVU_FMACa(mVU, recPass, 2, 2, 0, "MULy", (_XYZW_PS)?(cFs|cFt):cFs); } // Clamp (TOTA, DoM, Ice Age (VU0)) -mVUop(mVU_MULz) { mVU_FMACa(mVU, recPass, 2, 2, 0, "MULz", (_XYZW_PS)?(cFs|cFt):cFs); } // Clamp (TOTA, DoM, Ice Age (VU0)) -mVUop(mVU_MULw) { mVU_FMACa(mVU, recPass, 2, 2, 0, "MULw", (_XYZW_PS)?(cFs|cFt):cFs); } // Clamp (TOTA, DoM, Ice Age (VU0)) -mVUop(mVU_MULA) { mVU_FMACa(mVU, recPass, 1, 2, 1, "MULA", 0); } -mVUop(mVU_MULAi) { mVU_FMACa(mVU, recPass, 3, 2, 1, "MULAi", 0); } -mVUop(mVU_MULAq) { mVU_FMACa(mVU, recPass, 4, 2, 1, "MULAq", 0); } -mVUop(mVU_MULAx) { mVU_FMACa(mVU, recPass, 2, 2, 1, "MULAx", cFs);} // Clamp (TOTA, DoM, ...) -mVUop(mVU_MULAy) { mVU_FMACa(mVU, recPass, 2, 2, 1, "MULAy", cFs);} // Clamp (TOTA, DoM, ...) -mVUop(mVU_MULAz) { mVU_FMACa(mVU, recPass, 2, 2, 1, "MULAz", cFs);} // Clamp (TOTA, DoM, ...) -mVUop(mVU_MULAw) { mVU_FMACa(mVU, recPass, 2, 2, 1, "MULAw", cFs);} // Clamp (TOTA, DoM, ...) -mVUop(mVU_MADD) { mVU_FMACc(mVU, recPass, 1, "MADD", 0); } -mVUop(mVU_MADDi) { mVU_FMACc(mVU, recPass, 3, "MADDi", 0); } -mVUop(mVU_MADDq) { mVU_FMACc(mVU, recPass, 4, "MADDq", 0); } -mVUop(mVU_MADDx) { mVU_FMACc(mVU, recPass, 2, "MADDx", cFs);} // Clamp (TOTA, DoM, ...) -mVUop(mVU_MADDy) { mVU_FMACc(mVU, recPass, 2, "MADDy", cFs);} // Clamp (TOTA, DoM, ...) -mVUop(mVU_MADDz) { mVU_FMACc(mVU, recPass, 2, "MADDz", cFs);} // Clamp (TOTA, DoM, ...) -mVUop(mVU_MADDw) { mVU_FMACc(mVU, recPass, 2, "MADDw", (isCOP2)?(cACC|cFt|cFs):cFs);} // Clamp (ICO (COP2), TOTA, DoM) -mVUop(mVU_MADDA) { mVU_FMACb(mVU, recPass, 1, 0, "MADDA", 0); } -mVUop(mVU_MADDAi) { mVU_FMACb(mVU, recPass, 3, 0, "MADDAi", 0); } -mVUop(mVU_MADDAq) { mVU_FMACb(mVU, recPass, 4, 0, "MADDAq", 0); } -mVUop(mVU_MADDAx) { mVU_FMACb(mVU, recPass, 2, 0, "MADDAx", cFs);} // Clamp (TOTA, DoM, ...) -mVUop(mVU_MADDAy) { mVU_FMACb(mVU, recPass, 2, 0, "MADDAy", cFs);} // Clamp (TOTA, DoM, ...) -mVUop(mVU_MADDAz) { mVU_FMACb(mVU, recPass, 2, 0, "MADDAz", cFs);} // Clamp (TOTA, DoM, ...) -mVUop(mVU_MADDAw) { mVU_FMACb(mVU, recPass, 2, 0, "MADDAw", cFs);} // Clamp (TOTA, DoM, ...) -mVUop(mVU_MSUB) { mVU_FMACd(mVU, recPass, 1, "MSUB", 0); } -mVUop(mVU_MSUBi) { mVU_FMACd(mVU, recPass, 3, "MSUBi", 0); } -mVUop(mVU_MSUBq) { mVU_FMACd(mVU, recPass, 4, "MSUBq", 0); } -mVUop(mVU_MSUBx) { mVU_FMACd(mVU, recPass, 2, "MSUBx", 0); } -mVUop(mVU_MSUBy) { mVU_FMACd(mVU, recPass, 2, "MSUBy", 0); } -mVUop(mVU_MSUBz) { mVU_FMACd(mVU, recPass, 2, "MSUBz", 0); } -mVUop(mVU_MSUBw) { mVU_FMACd(mVU, recPass, 2, "MSUBw", 0); } -mVUop(mVU_MSUBA) { mVU_FMACb(mVU, recPass, 1, 1, "MSUBA", 0); } -mVUop(mVU_MSUBAi) { mVU_FMACb(mVU, recPass, 3, 1, "MSUBAi", 0); } -mVUop(mVU_MSUBAq) { mVU_FMACb(mVU, recPass, 4, 1, "MSUBAq", 0); } -mVUop(mVU_MSUBAx) { mVU_FMACb(mVU, recPass, 2, 1, "MSUBAx", 0); } -mVUop(mVU_MSUBAy) { mVU_FMACb(mVU, recPass, 2, 1, "MSUBAy", 0); } -mVUop(mVU_MSUBAz) { mVU_FMACb(mVU, recPass, 2, 1, "MSUBAz", 0); } -mVUop(mVU_MSUBAw) { mVU_FMACb(mVU, recPass, 2, 1, "MSUBAw", 0); } -mVUop(mVU_MAX) { mVU_FMACa(mVU, recPass, 1, 3, 0, "MAX", 0); } -mVUop(mVU_MAXi) { mVU_FMACa(mVU, recPass, 3, 3, 0, "MAXi", 0); } -mVUop(mVU_MAXx) { mVU_FMACa(mVU, recPass, 2, 3, 0, "MAXx", 0); } -mVUop(mVU_MAXy) { mVU_FMACa(mVU, recPass, 2, 3, 0, "MAXy", 0); } -mVUop(mVU_MAXz) { mVU_FMACa(mVU, recPass, 2, 3, 0, "MAXz", 0); } -mVUop(mVU_MAXw) { mVU_FMACa(mVU, recPass, 2, 3, 0, "MAXw", 0); } -mVUop(mVU_MINI) { mVU_FMACa(mVU, recPass, 1, 4, 0, "MINI", 0); } -mVUop(mVU_MINIi) { mVU_FMACa(mVU, recPass, 3, 4, 0, "MINIi", 0); } -mVUop(mVU_MINIx) { mVU_FMACa(mVU, recPass, 2, 4, 0, "MINIx", 0); } -mVUop(mVU_MINIy) { mVU_FMACa(mVU, recPass, 2, 4, 0, "MINIy", 0); } -mVUop(mVU_MINIz) { mVU_FMACa(mVU, recPass, 2, 4, 0, "MINIz", 0); } -mVUop(mVU_MINIw) { mVU_FMACa(mVU, recPass, 2, 4, 0, "MINIw", 0); } -mVUop(mVU_FTOI0) { mVU_FTOIx(mX, NULL, "FTOI0"); } -mVUop(mVU_FTOI4) { mVU_FTOIx(mX, mVUglob.FTOI_4, "FTOI4"); } -mVUop(mVU_FTOI12) { mVU_FTOIx(mX, mVUglob.FTOI_12, "FTOI12"); } -mVUop(mVU_FTOI15) { mVU_FTOIx(mX, mVUglob.FTOI_15, "FTOI15"); } -mVUop(mVU_ITOF0) { mVU_ITOFx(mX, NULL, "ITOF0"); } -mVUop(mVU_ITOF4) { mVU_ITOFx(mX, mVUglob.ITOF_4, "ITOF4"); } -mVUop(mVU_ITOF12) { mVU_ITOFx(mX, mVUglob.ITOF_12, "ITOF12"); } -mVUop(mVU_ITOF15) { mVU_ITOFx(mX, mVUglob.ITOF_15, "ITOF15"); } -mVUop(mVU_NOP) { pass3 { mVUlog("NOP"); } } +mVUop(mVU_ADD) { mVU_FMACa(mVU, recPass, 1, 0, 0, opADD, 0); } +mVUop(mVU_ADDi) { mVU_FMACa(mVU, recPass, 3, 5, 0, opADDi, 0); } +mVUop(mVU_ADDq) { mVU_FMACa(mVU, recPass, 4, 0, 0, opADDq, 0); } +mVUop(mVU_ADDx) { mVU_FMACa(mVU, recPass, 2, 0, 0, opADDx, 0); } +mVUop(mVU_ADDy) { mVU_FMACa(mVU, recPass, 2, 0, 0, opADDy, 0); } +mVUop(mVU_ADDz) { mVU_FMACa(mVU, recPass, 2, 0, 0, opADDz, 0); } +mVUop(mVU_ADDw) { mVU_FMACa(mVU, recPass, 2, 0, 0, opADDw, 0); } +mVUop(mVU_ADDA) { mVU_FMACa(mVU, recPass, 1, 0, 1, opADDA, 0); } +mVUop(mVU_ADDAi) { mVU_FMACa(mVU, recPass, 3, 0, 1, opADDAi, 0); } +mVUop(mVU_ADDAq) { mVU_FMACa(mVU, recPass, 4, 0, 1, opADDAq, 0); } +mVUop(mVU_ADDAx) { mVU_FMACa(mVU, recPass, 2, 0, 1, opADDAx, 0); } +mVUop(mVU_ADDAy) { mVU_FMACa(mVU, recPass, 2, 0, 1, opADDAy, 0); } +mVUop(mVU_ADDAz) { mVU_FMACa(mVU, recPass, 2, 0, 1, opADDAz, 0); } +mVUop(mVU_ADDAw) { mVU_FMACa(mVU, recPass, 2, 0, 1, opADDAw, 0); } +mVUop(mVU_SUB) { mVU_FMACa(mVU, recPass, 1, 1, 0, opSUB, (_XYZW_PS)?(cFs|cFt):0); } // Clamp (Kingdom Hearts I (VU0)) +mVUop(mVU_SUBi) { mVU_FMACa(mVU, recPass, 3, 1, 0, opSUBi, (_XYZW_PS)?(cFs|cFt):0); } // Clamp (Kingdom Hearts I (VU0)) +mVUop(mVU_SUBq) { mVU_FMACa(mVU, recPass, 4, 1, 0, opSUBq, (_XYZW_PS)?(cFs|cFt):0); } // Clamp (Kingdom Hearts I (VU0)) +mVUop(mVU_SUBx) { mVU_FMACa(mVU, recPass, 2, 1, 0, opSUBx, (_XYZW_PS)?(cFs|cFt):0); } // Clamp (Kingdom Hearts I (VU0)) +mVUop(mVU_SUBy) { mVU_FMACa(mVU, recPass, 2, 1, 0, opSUBy, (_XYZW_PS)?(cFs|cFt):0); } // Clamp (Kingdom Hearts I (VU0)) +mVUop(mVU_SUBz) { mVU_FMACa(mVU, recPass, 2, 1, 0, opSUBz, (_XYZW_PS)?(cFs|cFt):0); } // Clamp (Kingdom Hearts I (VU0)) +mVUop(mVU_SUBw) { mVU_FMACa(mVU, recPass, 2, 1, 0, opSUBw, (_XYZW_PS)?(cFs|cFt):0); } // Clamp (Kingdom Hearts I (VU0)) +mVUop(mVU_SUBA) { mVU_FMACa(mVU, recPass, 1, 1, 1, opSUBA, 0); } +mVUop(mVU_SUBAi) { mVU_FMACa(mVU, recPass, 3, 1, 1, opSUBAi, 0); } +mVUop(mVU_SUBAq) { mVU_FMACa(mVU, recPass, 4, 1, 1, opSUBAq, 0); } +mVUop(mVU_SUBAx) { mVU_FMACa(mVU, recPass, 2, 1, 1, opSUBAx, 0); } +mVUop(mVU_SUBAy) { mVU_FMACa(mVU, recPass, 2, 1, 1, opSUBAy, 0); } +mVUop(mVU_SUBAz) { mVU_FMACa(mVU, recPass, 2, 1, 1, opSUBAz, 0); } +mVUop(mVU_SUBAw) { mVU_FMACa(mVU, recPass, 2, 1, 1, opSUBAw, 0); } +mVUop(mVU_MUL) { mVU_FMACa(mVU, recPass, 1, 2, 0, opMUL, (_XYZW_PS)?(cFs|cFt):cFs); } // Clamp (TOTA, DoM, Ice Age (VU0)) +mVUop(mVU_MULi) { mVU_FMACa(mVU, recPass, 3, 2, 0, opMULi, (_XYZW_PS)?(cFs|cFt):cFs); } // Clamp (TOTA, DoM, Ice Age (VU0)) +mVUop(mVU_MULq) { mVU_FMACa(mVU, recPass, 4, 2, 0, opMULq, (_XYZW_PS)?(cFs|cFt):cFs); } // Clamp (TOTA, DoM, Ice Age (VU0)) +mVUop(mVU_MULx) { mVU_FMACa(mVU, recPass, 2, 2, 0, opMULx, (_XYZW_PS)?(cFs|cFt):cFs); } // Clamp (TOTA, DoM, Ice Age (vu0)) +mVUop(mVU_MULy) { mVU_FMACa(mVU, recPass, 2, 2, 0, opMULy, (_XYZW_PS)?(cFs|cFt):cFs); } // Clamp (TOTA, DoM, Ice Age (VU0)) +mVUop(mVU_MULz) { mVU_FMACa(mVU, recPass, 2, 2, 0, opMULz, (_XYZW_PS)?(cFs|cFt):cFs); } // Clamp (TOTA, DoM, Ice Age (VU0)) +mVUop(mVU_MULw) { mVU_FMACa(mVU, recPass, 2, 2, 0, opMULw, (_XYZW_PS)?(cFs|cFt):cFs); } // Clamp (TOTA, DoM, Ice Age (VU0)) +mVUop(mVU_MULA) { mVU_FMACa(mVU, recPass, 1, 2, 1, opMULA, 0); } +mVUop(mVU_MULAi) { mVU_FMACa(mVU, recPass, 3, 2, 1, opMULAi, 0); } +mVUop(mVU_MULAq) { mVU_FMACa(mVU, recPass, 4, 2, 1, opMULAq, 0); } +mVUop(mVU_MULAx) { mVU_FMACa(mVU, recPass, 2, 2, 1, opMULAx, cFs);} // Clamp (TOTA, DoM, ...) +mVUop(mVU_MULAy) { mVU_FMACa(mVU, recPass, 2, 2, 1, opMULAy, cFs);} // Clamp (TOTA, DoM, ...) +mVUop(mVU_MULAz) { mVU_FMACa(mVU, recPass, 2, 2, 1, opMULAz, cFs);} // Clamp (TOTA, DoM, ...) +mVUop(mVU_MULAw) { mVU_FMACa(mVU, recPass, 2, 2, 1, opMULAw, cFs);} // Clamp (TOTA, DoM, ...) +mVUop(mVU_MADD) { mVU_FMACc(mVU, recPass, 1, opMADD, 0); } +mVUop(mVU_MADDi) { mVU_FMACc(mVU, recPass, 3, opMADDi, 0); } +mVUop(mVU_MADDq) { mVU_FMACc(mVU, recPass, 4, opMADDq, 0); } +mVUop(mVU_MADDx) { mVU_FMACc(mVU, recPass, 2, opMADDx, cFs);} // Clamp (TOTA, DoM, ...) +mVUop(mVU_MADDy) { mVU_FMACc(mVU, recPass, 2, opMADDy, cFs);} // Clamp (TOTA, DoM, ...) +mVUop(mVU_MADDz) { mVU_FMACc(mVU, recPass, 2, opMADDz, cFs);} // Clamp (TOTA, DoM, ...) +mVUop(mVU_MADDw) { mVU_FMACc(mVU, recPass, 2, opMADDw, (isCOP2)?(cACC|cFt|cFs):cFs);} // Clamp (ICO (COP2), TOTA, DoM) +mVUop(mVU_MADDA) { mVU_FMACb(mVU, recPass, 1, 0, opMADDA, 0); } +mVUop(mVU_MADDAi) { mVU_FMACb(mVU, recPass, 3, 0, opMADDAi, 0); } +mVUop(mVU_MADDAq) { mVU_FMACb(mVU, recPass, 4, 0, opMADDAq, 0); } +mVUop(mVU_MADDAx) { mVU_FMACb(mVU, recPass, 2, 0, opMADDAx, cFs);} // Clamp (TOTA, DoM, ...) +mVUop(mVU_MADDAy) { mVU_FMACb(mVU, recPass, 2, 0, opMADDAy, cFs);} // Clamp (TOTA, DoM, ...) +mVUop(mVU_MADDAz) { mVU_FMACb(mVU, recPass, 2, 0, opMADDAz, cFs);} // Clamp (TOTA, DoM, ...) +mVUop(mVU_MADDAw) { mVU_FMACb(mVU, recPass, 2, 0, opMADDAw, cFs);} // Clamp (TOTA, DoM, ...) +mVUop(mVU_MSUB) { mVU_FMACd(mVU, recPass, 1, opMSUB, 0); } +mVUop(mVU_MSUBi) { mVU_FMACd(mVU, recPass, 3, opMSUBi, 0); } +mVUop(mVU_MSUBq) { mVU_FMACd(mVU, recPass, 4, opMSUBq, 0); } +mVUop(mVU_MSUBx) { mVU_FMACd(mVU, recPass, 2, opMSUBx, 0); } +mVUop(mVU_MSUBy) { mVU_FMACd(mVU, recPass, 2, opMSUBy, 0); } +mVUop(mVU_MSUBz) { mVU_FMACd(mVU, recPass, 2, opMSUBz, 0); } +mVUop(mVU_MSUBw) { mVU_FMACd(mVU, recPass, 2, opMSUBw, 0); } +mVUop(mVU_MSUBA) { mVU_FMACb(mVU, recPass, 1, 1, opMSUBA, 0); } +mVUop(mVU_MSUBAi) { mVU_FMACb(mVU, recPass, 3, 1, opMSUBAi, 0); } +mVUop(mVU_MSUBAq) { mVU_FMACb(mVU, recPass, 4, 1, opMSUBAq, 0); } +mVUop(mVU_MSUBAx) { mVU_FMACb(mVU, recPass, 2, 1, opMSUBAx, 0); } +mVUop(mVU_MSUBAy) { mVU_FMACb(mVU, recPass, 2, 1, opMSUBAy, 0); } +mVUop(mVU_MSUBAz) { mVU_FMACb(mVU, recPass, 2, 1, opMSUBAz, 0); } +mVUop(mVU_MSUBAw) { mVU_FMACb(mVU, recPass, 2, 1, opMSUBAw, 0); } +mVUop(mVU_MAX) { mVU_FMACa(mVU, recPass, 1, 3, 0, opMAX, 0); } +mVUop(mVU_MAXi) { mVU_FMACa(mVU, recPass, 3, 3, 0, opMAXi, 0); } +mVUop(mVU_MAXx) { mVU_FMACa(mVU, recPass, 2, 3, 0, opMAXx, 0); } +mVUop(mVU_MAXy) { mVU_FMACa(mVU, recPass, 2, 3, 0, opMAXy, 0); } +mVUop(mVU_MAXz) { mVU_FMACa(mVU, recPass, 2, 3, 0, opMAXz, 0); } +mVUop(mVU_MAXw) { mVU_FMACa(mVU, recPass, 2, 3, 0, opMAXw, 0); } +mVUop(mVU_MINI) { mVU_FMACa(mVU, recPass, 1, 4, 0, opMINI, 0); } +mVUop(mVU_MINIi) { mVU_FMACa(mVU, recPass, 3, 4, 0, opMINIi, 0); } +mVUop(mVU_MINIx) { mVU_FMACa(mVU, recPass, 2, 4, 0, opMINIx, 0); } +mVUop(mVU_MINIy) { mVU_FMACa(mVU, recPass, 2, 4, 0, opMINIy, 0); } +mVUop(mVU_MINIz) { mVU_FMACa(mVU, recPass, 2, 4, 0, opMINIz, 0); } +mVUop(mVU_MINIw) { mVU_FMACa(mVU, recPass, 2, 4, 0, opMINIw, 0); } +mVUop(mVU_FTOI0) { mVU_FTOIx(mX, NULL, opFTOI0); } +mVUop(mVU_FTOI4) { mVU_FTOIx(mX, mVUglob.FTOI_4, opFTOI4); } +mVUop(mVU_FTOI12) { mVU_FTOIx(mX, mVUglob.FTOI_12, opFTOI12); } +mVUop(mVU_FTOI15) { mVU_FTOIx(mX, mVUglob.FTOI_15, opFTOI15); } +mVUop(mVU_ITOF0) { mVU_ITOFx(mX, NULL, opITOF0); } +mVUop(mVU_ITOF4) { mVU_ITOFx(mX, mVUglob.ITOF_4, opITOF4); } +mVUop(mVU_ITOF12) { mVU_ITOFx(mX, mVUglob.ITOF_12, opITOF12); } +mVUop(mVU_ITOF15) { mVU_ITOFx(mX, mVUglob.ITOF_15, opITOF15); } +mVUop(mVU_NOP) { pass2 { mVU.profiler.EmitOp(opNOP); } pass3 { mVUlog("NOP"); } }