mirror of
https://github.com/libretro/Play-.git
synced 2025-01-25 10:37:56 +00:00
581b212a93
git-svn-id: http://svn.purei.org/purei/trunk@347 b36208d7-6611-0410-8bec-b1987f11c4a2
567 lines
11 KiB
C++
567 lines
11 KiB
C++
#include <assert.h>
|
|
#include "COP_VU.h"
|
|
#include "VUShared.h"
|
|
#include "MIPS.h"
|
|
#include "CodeGen.h"
|
|
#include "offsetof_def.h"
|
|
#include "MemoryUtils.h"
|
|
|
|
using namespace std;
|
|
|
|
CCOP_VU g_COPVU(MIPS_REGSIZE_64);
|
|
|
|
uint8 CCOP_VU::m_nFT = 0;
|
|
uint8 CCOP_VU::m_nFS = 0;
|
|
uint8 CCOP_VU::m_nFD = 0;
|
|
|
|
uint8 CCOP_VU::m_nDest = 0;
|
|
uint8 CCOP_VU::m_nFTF = 0;
|
|
uint8 CCOP_VU::m_nFSF = 0;
|
|
uint8 CCOP_VU::m_nBc = 0;
|
|
|
|
CCOP_VU::CCOP_VU(MIPS_REGSIZE nRegSize) :
|
|
CMIPSCoprocessor(nRegSize)
|
|
{
|
|
SetupReflectionTables();
|
|
}
|
|
|
|
void CCOP_VU::CompileInstruction(uint32 nAddress, CCodeGen* codeGen, CMIPS* pCtx, bool nParent)
|
|
{
|
|
if(nParent)
|
|
{
|
|
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);
|
|
|
|
switch((m_nOpcode >> 26) & 0x3F)
|
|
{
|
|
case 0x12:
|
|
//COP2
|
|
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()
|
|
{
|
|
ComputeMemAccessAddr();
|
|
|
|
for(unsigned int i = 0; i < 4; i++)
|
|
{
|
|
m_codeGen->PushRef(m_pCtx);
|
|
m_codeGen->PushIdx(1);
|
|
m_codeGen->Call(reinterpret_cast<void*>(&CMemoryUtils::GetWordProxy), 2, true);
|
|
|
|
m_codeGen->PullRel(offsetof(CMIPS, m_State.nCOP2[m_nFT].nV[i]));
|
|
|
|
if(i != 3)
|
|
{
|
|
m_codeGen->PushCst(4);
|
|
m_codeGen->Add();
|
|
}
|
|
}
|
|
|
|
m_codeGen->PullTop();
|
|
}
|
|
|
|
//3E
|
|
void CCOP_VU::SQC2()
|
|
{
|
|
ComputeMemAccessAddr();
|
|
|
|
for(unsigned int i = 0; i < 4; i++)
|
|
{
|
|
m_codeGen->PushRef(m_pCtx);
|
|
m_codeGen->PushRel(offsetof(CMIPS, m_State.nCOP2[m_nFT].nV[i]));
|
|
m_codeGen->PushIdx(2);
|
|
m_codeGen->Call(reinterpret_cast<void*>(&CMemoryUtils::SetWordProxy), 3, false);
|
|
|
|
if(i != 3)
|
|
{
|
|
m_codeGen->PushCst(4);
|
|
m_codeGen->Add();
|
|
}
|
|
}
|
|
|
|
m_codeGen->PullTop();
|
|
}
|
|
|
|
//////////////////////////////////////////////////
|
|
//COP2 Instructions
|
|
//////////////////////////////////////////////////
|
|
|
|
//01
|
|
void CCOP_VU::QMFC2()
|
|
{
|
|
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_nFS < 16)
|
|
{
|
|
m_codeGen->PushRel(offsetof(CMIPS, m_State.nCOP2VI[m_nFS]));
|
|
m_codeGen->PushCst(0xFFFF);
|
|
m_codeGen->And();
|
|
}
|
|
else
|
|
{
|
|
switch(m_nFS)
|
|
{
|
|
case 16: //STATUS
|
|
case 17: //MAC flag
|
|
case 18: //Clipping flag
|
|
case 20: //R
|
|
case 26: //TPC
|
|
case 28: //FBRST
|
|
case 29: //VPU-STAT
|
|
m_codeGen->PushRel(offsetof(CMIPS, m_State.nGPR[0].nV[0]));
|
|
break;
|
|
case 21:
|
|
m_codeGen->PushRel(offsetof(CMIPS, m_State.nCOP2I));
|
|
break;
|
|
case 22:
|
|
m_codeGen->PushRel(offsetof(CMIPS, m_State.nCOP2Q));
|
|
break;
|
|
default:
|
|
assert(0);
|
|
break;
|
|
}
|
|
}
|
|
|
|
m_codeGen->SeX();
|
|
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()
|
|
{
|
|
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 < 16)
|
|
{
|
|
throw runtime_error("Not implemented.");
|
|
}
|
|
}
|
|
|
|
//10-1F
|
|
void CCOP_VU::V()
|
|
{
|
|
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);
|
|
}
|
|
|
|
//04
|
|
//05
|
|
//06
|
|
//07
|
|
void CCOP_VU::VSUBbc()
|
|
{
|
|
VUShared::SUBbc(m_codeGen, m_nDest, m_nFD, m_nFS, m_nFT, m_nBc);
|
|
}
|
|
|
|
//08
|
|
//09
|
|
//0A
|
|
//0B
|
|
void CCOP_VU::VMADDbc()
|
|
{
|
|
VUShared::MADDbc(m_codeGen, m_nDest, m_nFD, m_nFS, m_nFT, m_nBc);
|
|
}
|
|
|
|
//0C
|
|
//0D
|
|
//0E
|
|
//0F
|
|
void CCOP_VU::VMSUBbc()
|
|
{
|
|
VUShared::MSUBbc(m_codeGen, m_nDest, m_nFD, m_nFS, m_nFT, m_nBc);
|
|
}
|
|
|
|
//10
|
|
void CCOP_VU::VMAXbc()
|
|
{
|
|
VUShared::MAXbc(m_codeGen, m_nDest, m_nFD, m_nFS, m_nFT, m_nBc);
|
|
}
|
|
|
|
//14
|
|
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);
|
|
}
|
|
|
|
//1C
|
|
void CCOP_VU::VMULq()
|
|
{
|
|
VUShared::MULq(m_codeGen, m_nDest, m_nFD, m_nFS, m_nAddress);
|
|
}
|
|
|
|
//20
|
|
void CCOP_VU::VADDq()
|
|
{
|
|
VUShared::ADDq(m_codeGen, m_nDest, m_nFD, m_nFS, m_nAddress);
|
|
}
|
|
|
|
//28
|
|
void CCOP_VU::VADD()
|
|
{
|
|
VUShared::ADD(m_codeGen, m_nDest, m_nFD, m_nFS, m_nFT);
|
|
}
|
|
|
|
//2A
|
|
void CCOP_VU::VMUL()
|
|
{
|
|
VUShared::MUL(m_codeGen, m_nDest, m_nFD, m_nFS, m_nFT);
|
|
}
|
|
|
|
//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);
|
|
}
|
|
|
|
//2E
|
|
void CCOP_VU::VOPMSUB()
|
|
{
|
|
VUShared::OPMSUB(m_codeGen, m_nFD, m_nFS, m_nFT);
|
|
}
|
|
|
|
//2F
|
|
void CCOP_VU::VMINI()
|
|
{
|
|
VUShared::MINI(m_codeGen, m_nDest, m_nFD, m_nFS, m_nFT);
|
|
}
|
|
|
|
//3C
|
|
void CCOP_VU::VX0()
|
|
{
|
|
m_pOpVx0[(m_nOpcode >> 6) & 0x1F]();
|
|
}
|
|
|
|
//3D
|
|
void CCOP_VU::VX1()
|
|
{
|
|
m_pOpVx1[(m_nOpcode >> 6) & 0x1F]();
|
|
}
|
|
|
|
//3E
|
|
void CCOP_VU::VX2()
|
|
{
|
|
m_pOpVx2[(m_nOpcode >> 6) & 0x1F]();
|
|
}
|
|
|
|
//3F
|
|
void CCOP_VU::VX3()
|
|
{
|
|
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);
|
|
}
|
|
|
|
//
|
|
void CCOP_VU::VSUBAbc()
|
|
{
|
|
VUShared::SUBAbc(m_codeGen, m_nDest, m_nFS, m_nFT, m_nBc);
|
|
}
|
|
|
|
//
|
|
void CCOP_VU::VMADDAbc()
|
|
{
|
|
VUShared::MADDAbc(m_codeGen, m_nDest, m_nFS, m_nFT, m_nBc);
|
|
}
|
|
|
|
//
|
|
void CCOP_VU::VMSUBAbc()
|
|
{
|
|
VUShared::MSUBAbc(m_codeGen, m_nDest, m_nFS, m_nFT, m_nBc);
|
|
}
|
|
|
|
//
|
|
void CCOP_VU::VMULAbc()
|
|
{
|
|
VUShared::MULAbc(m_codeGen, m_nDest, m_nFS, m_nFT, m_nBc);
|
|
}
|
|
|
|
//////////////////////////////////////////////////
|
|
//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);
|
|
}
|
|
|
|
//0A
|
|
void CCOP_VU::VADDA()
|
|
{
|
|
VUShared::ADDA(m_codeGen, m_nDest, m_nFS, m_nFT);
|
|
}
|
|
|
|
//0C
|
|
void CCOP_VU::VMOVE()
|
|
{
|
|
VUShared::MOVE(m_codeGen, m_nDest, m_nFT, m_nFS);
|
|
}
|
|
|
|
//0E
|
|
void CCOP_VU::VDIV()
|
|
{
|
|
VUShared::DIV(m_codeGen, m_nFS, m_nFSF, m_nFT, m_nFTF, m_nAddress, 1);
|
|
}
|
|
|
|
//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);
|
|
}
|
|
|
|
//0C
|
|
void CCOP_VU::VMR32()
|
|
{
|
|
VUShared::MR32(m_codeGen, m_nDest, m_nFT, m_nFS);
|
|
}
|
|
|
|
//0E
|
|
void CCOP_VU::VSQRT()
|
|
{
|
|
VUShared::SQRT(m_codeGen, m_nFT, m_nFTF, m_nAddress, 1);
|
|
}
|
|
|
|
//////////////////////////////////////////////////
|
|
//V2 Instructions
|
|
//////////////////////////////////////////////////
|
|
|
|
//0B
|
|
void CCOP_VU::VOPMULA()
|
|
{
|
|
VUShared::OPMULA(m_codeGen, m_nFS, m_nFT);
|
|
}
|
|
|
|
//0E
|
|
void CCOP_VU::VRSQRT()
|
|
{
|
|
VUShared::RSQRT(m_codeGen, m_nFS, m_nFSF, m_nFT, m_nFTF, m_nAddress, 1);
|
|
}
|
|
|
|
//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);
|
|
}
|
|
|
|
//07
|
|
void CCOP_VU::VCLIP()
|
|
{
|
|
VUShared::CLIP(m_codeGen, m_nFS, m_nFT);
|
|
}
|
|
|
|
//0B
|
|
void CCOP_VU::VNOP()
|
|
{
|
|
//Nothing to do
|
|
}
|
|
|
|
//0E
|
|
void CCOP_VU::VWAITQ()
|
|
{
|
|
VUShared::WAITQ(m_codeGen);
|
|
}
|
|
|
|
//10
|
|
void CCOP_VU::VRXOR()
|
|
{
|
|
VUShared::RXOR(m_codeGen, m_nFS, m_nFSF);
|
|
}
|
|
|
|
//////////////////////////////////////////////////
|
|
//Opcode Tables
|
|
//////////////////////////////////////////////////
|
|
|
|
void (*CCOP_VU::m_pOpCop2[0x20])() =
|
|
{
|
|
//0x00
|
|
Illegal, QMFC2, CFC2, Illegal, Illegal, QMTC2, CTC2, Illegal,
|
|
//0x08
|
|
Illegal, Illegal, Illegal, Illegal, Illegal, Illegal, Illegal, Illegal,
|
|
//0x10
|
|
V, V, V, V, V, V, V, V,
|
|
//0x18
|
|
V, V, V, V, V, V, V, V,
|
|
};
|
|
|
|
void (*CCOP_VU::m_pOpVector[0x40])() =
|
|
{
|
|
//0x00
|
|
VADDbc, VADDbc, VADDbc, VADDbc, VSUBbc, VSUBbc, VSUBbc, VSUBbc,
|
|
//0x08
|
|
VMADDbc, VMADDbc, VMADDbc, VMADDbc, VMSUBbc, VMSUBbc, VMSUBbc, VMSUBbc,
|
|
//0x10
|
|
VMAXbc, Illegal, Illegal, Illegal, VMINIbc, Illegal, Illegal, Illegal,
|
|
//0x18
|
|
VMULbc, VMULbc, VMULbc, VMULbc, VMULq, Illegal, Illegal, Illegal,
|
|
//0x20
|
|
VADDq, Illegal, Illegal, Illegal, Illegal, Illegal, Illegal, Illegal,
|
|
//0x28
|
|
VADD, Illegal, VMUL, VMAX, VSUB, Illegal, VOPMSUB, VMINI,
|
|
//0x30
|
|
Illegal, Illegal, Illegal, Illegal, Illegal, Illegal, Illegal, Illegal,
|
|
//0x38
|
|
Illegal, Illegal, Illegal, Illegal, VX0, VX1, VX2, VX3,
|
|
};
|
|
|
|
void (*CCOP_VU::m_pOpVx0[0x20])() =
|
|
{
|
|
//0x00
|
|
VADDAbc, VSUBAbc, VMADDAbc, VMSUBAbc, VITOF0, VFTOI0, VMULAbc, Illegal,
|
|
//0x08
|
|
Illegal, Illegal, VADDA, Illegal, VMOVE, Illegal, VDIV, Illegal,
|
|
//0x10
|
|
VRNEXT, Illegal, Illegal, Illegal, Illegal, Illegal, Illegal, Illegal,
|
|
//0x18
|
|
Illegal, Illegal, Illegal, Illegal, Illegal, Illegal, Illegal, Illegal,
|
|
};
|
|
|
|
void (*CCOP_VU::m_pOpVx1[0x20])() =
|
|
{
|
|
//0x00
|
|
VADDAbc, VSUBAbc, VMADDAbc, VMSUBAbc, VITOF4, VFTOI4, VMULAbc, Illegal,
|
|
//0x08
|
|
Illegal, Illegal, Illegal, Illegal, VMR32, Illegal, VSQRT, Illegal,
|
|
//0x10
|
|
Illegal, Illegal, Illegal, Illegal, Illegal, Illegal, Illegal, Illegal,
|
|
//0x18
|
|
Illegal, Illegal, Illegal, Illegal, Illegal, Illegal, Illegal, Illegal,
|
|
};
|
|
|
|
void (*CCOP_VU::m_pOpVx2[0x20])() =
|
|
{
|
|
//0x00
|
|
VADDAbc, VSUBAbc, VMADDAbc, VMSUBAbc, Illegal, Illegal, VMULAbc, Illegal,
|
|
//0x08
|
|
Illegal, Illegal, Illegal, VOPMULA, Illegal, Illegal, VRSQRT, Illegal,
|
|
//0x10
|
|
VRINIT, Illegal, Illegal, Illegal, Illegal, Illegal, Illegal, Illegal,
|
|
//0x18
|
|
Illegal, Illegal, Illegal, Illegal, Illegal, Illegal, Illegal, Illegal,
|
|
};
|
|
|
|
void (*CCOP_VU::m_pOpVx3[0x20])() =
|
|
{
|
|
//0x00
|
|
VADDAbc, VSUBAbc, VMADDAbc, VMSUBAbc, VITOF15, Illegal, VMULAbc, VCLIP,
|
|
//0x08
|
|
Illegal, Illegal, Illegal, VNOP, Illegal, Illegal, VWAITQ, Illegal,
|
|
//0x10
|
|
VRXOR, Illegal, Illegal, Illegal, Illegal, Illegal, Illegal, Illegal,
|
|
//0x18
|
|
Illegal, Illegal, Illegal, Illegal, Illegal, Illegal, Illegal, Illegal,
|
|
};
|