mirror of
https://github.com/libretro/Play-.git
synced 2025-02-26 06:25:30 +00:00
940 lines
20 KiB
C++
940 lines
20 KiB
C++
#include <assert.h>
|
|
#include "COP_VU.h"
|
|
#include "VUShared.h"
|
|
#include "../Log.h"
|
|
#include "../MIPS.h"
|
|
#include "../MemoryUtils.h"
|
|
#include "offsetof_def.h"
|
|
#include "Vpu.h"
|
|
|
|
#undef MAX
|
|
|
|
enum CTRL_REG
|
|
{
|
|
CTRL_REG_STATUS = 16,
|
|
CTRL_REG_MAC = 17,
|
|
CTRL_REG_CLIP = 18,
|
|
CTRL_REG_R = 20,
|
|
CTRL_REG_I = 21,
|
|
CTRL_REG_Q = 22,
|
|
CTRL_REG_TPC = 26,
|
|
CTRL_REG_CMSAR0 = 27,
|
|
CTRL_REG_FBRST = 28,
|
|
CTRL_REG_VPU_STAT = 29,
|
|
CTRL_REG_CMSAR1 = 31,
|
|
};
|
|
|
|
CCOP_VU::CCOP_VU(MIPS_REGSIZE nRegSize)
|
|
: CMIPSCoprocessor(nRegSize)
|
|
{
|
|
SetupReflectionTables();
|
|
}
|
|
|
|
void CCOP_VU::CompileInstruction(uint32 nAddress, CMipsJitter* codeGen, CMIPS* pCtx)
|
|
{
|
|
SetupQuickVariables(nAddress, codeGen, pCtx);
|
|
|
|
m_nDest = (uint8)((m_nOpcode >> 21) & 0x0F);
|
|
|
|
m_nFSF = ((m_nDest >> 0) & 0x03);
|
|
m_nFTF = ((m_nDest >> 2) & 0x03);
|
|
|
|
m_nFT = (uint8)((m_nOpcode >> 16) & 0x1F);
|
|
m_nFS = (uint8)((m_nOpcode >> 11) & 0x1F);
|
|
m_nFD = (uint8)((m_nOpcode >> 6) & 0x1F);
|
|
|
|
m_nBc = (uint8)((m_nOpcode >> 0) & 0x03);
|
|
|
|
m_nIT = m_nFT;
|
|
m_nIS = m_nFS;
|
|
m_nID = m_nFD;
|
|
m_nImm5 = m_nID;
|
|
m_nImm15 = (uint16)((m_nOpcode >> 6) & 0x7FFF);
|
|
|
|
switch((m_nOpcode >> 26) & 0x3F)
|
|
{
|
|
case 0x12:
|
|
//COP2
|
|
((this)->*(m_pOpCop2[(m_nOpcode >> 21) & 0x1F]))();
|
|
break;
|
|
case 0x36:
|
|
//LQC2
|
|
LQC2();
|
|
break;
|
|
case 0x3E:
|
|
//SQC2
|
|
SQC2();
|
|
break;
|
|
default:
|
|
Illegal();
|
|
break;
|
|
}
|
|
}
|
|
|
|
//////////////////////////////////////////////////
|
|
//General Instructions
|
|
//////////////////////////////////////////////////
|
|
|
|
//36
|
|
void CCOP_VU::LQC2()
|
|
{
|
|
if(m_nFT == 0) return;
|
|
|
|
ComputeMemAccessAddr();
|
|
|
|
m_codeGen->PushCtx();
|
|
m_codeGen->PushIdx(1);
|
|
m_codeGen->Call(reinterpret_cast<void*>(&MemoryUtils_GetQuadProxy), 2, Jitter::CJitter::RETURN_VALUE_128);
|
|
m_codeGen->MD_PullRel(offsetof(CMIPS, m_State.nCOP2[m_nFT]));
|
|
|
|
m_codeGen->PullTop();
|
|
}
|
|
|
|
//3E
|
|
void CCOP_VU::SQC2()
|
|
{
|
|
ComputeMemAccessAddr();
|
|
|
|
m_codeGen->PushCtx();
|
|
m_codeGen->MD_PushRel(offsetof(CMIPS, m_State.nCOP2[m_nFT]));
|
|
m_codeGen->PushIdx(2);
|
|
m_codeGen->Call(reinterpret_cast<void*>(&MemoryUtils_SetQuadProxy), 3, Jitter::CJitter::RETURN_VALUE_NONE);
|
|
|
|
m_codeGen->PullTop();
|
|
}
|
|
|
|
//////////////////////////////////////////////////
|
|
//COP2 Instructions
|
|
//////////////////////////////////////////////////
|
|
|
|
//01
|
|
void CCOP_VU::QMFC2()
|
|
{
|
|
if(m_nFT == 0) return;
|
|
|
|
for(unsigned int i = 0; i < 4; i++)
|
|
{
|
|
m_codeGen->PushRel(offsetof(CMIPS, m_State.nCOP2[m_nFS].nV[i]));
|
|
m_codeGen->PullRel(offsetof(CMIPS, m_State.nGPR[m_nFT].nV[i]));
|
|
}
|
|
}
|
|
|
|
//02
|
|
void CCOP_VU::CFC2()
|
|
{
|
|
if(m_nFT == 0) return;
|
|
|
|
if(m_nFS < 16)
|
|
{
|
|
m_codeGen->PushRel(offsetof(CMIPS, m_State.nCOP2VI[m_nFS]));
|
|
m_codeGen->PushCst(0xFFFF);
|
|
m_codeGen->And();
|
|
}
|
|
else
|
|
{
|
|
switch(m_nFS)
|
|
{
|
|
case CTRL_REG_CLIP:
|
|
VUShared::CheckFlagPipeline(VUShared::g_pipeInfoClip, m_codeGen, 4);
|
|
m_codeGen->PushRel(offsetof(CMIPS, m_State.nCOP2CF));
|
|
break;
|
|
case CTRL_REG_STATUS:
|
|
VUShared::GetStatus(m_codeGen, offsetof(CMIPS, m_State.nCOP2T), 4);
|
|
m_codeGen->PushRel(offsetof(CMIPS, m_State.nCOP2T));
|
|
break;
|
|
case CTRL_REG_R:
|
|
m_codeGen->PushRel(offsetof(CMIPS, m_State.nCOP2R));
|
|
break;
|
|
case CTRL_REG_MAC:
|
|
VUShared::CheckFlagPipeline(VUShared::g_pipeInfoMac, m_codeGen, 4);
|
|
m_codeGen->PushRel(offsetof(CMIPS, m_State.nCOP2MF));
|
|
break;
|
|
case CTRL_REG_TPC:
|
|
m_codeGen->PushRel(offsetof(CMIPS, m_State.callMsAddr));
|
|
m_codeGen->Srl(3);
|
|
break;
|
|
case CTRL_REG_FBRST:
|
|
case CTRL_REG_VPU_STAT:
|
|
m_codeGen->PushRel(offsetof(CMIPS, m_State.nGPR[0].nV[0]));
|
|
break;
|
|
case CTRL_REG_I:
|
|
m_codeGen->PushRel(offsetof(CMIPS, m_State.nCOP2I));
|
|
break;
|
|
case CTRL_REG_Q:
|
|
m_codeGen->PushRel(offsetof(CMIPS, m_State.nCOP2Q));
|
|
break;
|
|
default:
|
|
assert(false);
|
|
m_codeGen->PushRel(offsetof(CMIPS, m_State.nGPR[0].nV[0]));
|
|
break;
|
|
}
|
|
}
|
|
|
|
m_codeGen->PushTop();
|
|
m_codeGen->SignExt();
|
|
m_codeGen->PullRel(offsetof(CMIPS, m_State.nGPR[m_nFT].nV[1]));
|
|
m_codeGen->PullRel(offsetof(CMIPS, m_State.nGPR[m_nFT].nV[0]));
|
|
}
|
|
|
|
//05
|
|
void CCOP_VU::QMTC2()
|
|
{
|
|
if(m_nFS == 0) return;
|
|
|
|
for(unsigned int i = 0; i < 4; i++)
|
|
{
|
|
m_codeGen->PushRel(offsetof(CMIPS, m_State.nGPR[m_nFT].nV[i]));
|
|
m_codeGen->PullRel(offsetof(CMIPS, m_State.nCOP2[m_nFS].nV[i]));
|
|
}
|
|
}
|
|
|
|
//06
|
|
void CCOP_VU::CTC2()
|
|
{
|
|
if(m_nFS == 0)
|
|
{
|
|
//Moving stuff in VI0 register? (probably synchronizing with VU0 micro subroutine execution)
|
|
}
|
|
else if((m_nFS > 0) && (m_nFS < 16))
|
|
{
|
|
m_codeGen->PushRel(offsetof(CMIPS, m_State.nGPR[m_nFT].nV[0]));
|
|
m_codeGen->PushCst(0xFFFF);
|
|
m_codeGen->And();
|
|
m_codeGen->PullRel(offsetof(CMIPS, m_State.nCOP2VI[m_nFS]));
|
|
}
|
|
else
|
|
{
|
|
m_codeGen->PushRel(offsetof(CMIPS, m_State.nGPR[m_nFT].nV[0]));
|
|
|
|
switch(m_nFS)
|
|
{
|
|
case CTRL_REG_STATUS:
|
|
m_codeGen->PullTop();
|
|
VUShared::SetStatus(m_codeGen, offsetof(CMIPS, m_State.nGPR[m_nFT].nV[0]));
|
|
break;
|
|
case CTRL_REG_MAC:
|
|
//Read-only register
|
|
m_codeGen->PullTop();
|
|
break;
|
|
case CTRL_REG_CLIP:
|
|
m_codeGen->PushCst(0xFFFFFF);
|
|
m_codeGen->And();
|
|
m_codeGen->PushTop();
|
|
m_codeGen->PullRel(offsetof(CMIPS, m_State.nCOP2CF));
|
|
VUShared::ResetFlagPipeline(VUShared::g_pipeInfoClip, m_codeGen);
|
|
break;
|
|
case CTRL_REG_R:
|
|
m_codeGen->PushCst(0x7FFFFF);
|
|
m_codeGen->And();
|
|
m_codeGen->PullRel(offsetof(CMIPS, m_State.nCOP2R));
|
|
break;
|
|
case CTRL_REG_I:
|
|
m_codeGen->PullRel(offsetof(CMIPS, m_State.nCOP2I));
|
|
break;
|
|
case CTRL_REG_Q:
|
|
m_codeGen->PullRel(offsetof(CMIPS, m_State.nCOP2Q));
|
|
break;
|
|
case CTRL_REG_CMSAR0:
|
|
m_codeGen->PushCst(0xFFFF);
|
|
m_codeGen->And();
|
|
m_codeGen->PullRel(offsetof(CMIPS, m_State.cmsar0));
|
|
break;
|
|
case CTRL_REG_FBRST:
|
|
//Don't care
|
|
m_codeGen->PullTop();
|
|
break;
|
|
case CTRL_REG_CMSAR1:
|
|
{
|
|
m_codeGen->PushCst(0xFFFF);
|
|
m_codeGen->And();
|
|
uint32 valueCursor = m_codeGen->GetTopCursor();
|
|
|
|
//Push context
|
|
m_codeGen->PushCtx();
|
|
//Push value
|
|
m_codeGen->PushCursor(valueCursor);
|
|
//Compute Address
|
|
m_codeGen->PushCst(CVpu::VU_CMSAR1);
|
|
m_codeGen->Call(reinterpret_cast<void*>(&MemoryUtils_SetWordProxy), 3, false);
|
|
//Clear stack
|
|
assert(m_codeGen->GetTopCursor() == valueCursor);
|
|
m_codeGen->PullTop();
|
|
}
|
|
break;
|
|
default:
|
|
assert(false);
|
|
m_codeGen->PullTop();
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
//08
|
|
void CCOP_VU::BC2()
|
|
{
|
|
//Not implemented
|
|
//We assume that this is used to check if VU0 is still running
|
|
//after VCALLMS* is used (used in .hack games)
|
|
uint32 op = (m_nOpcode >> 16) & 0x03;
|
|
assert(op == 0x01);
|
|
}
|
|
|
|
//10-1F
|
|
void CCOP_VU::V()
|
|
{
|
|
((this)->*(m_pOpVector[(m_nOpcode & 0x3F)]))();
|
|
}
|
|
|
|
//////////////////////////////////////////////////
|
|
//Vector Instructions
|
|
//////////////////////////////////////////////////
|
|
|
|
//00
|
|
//01
|
|
//02
|
|
//03
|
|
void CCOP_VU::VADDbc()
|
|
{
|
|
VUShared::ADDbc(m_codeGen, m_nDest, m_nFD, m_nFS, m_nFT, m_nBc, 0);
|
|
}
|
|
|
|
//04
|
|
//05
|
|
//06
|
|
//07
|
|
void CCOP_VU::VSUBbc()
|
|
{
|
|
VUShared::SUBbc(m_codeGen, m_nDest, m_nFD, m_nFS, m_nFT, m_nBc, 0);
|
|
}
|
|
|
|
//08
|
|
//09
|
|
//0A
|
|
//0B
|
|
void CCOP_VU::VMADDbc()
|
|
{
|
|
VUShared::MADDbc(m_codeGen, m_nDest, m_nFD, m_nFS, m_nFT, m_nBc, 0);
|
|
}
|
|
|
|
//0C
|
|
//0D
|
|
//0E
|
|
//0F
|
|
void CCOP_VU::VMSUBbc()
|
|
{
|
|
VUShared::MSUBbc(m_codeGen, m_nDest, m_nFD, m_nFS, m_nFT, m_nBc, 0);
|
|
}
|
|
|
|
//10
|
|
//11
|
|
//12
|
|
//13
|
|
void CCOP_VU::VMAXbc()
|
|
{
|
|
VUShared::MAXbc(m_codeGen, m_nDest, m_nFD, m_nFS, m_nFT, m_nBc);
|
|
}
|
|
|
|
//14
|
|
//15
|
|
//16
|
|
//17
|
|
void CCOP_VU::VMINIbc()
|
|
{
|
|
VUShared::MINIbc(m_codeGen, m_nDest, m_nFD, m_nFS, m_nFT, m_nBc);
|
|
}
|
|
|
|
//18
|
|
//19
|
|
//1A
|
|
//1B
|
|
void CCOP_VU::VMULbc()
|
|
{
|
|
VUShared::MULbc(m_codeGen, m_nDest, m_nFD, m_nFS, m_nFT, m_nBc, 0);
|
|
}
|
|
|
|
//1C
|
|
void CCOP_VU::VMULq()
|
|
{
|
|
VUShared::MULq(m_codeGen, m_nDest, m_nFD, m_nFS, 0);
|
|
}
|
|
|
|
//1D
|
|
void CCOP_VU::VMAXi()
|
|
{
|
|
VUShared::MAXi(m_codeGen, m_nDest, m_nFD, m_nFS);
|
|
}
|
|
|
|
//1E
|
|
void CCOP_VU::VMULi()
|
|
{
|
|
VUShared::MULi(m_codeGen, m_nDest, m_nFD, m_nFS, 0);
|
|
}
|
|
|
|
//1F
|
|
void CCOP_VU::VMINIi()
|
|
{
|
|
VUShared::MINIi(m_codeGen, m_nDest, m_nFD, m_nFS);
|
|
}
|
|
|
|
//20
|
|
void CCOP_VU::VADDq()
|
|
{
|
|
VUShared::ADDq(m_codeGen, m_nDest, m_nFD, m_nFS, 0);
|
|
}
|
|
|
|
//21
|
|
void CCOP_VU::VMADDq()
|
|
{
|
|
VUShared::MADDq(m_codeGen, m_nDest, m_nFD, m_nFS, 0);
|
|
}
|
|
|
|
//22
|
|
void CCOP_VU::VADDi()
|
|
{
|
|
VUShared::ADDi(m_codeGen, m_nDest, m_nFD, m_nFS, 0);
|
|
}
|
|
|
|
//23
|
|
void CCOP_VU::VMADDi()
|
|
{
|
|
VUShared::MADDi(m_codeGen, m_nDest, m_nFD, m_nFS, 0);
|
|
}
|
|
|
|
//24
|
|
void CCOP_VU::VSUBq()
|
|
{
|
|
VUShared::SUBq(m_codeGen, m_nDest, m_nFD, m_nFS, 0);
|
|
}
|
|
|
|
//25
|
|
void CCOP_VU::VMSUBq()
|
|
{
|
|
VUShared::MSUBq(m_codeGen, m_nDest, m_nFD, m_nFS, 0);
|
|
}
|
|
|
|
//26
|
|
void CCOP_VU::VSUBi()
|
|
{
|
|
VUShared::SUBi(m_codeGen, m_nDest, m_nFD, m_nFS, 0);
|
|
}
|
|
|
|
//27
|
|
void CCOP_VU::VMSUBi()
|
|
{
|
|
VUShared::MSUBi(m_codeGen, m_nDest, m_nFD, m_nFS, 0);
|
|
}
|
|
|
|
//28
|
|
void CCOP_VU::VADD()
|
|
{
|
|
VUShared::ADD(m_codeGen, m_nDest, m_nFD, m_nFS, m_nFT, 0);
|
|
}
|
|
|
|
//29
|
|
void CCOP_VU::VMADD()
|
|
{
|
|
VUShared::MADD(m_codeGen, m_nDest, m_nFD, m_nFS, m_nFT, 0);
|
|
}
|
|
|
|
//2A
|
|
void CCOP_VU::VMUL()
|
|
{
|
|
VUShared::MUL(m_codeGen, m_nDest, m_nFD, m_nFS, m_nFT, 0);
|
|
}
|
|
|
|
//2B
|
|
void CCOP_VU::VMAX()
|
|
{
|
|
VUShared::MAX(m_codeGen, m_nDest, m_nFD, m_nFS, m_nFT);
|
|
}
|
|
|
|
//2C
|
|
void CCOP_VU::VSUB()
|
|
{
|
|
VUShared::SUB(m_codeGen, m_nDest, m_nFD, m_nFS, m_nFT, 0);
|
|
}
|
|
|
|
//2D
|
|
void CCOP_VU::VMSUB()
|
|
{
|
|
VUShared::MSUB(m_codeGen, m_nDest, m_nFD, m_nFS, m_nFT, 0);
|
|
}
|
|
|
|
//2E
|
|
void CCOP_VU::VOPMSUB()
|
|
{
|
|
VUShared::OPMSUB(m_codeGen, m_nFD, m_nFS, m_nFT, 0);
|
|
}
|
|
|
|
//2F
|
|
void CCOP_VU::VMINI()
|
|
{
|
|
VUShared::MINI(m_codeGen, m_nDest, m_nFD, m_nFS, m_nFT);
|
|
}
|
|
|
|
//30
|
|
void CCOP_VU::VIADD()
|
|
{
|
|
VUShared::IADD(m_codeGen, m_nID, m_nIS, m_nIT);
|
|
}
|
|
|
|
//31
|
|
void CCOP_VU::VISUB()
|
|
{
|
|
VUShared::ISUB(m_codeGen, m_nID, m_nIS, m_nIT);
|
|
}
|
|
|
|
//32
|
|
void CCOP_VU::VIADDI()
|
|
{
|
|
VUShared::IADDI(m_codeGen, m_nIT, m_nIS, m_nImm5);
|
|
}
|
|
|
|
//34
|
|
void CCOP_VU::VIAND()
|
|
{
|
|
VUShared::IAND(m_codeGen, m_nID, m_nIS, m_nIT);
|
|
}
|
|
|
|
//35
|
|
void CCOP_VU::VIOR()
|
|
{
|
|
VUShared::IOR(m_codeGen, m_nID, m_nIS, m_nIT);
|
|
}
|
|
|
|
//38
|
|
void CCOP_VU::VCALLMS()
|
|
{
|
|
m_codeGen->PushCst(1);
|
|
m_codeGen->PullRel(offsetof(CMIPS, m_State.callMsEnabled));
|
|
|
|
m_codeGen->PushCst(static_cast<uint32>(m_nImm15) * 8);
|
|
m_codeGen->PullRel(offsetof(CMIPS, m_State.callMsAddr));
|
|
|
|
m_codeGen->PushCst(MIPS_EXCEPTION_CALLMS);
|
|
m_codeGen->PullRel(offsetof(CMIPS, m_State.nHasException));
|
|
}
|
|
|
|
//39
|
|
void CCOP_VU::VCALLMSR()
|
|
{
|
|
m_codeGen->PushCst(1);
|
|
m_codeGen->PullRel(offsetof(CMIPS, m_State.callMsEnabled));
|
|
|
|
m_codeGen->PushRel(offsetof(CMIPS, m_State.cmsar0));
|
|
m_codeGen->Shl(3);
|
|
m_codeGen->PullRel(offsetof(CMIPS, m_State.callMsAddr));
|
|
|
|
m_codeGen->PushCst(MIPS_EXCEPTION_CALLMS);
|
|
m_codeGen->PullRel(offsetof(CMIPS, m_State.nHasException));
|
|
}
|
|
|
|
//3C
|
|
void CCOP_VU::VX0()
|
|
{
|
|
((this)->*(m_pOpVx0[(m_nOpcode >> 6) & 0x1F]))();
|
|
}
|
|
|
|
//3D
|
|
void CCOP_VU::VX1()
|
|
{
|
|
((this)->*(m_pOpVx1[(m_nOpcode >> 6) & 0x1F]))();
|
|
}
|
|
|
|
//3E
|
|
void CCOP_VU::VX2()
|
|
{
|
|
((this)->*(m_pOpVx2[(m_nOpcode >> 6) & 0x1F]))();
|
|
}
|
|
|
|
//3F
|
|
void CCOP_VU::VX3()
|
|
{
|
|
((this)->*(m_pOpVx3[(m_nOpcode >> 6) & 0x1F]))();
|
|
}
|
|
|
|
//////////////////////////////////////////////////
|
|
//Vx Common Instructions
|
|
//////////////////////////////////////////////////
|
|
|
|
//
|
|
void CCOP_VU::VADDAbc()
|
|
{
|
|
VUShared::ADDAbc(m_codeGen, m_nDest, m_nFS, m_nFT, m_nBc, 0);
|
|
}
|
|
|
|
//
|
|
void CCOP_VU::VSUBAbc()
|
|
{
|
|
VUShared::SUBAbc(m_codeGen, m_nDest, m_nFS, m_nFT, m_nBc, 0);
|
|
}
|
|
|
|
//
|
|
void CCOP_VU::VMADDAbc()
|
|
{
|
|
VUShared::MADDAbc(m_codeGen, m_nDest, m_nFS, m_nFT, m_nBc, 0);
|
|
}
|
|
|
|
//
|
|
void CCOP_VU::VMSUBAbc()
|
|
{
|
|
VUShared::MSUBAbc(m_codeGen, m_nDest, m_nFS, m_nFT, m_nBc, 0);
|
|
}
|
|
|
|
//
|
|
void CCOP_VU::VMULAbc()
|
|
{
|
|
VUShared::MULAbc(m_codeGen, m_nDest, m_nFS, m_nFT, m_nBc, 0);
|
|
}
|
|
|
|
//////////////////////////////////////////////////
|
|
//V0 Instructions
|
|
//////////////////////////////////////////////////
|
|
|
|
//04
|
|
void CCOP_VU::VITOF0()
|
|
{
|
|
VUShared::ITOF0(m_codeGen, m_nDest, m_nFT, m_nFS);
|
|
}
|
|
|
|
//05
|
|
void CCOP_VU::VFTOI0()
|
|
{
|
|
VUShared::FTOI0(m_codeGen, m_nDest, m_nFT, m_nFS);
|
|
}
|
|
|
|
//07
|
|
void CCOP_VU::VMULAq()
|
|
{
|
|
VUShared::MULAq(m_codeGen, m_nDest, m_nFS, 0);
|
|
}
|
|
|
|
//0A
|
|
void CCOP_VU::VADDA()
|
|
{
|
|
VUShared::ADDA(m_codeGen, m_nDest, m_nFS, m_nFT, 0);
|
|
}
|
|
|
|
//0B
|
|
void CCOP_VU::VSUBA()
|
|
{
|
|
VUShared::SUBA(m_codeGen, m_nDest, m_nFS, m_nFT, 0);
|
|
}
|
|
|
|
//0C
|
|
void CCOP_VU::VMOVE()
|
|
{
|
|
VUShared::MOVE(m_codeGen, m_nDest, m_nFT, m_nFS);
|
|
}
|
|
|
|
//0D
|
|
void CCOP_VU::VLQI()
|
|
{
|
|
VUShared::LQI(m_codeGen, m_nDest, m_nIT, m_nIS, m_vuMemAddressMask);
|
|
}
|
|
|
|
//0E
|
|
void CCOP_VU::VDIV()
|
|
{
|
|
VUShared::DIV(m_codeGen, m_nFS, m_nFSF, m_nFT, m_nFTF, 0);
|
|
VUShared::FlushPipeline(VUShared::g_pipeInfoQ, m_codeGen);
|
|
}
|
|
|
|
//0F
|
|
void CCOP_VU::VMTIR()
|
|
{
|
|
VUShared::MTIR(m_codeGen, m_nIT, m_nIS, m_nFSF);
|
|
}
|
|
|
|
//10
|
|
void CCOP_VU::VRNEXT()
|
|
{
|
|
VUShared::RNEXT(m_codeGen, m_nDest, m_nFT);
|
|
}
|
|
|
|
//////////////////////////////////////////////////
|
|
//V1 Instructions
|
|
//////////////////////////////////////////////////
|
|
|
|
//04
|
|
void CCOP_VU::VITOF4()
|
|
{
|
|
VUShared::ITOF4(m_codeGen, m_nDest, m_nFT, m_nFS);
|
|
}
|
|
|
|
//05
|
|
void CCOP_VU::VFTOI4()
|
|
{
|
|
VUShared::FTOI4(m_codeGen, m_nDest, m_nFT, m_nFS);
|
|
}
|
|
|
|
//07
|
|
void CCOP_VU::VABS()
|
|
{
|
|
VUShared::ABS(m_codeGen, m_nDest, m_nFT, m_nFS);
|
|
}
|
|
|
|
//08
|
|
void CCOP_VU::VMADDAq()
|
|
{
|
|
VUShared::MADDAq(m_codeGen, m_nDest, m_nFS, 0);
|
|
}
|
|
|
|
//09
|
|
void CCOP_VU::VMSUBAq()
|
|
{
|
|
VUShared::MSUBAq(m_codeGen, m_nDest, m_nFS, 0);
|
|
}
|
|
|
|
//0A
|
|
void CCOP_VU::VMADDA()
|
|
{
|
|
VUShared::MADDA(m_codeGen, m_nDest, m_nFS, m_nFT, 0);
|
|
}
|
|
|
|
//0B
|
|
void CCOP_VU::VMSUBA()
|
|
{
|
|
VUShared::MSUBA(m_codeGen, m_nDest, m_nFS, m_nFT, 0);
|
|
}
|
|
|
|
//0C
|
|
void CCOP_VU::VMR32()
|
|
{
|
|
VUShared::MR32(m_codeGen, m_nDest, m_nFT, m_nFS);
|
|
}
|
|
|
|
//0D
|
|
void CCOP_VU::VSQI()
|
|
{
|
|
VUShared::SQI(m_codeGen, m_nDest, m_nIS, m_nIT, m_vuMemAddressMask);
|
|
}
|
|
|
|
//0E
|
|
void CCOP_VU::VSQRT()
|
|
{
|
|
VUShared::SQRT(m_codeGen, m_nFT, m_nFTF, 0);
|
|
VUShared::FlushPipeline(VUShared::g_pipeInfoQ, m_codeGen);
|
|
}
|
|
|
|
//0F
|
|
void CCOP_VU::VMFIR()
|
|
{
|
|
VUShared::MFIR(m_codeGen, m_nDest, m_nIT, m_nIS);
|
|
}
|
|
|
|
//10
|
|
void CCOP_VU::VRGET()
|
|
{
|
|
VUShared::RGET(m_codeGen, m_nDest, m_nFT);
|
|
}
|
|
|
|
//////////////////////////////////////////////////
|
|
//V2 Instructions
|
|
//////////////////////////////////////////////////
|
|
|
|
//04
|
|
void CCOP_VU::VITOF12()
|
|
{
|
|
VUShared::ITOF12(m_codeGen, m_nDest, m_nFT, m_nFS);
|
|
}
|
|
|
|
//05
|
|
void CCOP_VU::VFTOI12()
|
|
{
|
|
VUShared::FTOI12(m_codeGen, m_nDest, m_nFT, m_nFS);
|
|
}
|
|
|
|
//07
|
|
void CCOP_VU::VMULAi()
|
|
{
|
|
VUShared::MULAi(m_codeGen, m_nDest, m_nFS, 0);
|
|
}
|
|
|
|
//0A
|
|
void CCOP_VU::VMULA()
|
|
{
|
|
VUShared::MULA(m_codeGen, m_nDest, m_nFS, m_nFT, 0);
|
|
}
|
|
|
|
//0B
|
|
void CCOP_VU::VOPMULA()
|
|
{
|
|
VUShared::OPMULA(m_codeGen, m_nFS, m_nFT);
|
|
}
|
|
|
|
//0D
|
|
void CCOP_VU::VLQD()
|
|
{
|
|
VUShared::LQD(m_codeGen, m_nDest, m_nIT, m_nIS, m_vuMemAddressMask);
|
|
}
|
|
|
|
//0E
|
|
void CCOP_VU::VRSQRT()
|
|
{
|
|
VUShared::RSQRT(m_codeGen, m_nFS, m_nFSF, m_nFT, m_nFTF, 0);
|
|
VUShared::FlushPipeline(VUShared::g_pipeInfoQ, m_codeGen);
|
|
}
|
|
|
|
//0F
|
|
void CCOP_VU::VILWR()
|
|
{
|
|
VUShared::ILWR(m_codeGen, m_nDest, m_nIT, m_nIS, m_vuMemAddressMask);
|
|
}
|
|
|
|
//10
|
|
void CCOP_VU::VRINIT()
|
|
{
|
|
VUShared::RINIT(m_codeGen, m_nFS, m_nFSF);
|
|
}
|
|
|
|
//////////////////////////////////////////////////
|
|
//V3 Instructions
|
|
//////////////////////////////////////////////////
|
|
|
|
//04
|
|
void CCOP_VU::VITOF15()
|
|
{
|
|
VUShared::ITOF15(m_codeGen, m_nDest, m_nFT, m_nFS);
|
|
}
|
|
|
|
//05
|
|
void CCOP_VU::VFTOI15()
|
|
{
|
|
VUShared::FTOI15(m_codeGen, m_nDest, m_nFT, m_nFS);
|
|
}
|
|
|
|
//07
|
|
void CCOP_VU::VCLIP()
|
|
{
|
|
VUShared::CLIP(m_codeGen, m_nFS, m_nFT, 0);
|
|
}
|
|
|
|
//08
|
|
void CCOP_VU::VMADDAi()
|
|
{
|
|
VUShared::MADDAi(m_codeGen, m_nDest, m_nFS, 0);
|
|
}
|
|
|
|
//09
|
|
void CCOP_VU::VMSUBAi()
|
|
{
|
|
VUShared::MSUBAi(m_codeGen, m_nDest, m_nFS, 0);
|
|
}
|
|
|
|
//0B
|
|
void CCOP_VU::VNOP()
|
|
{
|
|
//Nothing to do
|
|
}
|
|
|
|
//0D
|
|
void CCOP_VU::VSQD()
|
|
{
|
|
VUShared::SQD(m_codeGen, m_nDest, m_nIS, m_nIT, m_vuMemAddressMask);
|
|
}
|
|
|
|
//0E
|
|
void CCOP_VU::VWAITQ()
|
|
{
|
|
VUShared::WAITQ(m_codeGen);
|
|
}
|
|
|
|
//0F
|
|
void CCOP_VU::VISWR()
|
|
{
|
|
VUShared::ISWR(m_codeGen, m_nDest, m_nIT, m_nIS, m_vuMemAddressMask);
|
|
}
|
|
|
|
//10
|
|
void CCOP_VU::VRXOR()
|
|
{
|
|
VUShared::RXOR(m_codeGen, m_nFS, m_nFSF);
|
|
}
|
|
|
|
//////////////////////////////////////////////////
|
|
//Opcode Tables
|
|
//////////////////////////////////////////////////
|
|
|
|
// clang-format off
|
|
CCOP_VU::InstructionFuncConstant CCOP_VU::m_pOpCop2[0x20] =
|
|
{
|
|
//0x00
|
|
&CCOP_VU::Illegal, &CCOP_VU::QMFC2, &CCOP_VU::CFC2, &CCOP_VU::Illegal, &CCOP_VU::Illegal, &CCOP_VU::QMTC2, &CCOP_VU::CTC2, &CCOP_VU::Illegal,
|
|
//0x08
|
|
&CCOP_VU::BC2, &CCOP_VU::Illegal, &CCOP_VU::Illegal, &CCOP_VU::Illegal, &CCOP_VU::Illegal, &CCOP_VU::Illegal, &CCOP_VU::Illegal, &CCOP_VU::Illegal,
|
|
//0x10
|
|
&CCOP_VU::V, &CCOP_VU::V, &CCOP_VU::V, &CCOP_VU::V, &CCOP_VU::V, &CCOP_VU::V, &CCOP_VU::V, &CCOP_VU::V,
|
|
//0x18
|
|
&CCOP_VU::V, &CCOP_VU::V, &CCOP_VU::V, &CCOP_VU::V, &CCOP_VU::V, &CCOP_VU::V, &CCOP_VU::V, &CCOP_VU::V,
|
|
};
|
|
|
|
CCOP_VU::InstructionFuncConstant CCOP_VU::m_pOpVector[0x40] =
|
|
{
|
|
//0x00
|
|
&CCOP_VU::VADDbc, &CCOP_VU::VADDbc, &CCOP_VU::VADDbc, &CCOP_VU::VADDbc, &CCOP_VU::VSUBbc, &CCOP_VU::VSUBbc, &CCOP_VU::VSUBbc, &CCOP_VU::VSUBbc,
|
|
//0x08
|
|
&CCOP_VU::VMADDbc, &CCOP_VU::VMADDbc, &CCOP_VU::VMADDbc, &CCOP_VU::VMADDbc, &CCOP_VU::VMSUBbc, &CCOP_VU::VMSUBbc, &CCOP_VU::VMSUBbc, &CCOP_VU::VMSUBbc,
|
|
//0x10
|
|
&CCOP_VU::VMAXbc, &CCOP_VU::VMAXbc, &CCOP_VU::VMAXbc, &CCOP_VU::VMAXbc, &CCOP_VU::VMINIbc, &CCOP_VU::VMINIbc, &CCOP_VU::VMINIbc, &CCOP_VU::VMINIbc,
|
|
//0x18
|
|
&CCOP_VU::VMULbc, &CCOP_VU::VMULbc, &CCOP_VU::VMULbc, &CCOP_VU::VMULbc, &CCOP_VU::VMULq, &CCOP_VU::VMAXi, &CCOP_VU::VMULi, &CCOP_VU::VMINIi,
|
|
//0x20
|
|
&CCOP_VU::VADDq, &CCOP_VU::VMADDq, &CCOP_VU::VADDi, &CCOP_VU::VMADDi, &CCOP_VU::VSUBq, &CCOP_VU::VMSUBq, &CCOP_VU::VSUBi, &CCOP_VU::VMSUBi,
|
|
//0x28
|
|
&CCOP_VU::VADD, &CCOP_VU::VMADD, &CCOP_VU::VMUL, &CCOP_VU::VMAX, &CCOP_VU::VSUB, &CCOP_VU::VMSUB, &CCOP_VU::VOPMSUB, &CCOP_VU::VMINI,
|
|
//0x30
|
|
&CCOP_VU::VIADD, &CCOP_VU::VISUB, &CCOP_VU::VIADDI, &CCOP_VU::Illegal, &CCOP_VU::VIAND, &CCOP_VU::VIOR, &CCOP_VU::Illegal, &CCOP_VU::Illegal,
|
|
//0x38
|
|
&CCOP_VU::VCALLMS, &CCOP_VU::VCALLMSR, &CCOP_VU::Illegal, &CCOP_VU::Illegal, &CCOP_VU::VX0, &CCOP_VU::VX1, &CCOP_VU::VX2, &CCOP_VU::VX3,
|
|
};
|
|
|
|
CCOP_VU::InstructionFuncConstant CCOP_VU::m_pOpVx0[0x20] =
|
|
{
|
|
//0x00
|
|
&CCOP_VU::VADDAbc, &CCOP_VU::VSUBAbc, &CCOP_VU::VMADDAbc, &CCOP_VU::VMSUBAbc, &CCOP_VU::VITOF0, &CCOP_VU::VFTOI0, &CCOP_VU::VMULAbc, &CCOP_VU::VMULAq,
|
|
//0x08
|
|
&CCOP_VU::Illegal, &CCOP_VU::Illegal, &CCOP_VU::VADDA, &CCOP_VU::VSUBA, &CCOP_VU::VMOVE, &CCOP_VU::VLQI, &CCOP_VU::VDIV, &CCOP_VU::VMTIR,
|
|
//0x10
|
|
&CCOP_VU::VRNEXT, &CCOP_VU::Illegal, &CCOP_VU::Illegal, &CCOP_VU::Illegal, &CCOP_VU::Illegal, &CCOP_VU::Illegal, &CCOP_VU::Illegal, &CCOP_VU::Illegal,
|
|
//0x18
|
|
&CCOP_VU::Illegal, &CCOP_VU::Illegal, &CCOP_VU::Illegal, &CCOP_VU::Illegal, &CCOP_VU::Illegal, &CCOP_VU::Illegal, &CCOP_VU::Illegal, &CCOP_VU::Illegal,
|
|
};
|
|
|
|
CCOP_VU::InstructionFuncConstant CCOP_VU::m_pOpVx1[0x20] =
|
|
{
|
|
//0x00
|
|
&CCOP_VU::VADDAbc, &CCOP_VU::VSUBAbc, &CCOP_VU::VMADDAbc, &CCOP_VU::VMSUBAbc, &CCOP_VU::VITOF4, &CCOP_VU::VFTOI4, &CCOP_VU::VMULAbc, &CCOP_VU::VABS,
|
|
//0x08
|
|
&CCOP_VU::VMADDAq, &CCOP_VU::VMSUBAq, &CCOP_VU::VMADDA, &CCOP_VU::VMSUBA, &CCOP_VU::VMR32, &CCOP_VU::VSQI, &CCOP_VU::VSQRT, &CCOP_VU::VMFIR,
|
|
//0x10
|
|
&CCOP_VU::VRGET, &CCOP_VU::Illegal, &CCOP_VU::Illegal, &CCOP_VU::Illegal, &CCOP_VU::Illegal, &CCOP_VU::Illegal, &CCOP_VU::Illegal, &CCOP_VU::Illegal,
|
|
//0x18
|
|
&CCOP_VU::Illegal, &CCOP_VU::Illegal, &CCOP_VU::Illegal, &CCOP_VU::Illegal, &CCOP_VU::Illegal, &CCOP_VU::Illegal, &CCOP_VU::Illegal, &CCOP_VU::Illegal,
|
|
};
|
|
|
|
CCOP_VU::InstructionFuncConstant CCOP_VU::m_pOpVx2[0x20] =
|
|
{
|
|
//0x00
|
|
&CCOP_VU::VADDAbc, &CCOP_VU::VSUBAbc, &CCOP_VU::VMADDAbc, &CCOP_VU::VMSUBAbc, &CCOP_VU::VITOF12, &CCOP_VU::VFTOI12, &CCOP_VU::VMULAbc, &CCOP_VU::VMULAi,
|
|
//0x08
|
|
&CCOP_VU::Illegal, &CCOP_VU::Illegal, &CCOP_VU::VMULA, &CCOP_VU::VOPMULA, &CCOP_VU::Illegal, &CCOP_VU::VLQD, &CCOP_VU::VRSQRT, &CCOP_VU::VILWR,
|
|
//0x10
|
|
&CCOP_VU::VRINIT, &CCOP_VU::Illegal, &CCOP_VU::Illegal, &CCOP_VU::Illegal, &CCOP_VU::Illegal, &CCOP_VU::Illegal, &CCOP_VU::Illegal, &CCOP_VU::Illegal,
|
|
//0x18
|
|
&CCOP_VU::Illegal, &CCOP_VU::Illegal, &CCOP_VU::Illegal, &CCOP_VU::Illegal, &CCOP_VU::Illegal, &CCOP_VU::Illegal, &CCOP_VU::Illegal, &CCOP_VU::Illegal,
|
|
};
|
|
|
|
CCOP_VU::InstructionFuncConstant CCOP_VU::m_pOpVx3[0x20] =
|
|
{
|
|
//0x00
|
|
&CCOP_VU::VADDAbc, &CCOP_VU::VSUBAbc, &CCOP_VU::VMADDAbc, &CCOP_VU::VMSUBAbc, &CCOP_VU::VITOF15, &CCOP_VU::VFTOI15, &CCOP_VU::VMULAbc, &CCOP_VU::VCLIP,
|
|
//0x08
|
|
&CCOP_VU::VMADDAi, &CCOP_VU::VMSUBAi, &CCOP_VU::Illegal, &CCOP_VU::VNOP, &CCOP_VU::Illegal, &CCOP_VU::VSQD, &CCOP_VU::VWAITQ, &CCOP_VU::VISWR,
|
|
//0x10
|
|
&CCOP_VU::VRXOR, &CCOP_VU::Illegal, &CCOP_VU::Illegal, &CCOP_VU::Illegal, &CCOP_VU::Illegal, &CCOP_VU::Illegal, &CCOP_VU::Illegal, &CCOP_VU::Illegal,
|
|
//0x18
|
|
&CCOP_VU::Illegal, &CCOP_VU::Illegal, &CCOP_VU::Illegal, &CCOP_VU::Illegal, &CCOP_VU::Illegal, &CCOP_VU::Illegal, &CCOP_VU::Illegal, &CCOP_VU::Illegal,
|
|
};
|
|
// clang-format on
|