- Implemented an opcode profiler which prints statistics on how often VU opcodes are used (enabled with the mVUprofileProg macro)
- Get status flag conversion function to use EAX/ECX/EDX regs when being called from EE-rec (VU0 macro mode); this should play nicer with the EE-recs regalloc system.

git-svn-id: http://pcsx2.googlecode.com/svn/trunk@4940 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
cottonvibes 2011-10-15 08:26:59 +00:00
parent 2b3d5d0fa1
commit 5488e082f5
11 changed files with 374 additions and 140 deletions

View File

@ -715,11 +715,12 @@
<ClInclude Include="..\..\Memory.h" />
<ClInclude Include="..\..\vtlb.h" />
<ClInclude Include="..\..\MTVU.h" />
<ClInclude Include="..\..\VU.h" />
<ClInclude Include="..\..\VU.h" />
<ClInclude Include="..\..\VUmicro.h" />
<ClInclude Include="..\..\x86\microVU.h" />
<ClInclude Include="..\..\x86\microVU_IR.h" />
<ClInclude Include="..\..\x86\microVU_Misc.h" />
<ClInclude Include="..\..\x86\microVU_Profiler.h" />
<ClInclude Include="..\..\x86\sVU_Debug.h" />
<ClInclude Include="..\..\x86\sVU_Micro.h" />
<ClInclude Include="..\..\x86\sVU_zerorec.h" />

View File

@ -1201,6 +1201,9 @@
<ClInclude Include="..\..\Gif_Unit.h">
<Filter>System\Ps2\GS</Filter>
</ClInclude>
<ClInclude Include="..\..\x86\microVU_Profiler.h">
<Filter>System\Ps2\EmotionEngine\VU\Dynarec\microVU</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="..\..\..\3rdparty\wxWidgets\include\wx\msw\wx.rc">

View File

@ -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;

View File

@ -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<microRegAlloc> regAlloc; // Reg Alloc Class
ScopedPtr<AsciiFile> logFile; // Log File Pointer

View File

@ -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);
}

View File

@ -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++) {

View File

@ -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 [<a href=\"#addr%04x\">%04x</a>]", 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 [<a href=\"#addr%04x\">%04x</a>]", _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 [<a href=\"#addr%04x\">%04x</a>]", _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 [<a href=\"#addr%04x\">%04x</a>]", _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 [<a href=\"#addr%04x\">%04x</a>]", _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 [<a href=\"#addr%04x\">%04x</a>]", _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 [<a href=\"#addr%04x\">%04x</a>]", _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 [<a href=\"#addr%04x\">%04x</a>]", _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_); }
}

View File

@ -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;

View File

@ -170,10 +170,10 @@ typedef Fntype_mVUrecInst* Fnptr_mVUrecInst;
#define _mVUt template<int vuIndex>
// 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

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#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 <utility>
#include <string>
#include <algorithm>
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<u32, u32> > 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

View File

@ -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"); } }