mVU Macro: Implemented more stuff and did a big cleanup.

git-svn-id: http://pcsx2.googlecode.com/svn/trunk@1707 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
cottonvibes 2009-08-29 05:00:03 +00:00
parent 4d7bfbb86e
commit 2c1397e559
2 changed files with 185 additions and 445 deletions

View File

@ -87,11 +87,13 @@ microVUt(void) mVUallocMFLAGb(mV, int reg, int fInstance) {
} }
microVUt(void) mVUallocCFLAGa(mV, int reg, int fInstance) { microVUt(void) mVUallocCFLAGa(mV, int reg, int fInstance) {
MOV32MtoR(reg, (uptr)&mVU->clipFlag[fInstance]); if (fInstance < 4) MOV32MtoR(reg, (uptr)&mVU->clipFlag[fInstance]); // microVU
else MOV32MtoR(reg, (uptr)&mVU->regs->VI[REG_CLIP_FLAG].UL); // macroVU
} }
microVUt(void) mVUallocCFLAGb(mV, int reg, int fInstance) { microVUt(void) mVUallocCFLAGb(mV, int reg, int fInstance) {
MOV32RtoM((uptr)&mVU->clipFlag[fInstance], reg); if (fInstance < 4) MOV32RtoM((uptr)&mVU->clipFlag[fInstance], reg); // microVU
else MOV32RtoM((uptr)&mVU->regs->VI[REG_CLIP_FLAG].UL, reg); // macroVU
} }
//------------------------------------------------------------------ //------------------------------------------------------------------

View File

