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) {
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) {
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();
//------------------------------------------------------------------
// Macro VU - Helper Macros
//------------------------------------------------------------------
#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
// Macro VU - Helper Macros / Functions
//------------------------------------------------------------------
using namespace R5900::Dynarec;
#define printCOP2 0&&
//#define printCOP2 DevCon::Status
void setupMacroOp(int mode, const char* opName) {
DevCon::Status(opName);
printCOP2(opName);
microVU0.prog.IRinfo.curPC = 0;
microVU0.code = cpuRegs.code;
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
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) {
@ -356,7 +57,7 @@ void endMacroOp(int mode) {
}
#define REC_COP2_mVU0(f, opName, mode) \
void recV##f(s32 info) { \
void recV##f() { \
setupMacroOp(mode, opName); \
if (mode & 4) { \
mVU_##f(&microVU0, 0); \
@ -368,6 +69,19 @@ void endMacroOp(int 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
//------------------------------------------------------------------
@ -465,7 +179,7 @@ REC_COP2_mVU0(MSUBAz, "MSUBAz", 0);
REC_COP2_mVU0(MSUBAw, "MSUBAw", 0);
REC_COP2_mVU0(OPMULA, "OPMULA", 0);
REC_COP2_mVU0(OPMSUB, "OPMSUB", 0);
REC_COP2_VU0 (CLIP);
REC_COP2_mVU0(CLIP, "CLIP", 8);
//------------------------------------------------------------------
// Macro VU - Redirect Lower Instructions
@ -498,8 +212,8 @@ REC_COP2_mVU0(RXOR, "RXOR", 0);
// Macro VU - Misc...
//------------------------------------------------------------------
void recVNOP (s32 info) {}
void recVWAITQ(s32 info) {}
void recVNOP() {}
void recVWAITQ(){}
INTERPRETATE_COP2_FUNC(CALLMS);
INTERPRETATE_COP2_FUNC(CALLMSR);
@ -507,115 +221,156 @@ INTERPRETATE_COP2_FUNC(CALLMSR);
// Macro VU - Branches
//------------------------------------------------------------------
static void _setupBranchTest() {
void _setupBranchTest(u32*(jmpType)(u32), bool isLikely) {
printCOP2("COP2 Branch");
_eeFlushAllUnused();
TEST32ItoM((uptr)&VU0.VI[REG_VPU_STAT].UL, 0x100);
recDoBranchImm(jmpType(0), isLikely);
}
void recBC2F(s32 info) {
_setupBranchTest();
recDoBranchImm(JNZ32(0));
void recBC2F() { _setupBranchTest(JNZ32, false); }
void recBC2T() { _setupBranchTest(JZ32, false); }
void recBC2FL() { _setupBranchTest(JNZ32, true); }
void recBC2TL() { _setupBranchTest(JZ32, true); }
//------------------------------------------------------------------
// Macro VU - COP2 Transfer Instructions
//------------------------------------------------------------------
void COP2_Interlock(bool cond) {
if (cond) {
iFlushCall(FLUSH_NOCONST);
CALLFunc((uptr)_vu0WaitMicro);
}
}
void recBC2T(s32 info) {
_setupBranchTest();
recDoBranchImm(JZ32(0));
void TEST_FBRST_RESET(uptr resetFunct, int vuIndex) {
TEST32ItoR(EAX, (vuIndex) ? 0x200 : 0x002);
j8Ptr[0] = JZ8(0);
CALLFunc(resetFunct);
MOV32MtoR(EAX, (uptr)&cpuRegs.GPR.r[_Rt_].UL[0]);
x86SetJ8(j8Ptr[0]);
}
void recBC2FL(s32 info) {
_setupBranchTest();
recDoBranchImm_Likely(JNZ32(0));
static void recCFC2() {
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) {
_setupBranchTest();
recDoBranchImm_Likely(JZ32(0));
static void recCTC2() {
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
//------------------------------------------------------------------
void _vuRegsCOP2_SPECIAL (VURegs * VU, _VURegsNum *VUregsn);
void _vuRegsCOP2_SPECIAL2(VURegs * VU, _VURegsNum *VUregsn);
// information
void _vuRegsQMFC2(VURegs * VU, _VURegsNum *VUregsn) {
VUregsn->VFread0 = _Fs_;
VUregsn->VFr0xyzw= 0xf;
void recCOP2();
void recCOP2_BC2();
void recCOP2_SPEC1();
void recCOP2_SPEC2();
void rec_C2UNK() {
Console::Error("Cop2 bad opcode: %x", params cpuRegs.code);
}
void _vuRegsCFC2(VURegs * VU, _VURegsNum *VUregsn) {
VUregsn->VIread = 1<<_Fs_;
}
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); }
// This is called by EE Recs to setup sVU info, this isn't needed for mVU Macro (cottonvibes)
void _vuRegsCOP22(VURegs* VU, _VURegsNum* VUregsn) {}
// Recompilation
void (*recCOP2t[32])(s32 info) = {
void (*recCOP2t[32])() = {
rec_C2UNK, recQMFC2, recCFC2, rec_C2UNK, rec_C2UNK, recQMTC2, recCTC2, rec_C2UNK,
recCOP2_BC2, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK,
recCOP2_SPECIAL,recCOP2_SPECIAL,recCOP2_SPECIAL,recCOP2_SPECIAL,recCOP2_SPECIAL,recCOP2_SPECIAL,recCOP2_SPECIAL,recCOP2_SPECIAL,
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_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,
rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK,
rec_C2UNK, rec_C2UNK, rec_C2UNK, rec_C2UNK, 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,
recVMADDx, recVMADDy, recVMADDz, recVMADDw, recVMSUBx, recVMSUBy, recVMSUBz, recVMSUBw,
recVMAXx, recVMAXy, recVMAXz, recVMAXw, recVMINIx, recVMINIy, recVMINIz, recVMINIw,
@ -623,10 +378,10 @@ void (*recCOP2SPECIAL1t[64])(s32 info) = {
recVADDq, recVMADDq, recVADDi, recVMADDi, recVSUBq, recVMSUBq, recVSUBi, recVMSUBi,
recVADD, recVMADD, recVMUL, recVMAX, recVSUB, recVMSUB, recVOPMSUB, recVMINI,
recVIADD, recVISUB, recVIADDI, rec_C2UNK, recVIAND, recVIOR, rec_C2UNK, rec_C2UNK,
recVCALLMS, recVCALLMSR, rec_C2UNK, rec_C2UNK, recCOP2_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,
recVMADDAx,recVMADDAy, recVMADDAz, recVMADDAw, recVMSUBAx, recVMSUBAy, recVMSUBAz, recVMSUBAw,
recVITOF0, recVITOF4, recVITOF12, recVITOF15, recVFTOI0, recVFTOI4, recVFTOI12, recVFTOI15,
@ -647,26 +402,9 @@ void (*recCOP2SPECIAL2t[128])(s32 info) = {
namespace R5900 {
namespace Dynarec {
namespace OpcodeImpl
{
void recCOP2()
{
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); }
namespace OpcodeImpl { void recCOP2() { recCOP2t[_Rs_](); }}}}
void recCOP2_BC2 () { recCOP2_BC2t[_Rt_](); }
void recCOP2_SPEC1() { recCOP2SPECIAL1t[_Funct_](); }
void recCOP2_SPEC2() { recCOP2SPECIAL2t[(cpuRegs.code&3)|((cpuRegs.code>>4)&0x7c)](); }
#endif // CHECK_MACROVU0