mirror of
https://github.com/libretro/Play-.git
synced 2024-11-27 18:50:28 +00:00
1343 lines
30 KiB
C++
1343 lines
30 KiB
C++
#include <stddef.h>
|
|
#include "MA_MIPSIV.h"
|
|
#include "MIPS.h"
|
|
#include "Jitter.h"
|
|
#include "MemoryUtils.h"
|
|
#include "COP_SCU.h"
|
|
#include "offsetof_def.h"
|
|
#include "placeholder_def.h"
|
|
|
|
uint32 g_LWMaskRight[4] =
|
|
{
|
|
0x00FFFFFF,
|
|
0x0000FFFF,
|
|
0x000000FF,
|
|
0x00000000,
|
|
};
|
|
|
|
uint32 g_LWMaskLeft[4] =
|
|
{
|
|
0xFFFFFF00,
|
|
0xFFFF0000,
|
|
0xFF000000,
|
|
0x00000000,
|
|
};
|
|
|
|
uint64 g_LDMaskRight[8] =
|
|
{
|
|
0x00FFFFFFFFFFFFFFULL,
|
|
0x0000FFFFFFFFFFFFULL,
|
|
0x000000FFFFFFFFFFULL,
|
|
0x00000000FFFFFFFFULL,
|
|
0x0000000000FFFFFFULL,
|
|
0x000000000000FFFFULL,
|
|
0x00000000000000FFULL,
|
|
0x0000000000000000ULL,
|
|
};
|
|
|
|
uint64 g_LDMaskLeft[8] =
|
|
{
|
|
0xFFFFFFFFFFFFFF00ULL,
|
|
0xFFFFFFFFFFFF0000ULL,
|
|
0xFFFFFFFFFF000000ULL,
|
|
0xFFFFFFFF00000000ULL,
|
|
0xFFFFFF0000000000ULL,
|
|
0xFFFF000000000000ULL,
|
|
0xFF00000000000000ULL,
|
|
0x0000000000000000ULL,
|
|
};
|
|
|
|
extern "C" uint32 LWL_Proxy(uint32 address, uint32 rt, CMIPS* context)
|
|
{
|
|
uint32 alignedAddress = address & ~0x03;
|
|
uint32 byteOffset = address & 0x03;
|
|
uint32 accessType = 3 - byteOffset;
|
|
uint32 memory = MemoryUtils_GetWordProxy(context, alignedAddress);
|
|
memory <<= accessType * 8;
|
|
rt &= g_LWMaskRight[byteOffset];
|
|
rt |= memory;
|
|
return rt;
|
|
}
|
|
|
|
extern "C" uint32 LWR_Proxy(uint32 address, uint32 rt, CMIPS* context)
|
|
{
|
|
uint32 alignedAddress = address & ~0x03;
|
|
uint32 byteOffset = address & 0x03;
|
|
uint32 accessType = 3 - byteOffset;
|
|
uint32 memory = MemoryUtils_GetWordProxy(context, alignedAddress);
|
|
memory >>= byteOffset * 8;
|
|
rt &= g_LWMaskLeft[accessType];
|
|
rt |= memory;
|
|
return rt;
|
|
}
|
|
|
|
extern "C" uint64 LDL_Proxy(uint32 address, uint64 rt, CMIPS* context)
|
|
{
|
|
uint32 alignedAddress = address & ~0x07;
|
|
uint32 byteOffset = address & 0x07;
|
|
uint32 accessType = 7 - byteOffset;
|
|
uint64 memory = MemoryUtils_GetDoubleProxy(context, alignedAddress);
|
|
memory <<= accessType * 8;
|
|
rt &= g_LDMaskRight[byteOffset];
|
|
rt |= memory;
|
|
return rt;
|
|
}
|
|
|
|
extern "C" uint64 LDR_Proxy(uint32 address, uint64 rt, CMIPS* context)
|
|
{
|
|
uint32 alignedAddress = address & ~0x07;
|
|
uint32 byteOffset = address & 0x07;
|
|
uint32 accessType = 7 - byteOffset;
|
|
uint64 memory = MemoryUtils_GetDoubleProxy(context, alignedAddress);
|
|
memory >>= byteOffset * 8;
|
|
rt &= g_LDMaskLeft[accessType];
|
|
rt |= memory;
|
|
return rt;
|
|
}
|
|
|
|
extern "C" void SWL_Proxy(uint32 address, uint32 rt, CMIPS* context)
|
|
{
|
|
uint32 alignedAddress = address & ~0x03;
|
|
uint32 byteOffset = address & 0x03;
|
|
uint32 accessType = 3 - byteOffset;
|
|
rt >>= accessType * 8;
|
|
uint32 memory = MemoryUtils_GetWordProxy(context, alignedAddress);
|
|
memory &= g_LWMaskLeft[byteOffset];
|
|
memory |= rt;
|
|
MemoryUtils_SetWordProxy(context, memory, alignedAddress);
|
|
}
|
|
|
|
extern "C" void SWR_Proxy(uint32 address, uint32 rt, CMIPS* context)
|
|
{
|
|
uint32 alignedAddress = address & ~0x03;
|
|
uint32 byteOffset = address & 0x03;
|
|
uint32 accessType = 3 - byteOffset;
|
|
rt <<= byteOffset * 8;
|
|
uint32 memory = MemoryUtils_GetWordProxy(context, alignedAddress);
|
|
memory &= g_LWMaskRight[accessType];
|
|
memory |= rt;
|
|
MemoryUtils_SetWordProxy(context, memory, alignedAddress);
|
|
}
|
|
|
|
extern "C" void SDL_Proxy(uint32 address, uint64 rt, CMIPS* context)
|
|
{
|
|
uint32 alignedAddress = address & ~0x07;
|
|
uint32 byteOffset = address & 0x07;
|
|
uint32 accessType = 7 - byteOffset;
|
|
rt >>= accessType * 8;
|
|
uint64 memory = MemoryUtils_GetDoubleProxy(context, alignedAddress);
|
|
memory &= g_LDMaskLeft[byteOffset];
|
|
memory |= rt;
|
|
MemoryUtils_SetDoubleProxy(context, memory, alignedAddress);
|
|
}
|
|
|
|
extern "C" void SDR_Proxy(uint32 address, uint64 rt, CMIPS* context)
|
|
{
|
|
uint32 alignedAddress = address & ~0x07;
|
|
uint32 byteOffset = address & 0x07;
|
|
uint32 accessType = 7 - byteOffset;
|
|
rt <<= byteOffset * 8;
|
|
uint64 memory = MemoryUtils_GetDoubleProxy(context, alignedAddress);
|
|
memory &= g_LDMaskRight[accessType];
|
|
memory |= rt;
|
|
MemoryUtils_SetDoubleProxy(context, memory, alignedAddress);
|
|
}
|
|
|
|
CMA_MIPSIV::CMA_MIPSIV(MIPS_REGSIZE nRegSize)
|
|
: CMIPSArchitecture(nRegSize)
|
|
{
|
|
SetupInstructionTables();
|
|
SetupReflectionTables();
|
|
}
|
|
|
|
CMA_MIPSIV::~CMA_MIPSIV()
|
|
{
|
|
}
|
|
|
|
void CMA_MIPSIV::SetupInstructionTables()
|
|
{
|
|
for(unsigned int i = 0; i < MAX_GENERAL_OPS; i++)
|
|
{
|
|
m_pOpGeneral[i] = std::bind(m_cOpGeneral[i], this);
|
|
}
|
|
|
|
for(unsigned int i = 0; i < MAX_SPECIAL_OPS; i++)
|
|
{
|
|
m_pOpSpecial[i] = std::bind(m_cOpSpecial[i], this);
|
|
}
|
|
|
|
for(unsigned int i = 0; i < MAX_SPECIAL2_OPS; i++)
|
|
{
|
|
m_pOpSpecial2[i] = std::bind(&CMA_MIPSIV::Illegal, this);
|
|
}
|
|
|
|
for(unsigned int i = 0; i < MAX_REGIMM_OPS; i++)
|
|
{
|
|
m_pOpRegImm[i] = std::bind(m_cOpRegImm[i], this);
|
|
}
|
|
}
|
|
|
|
void CMA_MIPSIV::CompileInstruction(uint32 nAddress, CMipsJitter* codeGen, CMIPS* pCtx)
|
|
{
|
|
SetupQuickVariables(nAddress, codeGen, pCtx);
|
|
|
|
m_nRS = (uint8)((m_nOpcode >> 21) & 0x1F);
|
|
m_nRT = (uint8)((m_nOpcode >> 16) & 0x1F);
|
|
m_nRD = (uint8)((m_nOpcode >> 11) & 0x1F);
|
|
m_nSA = (uint8)((m_nOpcode >> 6) & 0x1F);
|
|
m_nImmediate = (uint16)(m_nOpcode & 0xFFFF);
|
|
|
|
if(m_nOpcode)
|
|
{
|
|
m_pOpGeneral[(m_nOpcode >> 26)]();
|
|
}
|
|
}
|
|
|
|
void CMA_MIPSIV::SPECIAL()
|
|
{
|
|
m_pOpSpecial[m_nImmediate & 0x3F]();
|
|
}
|
|
|
|
void CMA_MIPSIV::SPECIAL2()
|
|
{
|
|
m_pOpSpecial2[m_nImmediate & 0x3F]();
|
|
}
|
|
|
|
void CMA_MIPSIV::REGIMM()
|
|
{
|
|
m_pOpRegImm[m_nRT]();
|
|
}
|
|
|
|
//////////////////////////////////////////////////
|
|
//General Opcodes
|
|
//////////////////////////////////////////////////
|
|
|
|
//02
|
|
void CMA_MIPSIV::J()
|
|
{
|
|
m_codeGen->PushCst((m_nAddress & 0xF0000000) | ((m_nOpcode & 0x03FFFFFF) << 2));
|
|
m_codeGen->PullRel(offsetof(CMIPS, m_State.nDelayedJumpAddr));
|
|
}
|
|
|
|
//03
|
|
void CMA_MIPSIV::JAL()
|
|
{
|
|
//64-bit addresses?
|
|
|
|
//Save the address in RA
|
|
m_codeGen->PushCst(m_nAddress + 8);
|
|
m_codeGen->PullRel(offsetof(CMIPS, m_State.nGPR[31].nV[0]));
|
|
|
|
//Update jump address
|
|
m_codeGen->PushCst((m_nAddress & 0xF0000000) | ((m_nOpcode & 0x03FFFFFF) << 2));
|
|
m_codeGen->PullRel(offsetof(CMIPS, m_State.nDelayedJumpAddr));
|
|
}
|
|
|
|
//04
|
|
void CMA_MIPSIV::BEQ()
|
|
{
|
|
Template_BranchEq(true, false);
|
|
}
|
|
|
|
//05
|
|
void CMA_MIPSIV::BNE()
|
|
{
|
|
Template_BranchEq(false, false);
|
|
}
|
|
|
|
//06
|
|
void CMA_MIPSIV::BLEZ()
|
|
{
|
|
//Less/Equal & Not Likely
|
|
Template_BranchLez(true, false);
|
|
}
|
|
|
|
//07
|
|
void CMA_MIPSIV::BGTZ()
|
|
{
|
|
//Not Less/Equal & Not Likely
|
|
Template_BranchLez(false, false);
|
|
}
|
|
|
|
//08
|
|
void CMA_MIPSIV::ADDI()
|
|
{
|
|
m_codeGen->PushRel(offsetof(CMIPS, m_State.nGPR[m_nRS].nV[0]));
|
|
m_codeGen->PushCst(static_cast<int16>(m_nImmediate));
|
|
m_codeGen->Add();
|
|
if(m_regSize == MIPS_REGSIZE_64)
|
|
{
|
|
m_codeGen->PushTop();
|
|
m_codeGen->SignExt();
|
|
m_codeGen->PullRel(offsetof(CMIPS, m_State.nGPR[m_nRT].nV[1]));
|
|
}
|
|
m_codeGen->PullRel(offsetof(CMIPS, m_State.nGPR[m_nRT].nV[0]));
|
|
}
|
|
|
|
//09
|
|
void CMA_MIPSIV::ADDIU()
|
|
{
|
|
if(m_nRT == 0 && m_nRS == 0)
|
|
{
|
|
//Hack: PS2 IOP uses ADDIU R0, R0, $x for dynamic linking
|
|
m_codeGen->PushCst(m_nAddress);
|
|
m_codeGen->PullRel(offsetof(CMIPS, m_State.nCOP0[CCOP_SCU::EPC]));
|
|
|
|
m_codeGen->PushCst(MIPS_EXCEPTION_SYSCALL);
|
|
m_codeGen->PullRel(offsetof(CMIPS, m_State.nHasException));
|
|
}
|
|
else
|
|
{
|
|
if(m_nRT == 0) return;
|
|
|
|
m_codeGen->PushRel(offsetof(CMIPS, m_State.nGPR[m_nRS].nV[0]));
|
|
m_codeGen->PushCst(static_cast<int16>(m_nImmediate));
|
|
m_codeGen->Add();
|
|
if(m_regSize == MIPS_REGSIZE_64)
|
|
{
|
|
m_codeGen->PushTop();
|
|
m_codeGen->SignExt();
|
|
m_codeGen->PullRel(offsetof(CMIPS, m_State.nGPR[m_nRT].nV[1]));
|
|
}
|
|
m_codeGen->PullRel(offsetof(CMIPS, m_State.nGPR[m_nRT].nV[0]));
|
|
}
|
|
}
|
|
|
|
//0A
|
|
void CMA_MIPSIV::SLTI()
|
|
{
|
|
Template_SetLessThanImm(true);
|
|
}
|
|
|
|
//0B
|
|
void CMA_MIPSIV::SLTIU()
|
|
{
|
|
Template_SetLessThanImm(false);
|
|
}
|
|
|
|
//0C
|
|
void CMA_MIPSIV::ANDI()
|
|
{
|
|
if(m_nRT == 0) return;
|
|
|
|
m_codeGen->PushRel(offsetof(CMIPS, m_State.nGPR[m_nRS].nV[0]));
|
|
m_codeGen->PushCst(m_nImmediate);
|
|
|
|
m_codeGen->And();
|
|
m_codeGen->PullRel(offsetof(CMIPS, m_State.nGPR[m_nRT].nV[0]));
|
|
|
|
if(m_regSize == MIPS_REGSIZE_64)
|
|
{
|
|
m_codeGen->PushCst(0);
|
|
m_codeGen->PullRel(offsetof(CMIPS, m_State.nGPR[m_nRT].nV[1]));
|
|
}
|
|
}
|
|
|
|
//0D
|
|
void CMA_MIPSIV::ORI()
|
|
{
|
|
if(m_nRT == 0) return;
|
|
|
|
//Lower 32-bits
|
|
m_codeGen->PushRel(offsetof(CMIPS, m_State.nGPR[m_nRS].nV[0]));
|
|
m_codeGen->PushCst(m_nImmediate);
|
|
m_codeGen->Or();
|
|
m_codeGen->PullRel(offsetof(CMIPS, m_State.nGPR[m_nRT].nV[0]));
|
|
|
|
//Higher 32-bits (only if registers are different)
|
|
if((m_regSize == MIPS_REGSIZE_64) && (m_nRS != m_nRT))
|
|
{
|
|
m_codeGen->PushRel(offsetof(CMIPS, m_State.nGPR[m_nRS].nV[1]));
|
|
m_codeGen->PullRel(offsetof(CMIPS, m_State.nGPR[m_nRT].nV[1]));
|
|
}
|
|
}
|
|
|
|
//0E
|
|
void CMA_MIPSIV::XORI()
|
|
{
|
|
if(m_nRT == 0) return;
|
|
|
|
//Lower 32-bits
|
|
m_codeGen->PushRel(offsetof(CMIPS, m_State.nGPR[m_nRS].nV[0]));
|
|
m_codeGen->PushCst(m_nImmediate);
|
|
m_codeGen->Xor();
|
|
m_codeGen->PullRel(offsetof(CMIPS, m_State.nGPR[m_nRT].nV[0]));
|
|
|
|
//Higher 32-bits
|
|
m_codeGen->PushRel(offsetof(CMIPS, m_State.nGPR[m_nRS].nV[1]));
|
|
m_codeGen->PullRel(offsetof(CMIPS, m_State.nGPR[m_nRT].nV[1]));
|
|
}
|
|
|
|
//0F
|
|
void CMA_MIPSIV::LUI()
|
|
{
|
|
if(m_nRT == 0) return;
|
|
|
|
m_codeGen->PushCst(m_nImmediate << 16);
|
|
if(m_regSize == MIPS_REGSIZE_64)
|
|
{
|
|
m_codeGen->PushCst((m_nImmediate & 0x8000) ? 0xFFFFFFFF : 0x00000000);
|
|
m_codeGen->PullRel(offsetof(CMIPS, m_State.nGPR[m_nRT].nV[1]));
|
|
}
|
|
m_codeGen->PullRel(offsetof(CMIPS, m_State.nGPR[m_nRT].nV[0]));
|
|
}
|
|
|
|
//10
|
|
void CMA_MIPSIV::COP0()
|
|
{
|
|
if(m_pCtx->m_pCOP[0] != NULL)
|
|
{
|
|
m_pCtx->m_pCOP[0]->CompileInstruction(m_nAddress, m_codeGen, m_pCtx);
|
|
}
|
|
else
|
|
{
|
|
Illegal();
|
|
}
|
|
}
|
|
|
|
//11
|
|
void CMA_MIPSIV::COP1()
|
|
{
|
|
if(m_pCtx->m_pCOP[1] != NULL)
|
|
{
|
|
m_pCtx->m_pCOP[1]->CompileInstruction(m_nAddress, m_codeGen, m_pCtx);
|
|
}
|
|
else
|
|
{
|
|
Illegal();
|
|
}
|
|
}
|
|
|
|
//12
|
|
void CMA_MIPSIV::COP2()
|
|
{
|
|
if(m_pCtx->m_pCOP[2] != NULL)
|
|
{
|
|
m_pCtx->m_pCOP[2]->CompileInstruction(m_nAddress, m_codeGen, m_pCtx);
|
|
}
|
|
else
|
|
{
|
|
Illegal();
|
|
}
|
|
}
|
|
|
|
//14
|
|
void CMA_MIPSIV::BEQL()
|
|
{
|
|
Template_BranchEq(true, true);
|
|
}
|
|
|
|
//15
|
|
void CMA_MIPSIV::BNEL()
|
|
{
|
|
Template_BranchEq(false, true);
|
|
}
|
|
|
|
//16
|
|
void CMA_MIPSIV::BLEZL()
|
|
{
|
|
//Less/Equal & Likely
|
|
Template_BranchLez(true, true);
|
|
}
|
|
|
|
//17
|
|
void CMA_MIPSIV::BGTZL()
|
|
{
|
|
//Not Less/Equal & Likely
|
|
Template_BranchLez(false, true);
|
|
}
|
|
|
|
//18
|
|
void CMA_MIPSIV::DADDI()
|
|
{
|
|
//TODO: Check for overflow
|
|
DADDIU();
|
|
}
|
|
|
|
//19
|
|
void CMA_MIPSIV::DADDIU()
|
|
{
|
|
if(m_nRT == 0) return;
|
|
|
|
assert(m_regSize == MIPS_REGSIZE_64);
|
|
|
|
m_codeGen->PushRel64(offsetof(CMIPS, m_State.nGPR[m_nRS].nV[0]));
|
|
m_codeGen->PushCst64(static_cast<int16>(m_nImmediate));
|
|
m_codeGen->Add64();
|
|
m_codeGen->PullRel64(offsetof(CMIPS, m_State.nGPR[m_nRT].nV[0]));
|
|
}
|
|
|
|
//1A
|
|
void CMA_MIPSIV::LDL()
|
|
{
|
|
if(m_nRT == 0) return;
|
|
|
|
assert(m_regSize == MIPS_REGSIZE_64);
|
|
|
|
ComputeMemAccessAddr();
|
|
m_codeGen->PushRel64(offsetof(CMIPS, m_State.nGPR[m_nRT]));
|
|
m_codeGen->PushCtx();
|
|
m_codeGen->Call(reinterpret_cast<void*>(&LDL_Proxy), 3, Jitter::CJitter::RETURN_VALUE_64);
|
|
m_codeGen->PullRel64(offsetof(CMIPS, m_State.nGPR[m_nRT]));
|
|
}
|
|
|
|
//1B
|
|
void CMA_MIPSIV::LDR()
|
|
{
|
|
if(m_nRT == 0) return;
|
|
|
|
assert(m_regSize == MIPS_REGSIZE_64);
|
|
|
|
ComputeMemAccessAddr();
|
|
m_codeGen->PushRel64(offsetof(CMIPS, m_State.nGPR[m_nRT]));
|
|
m_codeGen->PushCtx();
|
|
m_codeGen->Call(reinterpret_cast<void*>(&LDR_Proxy), 3, Jitter::CJitter::RETURN_VALUE_64);
|
|
m_codeGen->PullRel64(offsetof(CMIPS, m_State.nGPR[m_nRT]));
|
|
}
|
|
|
|
//20
|
|
void CMA_MIPSIV::LB()
|
|
{
|
|
if(m_nRT == 0) return;
|
|
|
|
ComputeMemAccessAddr();
|
|
|
|
m_codeGen->PushCtx();
|
|
m_codeGen->PushIdx(1);
|
|
m_codeGen->Call(reinterpret_cast<void*>(&MemoryUtils_GetByteProxy), 2, true);
|
|
|
|
m_codeGen->SignExt8();
|
|
if(m_regSize == MIPS_REGSIZE_64)
|
|
{
|
|
m_codeGen->PushTop();
|
|
m_codeGen->SignExt();
|
|
m_codeGen->PullRel(offsetof(CMIPS, m_State.nGPR[m_nRT].nV[1]));
|
|
}
|
|
m_codeGen->PullRel(offsetof(CMIPS, m_State.nGPR[m_nRT].nV[0]));
|
|
|
|
m_codeGen->PullTop();
|
|
}
|
|
|
|
//21
|
|
void CMA_MIPSIV::LH()
|
|
{
|
|
if(m_nRT == 0) return;
|
|
|
|
ComputeMemAccessAddr();
|
|
|
|
m_codeGen->PushCtx();
|
|
m_codeGen->PushIdx(1);
|
|
m_codeGen->Call(reinterpret_cast<void*>(&MemoryUtils_GetHalfProxy), 2, true);
|
|
|
|
m_codeGen->SignExt16();
|
|
if(m_regSize == MIPS_REGSIZE_64)
|
|
{
|
|
m_codeGen->PushTop();
|
|
m_codeGen->SignExt();
|
|
m_codeGen->PullRel(offsetof(CMIPS, m_State.nGPR[m_nRT].nV[1]));
|
|
}
|
|
m_codeGen->PullRel(offsetof(CMIPS, m_State.nGPR[m_nRT].nV[0]));
|
|
|
|
m_codeGen->PullTop();
|
|
}
|
|
|
|
//22
|
|
void CMA_MIPSIV::LWL()
|
|
{
|
|
if(m_nRT == 0) return;
|
|
|
|
ComputeMemAccessAddr();
|
|
m_codeGen->PushRel(offsetof(CMIPS, m_State.nGPR[m_nRT].nV[0]));
|
|
m_codeGen->PushCtx();
|
|
m_codeGen->Call(reinterpret_cast<void*>(&LWL_Proxy), 3, true);
|
|
|
|
if(m_regSize == MIPS_REGSIZE_64)
|
|
{
|
|
m_codeGen->PushTop();
|
|
m_codeGen->SignExt();
|
|
m_codeGen->PullRel(offsetof(CMIPS, m_State.nGPR[m_nRT].nV[1]));
|
|
}
|
|
m_codeGen->PullRel(offsetof(CMIPS, m_State.nGPR[m_nRT].nV[0]));
|
|
}
|
|
|
|
//23
|
|
void CMA_MIPSIV::LW()
|
|
{
|
|
Template_LoadUnsigned32(reinterpret_cast<void*>(&MemoryUtils_GetWordProxy));
|
|
}
|
|
|
|
//24
|
|
void CMA_MIPSIV::LBU()
|
|
{
|
|
Template_LoadUnsigned32(reinterpret_cast<void*>(&MemoryUtils_GetByteProxy));
|
|
}
|
|
|
|
//25
|
|
void CMA_MIPSIV::LHU()
|
|
{
|
|
Template_LoadUnsigned32(reinterpret_cast<void*>(&MemoryUtils_GetHalfProxy));
|
|
}
|
|
|
|
//26
|
|
void CMA_MIPSIV::LWR()
|
|
{
|
|
if(m_nRT == 0) return;
|
|
|
|
ComputeMemAccessAddr();
|
|
m_codeGen->PushRel(offsetof(CMIPS, m_State.nGPR[m_nRT].nV[0]));
|
|
m_codeGen->PushCtx();
|
|
m_codeGen->Call(reinterpret_cast<void*>(&LWR_Proxy), 3, true);
|
|
|
|
if(m_regSize == MIPS_REGSIZE_64)
|
|
{
|
|
m_codeGen->PushTop();
|
|
m_codeGen->SignExt();
|
|
m_codeGen->PullRel(offsetof(CMIPS, m_State.nGPR[m_nRT].nV[1]));
|
|
}
|
|
m_codeGen->PullRel(offsetof(CMIPS, m_State.nGPR[m_nRT].nV[0]));
|
|
}
|
|
|
|
//27
|
|
void CMA_MIPSIV::LWU()
|
|
{
|
|
if(m_nRT == 0) return;
|
|
|
|
ComputeMemAccessAddr();
|
|
|
|
m_codeGen->PushCtx();
|
|
m_codeGen->PushIdx(1);
|
|
m_codeGen->Call(reinterpret_cast<void*>(&MemoryUtils_GetWordProxy), 2, true);
|
|
m_codeGen->PullRel(offsetof(CMIPS, m_State.nGPR[m_nRT].nV[0]));
|
|
|
|
m_codeGen->PushCst(0);
|
|
m_codeGen->PullRel(offsetof(CMIPS, m_State.nGPR[m_nRT].nV[1]));
|
|
|
|
m_codeGen->PullTop();
|
|
}
|
|
|
|
//28
|
|
void CMA_MIPSIV::SB()
|
|
{
|
|
ComputeMemAccessAddr();
|
|
|
|
m_codeGen->PushCtx();
|
|
m_codeGen->PushRel(offsetof(CMIPS, m_State.nGPR[m_nRT].nV[0]));
|
|
m_codeGen->PushIdx(2);
|
|
m_codeGen->Call(reinterpret_cast<void*>(&MemoryUtils_SetByteProxy), 3, false);
|
|
|
|
m_codeGen->PullTop();
|
|
}
|
|
|
|
//29
|
|
void CMA_MIPSIV::SH()
|
|
{
|
|
ComputeMemAccessAddr();
|
|
|
|
m_codeGen->PushCtx();
|
|
m_codeGen->PushRel(offsetof(CMIPS, m_State.nGPR[m_nRT].nV[0]));
|
|
m_codeGen->PushIdx(2);
|
|
m_codeGen->Call(reinterpret_cast<void*>(&MemoryUtils_SetHalfProxy), 3, false);
|
|
|
|
m_codeGen->PullTop();
|
|
}
|
|
|
|
//2A
|
|
void CMA_MIPSIV::SWL()
|
|
{
|
|
ComputeMemAccessAddr();
|
|
m_codeGen->PushRel(offsetof(CMIPS, m_State.nGPR[m_nRT].nV[0]));
|
|
m_codeGen->PushCtx();
|
|
m_codeGen->Call(reinterpret_cast<void*>(&SWL_Proxy), 3, false);
|
|
}
|
|
|
|
//2B
|
|
void CMA_MIPSIV::SW()
|
|
{
|
|
ComputeMemAccessAddr();
|
|
|
|
m_codeGen->PushCtx();
|
|
m_codeGen->PushRel(offsetof(CMIPS, m_State.nGPR[m_nRT].nV[0]));
|
|
m_codeGen->PushIdx(2);
|
|
m_codeGen->Call(reinterpret_cast<void*>(&MemoryUtils_SetWordProxy), 3, false);
|
|
|
|
m_codeGen->PullTop();
|
|
}
|
|
|
|
//2C
|
|
void CMA_MIPSIV::SDL()
|
|
{
|
|
assert(m_regSize == MIPS_REGSIZE_64);
|
|
|
|
ComputeMemAccessAddr();
|
|
m_codeGen->PushRel64(offsetof(CMIPS, m_State.nGPR[m_nRT]));
|
|
m_codeGen->PushCtx();
|
|
m_codeGen->Call(reinterpret_cast<void*>(&SDL_Proxy), 3, false);
|
|
}
|
|
|
|
//2D
|
|
void CMA_MIPSIV::SDR()
|
|
{
|
|
assert(m_regSize == MIPS_REGSIZE_64);
|
|
|
|
ComputeMemAccessAddr();
|
|
m_codeGen->PushRel64(offsetof(CMIPS, m_State.nGPR[m_nRT]));
|
|
m_codeGen->PushCtx();
|
|
m_codeGen->Call(reinterpret_cast<void*>(&SDR_Proxy), 3, false);
|
|
}
|
|
|
|
//2E
|
|
void CMA_MIPSIV::SWR()
|
|
{
|
|
ComputeMemAccessAddr();
|
|
m_codeGen->PushRel(offsetof(CMIPS, m_State.nGPR[m_nRT].nV[0]));
|
|
m_codeGen->PushCtx();
|
|
m_codeGen->Call(reinterpret_cast<void*>(&SWR_Proxy), 3, false);
|
|
}
|
|
|
|
//2F
|
|
void CMA_MIPSIV::CACHE()
|
|
{
|
|
//No cache in our system. Nothing to do.
|
|
}
|
|
|
|
//31
|
|
void CMA_MIPSIV::LWC1()
|
|
{
|
|
if(m_pCtx->m_pCOP[1] != NULL)
|
|
{
|
|
m_pCtx->m_pCOP[1]->CompileInstruction(m_nAddress, m_codeGen, m_pCtx);
|
|
}
|
|
else
|
|
{
|
|
Illegal();
|
|
}
|
|
}
|
|
|
|
//33
|
|
void CMA_MIPSIV::PREF()
|
|
{
|
|
//Nothing to do
|
|
}
|
|
|
|
//36
|
|
void CMA_MIPSIV::LDC2()
|
|
{
|
|
if(m_pCtx->m_pCOP[2] != NULL)
|
|
{
|
|
m_pCtx->m_pCOP[2]->CompileInstruction(m_nAddress, m_codeGen, m_pCtx);
|
|
}
|
|
else
|
|
{
|
|
Illegal();
|
|
}
|
|
}
|
|
|
|
//37
|
|
void CMA_MIPSIV::LD()
|
|
{
|
|
if(m_nRT == 0) return;
|
|
|
|
assert(m_regSize == MIPS_REGSIZE_64);
|
|
|
|
ComputeMemAccessAddr();
|
|
|
|
m_codeGen->PushCtx();
|
|
m_codeGen->PushIdx(1);
|
|
m_codeGen->Call(reinterpret_cast<void*>(&MemoryUtils_GetDoubleProxy), 2, Jitter::CJitter::RETURN_VALUE_64);
|
|
m_codeGen->PullRel64(offsetof(CMIPS, m_State.nGPR[m_nRT]));
|
|
|
|
m_codeGen->PullTop();
|
|
}
|
|
|
|
//39
|
|
void CMA_MIPSIV::SWC1()
|
|
{
|
|
if(m_pCtx->m_pCOP[1] != NULL)
|
|
{
|
|
m_pCtx->m_pCOP[1]->CompileInstruction(m_nAddress, m_codeGen, m_pCtx);
|
|
}
|
|
else
|
|
{
|
|
Illegal();
|
|
}
|
|
}
|
|
|
|
//3E
|
|
void CMA_MIPSIV::SDC2()
|
|
{
|
|
if(m_pCtx->m_pCOP[2] != NULL)
|
|
{
|
|
m_pCtx->m_pCOP[2]->CompileInstruction(m_nAddress, m_codeGen, m_pCtx);
|
|
}
|
|
else
|
|
{
|
|
Illegal();
|
|
}
|
|
}
|
|
|
|
//3F
|
|
void CMA_MIPSIV::SD()
|
|
{
|
|
assert(m_regSize == MIPS_REGSIZE_64);
|
|
|
|
ComputeMemAccessAddr();
|
|
|
|
m_codeGen->PushCtx();
|
|
m_codeGen->PushRel64(offsetof(CMIPS, m_State.nGPR[m_nRT]));
|
|
m_codeGen->PushIdx(2);
|
|
m_codeGen->Call(reinterpret_cast<void*>(&MemoryUtils_SetDoubleProxy), 3, Jitter::CJitter::RETURN_VALUE_NONE);
|
|
|
|
m_codeGen->PullTop();
|
|
}
|
|
|
|
//////////////////////////////////////////////////
|
|
//Special Opcodes
|
|
//////////////////////////////////////////////////
|
|
|
|
//00
|
|
void CMA_MIPSIV::SLL()
|
|
{
|
|
void (Jitter::CJitter::*shiftFunction)(uint8) = &Jitter::CJitter::Shl;
|
|
Template_ShiftCst32(std::bind(shiftFunction, m_codeGen, std::placeholders::_1));
|
|
}
|
|
|
|
//02
|
|
void CMA_MIPSIV::SRL()
|
|
{
|
|
void (Jitter::CJitter::*shiftFunction)(uint8) = &Jitter::CJitter::Srl;
|
|
Template_ShiftCst32(std::bind(shiftFunction, m_codeGen, std::placeholders::_1));
|
|
}
|
|
|
|
//03
|
|
void CMA_MIPSIV::SRA()
|
|
{
|
|
void (Jitter::CJitter::*shiftFunction)(uint8) = &Jitter::CJitter::Sra;
|
|
Template_ShiftCst32(std::bind(shiftFunction, m_codeGen, std::placeholders::_1));
|
|
}
|
|
|
|
//04
|
|
void CMA_MIPSIV::SLLV()
|
|
{
|
|
void (Jitter::CJitter::*shiftFunction)() = &Jitter::CJitter::Shl;
|
|
Template_ShiftVar32(std::bind(shiftFunction, m_codeGen));
|
|
}
|
|
|
|
//06
|
|
void CMA_MIPSIV::SRLV()
|
|
{
|
|
void (Jitter::CJitter::*shiftFunction)() = &Jitter::CJitter::Srl;
|
|
Template_ShiftVar32(std::bind(shiftFunction, m_codeGen));
|
|
}
|
|
|
|
//07
|
|
void CMA_MIPSIV::SRAV()
|
|
{
|
|
void (Jitter::CJitter::*shiftFunction)() = &Jitter::CJitter::Sra;
|
|
Template_ShiftVar32(std::bind(shiftFunction, m_codeGen));
|
|
}
|
|
|
|
//08
|
|
void CMA_MIPSIV::JR()
|
|
{
|
|
//TODO: 64-bits addresses
|
|
m_codeGen->PushRel(offsetof(CMIPS, m_State.nGPR[m_nRS].nV[0]));
|
|
m_codeGen->PullRel(offsetof(CMIPS, m_State.nDelayedJumpAddr));
|
|
}
|
|
|
|
//09
|
|
void CMA_MIPSIV::JALR()
|
|
{
|
|
//TODO: 64-bits addresses
|
|
|
|
//Set the jump address
|
|
m_codeGen->PushRel(offsetof(CMIPS, m_State.nGPR[m_nRS].nV[0]));
|
|
m_codeGen->PullRel(offsetof(CMIPS, m_State.nDelayedJumpAddr));
|
|
|
|
if(m_nRD != 0)
|
|
{
|
|
//Save address in register
|
|
m_codeGen->PushCst(m_nAddress + 8);
|
|
m_codeGen->PullRel(offsetof(CMIPS, m_State.nGPR[m_nRD].nV[0]));
|
|
}
|
|
}
|
|
|
|
//0A
|
|
void CMA_MIPSIV::MOVZ()
|
|
{
|
|
Template_MovEqual(true);
|
|
}
|
|
|
|
//0B
|
|
void CMA_MIPSIV::MOVN()
|
|
{
|
|
Template_MovEqual(false);
|
|
}
|
|
|
|
//0C
|
|
void CMA_MIPSIV::SYSCALL()
|
|
{
|
|
//Save current EPC
|
|
m_codeGen->PushCst(m_nAddress);
|
|
m_codeGen->PullRel(offsetof(CMIPS, m_State.nCOP0[CCOP_SCU::EPC]));
|
|
m_codeGen->PushCst(MIPS_EXCEPTION_SYSCALL);
|
|
m_codeGen->PullRel(offsetof(CMIPS, m_State.nHasException));
|
|
}
|
|
|
|
//0D
|
|
void CMA_MIPSIV::BREAK()
|
|
{
|
|
//NOP
|
|
}
|
|
|
|
//0F
|
|
void CMA_MIPSIV::SYNC()
|
|
{
|
|
//NOP
|
|
}
|
|
|
|
//10
|
|
void CMA_MIPSIV::MFHI()
|
|
{
|
|
if(m_nRD == 0) return;
|
|
|
|
m_codeGen->PushRel(offsetof(CMIPS, m_State.nHI[0]));
|
|
m_codeGen->PullRel(offsetof(CMIPS, m_State.nGPR[m_nRD].nV[0]));
|
|
|
|
m_codeGen->PushRel(offsetof(CMIPS, m_State.nHI[1]));
|
|
m_codeGen->PullRel(offsetof(CMIPS, m_State.nGPR[m_nRD].nV[1]));
|
|
}
|
|
|
|
//11
|
|
void CMA_MIPSIV::MTHI()
|
|
{
|
|
m_codeGen->PushRel(offsetof(CMIPS, m_State.nGPR[m_nRS].nV[0]));
|
|
m_codeGen->PullRel(offsetof(CMIPS, m_State.nHI[0]));
|
|
|
|
m_codeGen->PushRel(offsetof(CMIPS, m_State.nGPR[m_nRS].nV[1]));
|
|
m_codeGen->PullRel(offsetof(CMIPS, m_State.nHI[1]));
|
|
}
|
|
|
|
//12
|
|
void CMA_MIPSIV::MFLO()
|
|
{
|
|
if(m_nRD == 0) return;
|
|
|
|
m_codeGen->PushRel(offsetof(CMIPS, m_State.nLO[0]));
|
|
m_codeGen->PullRel(offsetof(CMIPS, m_State.nGPR[m_nRD].nV[0]));
|
|
|
|
m_codeGen->PushRel(offsetof(CMIPS, m_State.nLO[1]));
|
|
m_codeGen->PullRel(offsetof(CMIPS, m_State.nGPR[m_nRD].nV[1]));
|
|
}
|
|
|
|
//13
|
|
void CMA_MIPSIV::MTLO()
|
|
{
|
|
m_codeGen->PushRel(offsetof(CMIPS, m_State.nGPR[m_nRS].nV[0]));
|
|
m_codeGen->PullRel(offsetof(CMIPS, m_State.nLO[0]));
|
|
|
|
m_codeGen->PushRel(offsetof(CMIPS, m_State.nGPR[m_nRS].nV[1]));
|
|
m_codeGen->PullRel(offsetof(CMIPS, m_State.nLO[1]));
|
|
}
|
|
|
|
//14
|
|
void CMA_MIPSIV::DSLLV()
|
|
{
|
|
if(m_nRD == 0) return;
|
|
|
|
assert(m_regSize == MIPS_REGSIZE_64);
|
|
|
|
m_codeGen->PushRel64(offsetof(CMIPS, m_State.nGPR[m_nRT].nV[0]));
|
|
m_codeGen->PushRel(offsetof(CMIPS, m_State.nGPR[m_nRS].nV[0]));
|
|
m_codeGen->Shl64();
|
|
m_codeGen->PullRel64(offsetof(CMIPS, m_State.nGPR[m_nRD].nV[0]));
|
|
}
|
|
|
|
//16
|
|
void CMA_MIPSIV::DSRLV()
|
|
{
|
|
if(m_nRD == 0) return;
|
|
|
|
assert(m_regSize == MIPS_REGSIZE_64);
|
|
|
|
m_codeGen->PushRel64(offsetof(CMIPS, m_State.nGPR[m_nRT].nV[0]));
|
|
m_codeGen->PushRel(offsetof(CMIPS, m_State.nGPR[m_nRS].nV[0]));
|
|
m_codeGen->Srl64();
|
|
m_codeGen->PullRel64(offsetof(CMIPS, m_State.nGPR[m_nRD].nV[0]));
|
|
}
|
|
|
|
//17
|
|
void CMA_MIPSIV::DSRAV()
|
|
{
|
|
if(m_nRD == 0) return;
|
|
|
|
assert(m_regSize == MIPS_REGSIZE_64);
|
|
|
|
m_codeGen->PushRel64(offsetof(CMIPS, m_State.nGPR[m_nRT].nV[0]));
|
|
m_codeGen->PushRel(offsetof(CMIPS, m_State.nGPR[m_nRS].nV[0]));
|
|
m_codeGen->Sra64();
|
|
m_codeGen->PullRel64(offsetof(CMIPS, m_State.nGPR[m_nRD].nV[0]));
|
|
}
|
|
|
|
//18
|
|
void CMA_MIPSIV::MULT()
|
|
{
|
|
Template_Mult32(true, 0);
|
|
}
|
|
|
|
//19
|
|
void CMA_MIPSIV::MULTU()
|
|
{
|
|
Template_Mult32(false, 0);
|
|
}
|
|
|
|
//1A
|
|
void CMA_MIPSIV::DIV()
|
|
{
|
|
Template_Div32(true, 0);
|
|
}
|
|
|
|
//1B
|
|
void CMA_MIPSIV::DIVU()
|
|
{
|
|
Template_Div32(false, 0);
|
|
}
|
|
|
|
//20
|
|
void CMA_MIPSIV::ADD()
|
|
{
|
|
Template_Add32(true);
|
|
}
|
|
|
|
//21
|
|
void CMA_MIPSIV::ADDU()
|
|
{
|
|
Template_Add32(false);
|
|
}
|
|
|
|
//22
|
|
void CMA_MIPSIV::SUB()
|
|
{
|
|
Template_Sub32(true);
|
|
}
|
|
|
|
//23
|
|
void CMA_MIPSIV::SUBU()
|
|
{
|
|
Template_Sub32(false);
|
|
}
|
|
|
|
//24
|
|
void CMA_MIPSIV::AND()
|
|
{
|
|
if(m_nRD == 0) return;
|
|
|
|
if(m_regSize == MIPS_REGSIZE_32)
|
|
{
|
|
m_codeGen->PushRel(offsetof(CMIPS, m_State.nGPR[m_nRS].nV[0]));
|
|
m_codeGen->PushRel(offsetof(CMIPS, m_State.nGPR[m_nRT].nV[0]));
|
|
m_codeGen->And();
|
|
m_codeGen->PullRel(offsetof(CMIPS, m_State.nGPR[m_nRD].nV[0]));
|
|
}
|
|
else
|
|
{
|
|
m_codeGen->PushRel64(offsetof(CMIPS, m_State.nGPR[m_nRS].nV[0]));
|
|
m_codeGen->PushRel64(offsetof(CMIPS, m_State.nGPR[m_nRT].nV[0]));
|
|
m_codeGen->And64();
|
|
m_codeGen->PullRel64(offsetof(CMIPS, m_State.nGPR[m_nRD].nV[0]));
|
|
}
|
|
}
|
|
|
|
//25
|
|
void CMA_MIPSIV::OR()
|
|
{
|
|
if(m_nRD == 0) return;
|
|
|
|
//TODO: Use a 64-bits op
|
|
unsigned int regCount = (m_regSize == MIPS_REGSIZE_64) ? 2 : 1;
|
|
for(unsigned int i = 0; i < regCount; i++)
|
|
{
|
|
m_codeGen->PushRel(offsetof(CMIPS, m_State.nGPR[m_nRS].nV[i]));
|
|
m_codeGen->PushRel(offsetof(CMIPS, m_State.nGPR[m_nRT].nV[i]));
|
|
|
|
m_codeGen->Or();
|
|
|
|
m_codeGen->PullRel(offsetof(CMIPS, m_State.nGPR[m_nRD].nV[i]));
|
|
}
|
|
}
|
|
|
|
//26
|
|
void CMA_MIPSIV::XOR()
|
|
{
|
|
if(m_nRD == 0) return;
|
|
|
|
unsigned int regCount = (m_regSize == MIPS_REGSIZE_64) ? 2 : 1;
|
|
for(unsigned int i = 0; i < regCount; i++)
|
|
{
|
|
m_codeGen->PushRel(offsetof(CMIPS, m_State.nGPR[m_nRS].nV[i]));
|
|
m_codeGen->PushRel(offsetof(CMIPS, m_State.nGPR[m_nRT].nV[i]));
|
|
|
|
m_codeGen->Xor();
|
|
|
|
m_codeGen->PullRel(offsetof(CMIPS, m_State.nGPR[m_nRD].nV[i]));
|
|
}
|
|
}
|
|
|
|
//27
|
|
void CMA_MIPSIV::NOR()
|
|
{
|
|
if(m_nRD == 0) return;
|
|
|
|
unsigned int regCount = (m_regSize == MIPS_REGSIZE_64) ? 2 : 1;
|
|
for(unsigned int i = 0; i < regCount; i++)
|
|
{
|
|
m_codeGen->PushRel(offsetof(CMIPS, m_State.nGPR[m_nRS].nV[i]));
|
|
m_codeGen->PushRel(offsetof(CMIPS, m_State.nGPR[m_nRT].nV[i]));
|
|
|
|
m_codeGen->Or();
|
|
m_codeGen->Not();
|
|
|
|
m_codeGen->PullRel(offsetof(CMIPS, m_State.nGPR[m_nRD].nV[i]));
|
|
}
|
|
}
|
|
|
|
//2A
|
|
void CMA_MIPSIV::SLT()
|
|
{
|
|
Template_SetLessThanReg(true);
|
|
}
|
|
|
|
//2B
|
|
void CMA_MIPSIV::SLTU()
|
|
{
|
|
Template_SetLessThanReg(false);
|
|
}
|
|
|
|
//2C
|
|
void CMA_MIPSIV::DADD()
|
|
{
|
|
Template_Add64(true);
|
|
}
|
|
|
|
//2D
|
|
void CMA_MIPSIV::DADDU()
|
|
{
|
|
Template_Add64(false);
|
|
}
|
|
|
|
//2E
|
|
void CMA_MIPSIV::DSUB()
|
|
{
|
|
Template_Sub64(true);
|
|
}
|
|
|
|
//2F
|
|
void CMA_MIPSIV::DSUBU()
|
|
{
|
|
Template_Sub64(false);
|
|
}
|
|
|
|
//34
|
|
void CMA_MIPSIV::TEQ()
|
|
{
|
|
//Not implemented
|
|
assert(false);
|
|
}
|
|
|
|
//38
|
|
void CMA_MIPSIV::DSLL()
|
|
{
|
|
if(m_nRD == 0) return;
|
|
|
|
assert(m_regSize == MIPS_REGSIZE_64);
|
|
|
|
m_codeGen->PushRel64(offsetof(CMIPS, m_State.nGPR[m_nRT].nV[0]));
|
|
m_codeGen->Shl64(m_nSA);
|
|
m_codeGen->PullRel64(offsetof(CMIPS, m_State.nGPR[m_nRD].nV[0]));
|
|
}
|
|
|
|
//3A
|
|
void CMA_MIPSIV::DSRL()
|
|
{
|
|
if(m_nRD == 0) return;
|
|
|
|
assert(m_regSize == MIPS_REGSIZE_64);
|
|
|
|
m_codeGen->PushRel64(offsetof(CMIPS, m_State.nGPR[m_nRT].nV[0]));
|
|
m_codeGen->Srl64(m_nSA);
|
|
m_codeGen->PullRel64(offsetof(CMIPS, m_State.nGPR[m_nRD].nV[0]));
|
|
}
|
|
|
|
//3B
|
|
void CMA_MIPSIV::DSRA()
|
|
{
|
|
if(m_nRD == 0) return;
|
|
|
|
assert(m_regSize == MIPS_REGSIZE_64);
|
|
|
|
m_codeGen->PushRel64(offsetof(CMIPS, m_State.nGPR[m_nRT].nV[0]));
|
|
m_codeGen->Sra64(m_nSA);
|
|
m_codeGen->PullRel64(offsetof(CMIPS, m_State.nGPR[m_nRD].nV[0]));
|
|
}
|
|
|
|
//3C
|
|
void CMA_MIPSIV::DSLL32()
|
|
{
|
|
if(m_nRD == 0) return;
|
|
|
|
assert(m_regSize == MIPS_REGSIZE_64);
|
|
|
|
m_codeGen->PushRel64(offsetof(CMIPS, m_State.nGPR[m_nRT].nV[0]));
|
|
m_codeGen->Shl64(m_nSA + 32);
|
|
m_codeGen->PullRel64(offsetof(CMIPS, m_State.nGPR[m_nRD].nV[0]));
|
|
}
|
|
|
|
//3E
|
|
void CMA_MIPSIV::DSRL32()
|
|
{
|
|
if(m_nRD == 0) return;
|
|
|
|
assert(m_regSize == MIPS_REGSIZE_64);
|
|
|
|
m_codeGen->PushRel64(offsetof(CMIPS, m_State.nGPR[m_nRT].nV[0]));
|
|
m_codeGen->Srl64(m_nSA + 32);
|
|
m_codeGen->PullRel64(offsetof(CMIPS, m_State.nGPR[m_nRD].nV[0]));
|
|
}
|
|
|
|
//3F
|
|
void CMA_MIPSIV::DSRA32()
|
|
{
|
|
if(m_nRD == 0) return;
|
|
|
|
assert(m_regSize == MIPS_REGSIZE_64);
|
|
|
|
m_codeGen->PushRel64(offsetof(CMIPS, m_State.nGPR[m_nRT].nV[0]));
|
|
m_codeGen->Sra64(m_nSA + 32);
|
|
m_codeGen->PullRel64(offsetof(CMIPS, m_State.nGPR[m_nRD].nV[0]));
|
|
}
|
|
|
|
//////////////////////////////////////////////////
|
|
//RegImm Opcodes
|
|
//////////////////////////////////////////////////
|
|
|
|
//00
|
|
void CMA_MIPSIV::BLTZ()
|
|
{
|
|
//Not greater/equal & not likely
|
|
Template_BranchGez(false, false);
|
|
}
|
|
|
|
//01
|
|
void CMA_MIPSIV::BGEZ()
|
|
{
|
|
//Greater/equal & not likely
|
|
Template_BranchGez(true, false);
|
|
}
|
|
|
|
//02
|
|
void CMA_MIPSIV::BLTZL()
|
|
{
|
|
//Not greater/equal & likely
|
|
Template_BranchGez(false, true);
|
|
}
|
|
|
|
//03
|
|
void CMA_MIPSIV::BGEZL()
|
|
{
|
|
//Greater/equal & likely
|
|
Template_BranchGez(true, true);
|
|
}
|
|
|
|
//10
|
|
void CMA_MIPSIV::BLTZAL()
|
|
{
|
|
m_codeGen->PushCst(m_nAddress + 8);
|
|
m_codeGen->PullRel(offsetof(CMIPS, m_State.nGPR[CMIPS::RA].nV[0]));
|
|
|
|
BLTZ();
|
|
}
|
|
|
|
//11
|
|
void CMA_MIPSIV::BGEZAL()
|
|
{
|
|
m_codeGen->PushCst(m_nAddress + 8);
|
|
m_codeGen->PullRel(offsetof(CMIPS, m_State.nGPR[CMIPS::RA].nV[0]));
|
|
|
|
BGEZ();
|
|
}
|
|
|
|
//12
|
|
void CMA_MIPSIV::BLTZALL()
|
|
{
|
|
m_codeGen->PushCst(m_nAddress + 8);
|
|
m_codeGen->PullRel(offsetof(CMIPS, m_State.nGPR[CMIPS::RA].nV[0]));
|
|
|
|
BLTZL();
|
|
}
|
|
|
|
//13
|
|
void CMA_MIPSIV::BGEZALL()
|
|
{
|
|
m_codeGen->PushCst(m_nAddress + 8);
|
|
m_codeGen->PullRel(offsetof(CMIPS, m_State.nGPR[CMIPS::RA].nV[0]));
|
|
|
|
BGEZL();
|
|
}
|
|
|
|
//////////////////////////////////////////////////
|
|
//Opcode Tables
|
|
//////////////////////////////////////////////////
|
|
|
|
// clang-format off
|
|
CMA_MIPSIV::InstructionFuncConstant CMA_MIPSIV::m_cOpGeneral[MAX_GENERAL_OPS] =
|
|
{
|
|
//0x00
|
|
&CMA_MIPSIV::SPECIAL, &CMA_MIPSIV::REGIMM, &CMA_MIPSIV::J, &CMA_MIPSIV::JAL, &CMA_MIPSIV::BEQ, &CMA_MIPSIV::BNE, &CMA_MIPSIV::BLEZ, &CMA_MIPSIV::BGTZ,
|
|
//0x08
|
|
&CMA_MIPSIV::ADDI, &CMA_MIPSIV::ADDIU, &CMA_MIPSIV::SLTI, &CMA_MIPSIV::SLTIU, &CMA_MIPSIV::ANDI, &CMA_MIPSIV::ORI, &CMA_MIPSIV::XORI, &CMA_MIPSIV::LUI,
|
|
//0x10
|
|
&CMA_MIPSIV::COP0, &CMA_MIPSIV::COP1, &CMA_MIPSIV::COP2, &CMA_MIPSIV::Illegal, &CMA_MIPSIV::BEQL, &CMA_MIPSIV::BNEL, &CMA_MIPSIV::BLEZL, &CMA_MIPSIV::BGTZL,
|
|
//0x18
|
|
&CMA_MIPSIV::DADDI, &CMA_MIPSIV::DADDIU, &CMA_MIPSIV::LDL, &CMA_MIPSIV::LDR, &CMA_MIPSIV::SPECIAL2, &CMA_MIPSIV::Illegal, &CMA_MIPSIV::Illegal, &CMA_MIPSIV::Illegal,
|
|
//0x20
|
|
&CMA_MIPSIV::LB, &CMA_MIPSIV::LH, &CMA_MIPSIV::LWL, &CMA_MIPSIV::LW, &CMA_MIPSIV::LBU, &CMA_MIPSIV::LHU, &CMA_MIPSIV::LWR, &CMA_MIPSIV::LWU,
|
|
//0x28
|
|
&CMA_MIPSIV::SB, &CMA_MIPSIV::SH, &CMA_MIPSIV::SWL, &CMA_MIPSIV::SW, &CMA_MIPSIV::SDL, &CMA_MIPSIV::SDR, &CMA_MIPSIV::SWR, &CMA_MIPSIV::CACHE,
|
|
//0x30
|
|
&CMA_MIPSIV::Illegal, &CMA_MIPSIV::LWC1, &CMA_MIPSIV::Illegal, &CMA_MIPSIV::PREF, &CMA_MIPSIV::Illegal, &CMA_MIPSIV::Illegal, &CMA_MIPSIV::LDC2, &CMA_MIPSIV::LD,
|
|
//0x38
|
|
&CMA_MIPSIV::Illegal, &CMA_MIPSIV::SWC1, &CMA_MIPSIV::Illegal, &CMA_MIPSIV::Illegal, &CMA_MIPSIV::Illegal, &CMA_MIPSIV::Illegal, &CMA_MIPSIV::SDC2, &CMA_MIPSIV::SD,
|
|
};
|
|
|
|
CMA_MIPSIV::InstructionFuncConstant CMA_MIPSIV::m_cOpSpecial[MAX_SPECIAL_OPS] =
|
|
{
|
|
//0x00
|
|
&CMA_MIPSIV::SLL, &CMA_MIPSIV::Illegal, &CMA_MIPSIV::SRL, &CMA_MIPSIV::SRA, &CMA_MIPSIV::SLLV, &CMA_MIPSIV::Illegal, &CMA_MIPSIV::SRLV, &CMA_MIPSIV::SRAV,
|
|
//0x08
|
|
&CMA_MIPSIV::JR, &CMA_MIPSIV::JALR, &CMA_MIPSIV::MOVZ, &CMA_MIPSIV::MOVN, &CMA_MIPSIV::SYSCALL, &CMA_MIPSIV::BREAK, &CMA_MIPSIV::Illegal, &CMA_MIPSIV::SYNC,
|
|
//0x10
|
|
&CMA_MIPSIV::MFHI, &CMA_MIPSIV::MTHI, &CMA_MIPSIV::MFLO, &CMA_MIPSIV::MTLO, &CMA_MIPSIV::DSLLV, &CMA_MIPSIV::Illegal, &CMA_MIPSIV::DSRLV, &CMA_MIPSIV::DSRAV,
|
|
//0x18
|
|
&CMA_MIPSIV::MULT, &CMA_MIPSIV::MULTU, &CMA_MIPSIV::DIV, &CMA_MIPSIV::DIVU, &CMA_MIPSIV::Illegal, &CMA_MIPSIV::Illegal, &CMA_MIPSIV::Illegal, &CMA_MIPSIV::Illegal,
|
|
//0x20
|
|
&CMA_MIPSIV::ADD, &CMA_MIPSIV::ADDU, &CMA_MIPSIV::SUB, &CMA_MIPSIV::SUBU, &CMA_MIPSIV::AND, &CMA_MIPSIV::OR, &CMA_MIPSIV::XOR, &CMA_MIPSIV::NOR,
|
|
//0x28
|
|
&CMA_MIPSIV::Illegal, &CMA_MIPSIV::Illegal, &CMA_MIPSIV::SLT, &CMA_MIPSIV::SLTU, &CMA_MIPSIV::DADD, &CMA_MIPSIV::DADDU, &CMA_MIPSIV::DSUB, &CMA_MIPSIV::DSUBU,
|
|
//0x30
|
|
&CMA_MIPSIV::Illegal, &CMA_MIPSIV::Illegal, &CMA_MIPSIV::Illegal, &CMA_MIPSIV::Illegal, &CMA_MIPSIV::TEQ, &CMA_MIPSIV::Illegal, &CMA_MIPSIV::Illegal, &CMA_MIPSIV::Illegal,
|
|
//0x38
|
|
&CMA_MIPSIV::DSLL, &CMA_MIPSIV::Illegal, &CMA_MIPSIV::DSRL, &CMA_MIPSIV::DSRA, &CMA_MIPSIV::DSLL32, &CMA_MIPSIV::Illegal, &CMA_MIPSIV::DSRL32, &CMA_MIPSIV::DSRA32,
|
|
};
|
|
|
|
CMA_MIPSIV::InstructionFuncConstant CMA_MIPSIV::m_cOpRegImm[MAX_REGIMM_OPS] =
|
|
{
|
|
//0x00
|
|
&CMA_MIPSIV::BLTZ, &CMA_MIPSIV::BGEZ, &CMA_MIPSIV::BLTZL, &CMA_MIPSIV::BGEZL, &CMA_MIPSIV::Illegal, &CMA_MIPSIV::Illegal, &CMA_MIPSIV::Illegal, &CMA_MIPSIV::Illegal,
|
|
//0x08
|
|
&CMA_MIPSIV::Illegal, &CMA_MIPSIV::Illegal, &CMA_MIPSIV::Illegal, &CMA_MIPSIV::Illegal, &CMA_MIPSIV::Illegal, &CMA_MIPSIV::Illegal, &CMA_MIPSIV::Illegal, &CMA_MIPSIV::Illegal,
|
|
//0x10
|
|
&CMA_MIPSIV::BLTZAL, &CMA_MIPSIV::BGEZAL, &CMA_MIPSIV::BLTZALL, &CMA_MIPSIV::BGEZALL, &CMA_MIPSIV::Illegal, &CMA_MIPSIV::Illegal, &CMA_MIPSIV::Illegal, &CMA_MIPSIV::Illegal,
|
|
//0x18
|
|
&CMA_MIPSIV::Illegal, &CMA_MIPSIV::Illegal, &CMA_MIPSIV::Illegal, &CMA_MIPSIV::Illegal, &CMA_MIPSIV::Illegal, &CMA_MIPSIV::Illegal, &CMA_MIPSIV::Illegal, &CMA_MIPSIV::Illegal,
|
|
};
|
|
// clang-format on
|