@ -25,319 +25,16 @@
extern void _vu0WaitMicro(); extern void _vu0WaitMicro();
//------------------------------------------------------------------ //------------------------------------------------------------------
// Macro VU - Helper Macros // Macro VU - Helper Macros / Functions
//------------------------------------------------------------------
#undef _Ft_
#undef _Fs_
#undef _Fd_
#undef _Fsf_
#undef _Ftf_
#undef _Cc_
#define _Ft_ _Rt_
#define _Fs_ _Rd_
#define _Fd_ _Sa_
#define _Fsf_ ((cpuRegs.code >> 21) & 0x03)
#define _Ftf_ ((cpuRegs.code >> 23) & 0x03)
#define _Cc_ (cpuRegs.code & 0x03)
#define REC_COP2_VU0(f) \
void recV##f( s32 info ) { \
recVUMI_##f( &VU0, info ); \
}
#define INTERPRETATE_COP2_FUNC(f) \
void recV##f(s32 info) { \
MOV32ItoM((uptr)&cpuRegs.code, cpuRegs.code); \
MOV32ItoM((uptr)&cpuRegs.pc, pc); \
iFlushCall(FLUSH_EVERYTHING); \
CALLFunc((uptr)V##f); \
_freeX86regs(); \
}
void recCOP2(s32 info);
void recCOP2_SPECIAL(s32 info);
void recCOP2_BC2(s32 info);
void recCOP2_SPECIAL2(s32 info);
void rec_C2UNK( s32 info ) {
Console::Error("Cop2 bad opcode: %x", params cpuRegs.code);
}
void _vuRegs_C2UNK(VURegs * VU, _VURegsNum *VUregsn) {
Console::Error("Cop2 bad _vuRegs code:%x", params cpuRegs.code);
}
static void recCFC2(s32 info)
{
int mmreg;
if (cpuRegs.code & 1) {
iFlushCall(FLUSH_NOCONST);
CALLFunc((uptr)_vu0WaitMicro);
}
if(!_Rt_) return;
_deleteGPRtoXMMreg(_Rt_, 2);
mmreg = _checkMMXreg(MMX_GPR+_Rt_, MODE_WRITE);
if (mmreg >= 0) {
if( _Fs_ >= 16 ) {
MOVDMtoMMX(mmreg, (uptr)&VU0.VI[ _Fs_ ].UL);
if (EEINST_ISLIVE1(_Rt_)) { _signExtendGPRtoMMX(mmreg, _Rt_, 0); }
else { EEINST_RESETHASLIVE1(_Rt_); }
}
else MOVDMtoMMX(mmreg, (uptr)&VU0.VI[ _Fs_ ].UL);
SetMMXstate();
}
else {
MOV32MtoR(EAX, (uptr)&VU0.VI[ _Fs_ ].UL);
MOV32RtoM((uptr)&cpuRegs.GPR.r[_Rt_].UL[0],EAX);
if(EEINST_ISLIVE1(_Rt_)) {
if( _Fs_ < 16 ) {
// no sign extending
MOV32ItoM((uptr)&cpuRegs.GPR.r[_Rt_].UL[1],0);
}
else {
CDQ();
MOV32RtoM((uptr)&cpuRegs.GPR.r[_Rt_].UL[1], EDX);
}
}
else { EEINST_RESETHASLIVE1(_Rt_); }
}
_eeOnWriteReg(_Rt_, 1);
}
static void recCTC2(s32 info)
{
if (cpuRegs.code & 1) {
iFlushCall(FLUSH_NOCONST);
CALLFunc((uptr)_vu0WaitMicro);
}
if(!_Fs_) return;
if( GPR_IS_CONST1(_Rt_) )
{
switch(_Fs_) {
case REG_MAC_FLAG: // read-only
case REG_TPC: // read-only
case REG_VPU_STAT: // read-only
break;
case REG_FBRST:
if( g_cpuConstRegs[_Rt_].UL[0] & 0x202 )
iFlushCall(FLUSH_FREE_TEMPX86);
_deleteX86reg(X86TYPE_VI, REG_FBRST, 2);
if( g_cpuConstRegs[_Rt_].UL[0] & 2 )
CALLFunc((uptr)vu0ResetRegs);
if( g_cpuConstRegs[_Rt_].UL[0] & 0x200 )
CALLFunc((uptr)vu1ResetRegs);
MOV16ItoM((uptr)&VU0.VI[REG_FBRST].UL,g_cpuConstRegs[_Rt_].UL[0]&0x0c0c);
break;
case REG_CMSAR1: // REG_CMSAR1
iFlushCall(FLUSH_NOCONST);// since CALLFunc
assert( _checkX86reg(X86TYPE_VI, REG_VPU_STAT, 0) < 0 &&
_checkX86reg(X86TYPE_VI, REG_TPC, 0) < 0 );
// Execute VU1 Micro SubRoutine
_callFunctionArg1((uptr)vu1ExecMicro, MEM_CONSTTAG, g_cpuConstRegs[_Rt_].UL[0]&0xffff);
break;
default:
{
if( _Fs_ < 16 )
assert( (g_cpuConstRegs[_Rt_].UL[0]&0xffff0000)==0);
// a lot of games have vu0 spinning on some integer
// then they modify the register and expect vu0 to stop spinning within 10 cycles (donald duck)
// Use vu0ExecMicro instead because it properly stalls for already-running micro
// instructions, and also sets the nextBranchCycle as needed. (air)
MOV32ItoM((uptr)&VU0.VI[_Fs_].UL,g_cpuConstRegs[_Rt_].UL[0]);
//PUSH32I( -1 );
iFlushCall(FLUSH_NOCONST);
CALLFunc((uptr)CpuVU0.ExecuteBlock);
//CALLFunc((uptr)vu0ExecMicro);
//ADD32ItoR( ESP, 4 );
break;
}
}
}
else
{
switch(_Fs_) {
case REG_MAC_FLAG: // read-only
case REG_TPC: // read-only
case REG_VPU_STAT: // read-only
break;
case REG_FBRST:
iFlushCall(FLUSH_FREE_TEMPX86);
assert( _checkX86reg(X86TYPE_VI, REG_FBRST, 0) < 0 );
_eeMoveGPRtoR(EAX, _Rt_);
TEST32ItoR(EAX,0x2);
j8Ptr[0] = JZ8(0);
CALLFunc((uptr)vu0ResetRegs);
_eeMoveGPRtoR(EAX, _Rt_);
x86SetJ8(j8Ptr[0]);
TEST32ItoR(EAX,0x200);
j8Ptr[0] = JZ8(0);
CALLFunc((uptr)vu1ResetRegs);
_eeMoveGPRtoR(EAX, _Rt_);
x86SetJ8(j8Ptr[0]);
AND32ItoR(EAX,0x0C0C);
MOV16RtoM((uptr)&VU0.VI[REG_FBRST].UL,EAX);
break;
case REG_CMSAR1: // REG_CMSAR1
iFlushCall(FLUSH_NOCONST);
_eeMoveGPRtoR(EAX, _Rt_);
_callFunctionArg1((uptr)vu1ExecMicro, MEM_X86TAG|EAX, 0); // Execute VU1 Micro SubRoutine
break;
default:
_eeMoveGPRtoM((uptr)&VU0.VI[_Fs_].UL,_Rt_);
// a lot of games have vu0 spinning on some integer
// then they modify the register and expect vu0 to stop spinning within 10 cycles (donald duck)
iFlushCall(FLUSH_NOCONST);
break;
}
}
}
static void recQMFC2(s32 info)
{
int t0reg, fsreg;
if (cpuRegs.code & 1) {
iFlushCall(FLUSH_NOCONST);
CALLFunc((uptr)_vu0WaitMicro);
}
if(!_Rt_) return;
_deleteMMXreg(MMX_GPR+_Rt_, 2);
_deleteX86reg(X86TYPE_GPR, _Rt_, 2);
_eeOnWriteReg(_Rt_, 0);
// could 'borrow' the reg
fsreg = _checkXMMreg(XMMTYPE_VFREG, _Fs_, MODE_READ);
if( fsreg >= 0 ) {
if ( xmmregs[fsreg].mode & MODE_WRITE ) {
_xmmregs temp;
t0reg = _allocGPRtoXMMreg(-1, _Rt_, MODE_WRITE);
SSEX_MOVDQA_XMM_to_XMM(t0reg, fsreg);
// change regs
temp = xmmregs[t0reg];
xmmregs[t0reg] = xmmregs[fsreg];
xmmregs[fsreg] = temp;
}
else {
// swap regs
t0reg = _allocGPRtoXMMreg(-1, _Rt_, MODE_WRITE);
xmmregs[fsreg] = xmmregs[t0reg];
xmmregs[t0reg].inuse = 0;
}
}
else {
t0reg = _allocGPRtoXMMreg(-1, _Rt_, MODE_WRITE);
if (t0reg >= 0) SSE_MOVAPS_M128_to_XMM( t0reg, (uptr)&VU0.VF[_Fs_].UD[0]);
else _recMove128MtoM((uptr)&cpuRegs.GPR.r[_Rt_].UL[0], (uptr)&VU0.VF[_Fs_].UL[0]);
}
_clearNeededXMMregs();
}
static void recQMTC2(s32 info)
{
int mmreg;
if (cpuRegs.code & 1) {
iFlushCall(FLUSH_NOCONST);
CALLFunc((uptr)_vu0WaitMicro);
}
if (!_Fs_) return;
mmreg = _checkXMMreg(XMMTYPE_GPRREG, _Rt_, MODE_READ);
if( mmreg >= 0) {
int fsreg = _checkXMMreg(XMMTYPE_VFREG, _Fs_, MODE_WRITE);
int flag = ((xmmregs[mmreg].mode&MODE_WRITE) && (g_pCurInstInfo->regs[_Rt_]&(EEINST_LIVE0|EEINST_LIVE1|EEINST_LIVE2)));
if( fsreg >= 0 ) {
if (flag) {
SSE_MOVAPS_XMM_to_XMM(fsreg, mmreg);
}
else {
// swap regs
xmmregs[mmreg] = xmmregs[fsreg];
xmmregs[mmreg].mode = MODE_WRITE;
xmmregs[fsreg].inuse = 0;
g_xmmtypes[mmreg] = XMMT_FPS;
}
}
else {
if (flag) SSE_MOVAPS_XMM_to_M128((uptr)&cpuRegs.GPR.r[_Rt_], mmreg);
// swap regs
xmmregs[mmreg].type = XMMTYPE_VFREG;
xmmregs[mmreg].VU = 0;
xmmregs[mmreg].reg = _Fs_;
xmmregs[mmreg].mode = MODE_WRITE;
g_xmmtypes[mmreg] = XMMT_FPS;
}
}
else {
int fsreg = _allocVFtoXMMreg(&VU0, -1, _Fs_, MODE_WRITE);
if( fsreg >= 0 ) {
mmreg = _checkMMXreg(MMX_GPR+_Rt_, MODE_READ);
if( mmreg >= 0) {
SetMMXstate();
SSE2_MOVQ2DQ_MM_to_XMM(fsreg, mmreg);
SSE_MOVHPS_M64_to_XMM(fsreg, (uptr)&cpuRegs.GPR.r[_Rt_].UL[2]);
}
else {
if( GPR_IS_CONST1( _Rt_ ) ) {
assert( _checkXMMreg(XMMTYPE_GPRREG, _Rt_, MODE_READ) == -1 );
_flushConstReg(_Rt_);
}
SSE_MOVAPS_M128_to_XMM(fsreg, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ]);
}
}
else {
_deleteEEreg(_Rt_, 0);
_recMove128MtoM((uptr)&VU0.VF[_Fs_].UL[0], (uptr)&cpuRegs.GPR.r[_Rt_].UL[0]);
}
}
_clearNeededXMMregs();
}
//------------------------------------------------------------------
// Macro VU - Instructions
//------------------------------------------------------------------ //------------------------------------------------------------------
using namespace R5900::Dynarec; using namespace R5900::Dynarec;
#define printCOP2 0&&
//#define printCOP2 DevCon::Status
void setupMacroOp(int mode, const char* opName) { void setupMacroOp(int mode, const char* opName) {
DevCon::Status(opName); printCOP2(opName);
microVU0.prog.IRinfo.curPC = 0; microVU0.prog.IRinfo.curPC = 0;
microVU0.code = cpuRegs.code; microVU0.code = cpuRegs.code;
memset(&microVU0.prog.IRinfo.info[0], 0, sizeof(microVU0.prog.IRinfo.info[0])); memset(&microVU0.prog.IRinfo.info[0], 0, sizeof(microVU0.prog.IRinfo.info[0]));
@ -346,6 +43,10 @@ void setupMacroOp(int mode, const char* opName) {
if (mode & 1) { // Q-Reg will be Read if (mode & 1) { // Q-Reg will be Read
SSE_MOVSS_M32_to_XMM(xmmPQ, (uptr)&microVU0.regs->VI[REG_Q].UL); SSE_MOVSS_M32_to_XMM(xmmPQ, (uptr)&microVU0.regs->VI[REG_Q].UL);
} }
if (mode & 8) { // Clip Instruction
microVU0.prog.IRinfo.info[0].cFlag.write = 0xff;
microVU0.prog.IRinfo.info[0].cFlag.lastWrite = 0xff;
}
} }
void endMacroOp(int mode) { void endMacroOp(int mode) {
@ -356,7 +57,7 @@ void endMacroOp(int mode) {
} }
#define REC_COP2_mVU0(f, opName, mode) \ #define REC_COP2_mVU0(f, opName, mode) \
void recV##f(s32 info) { \ void recV##f() { \
setupMacroOp(mode, opName); \ setupMacroOp(mode, opName); \
if (mode & 4) { \ if (mode & 4) { \
mVU_##f(&microVU0, 0); \ mVU_##f(&microVU0, 0); \
@ -368,6 +69,19 @@ void endMacroOp(int mode) {
endMacroOp(mode); \ endMacroOp(mode); \
} }
#define INTERPRETATE_COP2_FUNC(f) \
void recV##f() { \
MOV32ItoM((uptr)&cpuRegs.code, cpuRegs.code); \
MOV32ItoM((uptr)&cpuRegs.pc, pc); \
iFlushCall(FLUSH_EVERYTHING); \
CALLFunc((uptr)V##f); \
_freeX86regs(); \
}
//------------------------------------------------------------------
// Macro VU - Instructions
//------------------------------------------------------------------
//------------------------------------------------------------------ //------------------------------------------------------------------
// Macro VU - Redirect Upper Instructions // Macro VU - Redirect Upper Instructions
//------------------------------------------------------------------ //------------------------------------------------------------------
@ -465,7 +179,7 @@ REC_COP2_mVU0(MSUBAz, "MSUBAz", 0);
REC_COP2_mVU0(MSUBAw, "MSUBAw", 0); REC_COP2_mVU0(MSUBAw, "MSUBAw", 0);
REC_COP2_mVU0(OPMULA, "OPMULA", 0); REC_COP2_mVU0(OPMULA, "OPMULA", 0);
REC_COP2_mVU0(OPMSUB, "OPMSUB", 0); REC_COP2_mVU0(OPMSUB, "OPMSUB", 0);
REC_COP2_VU0 (CLIP); REC_COP2_mVU0(CLIP, "CLIP", 8);
//------------------------------------------------------------------ //------------------------------------------------------------------
// Macro VU - Redirect Lower Instructions // Macro VU - Redirect Lower Instructions
@ -498,8 +212,8 @@ REC_COP2_mVU0(RXOR, "RXOR", 0);
// Macro VU - Misc... // Macro VU - Misc...
//------------------------------------------------------------------ //------------------------------------------------------------------
void recVNOP (s32 info) {} void recVNOP() {}
void recVWAITQ(s32 info) {} void recVWAITQ(){}
INTERPRETATE_COP2_FUNC(CALLMS); INTERPRETATE_COP2_FUNC(CALLMS);
INTERPRETATE_COP2_FUNC(CALLMSR); INTERPRETATE_COP2_FUNC(CALLMSR);
@ -507,166 +221,190 @@ INTERPRETATE_COP2_FUNC(CALLMSR);
// Macro VU - Branches // Macro VU - Branches
//------------------------------------------------------------------ //------------------------------------------------------------------
static void _setupBranchTest() { void _setupBranchTest(u32*(jmpType)(u32), bool isLikely) {
printCOP2("COP2 Branch");
_eeFlushAllUnused(); _eeFlushAllUnused();
TEST32ItoM((uptr)&VU0.VI[REG_VPU_STAT].UL, 0x100); TEST32ItoM((uptr)&VU0.VI[REG_VPU_STAT].UL, 0x100);
recDoBranchImm(jmpType(0), isLikely);
} }
void recBC2F(s32 info) { void recBC2F() { _setupBranchTest(JNZ32, false); }
_setupBranchTest(); void recBC2T() { _setupBranchTest(JZ32, false); }
recDoBranchImm(JNZ32(0)); void recBC2FL() { _setupBranchTest(JNZ32, true); }
void recBC2TL() { _setupBranchTest(JZ32, true); }
//------------------------------------------------------------------
// Macro VU - COP2 Transfer Instructions
//------------------------------------------------------------------
void COP2_Interlock(bool cond) {
if (cond) {
iFlushCall(FLUSH_NOCONST);
CALLFunc((uptr)_vu0WaitMicro);
}
} }
void recBC2T(s32 info) { void TEST_FBRST_RESET(uptr resetFunct, int vuIndex) {
_setupBranchTest(); TEST32ItoR(EAX, (vuIndex) ? 0x200 : 0x002);
recDoBranchImm(JZ32(0)); j8Ptr[0] = JZ8(0);
CALLFunc(resetFunct);
MOV32MtoR(EAX, (uptr)&cpuRegs.GPR.r[_Rt_].UL[0]);
x86SetJ8(j8Ptr[0]);
} }
void recBC2FL(s32 info) { static void recCFC2() {
_setupBranchTest();
recDoBranchImm_Likely(JNZ32(0)); printCOP2("CFC2");
COP2_Interlock(cpuRegs.code & 1);
if (!_Rt_) return;
iFlushCall(FLUSH_EVERYTHING);
MOV32MtoR(EAX, (uptr)&microVU0.regs->VI[_Rd_].UL);
MOV32RtoM((uptr)&cpuRegs.GPR.r[_Rt_].UL[0], EAX);
if( _Rd_ >= 16 ) {
CDQ(); // Sign Extend
MOV32RtoM ((uptr)&cpuRegs.GPR.r[_Rt_].UL[1], EDX);
}
else MOV32ItoM((uptr)&cpuRegs.GPR.r[_Rt_].UL[1], 0);
// FixMe: I think this is needed, but not sure how it works
_eeOnWriteReg(_Rt_, 1);
} }
void recBC2TL(s32 info) { static void recCTC2() {
_setupBranchTest();
recDoBranchImm_Likely(JZ32(0)); printCOP2("CTC2");
COP2_Interlock(cpuRegs.code & 1);
if (!_Rd_) return;
iFlushCall(FLUSH_EVERYTHING);
switch(_Rd_) {
case REG_MAC_FLAG: case REG_TPC:
case REG_VPU_STAT: break; // Read Only Regs
case REG_R:
MOV32MtoR(EAX, (uptr)&cpuRegs.GPR.r[_Rt_].UL[0]);
OR32ItoR (EAX, 0x3f800000);
MOV32RtoM((uptr)&microVU0.regs->VI[REG_R].UL, EAX);
break;
case REG_CMSAR1: // REG_CMSAR1
if (_Rt_) {
MOV32MtoR(EAX, (uptr)&cpuRegs.GPR.r[_Rt_].UL[0]);
PUSH32R(EAX);
}
else PUSH32I(0);
CALLFunc((uptr)vu1ExecMicro); // Execute VU1 Micro SubRoutine
ADD32ItoR(ESP, 4);
break;
case REG_FBRST:
if (!_Rt_) {
MOV32ItoM((uptr)&microVU0.regs->VI[REG_FBRST].UL, 0);
return;
}
else MOV32MtoR(EAX, (uptr)&cpuRegs.GPR.r[_Rt_].UL[0]);
TEST_FBRST_RESET((uptr)vu0ResetRegs, 0);
TEST_FBRST_RESET((uptr)vu1ResetRegs, 1);
AND32ItoR(EAX, 0x0C0C);
MOV32RtoM((uptr)&microVU0.regs->VI[REG_FBRST].UL, EAX);
break;
default:
_eeMoveGPRtoM((uptr)&microVU0.regs->VI[_Rd_].UL, _Rt_);
break;
}
}
static void recQMFC2() {
printCOP2("QMFC2");
COP2_Interlock(cpuRegs.code & 1);
if (!_Rt_) return;
iFlushCall(FLUSH_EVERYTHING);
// FixMe: For some reason this line is needed or else games break:
_eeOnWriteReg(_Rt_, 0);
SSE_MOVAPS_M128_to_XMM(xmmT1, (uptr)&microVU0.regs->VF[_Rd_].UL[0]);
SSE_MOVAPS_XMM_to_M128((uptr)&cpuRegs.GPR.r[_Rt_].UL[0], xmmT1);
}
static void recQMTC2() {
printCOP2("QMTC2");
COP2_Interlock(cpuRegs.code & 1);
if (!_Rd_) return;
iFlushCall(FLUSH_EVERYTHING);
SSE_MOVAPS_M128_to_XMM(xmmT1, (uptr)&cpuRegs.GPR.r[_Rt_].UL[0]);
SSE_MOVAPS_XMM_to_M128((uptr)&microVU0.regs->VF[_Rd_].UL[0], xmmT1);
} }
//------------------------------------------------------------------ //------------------------------------------------------------------
// Macro VU - Tables // Macro VU - Tables
//------------------------------------------------------------------ //------------------------------------------------------------------
void _vuRegsCOP2_SPECIAL (VURegs * VU, _VURegsNum *VUregsn); void recCOP2();
void _vuRegsCOP2_SPECIAL2(VURegs * VU, _VURegsNum *VUregsn); void recCOP2_BC2();
void recCOP2_SPEC1();
// information void recCOP2_SPEC2();
void _vuRegsQMFC2(VURegs * VU, _VURegsNum *VUregsn) { void rec_C2UNK() {
VUregsn->VFread0 = _Fs_; Console::Error("Cop2 bad opcode: %x", params cpuRegs.code);
VUregsn->VFr0xyzw= 0xf;
} }
void _vuRegsCFC2(VURegs * VU, _VURegsNum *VUregsn) { // This is called by EE Recs to setup sVU info, this isn't needed for mVU Macro (cottonvibes)
VUregsn->VIread = 1<<_Fs_; void _vuRegsCOP22(VURegs* VU, _VURegsNum* VUregsn) {}
}
void _vuRegsQMTC2(VURegs * VU, _VURegsNum *VUregsn) {
VUregsn->VFwrite = _Fs_;
VUregsn->VFwxyzw= 0xf;
}
void _vuRegsCTC2(VURegs * VU, _VURegsNum *VUregsn) {
VUregsn->VIwrite = 1<<_Fs_;
}
void (*_vuRegsCOP2t[32])(VURegs * VU, _VURegsNum *VUregsn) = {
_vuRegs_C2UNK, _vuRegsQMFC2, _vuRegsCFC2, _vuRegs_C2UNK, _vuRegs_C2UNK, _vuRegsQMTC2, _vuRegsCTC2, _vuRegs_C2UNK,
_vuRegsNOP, _vuRegs_C2UNK, _vuRegs_C2UNK, _vuRegs_C2UNK, _vuRegs_C2UNK, _vuRegs_C2UNK, _vuRegs_C2UNK, _vuRegs_C2UNK,
_vuRegsCOP2_SPECIAL,_vuRegsCOP2_SPECIAL,_vuRegsCOP2_SPECIAL,_vuRegsCOP2_SPECIAL,_vuRegsCOP2_SPECIAL,_vuRegsCOP2_SPECIAL,_vuRegsCOP2_SPECIAL,_vuRegsCOP2_SPECIAL,
_vuRegsCOP2_SPECIAL,_vuRegsCOP2_SPECIAL,_vuRegsCOP2_SPECIAL,_vuRegsCOP2_SPECIAL,_vuRegsCOP2_SPECIAL,_vuRegsCOP2_SPECIAL,_vuRegsCOP2_SPECIAL,_vuRegsCOP2_SPECIAL,
};
void (*_vuRegsCOP2SPECIAL1t[64])(VURegs * VU, _VURegsNum *VUregsn) = {
_vuRegsADDx, _vuRegsADDy, _vuRegsADDz, _vuRegsADDw, _vuRegsSUBx, _vuRegsSUBy, _vuRegsSUBz, _vuRegsSUBw,
_vuRegsMADDx, _vuRegsMADDy, _vuRegsMADDz, _vuRegsMADDw, _vuRegsMSUBx, _vuRegsMSUBy, _vuRegsMSUBz, _vuRegsMSUBw,
_vuRegsMAXx, _vuRegsMAXy, _vuRegsMAXz, _vuRegsMAXw, _vuRegsMINIx, _vuRegsMINIy, _vuRegsMINIz, _vuRegsMINIw,
_vuRegsMULx, _vuRegsMULy, _vuRegsMULz, _vuRegsMULw, _vuRegsMULq, _vuRegsMAXi, _vuRegsMULi, _vuRegsMINIi,
_vuRegsADDq, _vuRegsMADDq, _vuRegsADDi, _vuRegsMADDi, _vuRegsSUBq, _vuRegsMSUBq, _vuRegsSUBi, _vuRegsMSUBi,
_vuRegsADD, _vuRegsMADD, _vuRegsMUL, _vuRegsMAX, _vuRegsSUB, _vuRegsMSUB, _vuRegsOPMSUB, _vuRegsMINI,
_vuRegsIADD, _vuRegsISUB, _vuRegsIADDI, _vuRegs_C2UNK, _vuRegsIAND, _vuRegsIOR, _vuRegs_C2UNK, _vuRegs_C2UNK,
_vuRegsNOP, _vuRegsNOP, _vuRegs_C2UNK, _vuRegs_C2UNK, _vuRegsCOP2_SPECIAL2,_vuRegsCOP2_SPECIAL2,_vuRegsCOP2_SPECIAL2,_vuRegsCOP2_SPECIAL2,
};
void (*_vuRegsCOP2SPECIAL2t[128])(VURegs * VU, _VURegsNum *VUregsn) = {
_vuRegsADDAx ,_vuRegsADDAy ,_vuRegsADDAz ,_vuRegsADDAw ,_vuRegsSUBAx ,_vuRegsSUBAy ,_vuRegsSUBAz ,_vuRegsSUBAw,
_vuRegsMADDAx ,_vuRegsMADDAy ,_vuRegsMADDAz ,_vuRegsMADDAw ,_vuRegsMSUBAx ,_vuRegsMSUBAy ,_vuRegsMSUBAz ,_vuRegsMSUBAw,
_vuRegsITOF0 ,_vuRegsITOF4 ,_vuRegsITOF12 ,_vuRegsITOF15 ,_vuRegsFTOI0 ,_vuRegsFTOI4 ,_vuRegsFTOI12 ,_vuRegsFTOI15,
_vuRegsMULAx ,_vuRegsMULAy ,_vuRegsMULAz ,_vuRegsMULAw ,_vuRegsMULAq ,_vuRegsABS ,_vuRegsMULAi ,_vuRegsCLIP,
_vuRegsADDAq ,_vuRegsMADDAq ,_vuRegsADDAi ,_vuRegsMADDAi ,_vuRegsSUBAq ,_vuRegsMSUBAq ,_vuRegsSUBAi ,_vuRegsMSUBAi,
_vuRegsADDA ,_vuRegsMADDA ,_vuRegsMULA ,_vuRegs_C2UNK ,_vuRegsSUBA ,_vuRegsMSUBA ,_vuRegsOPMULA ,_vuRegsNOP,
_vuRegsMOVE ,_vuRegsMR32 ,_vuRegs_C2UNK ,_vuRegs_C2UNK ,_vuRegsLQI ,_vuRegsSQI ,_vuRegsLQD ,_vuRegsSQD,
_vuRegsDIV ,_vuRegsSQRT ,_vuRegsRSQRT ,_vuRegsWAITQ ,_vuRegsMTIR ,_vuRegsMFIR ,_vuRegsILWR ,_vuRegsISWR,
_vuRegsRNEXT ,_vuRegsRGET ,_vuRegsRINIT ,_vuRegsRXOR ,_vuRegs_C2UNK ,_vuRegs_C2UNK ,_vuRegs_C2UNK ,_vuRegs_C2UNK,
_vuRegs_C2UNK ,_vuRegs_C2UNK ,_vuRegs_C2UNK ,_vuRegs_C2UNK ,_vuRegs_C2UNK ,_vuRegs_C2UNK ,_vuRegs_C2UNK ,_vuRegs_C2UNK,
_vuRegs_C2UNK ,_vuRegs_C2UNK ,_vuRegs_C2UNK ,_vuRegs_C2UNK ,_vuRegs_C2UNK ,_vuRegs_C2UNK ,_vuRegs_C2UNK ,_vuRegs_C2UNK,
_vuRegs_C2UNK ,_vuRegs_C2UNK ,_vuRegs_C2UNK ,_vuRegs_C2UNK ,_vuRegs_C2UNK ,_vuRegs_C2UNK ,_vuRegs_C2UNK ,_vuRegs_C2UNK,
_vuRegs_C2UNK ,_vuRegs_C2UNK ,_vuRegs_C2UNK ,_vuRegs_C2UNK ,_vuRegs_C2UNK ,_vuRegs_C2UNK ,_vuRegs_C2UNK ,_vuRegs_C2UNK,
_vuRegs_C2UNK ,_vuRegs_C2UNK ,_vuRegs_C2UNK ,_vuRegs_C2UNK ,_vuRegs_C2UNK ,_vuRegs_C2UNK ,_vuRegs_C2UNK ,_vuRegs_C2UNK,
_vuRegs_C2UNK ,_vuRegs_C2UNK ,_vuRegs_C2UNK ,_vuRegs_C2UNK ,_vuRegs_C2UNK ,_vuRegs_C2UNK ,_vuRegs_C2UNK ,_vuRegs_C2UNK,
_vuRegs_C2UNK ,_vuRegs_C2UNK ,_vuRegs_C2UNK ,_vuRegs_C2UNK ,_vuRegs_C2UNK ,_vuRegs_C2UNK ,_vuRegs_C2UNK ,_vuRegs_C2UNK,
};
#define cParams VURegs* VU, _VURegsNum* VUregsn
void _vuRegsCOP22(cParams) { _vuRegsCOP2t[_Rs_](VU, VUregsn); }
void _vuRegsCOP2_SPECIAL (cParams) { _vuRegsCOP2SPECIAL1t[_Funct_](VU, VUregsn); }
void _vuRegsCOP2_SPECIAL2(cParams) { _vuRegsCOP2SPECIAL2t[(cpuRegs.code&3)|((cpuRegs.code>>4)&0x7c)](VU, VUregsn); }
// Recompilation // Recompilation
void (*recCOP2t[32])(s32 info) = { void (*recCOP2t[32])() = {
rec_C2UNK, recQMFC2, recCFC2, rec_C2UNK, rec_C2UNK, recQMTC2, recCTC2, rec_C2UNK, rec_C2UNK, recQMFC2, recCFC2, rec_C2UNK, rec_C2UNK, recQMTC2, recCTC2, rec_C2UNK,
recCOP2_BC2, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, recCOP2_BC2, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK,
recCOP2_SPECIAL,recCOP2_SPECIAL,recCOP2_SPECIAL,recCOP2_SPECIAL,recCOP2_SPECIAL,recCOP2_SPECIAL,recCOP2_SPECIAL,recCOP2_SPECIAL, recCOP2_SPEC1, recCOP2_SPEC1, recCOP2_SPEC1, recCOP2_SPEC1, recCOP2_SPEC1, recCOP2_SPEC1, recCOP2_SPEC1, recCOP2_SPEC1,
recCOP2_SPECIAL,recCOP2_SPECIAL,recCOP2_SPECIAL,recCOP2_SPECIAL,recCOP2_SPECIAL,recCOP2_SPECIAL,recCOP2_SPECIAL,recCOP2_SPECIAL, recCOP2_SPEC1, recCOP2_SPEC1, recCOP2_SPEC1, recCOP2_SPEC1, recCOP2_SPEC1, recCOP2_SPEC1, recCOP2_SPEC1, recCOP2_SPEC1,
}; };
void (*recCOP2_BC2t[32])(s32 info) = { void (*recCOP2_BC2t[32])() = {
recBC2F, recBC2T, recBC2FL, recBC2TL, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, recBC2F, recBC2T, recBC2FL, recBC2TL, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK,
rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK,
rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK,
rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK,
}; };
void (*recCOP2SPECIAL1t[64])(s32 info) = { void (*recCOP2SPECIAL1t[64])() = {
recVADDx, recVADDy, recVADDz, recVADDw, recVSUBx, recVSUBy, recVSUBz, recVSUBw, recVADDx, recVADDy, recVADDz, recVADDw, recVSUBx, recVSUBy, recVSUBz, recVSUBw,
recVMADDx, recVMADDy, recVMADDz, recVMADDw, recVMSUBx, recVMSUBy, recVMSUBz, recVMSUBw, recVMADDx, recVMADDy, recVMADDz, recVMADDw, recVMSUBx, recVMSUBy, recVMSUBz, recVMSUBw,
recVMAXx, recVMAXy, recVMAXz, recVMAXw, recVMINIx, recVMINIy, recVMINIz, recVMINIw, recVMAXx, recVMAXy, recVMAXz, recVMAXw, recVMINIx, recVMINIy, recVMINIz, recVMINIw,
recVMULx, recVMULy, recVMULz, recVMULw, recVMULq, recVMAXi, recVMULi, recVMINIi, recVMULx, recVMULy, recVMULz, recVMULw, recVMULq, recVMAXi, recVMULi, recVMINIi,
recVADDq, recVMADDq, recVADDi, recVMADDi, recVSUBq, recVMSUBq, recVSUBi, recVMSUBi, recVADDq, recVMADDq, recVADDi, recVMADDi, recVSUBq, recVMSUBq, recVSUBi, recVMSUBi,
recVADD, recVMADD, recVMUL, recVMAX, recVSUB, recVMSUB, recVOPMSUB, recVMINI, recVADD, recVMADD, recVMUL, recVMAX, recVSUB, recVMSUB, recVOPMSUB, recVMINI,
recVIADD, recVISUB, recVIADDI, rec_C2UNK, recVIAND, recVIOR, rec_C2UNK, rec_C2UNK, recVIADD, recVISUB, recVIADDI, rec_C2UNK, recVIAND, recVIOR, rec_C2UNK, rec_C2UNK,
recVCALLMS, recVCALLMSR, rec_C2UNK, rec_C2UNK, recCOP2_SPECIAL2,recCOP2_SPECIAL2,recCOP2_SPECIAL2,recCOP2_SPECIAL2, recVCALLMS, recVCALLMSR,rec_C2UNK, rec_C2UNK, recCOP2_SPEC2, recCOP2_SPEC2, recCOP2_SPEC2, recCOP2_SPEC2,
}; };
void (*recCOP2SPECIAL2t[128])(s32 info) = { void (*recCOP2SPECIAL2t[128])() = {
recVADDAx ,recVADDAy ,recVADDAz ,recVADDAw ,recVSUBAx ,recVSUBAy ,recVSUBAz ,recVSUBAw, recVADDAx, recVADDAy, recVADDAz, recVADDAw, recVSUBAx, recVSUBAy, recVSUBAz, recVSUBAw,
recVMADDAx ,recVMADDAy ,recVMADDAz ,recVMADDAw ,recVMSUBAx ,recVMSUBAy ,recVMSUBAz ,recVMSUBAw, recVMADDAx,recVMADDAy, recVMADDAz, recVMADDAw, recVMSUBAx, recVMSUBAy, recVMSUBAz, recVMSUBAw,
recVITOF0 ,recVITOF4 ,recVITOF12 ,recVITOF15 ,recVFTOI0 ,recVFTOI4 ,recVFTOI12 ,recVFTOI15, recVITOF0, recVITOF4, recVITOF12, recVITOF15, recVFTOI0, recVFTOI4, recVFTOI12, recVFTOI15,
recVMULAx ,recVMULAy ,recVMULAz ,recVMULAw ,recVMULAq ,recVABS ,recVMULAi ,recVCLIP, recVMULAx, recVMULAy, recVMULAz, recVMULAw, recVMULAq, recVABS, recVMULAi, recVCLIP,
recVADDAq ,recVMADDAq ,recVADDAi ,recVMADDAi ,recVSUBAq ,recVMSUBAq ,recVSUBAi ,recVMSUBAi, recVADDAq, recVMADDAq, recVADDAi, recVMADDAi, recVSUBAq, recVMSUBAq, recVSUBAi, recVMSUBAi,
recVADDA ,recVMADDA ,recVMULA ,rec_C2UNK ,recVSUBA ,recVMSUBA ,recVOPMULA ,recVNOP, recVADDA, recVMADDA, recVMULA, rec_C2UNK, recVSUBA, recVMSUBA, recVOPMULA, recVNOP,
recVMOVE ,recVMR32 ,rec_C2UNK ,rec_C2UNK ,recVLQI ,recVSQI ,recVLQD ,recVSQD, recVMOVE, recVMR32, rec_C2UNK, rec_C2UNK, recVLQI, recVSQI, recVLQD, recVSQD,
recVDIV ,recVSQRT ,recVRSQRT ,recVWAITQ ,recVMTIR ,recVMFIR ,recVILWR ,recVISWR, recVDIV, recVSQRT, recVRSQRT, recVWAITQ, recVMTIR, recVMFIR, recVILWR, recVISWR,
recVRNEXT ,recVRGET ,recVRINIT ,recVRXOR ,rec_C2UNK ,rec_C2UNK ,rec_C2UNK ,rec_C2UNK, recVRNEXT, recVRGET, recVRINIT, recVRXOR, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK,
rec_C2UNK ,rec_C2UNK ,rec_C2UNK ,rec_C2UNK ,rec_C2UNK ,rec_C2UNK ,rec_C2UNK ,rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK,
rec_C2UNK ,rec_C2UNK ,rec_C2UNK ,rec_C2UNK ,rec_C2UNK ,rec_C2UNK ,rec_C2UNK ,rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK,
rec_C2UNK ,rec_C2UNK ,rec_C2UNK ,rec_C2UNK ,rec_C2UNK ,rec_C2UNK ,rec_C2UNK ,rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK,
rec_C2UNK ,rec_C2UNK ,rec_C2UNK ,rec_C2UNK ,rec_C2UNK ,rec_C2UNK ,rec_C2UNK ,rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK,
rec_C2UNK ,rec_C2UNK ,rec_C2UNK ,rec_C2UNK ,rec_C2UNK ,rec_C2UNK ,rec_C2UNK ,rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK,
rec_C2UNK ,rec_C2UNK ,rec_C2UNK ,rec_C2UNK ,rec_C2UNK ,rec_C2UNK ,rec_C2UNK ,rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK,
rec_C2UNK ,rec_C2UNK ,rec_C2UNK ,rec_C2UNK ,rec_C2UNK ,rec_C2UNK ,rec_C2UNK ,rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK,
}; };
namespace R5900 { namespace R5900 {
namespace Dynarec { namespace Dynarec {
namespace OpcodeImpl namespace OpcodeImpl { void recCOP2() { recCOP2t[_Rs_](); }}}}
{ void recCOP2_BC2 () { recCOP2_BC2t[_Rt_](); }
void recCOP2() void recCOP2_SPEC1() { recCOP2SPECIAL1t[_Funct_](); }
{ void recCOP2_SPEC2() { recCOP2SPECIAL2t[(cpuRegs.code&3)|((cpuRegs.code>>4)&0x7c)](); }
VU0.code = cpuRegs.code;
g_pCurInstInfo->vuregs.pipe = 0xff; // to notify eeVURecompileCode that COP2
s32 info = eeVURecompileCode(&VU0, &g_pCurInstInfo->vuregs);
info |= PROCESS_VU_COP2;
info |= PROCESS_VU_UPDATEFLAGS;
recCOP2t[_Rs_]( info );
_freeX86regs();
}
}}}
void recCOP2_BC2(s32 info) { recCOP2_BC2t[_Rt_](info); }
void recCOP2_SPECIAL(s32 info) { recCOP2SPECIAL1t[_Funct_]( info ); }
void recCOP2_SPECIAL2(s32 info) { recCOP2SPECIAL2t[(cpuRegs.code&3)|((cpuRegs.code>>4)&0x7c)](info); }
#endif // CHECK_MACROVU0 #endif // CHECK_MACROVU0