2007-11-02 03:05:08 +00:00
|
|
|
#include <stddef.h>
|
|
|
|
#include "MA_MIPSIV.h"
|
|
|
|
#include "MIPS.h"
|
|
|
|
#include "CodeGen.h"
|
|
|
|
|
|
|
|
#undef offsetof
|
|
|
|
#define offsetof(a, b) (reinterpret_cast<uint8*>(&reinterpret_cast<a*>(0x10)->b) - reinterpret_cast<uint8*>(0x10))
|
|
|
|
|
|
|
|
CMA_MIPSIV g_MAMIPSIV(MIPS_REGSIZE_64);
|
|
|
|
|
|
|
|
uint8 CMA_MIPSIV::m_nRS;
|
|
|
|
uint8 CMA_MIPSIV::m_nRT;
|
|
|
|
uint8 CMA_MIPSIV::m_nRD;
|
|
|
|
uint8 CMA_MIPSIV::m_nSA;
|
|
|
|
uint16 CMA_MIPSIV::m_nImmediate;
|
|
|
|
|
|
|
|
uint32 CMA_MIPSIV::m_nLWLMask[4] =
|
|
|
|
{
|
|
|
|
0x00FFFFFF,
|
|
|
|
0x0000FFFF,
|
|
|
|
0x000000FF,
|
|
|
|
0x00000000,
|
|
|
|
};
|
|
|
|
|
|
|
|
uint32 CMA_MIPSIV::m_nLWLShift[4] =
|
|
|
|
{
|
|
|
|
24,
|
|
|
|
16,
|
|
|
|
8,
|
|
|
|
0,
|
|
|
|
};
|
|
|
|
|
|
|
|
uint32 CMA_MIPSIV::m_nLWRMask[4] =
|
|
|
|
{
|
|
|
|
0x00000000,
|
|
|
|
0xFF000000,
|
|
|
|
0xFFFF0000,
|
|
|
|
0xFFFFFF00,
|
|
|
|
};
|
|
|
|
|
|
|
|
uint32 CMA_MIPSIV::m_nLWRShift[4] =
|
|
|
|
{
|
|
|
|
0,
|
|
|
|
8,
|
|
|
|
16,
|
|
|
|
24,
|
|
|
|
};
|
|
|
|
|
|
|
|
uint32 CMA_MIPSIV::m_nSWLMask[4] =
|
|
|
|
{
|
|
|
|
0xFFFFFF00,
|
|
|
|
0xFFFF0000,
|
|
|
|
0xFF000000,
|
|
|
|
0x00000000,
|
|
|
|
};
|
|
|
|
|
|
|
|
uint32 CMA_MIPSIV::m_nSWLShift[4] =
|
|
|
|
{
|
|
|
|
24,
|
|
|
|
16,
|
|
|
|
8,
|
|
|
|
0,
|
|
|
|
};
|
|
|
|
|
|
|
|
uint32 CMA_MIPSIV::m_nSWRMask[4] =
|
|
|
|
{
|
|
|
|
0x00000000,
|
|
|
|
0x000000FF,
|
|
|
|
0x0000FFFF,
|
|
|
|
0x00FFFFFF,
|
|
|
|
};
|
|
|
|
|
|
|
|
uint32 CMA_MIPSIV::m_nSWRShift[4] =
|
|
|
|
{
|
|
|
|
0,
|
|
|
|
8,
|
|
|
|
16,
|
|
|
|
24,
|
|
|
|
};
|
|
|
|
|
|
|
|
uint32 CMA_MIPSIV::m_nLDLMaskLo[8] =
|
|
|
|
{
|
|
|
|
0xFFFFFFFF,
|
|
|
|
0xFFFFFFFF,
|
|
|
|
0xFFFFFFFF,
|
|
|
|
0xFFFFFFFF,
|
|
|
|
0x00FFFFFF,
|
|
|
|
0x0000FFFF,
|
|
|
|
0x000000FF,
|
|
|
|
0x00000000,
|
|
|
|
};
|
|
|
|
|
|
|
|
uint32 CMA_MIPSIV::m_nLDLMaskHi[8] =
|
|
|
|
{
|
|
|
|
0x00FFFFFF,
|
|
|
|
0x0000FFFF,
|
|
|
|
0x000000FF,
|
|
|
|
0x00000000,
|
|
|
|
0x00000000,
|
|
|
|
0x00000000,
|
|
|
|
0x00000000,
|
|
|
|
0x00000000,
|
|
|
|
};
|
|
|
|
|
|
|
|
uint32 CMA_MIPSIV::m_nLDLShift[8] =
|
|
|
|
{
|
|
|
|
56,
|
|
|
|
48,
|
|
|
|
40,
|
|
|
|
32,
|
|
|
|
24,
|
|
|
|
16,
|
|
|
|
8,
|
|
|
|
0
|
|
|
|
};
|
|
|
|
|
|
|
|
uint32 CMA_MIPSIV::m_nLDRMaskLo[8] =
|
|
|
|
{
|
|
|
|
0x00000000,
|
|
|
|
0x00000000,
|
|
|
|
0x00000000,
|
|
|
|
0x00000000,
|
|
|
|
0x00000000,
|
|
|
|
0xFF000000,
|
|
|
|
0xFFFF0000,
|
|
|
|
0xFFFFFF00,
|
|
|
|
};
|
|
|
|
|
|
|
|
uint32 CMA_MIPSIV::m_nLDRMaskHi[8] =
|
|
|
|
{
|
|
|
|
0x00000000,
|
|
|
|
0xFF000000,
|
|
|
|
0xFFFF0000,
|
|
|
|
0xFFFFFF00,
|
|
|
|
0xFFFFFFFF,
|
|
|
|
0xFFFFFFFF,
|
|
|
|
0xFFFFFFFF,
|
|
|
|
0xFFFFFFFF,
|
|
|
|
};
|
|
|
|
|
|
|
|
uint32 CMA_MIPSIV::m_nLDRShift[8] =
|
|
|
|
{
|
|
|
|
0,
|
|
|
|
8,
|
|
|
|
16,
|
|
|
|
24,
|
|
|
|
32,
|
|
|
|
40,
|
|
|
|
48,
|
|
|
|
56,
|
|
|
|
};
|
|
|
|
|
|
|
|
uint32 CMA_MIPSIV::m_nSDLMaskLo[8] =
|
|
|
|
{
|
|
|
|
0xFFFFFF00,
|
|
|
|
0xFFFF0000,
|
|
|
|
0xFF000000,
|
|
|
|
0x00000000,
|
|
|
|
0x00000000,
|
|
|
|
0x00000000,
|
|
|
|
0x00000000,
|
|
|
|
0x00000000,
|
|
|
|
};
|
|
|
|
|
|
|
|
uint32 CMA_MIPSIV::m_nSDLMaskHi[8] =
|
|
|
|
{
|
|
|
|
0xFFFFFFFF,
|
|
|
|
0xFFFFFFFF,
|
|
|
|
0xFFFFFFFF,
|
|
|
|
0xFFFFFFFF,
|
|
|
|
0xFFFFFF00,
|
|
|
|
0xFFFF0000,
|
|
|
|
0xFF000000,
|
|
|
|
0x00000000,
|
|
|
|
};
|
|
|
|
|
|
|
|
uint32 CMA_MIPSIV::m_nSDLShift[8] =
|
|
|
|
{
|
|
|
|
56,
|
|
|
|
48,
|
|
|
|
40,
|
|
|
|
32,
|
|
|
|
24,
|
|
|
|
16,
|
|
|
|
8,
|
|
|
|
0,
|
|
|
|
};
|
|
|
|
|
|
|
|
uint32 CMA_MIPSIV::m_nSDRMaskLo[8] =
|
|
|
|
{
|
|
|
|
0x00000000,
|
|
|
|
0x000000FF,
|
|
|
|
0x0000FFFF,
|
|
|
|
0x00FFFFFF,
|
|
|
|
0xFFFFFFFF,
|
|
|
|
0xFFFFFFFF,
|
|
|
|
0xFFFFFFFF,
|
|
|
|
0xFFFFFFFF,
|
|
|
|
};
|
|
|
|
|
|
|
|
uint32 CMA_MIPSIV::m_nSDRMaskHi[8] =
|
|
|
|
{
|
|
|
|
0x00000000,
|
|
|
|
0x00000000,
|
|
|
|
0x00000000,
|
|
|
|
0x00000000,
|
|
|
|
0x00000000,
|
|
|
|
0x000000FF,
|
|
|
|
0x0000FFFF,
|
|
|
|
0x00FFFFFF,
|
|
|
|
};
|
|
|
|
|
|
|
|
uint32 CMA_MIPSIV::m_nSDRShift[8] =
|
|
|
|
{
|
|
|
|
0,
|
|
|
|
8,
|
|
|
|
16,
|
|
|
|
24,
|
|
|
|
32,
|
|
|
|
40,
|
|
|
|
48,
|
|
|
|
56,
|
|
|
|
};
|
|
|
|
|
|
|
|
CMA_MIPSIV::CMA_MIPSIV(MIPS_REGSIZE nRegSize) :
|
|
|
|
CMIPSArchitecture(nRegSize)
|
|
|
|
{
|
|
|
|
SetupReflectionTables();
|
|
|
|
}
|
|
|
|
|
|
|
|
void CMA_MIPSIV::CompileInstruction(uint32 nAddress, CCacheBlock* pBlock, CMIPS* pCtx, bool nParent)
|
|
|
|
{
|
|
|
|
if(nParent)
|
|
|
|
{
|
|
|
|
SetupQuickVariables(nAddress, pBlock, 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()
|
|
|
|
{
|
|
|
|
CCodeGen::Begin(m_pB);
|
|
|
|
{
|
|
|
|
CCodeGen::PushRel(offsetof(CMIPS, m_State.nPC));
|
|
|
|
|
|
|
|
CCodeGen::PushCst(0xF0000000);
|
|
|
|
CCodeGen::And();
|
|
|
|
|
|
|
|
CCodeGen::PushCst((m_nOpcode & 0x03FFFFFF) << 2);
|
|
|
|
CCodeGen::Add();
|
|
|
|
|
|
|
|
CCodeGen::PullRel(offsetof(CMIPS, m_State.nDelayedJumpAddr));
|
|
|
|
|
|
|
|
m_pB->SetDelayedJumpCheck();
|
|
|
|
}
|
|
|
|
CCodeGen::End();
|
|
|
|
}
|
|
|
|
|
|
|
|
//03
|
|
|
|
void CMA_MIPSIV::JAL()
|
|
|
|
{
|
|
|
|
//64-bit addresses?
|
|
|
|
|
|
|
|
CCodeGen::Begin(m_pB);
|
|
|
|
{
|
|
|
|
//Save the address in RA
|
|
|
|
CCodeGen::PushRel(offsetof(CMIPS, m_State.nPC));
|
|
|
|
CCodeGen::PushCst(4);
|
|
|
|
CCodeGen::Add();
|
|
|
|
CCodeGen::PullRel(offsetof(CMIPS, m_State.nGPR[31].nV[0]));
|
|
|
|
|
|
|
|
//Update jump address
|
|
|
|
CCodeGen::PushRel(offsetof(CMIPS, m_State.nPC));
|
|
|
|
|
|
|
|
CCodeGen::PushCst(0xF0000000);
|
|
|
|
CCodeGen::And();
|
|
|
|
|
|
|
|
CCodeGen::PushCst((m_nOpcode & 0x03FFFFFF) << 2);
|
|
|
|
CCodeGen::Add();
|
|
|
|
|
|
|
|
CCodeGen::PullRel(offsetof(CMIPS, m_State.nDelayedJumpAddr));
|
|
|
|
|
|
|
|
m_pB->SetDelayedJumpCheck();
|
|
|
|
|
|
|
|
}
|
|
|
|
CCodeGen::End();
|
|
|
|
}
|
|
|
|
|
|
|
|
//04
|
|
|
|
void CMA_MIPSIV::BEQ()
|
|
|
|
{
|
|
|
|
CCodeGen::Begin(m_pB);
|
|
|
|
{
|
|
|
|
CCodeGen::PushRel(offsetof(CMIPS, m_State.nGPR[m_nRS].nV[0]));
|
|
|
|
CCodeGen::PushRel(offsetof(CMIPS, m_State.nGPR[m_nRS].nV[1]));
|
|
|
|
|
|
|
|
CCodeGen::PushRel(offsetof(CMIPS, m_State.nGPR[m_nRT].nV[0]));
|
|
|
|
CCodeGen::PushRel(offsetof(CMIPS, m_State.nGPR[m_nRT].nV[1]));
|
|
|
|
|
|
|
|
CCodeGen::Cmp64(CCodeGen::CONDITION_EQ);
|
|
|
|
|
|
|
|
BranchEx(true);
|
|
|
|
}
|
|
|
|
CCodeGen::End();
|
|
|
|
}
|
|
|
|
|
|
|
|
//05
|
|
|
|
void CMA_MIPSIV::BNE()
|
|
|
|
{
|
|
|
|
CCodeGen::Begin(m_pB);
|
|
|
|
{
|
|
|
|
CCodeGen::PushRel(offsetof(CMIPS, m_State.nGPR[m_nRS].nV[0]));
|
|
|
|
CCodeGen::PushRel(offsetof(CMIPS, m_State.nGPR[m_nRS].nV[1]));
|
|
|
|
|
|
|
|
CCodeGen::PushRel(offsetof(CMIPS, m_State.nGPR[m_nRT].nV[0]));
|
|
|
|
CCodeGen::PushRel(offsetof(CMIPS, m_State.nGPR[m_nRT].nV[1]));
|
|
|
|
|
|
|
|
CCodeGen::Cmp64(CCodeGen::CONDITION_EQ);
|
|
|
|
|
|
|
|
BranchEx(false);
|
|
|
|
}
|
|
|
|
CCodeGen::End();
|
|
|
|
}
|
|
|
|
|
|
|
|
//06
|
|
|
|
void CMA_MIPSIV::BLEZ()
|
|
|
|
{
|
|
|
|
CCodeGen::Begin(m_pB);
|
|
|
|
{
|
|
|
|
CCodeGen::PushRel(offsetof(CMIPS, m_State.nGPR[m_nRS].nV[0]));
|
|
|
|
CCodeGen::PushRel(offsetof(CMIPS, m_State.nGPR[m_nRS].nV[1]));
|
|
|
|
|
|
|
|
CCodeGen::PushCst(0);
|
|
|
|
CCodeGen::PushCst(0);
|
|
|
|
|
|
|
|
CCodeGen::Cmp64(CCodeGen::CONDITION_LE);
|
|
|
|
|
|
|
|
BranchEx(true);
|
|
|
|
}
|
|
|
|
CCodeGen::End();
|
|
|
|
}
|
|
|
|
|
|
|
|
//07
|
|
|
|
void CMA_MIPSIV::BGTZ()
|
|
|
|
{
|
|
|
|
//Check sign bit
|
|
|
|
m_pB->PushAddr(&m_pCtx->m_State.nGPR[m_nRS].nV[1]);
|
|
|
|
m_pB->AndImm(0x80000000);
|
|
|
|
m_pB->PushImm(0x00000000);
|
|
|
|
m_pB->Cmp(JCC_CONDITION_EQ);
|
|
|
|
|
|
|
|
//Check if parts aren't equal to zero
|
|
|
|
m_pB->PushAddr(&m_pCtx->m_State.nGPR[m_nRS].nV[1]);
|
|
|
|
m_pB->PushImm(0x00000000);
|
|
|
|
m_pB->Cmp(JCC_CONDITION_NE);
|
|
|
|
|
|
|
|
m_pB->PushAddr(&m_pCtx->m_State.nGPR[m_nRS].nV[0]);
|
|
|
|
m_pB->PushImm(0x00000000);
|
|
|
|
m_pB->Cmp(JCC_CONDITION_NE);
|
|
|
|
|
|
|
|
m_pB->Or();
|
|
|
|
m_pB->And();
|
|
|
|
|
|
|
|
Branch(true);
|
|
|
|
}
|
|
|
|
|
|
|
|
//08
|
|
|
|
void CMA_MIPSIV::ADDI()
|
|
|
|
{
|
|
|
|
m_pB->PushAddr(&m_pCtx->m_State.nGPR[m_nRS].nV[0]);
|
|
|
|
m_pB->AddImm((int16)m_nImmediate);
|
|
|
|
SignExtendTop32(m_nRT);
|
|
|
|
m_pB->PullAddr(&m_pCtx->m_State.nGPR[m_nRT].nV[0]);
|
|
|
|
}
|
|
|
|
|
|
|
|
//09
|
|
|
|
void CMA_MIPSIV::ADDIU()
|
|
|
|
{
|
2007-11-02 21:30:00 +00:00
|
|
|
if(m_nRT == 0)
|
|
|
|
{
|
|
|
|
//Hack: PS2 IOP uses ADDIU R0, R0, $x for dynamic linking
|
|
|
|
SYSCALL();
|
|
|
|
return;
|
|
|
|
}
|
2007-11-02 03:05:08 +00:00
|
|
|
|
|
|
|
CCodeGen::Begin(m_pB);
|
|
|
|
{
|
|
|
|
CCodeGen::PushRel(offsetof(CMIPS, m_State.nGPR[m_nRS].nV[0]));
|
|
|
|
CCodeGen::PushCst((int16)m_nImmediate);
|
|
|
|
CCodeGen::Add();
|
|
|
|
CCodeGen::SeX();
|
|
|
|
CCodeGen::PullRel(offsetof(CMIPS, m_State.nGPR[m_nRT].nV[1]));
|
|
|
|
CCodeGen::PullRel(offsetof(CMIPS, m_State.nGPR[m_nRT].nV[0]));
|
|
|
|
}
|
|
|
|
CCodeGen::End();
|
|
|
|
}
|
|
|
|
|
|
|
|
//0A
|
|
|
|
void CMA_MIPSIV::SLTI()
|
|
|
|
{
|
|
|
|
CCodeGen::Begin(m_pB);
|
|
|
|
{
|
|
|
|
CCodeGen::PushRel(offsetof(CMIPS, m_State.nGPR[m_nRS].nV[0]));
|
|
|
|
CCodeGen::PushRel(offsetof(CMIPS, m_State.nGPR[m_nRS].nV[1]));
|
|
|
|
|
|
|
|
CCodeGen::PushCst(static_cast<int16>(m_nImmediate));
|
|
|
|
CCodeGen::PushCst(m_nImmediate & 0x8000 ? 0xFFFFFFFF : 0x00000000);
|
|
|
|
|
|
|
|
CCodeGen::Cmp64(CCodeGen::CONDITION_LT);
|
|
|
|
|
|
|
|
CCodeGen::PullRel(offsetof(CMIPS, m_State.nGPR[m_nRT].nV[0]));
|
|
|
|
|
|
|
|
//Clear higher 32-bits
|
|
|
|
CCodeGen::PushCst(0);
|
|
|
|
CCodeGen::PullRel(offsetof(CMIPS, m_State.nGPR[m_nRT].nV[1]));
|
|
|
|
}
|
|
|
|
CCodeGen::End();
|
|
|
|
}
|
|
|
|
|
|
|
|
//0B
|
|
|
|
void CMA_MIPSIV::SLTIU()
|
|
|
|
{
|
|
|
|
CCodeGen::Begin(m_pB);
|
|
|
|
{
|
|
|
|
CCodeGen::PushRel(offsetof(CMIPS, m_State.nGPR[m_nRS].nV[0]));
|
|
|
|
CCodeGen::PushRel(offsetof(CMIPS, m_State.nGPR[m_nRS].nV[1]));
|
|
|
|
|
|
|
|
CCodeGen::PushCst(static_cast<int16>(m_nImmediate));
|
|
|
|
CCodeGen::PushCst(m_nImmediate & 0x8000 ? 0xFFFFFFFF : 0x00000000);
|
|
|
|
|
|
|
|
CCodeGen::Cmp64(CCodeGen::CONDITION_BL);
|
|
|
|
|
|
|
|
CCodeGen::PullRel(offsetof(CMIPS, m_State.nGPR[m_nRT].nV[0]));
|
|
|
|
|
|
|
|
//Clear higher 32-bits
|
|
|
|
CCodeGen::PushCst(0);
|
|
|
|
CCodeGen::PullRel(offsetof(CMIPS, m_State.nGPR[m_nRT].nV[1]));
|
|
|
|
}
|
|
|
|
CCodeGen::End();
|
|
|
|
}
|
|
|
|
|
|
|
|
//0C
|
|
|
|
void CMA_MIPSIV::ANDI()
|
|
|
|
{
|
|
|
|
CCodeGen::Begin(m_pB);
|
|
|
|
{
|
|
|
|
CCodeGen::PushRel(offsetof(CMIPS, m_State.nGPR[m_nRS].nV[0]));
|
|
|
|
CCodeGen::PushCst(m_nImmediate);
|
|
|
|
|
|
|
|
CCodeGen::And();
|
|
|
|
CCodeGen::PullRel(offsetof(CMIPS, m_State.nGPR[m_nRT].nV[0]));
|
|
|
|
|
|
|
|
CCodeGen::PushCst(0);
|
|
|
|
CCodeGen::PullRel(offsetof(CMIPS, m_State.nGPR[m_nRT].nV[1]));
|
|
|
|
}
|
|
|
|
CCodeGen::End();
|
|
|
|
}
|
|
|
|
|
|
|
|
//0D
|
|
|
|
void CMA_MIPSIV::ORI()
|
|
|
|
{
|
|
|
|
CCodeGen::Begin(m_pB);
|
|
|
|
{
|
|
|
|
//Lower 32-bits
|
|
|
|
CCodeGen::PushRel(offsetof(CMIPS, m_State.nGPR[m_nRS].nV[0]));
|
|
|
|
CCodeGen::PushCst(m_nImmediate);
|
|
|
|
CCodeGen::Or();
|
|
|
|
CCodeGen::PullRel(offsetof(CMIPS, m_State.nGPR[m_nRT].nV[0]));
|
|
|
|
|
|
|
|
//Higher 32-bits (only if registers are different)
|
|
|
|
if(m_nRS != m_nRT)
|
|
|
|
{
|
|
|
|
CCodeGen::PushRel(offsetof(CMIPS, m_State.nGPR[m_nRS].nV[1]));
|
|
|
|
CCodeGen::PullRel(offsetof(CMIPS, m_State.nGPR[m_nRT].nV[1]));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
CCodeGen::End();
|
|
|
|
}
|
|
|
|
|
|
|
|
//0E
|
|
|
|
void CMA_MIPSIV::XORI()
|
|
|
|
{
|
|
|
|
//Lower 32-bits
|
|
|
|
m_pB->PushAddr(&m_pCtx->m_State.nGPR[m_nRS].nV[0]);
|
|
|
|
m_pB->PushImm(m_nImmediate);
|
|
|
|
m_pB->Xor();
|
|
|
|
m_pB->PullAddr(&m_pCtx->m_State.nGPR[m_nRT].nV[0]);
|
|
|
|
|
|
|
|
//Higher 32-bits
|
|
|
|
m_pB->PushAddr(&m_pCtx->m_State.nGPR[m_nRS].nV[1]);
|
|
|
|
m_pB->PullAddr(&m_pCtx->m_State.nGPR[m_nRT].nV[1]);
|
|
|
|
}
|
|
|
|
|
|
|
|
//0F
|
|
|
|
void CMA_MIPSIV::LUI()
|
|
|
|
{
|
|
|
|
CCodeGen::Begin(m_pB);
|
|
|
|
{
|
|
|
|
CCodeGen::PushCst(m_nImmediate << 16);
|
|
|
|
CCodeGen::PushCst((m_nImmediate & 0x8000) ? 0xFFFFFFFF : 0x00000000);
|
|
|
|
CCodeGen::PullRel(offsetof(CMIPS, m_State.nGPR[m_nRT].nV[1]));
|
|
|
|
CCodeGen::PullRel(offsetof(CMIPS, m_State.nGPR[m_nRT].nV[0]));
|
|
|
|
}
|
|
|
|
CCodeGen::End();
|
|
|
|
}
|
|
|
|
|
|
|
|
//10
|
|
|
|
void CMA_MIPSIV::COP0()
|
|
|
|
{
|
|
|
|
if(m_pCtx->m_pCOP[0] != NULL)
|
|
|
|
{
|
|
|
|
m_pCtx->m_pCOP[0]->CompileInstruction(m_nAddress, m_pB, m_pCtx, false);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Illegal();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//11
|
|
|
|
void CMA_MIPSIV::COP1()
|
|
|
|
{
|
|
|
|
if(m_pCtx->m_pCOP[1] != NULL)
|
|
|
|
{
|
|
|
|
m_pCtx->m_pCOP[1]->CompileInstruction(m_nAddress, m_pB, m_pCtx, false);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Illegal();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//12
|
|
|
|
void CMA_MIPSIV::COP2()
|
|
|
|
{
|
|
|
|
if(m_pCtx->m_pCOP[2] != NULL)
|
|
|
|
{
|
|
|
|
m_pCtx->m_pCOP[2]->CompileInstruction(m_nAddress, m_pB, m_pCtx, false);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Illegal();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//14
|
|
|
|
void CMA_MIPSIV::BEQL()
|
|
|
|
{
|
|
|
|
m_pB->PushAddr(&m_pCtx->m_State.nGPR[m_nRS].nV[0]);
|
|
|
|
m_pB->PushAddr(&m_pCtx->m_State.nGPR[m_nRT].nV[0]);
|
|
|
|
m_pB->Cmp(JCC_CONDITION_EQ);
|
|
|
|
|
|
|
|
m_pB->PushAddr(&m_pCtx->m_State.nGPR[m_nRS].nV[1]);
|
|
|
|
m_pB->PushAddr(&m_pCtx->m_State.nGPR[m_nRT].nV[1]);
|
|
|
|
m_pB->Cmp(JCC_CONDITION_EQ);
|
|
|
|
|
|
|
|
m_pB->And();
|
|
|
|
|
|
|
|
BranchLikely(true);
|
|
|
|
}
|
|
|
|
|
|
|
|
//15
|
|
|
|
void CMA_MIPSIV::BNEL()
|
|
|
|
{
|
|
|
|
m_pB->PushAddr(&m_pCtx->m_State.nGPR[m_nRS].nV[0]);
|
|
|
|
m_pB->PushAddr(&m_pCtx->m_State.nGPR[m_nRT].nV[0]);
|
|
|
|
m_pB->Cmp(JCC_CONDITION_EQ);
|
|
|
|
|
|
|
|
m_pB->PushAddr(&m_pCtx->m_State.nGPR[m_nRS].nV[1]);
|
|
|
|
m_pB->PushAddr(&m_pCtx->m_State.nGPR[m_nRT].nV[1]);
|
|
|
|
m_pB->Cmp(JCC_CONDITION_EQ);
|
|
|
|
|
|
|
|
m_pB->And();
|
|
|
|
|
|
|
|
BranchLikely(false);
|
|
|
|
}
|
|
|
|
|
|
|
|
//16
|
|
|
|
void CMA_MIPSIV::BLEZL()
|
|
|
|
{
|
|
|
|
//Check sign bit
|
|
|
|
m_pB->PushAddr(&m_pCtx->m_State.nGPR[m_nRS].nV[1]);
|
|
|
|
m_pB->AndImm(0x80000000);
|
|
|
|
m_pB->PushImm(0x00000000);
|
|
|
|
m_pB->Cmp(JCC_CONDITION_EQ);
|
|
|
|
|
|
|
|
//Check if parts aren't equal to zero
|
|
|
|
m_pB->PushAddr(&m_pCtx->m_State.nGPR[m_nRS].nV[1]);
|
|
|
|
m_pB->PushImm(0x00000000);
|
|
|
|
m_pB->Cmp(JCC_CONDITION_NE);
|
|
|
|
|
|
|
|
m_pB->PushAddr(&m_pCtx->m_State.nGPR[m_nRS].nV[0]);
|
|
|
|
m_pB->PushImm(0x00000000);
|
|
|
|
m_pB->Cmp(JCC_CONDITION_NE);
|
|
|
|
|
|
|
|
m_pB->Or();
|
|
|
|
m_pB->And();
|
|
|
|
|
|
|
|
BranchLikely(false);
|
|
|
|
}
|
|
|
|
|
|
|
|
//17
|
|
|
|
void CMA_MIPSIV::BGTZL()
|
|
|
|
{
|
|
|
|
//Check sign bit
|
|
|
|
m_pB->PushAddr(&m_pCtx->m_State.nGPR[m_nRS].nV[1]);
|
|
|
|
m_pB->AndImm(0x80000000);
|
|
|
|
m_pB->PushImm(0x00000000);
|
|
|
|
m_pB->Cmp(JCC_CONDITION_EQ);
|
|
|
|
|
|
|
|
//Check if parts aren't equal to zero
|
|
|
|
m_pB->PushAddr(&m_pCtx->m_State.nGPR[m_nRS].nV[1]);
|
|
|
|
m_pB->PushImm(0x00000000);
|
|
|
|
m_pB->Cmp(JCC_CONDITION_NE);
|
|
|
|
|
|
|
|
m_pB->PushAddr(&m_pCtx->m_State.nGPR[m_nRS].nV[0]);
|
|
|
|
m_pB->PushImm(0x00000000);
|
|
|
|
m_pB->Cmp(JCC_CONDITION_NE);
|
|
|
|
|
|
|
|
m_pB->Or();
|
|
|
|
m_pB->And();
|
|
|
|
|
|
|
|
BranchLikely(true);
|
|
|
|
}
|
|
|
|
|
|
|
|
//19
|
|
|
|
void CMA_MIPSIV::DADDIU()
|
|
|
|
{
|
|
|
|
CCodeGen::Begin(m_pB);
|
|
|
|
{
|
|
|
|
CCodeGen::PushRel(offsetof(CMIPS, m_State.nGPR[m_nRS].nV[0]));
|
|
|
|
CCodeGen::PushRel(offsetof(CMIPS, m_State.nGPR[m_nRS].nV[1]));
|
|
|
|
|
|
|
|
CCodeGen::PushCst(static_cast<int16>(m_nImmediate));
|
|
|
|
CCodeGen::PushCst((m_nImmediate & 0x8000) == 0 ? 0x00000000 : 0xFFFFFFFF);
|
|
|
|
|
|
|
|
CCodeGen::Add64();
|
|
|
|
|
|
|
|
CCodeGen::PullRel(offsetof(CMIPS, m_State.nGPR[m_nRT].nV[1]));
|
|
|
|
CCodeGen::PullRel(offsetof(CMIPS, m_State.nGPR[m_nRT].nV[0]));
|
|
|
|
}
|
|
|
|
CCodeGen::End();
|
|
|
|
}
|
|
|
|
|
|
|
|
//1A
|
|
|
|
void CMA_MIPSIV::LDL()
|
|
|
|
{
|
|
|
|
ComputeMemAccessAddr();
|
|
|
|
|
|
|
|
m_pB->PushValueAt(0);
|
|
|
|
m_pB->AndImm(0x00000007);
|
|
|
|
m_pB->PushValueAt(1);
|
|
|
|
m_pB->AndImm(~0x00000007);
|
|
|
|
//2 - BYTE EA
|
|
|
|
//1 - OFFSET
|
|
|
|
//0 - EA
|
|
|
|
|
|
|
|
//Get the lower word
|
|
|
|
m_pB->PushValueAt(0);
|
|
|
|
m_pB->PushRef(m_pCtx);
|
|
|
|
m_pB->Call(reinterpret_cast<void*>(&CCacheBlock::GetWordProxy), 2, true);
|
|
|
|
//3 - BYTE EA
|
|
|
|
//2 - OFFSET
|
|
|
|
//1 - EA
|
|
|
|
//0 - LOWORD
|
|
|
|
|
|
|
|
//Get the high word
|
|
|
|
m_pB->PushValueAt(1);
|
|
|
|
m_pB->AddImm(4);
|
|
|
|
m_pB->PushRef(m_pCtx);
|
|
|
|
m_pB->Call(reinterpret_cast<void*>(&CCacheBlock::GetWordProxy), 2, true);
|
|
|
|
//4 - BYTE EA
|
|
|
|
//3 - OFFSET
|
|
|
|
//2 - EA
|
|
|
|
//1 - LOWORD
|
|
|
|
//0 - HIWORD
|
|
|
|
|
|
|
|
//Shift the 64-bits word left
|
|
|
|
m_pB->PushValueAt(3);
|
|
|
|
m_pB->Lookup(m_nLDLShift);
|
|
|
|
m_pB->Sll64();
|
|
|
|
//4 - BYTE EA
|
|
|
|
//3 - OFFSET
|
|
|
|
//2 - EA
|
|
|
|
//1 - LOWORD SHIFTED
|
|
|
|
//0 - HIWORD SHIFTED
|
|
|
|
|
|
|
|
////////////////////////
|
|
|
|
//Higher 32-bits
|
|
|
|
////////////////////////
|
|
|
|
|
|
|
|
//Get the mask for this register
|
|
|
|
m_pB->PushValueAt(3);
|
|
|
|
m_pB->Lookup(m_nLDLMaskHi);
|
|
|
|
//5 - BYTE EA
|
|
|
|
//4 - OFFSET
|
|
|
|
//3 - EA
|
|
|
|
//2 - LOWORD SHIFTED
|
|
|
|
//1 - HIWORD SHIFTED
|
|
|
|
//0 - HIMASK
|
|
|
|
|
|
|
|
//Obtain the value of the register, mask, or with the value, sign extend, save
|
|
|
|
m_pB->PushAddr(&m_pCtx->m_State.nGPR[m_nRT].nV[1]);
|
|
|
|
m_pB->And();
|
|
|
|
m_pB->Or();
|
|
|
|
m_pB->PullAddr(&m_pCtx->m_State.nGPR[m_nRT].nV[1]);
|
|
|
|
//3 - BYTE EA
|
|
|
|
//2 - OFFSET
|
|
|
|
//1 - EA
|
|
|
|
//0 - LOWORD SHIFTED
|
|
|
|
|
|
|
|
////////////////////////
|
|
|
|
//Lower 32-bits
|
|
|
|
////////////////////////
|
|
|
|
|
|
|
|
//Get the mask for this register
|
|
|
|
m_pB->PushValueAt(2);
|
|
|
|
m_pB->Lookup(m_nLDLMaskLo);
|
|
|
|
//4 - BYTE EA
|
|
|
|
//3 - OFFSET
|
|
|
|
//2 - EA
|
|
|
|
//1 - LOWORD SHIFTED
|
|
|
|
//0 - LOMASK
|
|
|
|
|
|
|
|
//Obtain the value of the register, mask, or with the value and save
|
|
|
|
m_pB->PushAddr(&m_pCtx->m_State.nGPR[m_nRT].nV[0]);
|
|
|
|
m_pB->And();
|
|
|
|
m_pB->Or();
|
|
|
|
m_pB->PullAddr(&m_pCtx->m_State.nGPR[m_nRT].nV[0]);
|
|
|
|
//2 - BYTE EA
|
|
|
|
//1 - OFFSET
|
|
|
|
//0 - EA
|
|
|
|
|
|
|
|
//Done, free the stack
|
|
|
|
m_pB->Free(3);
|
|
|
|
}
|
|
|
|
|
|
|
|
//1B
|
|
|
|
void CMA_MIPSIV::LDR()
|
|
|
|
{
|
|
|
|
ComputeMemAccessAddr();
|
|
|
|
|
|
|
|
m_pB->PushValueAt(0);
|
|
|
|
m_pB->AndImm(0x00000007);
|
|
|
|
m_pB->PushValueAt(1);
|
|
|
|
m_pB->AndImm(~0x00000007);
|
|
|
|
//2 - BYTE EA
|
|
|
|
//1 - OFFSET
|
|
|
|
//0 - EA
|
|
|
|
|
|
|
|
//Get the lower word
|
|
|
|
m_pB->PushValueAt(0);
|
|
|
|
m_pB->PushRef(m_pCtx);
|
|
|
|
m_pB->Call(reinterpret_cast<void*>(&CCacheBlock::GetWordProxy), 2, true);
|
|
|
|
//3 - BYTE EA
|
|
|
|
//2 - OFFSET
|
|
|
|
//1 - EA
|
|
|
|
//0 - LOWORD
|
|
|
|
|
|
|
|
//Get the high word
|
|
|
|
m_pB->PushValueAt(1);
|
|
|
|
m_pB->AddImm(4);
|
|
|
|
m_pB->PushRef(m_pCtx);
|
|
|
|
m_pB->Call(reinterpret_cast<void*>(&CCacheBlock::GetWordProxy), 2, true);
|
|
|
|
//4 - BYTE EA
|
|
|
|
//3 - OFFSET
|
|
|
|
//2 - EA
|
|
|
|
//1 - LOWORD
|
|
|
|
//0 - HIWORD
|
|
|
|
|
|
|
|
//Shift the 64-bits word right
|
|
|
|
m_pB->PushValueAt(3);
|
|
|
|
m_pB->Lookup(m_nLDRShift);
|
|
|
|
m_pB->Srl64();
|
|
|
|
//4 - BYTE EA
|
|
|
|
//3 - OFFSET
|
|
|
|
//2 - EA
|
|
|
|
//1 - LOWORD SHIFTED
|
|
|
|
//0 - HIWORD SHIFTED
|
|
|
|
|
|
|
|
////////////////////////
|
|
|
|
//Higher 32-bits
|
|
|
|
////////////////////////
|
|
|
|
|
|
|
|
//Get the mask for this register
|
|
|
|
m_pB->PushValueAt(3);
|
|
|
|
m_pB->Lookup(m_nLDRMaskHi);
|
|
|
|
//5 - BYTE EA
|
|
|
|
//4 - OFFSET
|
|
|
|
//3 - EA
|
|
|
|
//2 - LOWORD SHIFTED
|
|
|
|
//1 - HIWORD SHIFTED
|
|
|
|
//0 - HIMASK
|
|
|
|
|
|
|
|
//Obtain the value of the register, mask, or with the value, sign extend, save
|
|
|
|
m_pB->PushAddr(&m_pCtx->m_State.nGPR[m_nRT].nV[1]);
|
|
|
|
m_pB->And();
|
|
|
|
m_pB->Or();
|
|
|
|
m_pB->PullAddr(&m_pCtx->m_State.nGPR[m_nRT].nV[1]);
|
|
|
|
//3 - BYTE EA
|
|
|
|
//2 - OFFSET
|
|
|
|
//1 - EA
|
|
|
|
//0 - LOWORD SHIFTED
|
|
|
|
|
|
|
|
////////////////////////
|
|
|
|
//Lower 32-bits
|
|
|
|
////////////////////////
|
|
|
|
|
|
|
|
//Get the mask for this register
|
|
|
|
m_pB->PushValueAt(2);
|
|
|
|
m_pB->Lookup(m_nLDRMaskLo);
|
|
|
|
//4 - BYTE EA
|
|
|
|
//3 - OFFSET
|
|
|
|
//2 - EA
|
|
|
|
//1 - LOWORD SHIFTED
|
|
|
|
//0 - LOMASK
|
|
|
|
|
|
|
|
//Obtain the value of the register, mask, or with the value and save
|
|
|
|
m_pB->PushAddr(&m_pCtx->m_State.nGPR[m_nRT].nV[0]);
|
|
|
|
m_pB->And();
|
|
|
|
m_pB->Or();
|
|
|
|
m_pB->PullAddr(&m_pCtx->m_State.nGPR[m_nRT].nV[0]);
|
|
|
|
//2 - BYTE EA
|
|
|
|
//1 - OFFSET
|
|
|
|
//0 - EA
|
|
|
|
|
|
|
|
//Done, free the stack
|
|
|
|
m_pB->Free(3);
|
|
|
|
}
|
|
|
|
|
|
|
|
//20
|
|
|
|
void CMA_MIPSIV::LB()
|
|
|
|
{
|
|
|
|
ComputeMemAccessAddr();
|
|
|
|
|
|
|
|
m_pB->PushRef(m_pCtx);
|
|
|
|
m_pB->Call(reinterpret_cast<void*>(&CCacheBlock::GetByteProxy), 2, true);
|
|
|
|
m_pB->SeX8();
|
|
|
|
SignExtendTop32(m_nRT);
|
|
|
|
m_pB->PullAddr(&m_pCtx->m_State.nGPR[m_nRT].nV[0]);
|
|
|
|
}
|
|
|
|
|
|
|
|
//21
|
|
|
|
void CMA_MIPSIV::LH()
|
|
|
|
{
|
|
|
|
ComputeMemAccessAddr();
|
|
|
|
|
|
|
|
//Load the word
|
|
|
|
m_pB->PushRef(m_pCtx);
|
|
|
|
m_pB->Call(reinterpret_cast<void*>(&CCacheBlock::GetHalfProxy), 2, true);
|
|
|
|
m_pB->SeX16();
|
|
|
|
SignExtendTop32(m_nRT);
|
|
|
|
m_pB->PullAddr(&m_pCtx->m_State.nGPR[m_nRT].nV[0]);
|
|
|
|
}
|
|
|
|
|
|
|
|
//22
|
|
|
|
void CMA_MIPSIV::LWL()
|
|
|
|
{
|
|
|
|
ComputeMemAccessAddr();
|
|
|
|
|
|
|
|
m_pB->PushValueAt(0);
|
|
|
|
m_pB->AndImm(0x00000003);
|
|
|
|
m_pB->PushValueAt(1);
|
|
|
|
m_pB->AndImm(~0x00000003);
|
|
|
|
//2 - BYTE EA
|
|
|
|
//1 - OFFSET
|
|
|
|
//0 - EA
|
|
|
|
|
|
|
|
//Get the word
|
|
|
|
m_pB->PushValueAt(0);
|
|
|
|
m_pB->PushRef(m_pCtx);
|
|
|
|
m_pB->Call(reinterpret_cast<void*>(&CCacheBlock::GetWordProxy), 2, true);
|
|
|
|
//3 - BYTE EA
|
|
|
|
//2 - OFFSET
|
|
|
|
//1 - EA
|
|
|
|
//0 - WORD
|
|
|
|
|
|
|
|
//Shift the word left
|
|
|
|
m_pB->PushValueAt(2);
|
|
|
|
m_pB->Lookup(m_nLWLShift);
|
|
|
|
m_pB->Sll();
|
|
|
|
//3 - BYTE EA
|
|
|
|
//2 - OFFSET
|
|
|
|
//1 - EA
|
|
|
|
//0 - WORD SHIFTED
|
|
|
|
|
|
|
|
//Get the mask for this register
|
|
|
|
m_pB->PushValueAt(2);
|
|
|
|
m_pB->Lookup(m_nLWLMask);
|
|
|
|
//4 - BYTE EA
|
|
|
|
//3 - OFFSET
|
|
|
|
//2 - EA
|
|
|
|
//1 - WORD SHIFTED
|
|
|
|
//0 - MASK
|
|
|
|
|
|
|
|
//Obtain the value of the register, mask, or with the value, sign extend, save
|
|
|
|
m_pB->PushAddr(&m_pCtx->m_State.nGPR[m_nRT].nV[0]);
|
|
|
|
m_pB->And();
|
|
|
|
m_pB->Or();
|
|
|
|
SignExtendTop32(m_nRT);
|
|
|
|
m_pB->PullAddr(&m_pCtx->m_State.nGPR[m_nRT].nV[0]);
|
|
|
|
//2 - BYTE EA
|
|
|
|
//1 - OFFSET
|
|
|
|
//0 - EA
|
|
|
|
|
|
|
|
//Done, free the stack
|
|
|
|
m_pB->Free(3);
|
|
|
|
}
|
|
|
|
|
|
|
|
//23
|
|
|
|
void CMA_MIPSIV::LW()
|
|
|
|
{
|
|
|
|
Template_LoadUnsigned32()(reinterpret_cast<void*>(&CCacheBlock::GetWordProxy));
|
|
|
|
}
|
|
|
|
|
|
|
|
//24
|
|
|
|
void CMA_MIPSIV::LBU()
|
|
|
|
{
|
|
|
|
Template_LoadUnsigned32()(reinterpret_cast<void*>(&CCacheBlock::GetByteProxy));
|
|
|
|
}
|
|
|
|
|
|
|
|
//25
|
|
|
|
void CMA_MIPSIV::LHU()
|
|
|
|
{
|
|
|
|
Template_LoadUnsigned32()(reinterpret_cast<void*>(&CCacheBlock::GetHalfProxy));
|
|
|
|
}
|
|
|
|
|
|
|
|
//26
|
|
|
|
void CMA_MIPSIV::LWR()
|
|
|
|
{
|
|
|
|
ComputeMemAccessAddr();
|
|
|
|
|
|
|
|
m_pB->PushValueAt(0);
|
|
|
|
m_pB->AndImm(0x00000003);
|
|
|
|
m_pB->PushValueAt(1);
|
|
|
|
m_pB->AndImm(~0x00000003);
|
|
|
|
//2 - BYTE EA
|
|
|
|
//1 - OFFSET
|
|
|
|
//0 - EA
|
|
|
|
|
|
|
|
//Get the word
|
|
|
|
m_pB->PushValueAt(0);
|
|
|
|
m_pB->PushRef(m_pCtx);
|
|
|
|
m_pB->Call(reinterpret_cast<void*>(&CCacheBlock::GetWordProxy), 2, true);
|
|
|
|
//3 - BYTE EA
|
|
|
|
//2 - OFFSET
|
|
|
|
//1 - EA
|
|
|
|
//0 - WORD
|
|
|
|
|
|
|
|
//Shift the word right
|
|
|
|
m_pB->PushValueAt(2);
|
|
|
|
m_pB->Lookup(m_nLWRShift);
|
|
|
|
m_pB->Srl();
|
|
|
|
//3 - BYTE EA
|
|
|
|
//2 - OFFSET
|
|
|
|
//1 - EA
|
|
|
|
//0 - WORD SHIFTED
|
|
|
|
|
|
|
|
//Get the mask for this register
|
|
|
|
m_pB->PushValueAt(2);
|
|
|
|
m_pB->Lookup(m_nLWRMask);
|
|
|
|
//4 - BYTE EA
|
|
|
|
//3 - OFFSET
|
|
|
|
//2 - EA
|
|
|
|
//1 - WORD SHIFTED
|
|
|
|
//0 - MASK
|
|
|
|
|
|
|
|
//Obtain the value of the register, mask, or with the value, sign extend, save
|
|
|
|
m_pB->PushAddr(&m_pCtx->m_State.nGPR[m_nRT].nV[0]);
|
|
|
|
m_pB->And();
|
|
|
|
m_pB->Or();
|
|
|
|
SignExtendTop32(m_nRT);
|
|
|
|
m_pB->PullAddr(&m_pCtx->m_State.nGPR[m_nRT].nV[0]);
|
|
|
|
//2 - BYTE EA
|
|
|
|
//1 - OFFSET
|
|
|
|
//0 - EA
|
|
|
|
|
|
|
|
//Done, free the stack
|
|
|
|
m_pB->Free(3);
|
|
|
|
}
|
|
|
|
|
|
|
|
//27
|
|
|
|
void CMA_MIPSIV::LWU()
|
|
|
|
{
|
|
|
|
ComputeMemAccessAddr();
|
|
|
|
|
|
|
|
//Load the word
|
|
|
|
m_pB->PushRef(m_pCtx);
|
|
|
|
m_pB->Call(reinterpret_cast<void*>(&CCacheBlock::GetWordProxy), 2, true);
|
|
|
|
m_pB->PullAddr(&m_pCtx->m_State.nGPR[m_nRT].nV[0]);
|
|
|
|
|
|
|
|
//Zero extend the value
|
|
|
|
m_pB->PushImm(0);
|
|
|
|
m_pB->PullAddr(&m_pCtx->m_State.nGPR[m_nRT].nV[1]);
|
|
|
|
}
|
|
|
|
|
|
|
|
//28
|
|
|
|
void CMA_MIPSIV::SB()
|
|
|
|
{
|
|
|
|
CCodeGen::Begin(m_pB);
|
|
|
|
{
|
|
|
|
ComputeMemAccessAddrEx();
|
|
|
|
|
|
|
|
CCodeGen::PushRef(m_pCtx);
|
|
|
|
CCodeGen::PushRel(offsetof(CMIPS, m_State.nGPR[m_nRT].nV[0]));
|
|
|
|
CCodeGen::PushIdx(2);
|
|
|
|
CCodeGen::Call(reinterpret_cast<void*>(&CCacheBlock::SetByteProxy), 3, false);
|
|
|
|
|
|
|
|
CCodeGen::PullTop();
|
|
|
|
}
|
|
|
|
CCodeGen::End();
|
|
|
|
}
|
|
|
|
|
|
|
|
//29
|
|
|
|
void CMA_MIPSIV::SH()
|
|
|
|
{
|
|
|
|
CCodeGen::Begin(m_pB);
|
|
|
|
{
|
|
|
|
ComputeMemAccessAddrEx();
|
|
|
|
|
|
|
|
CCodeGen::PushRef(m_pCtx);
|
|
|
|
CCodeGen::PushRel(offsetof(CMIPS, m_State.nGPR[m_nRT].nV[0]));
|
|
|
|
CCodeGen::PushIdx(2);
|
|
|
|
CCodeGen::Call(reinterpret_cast<void*>(&CCacheBlock::SetHalfProxy), 3, false);
|
|
|
|
|
|
|
|
CCodeGen::PullTop();
|
|
|
|
}
|
|
|
|
CCodeGen::End();
|
|
|
|
}
|
|
|
|
|
|
|
|
//2A
|
|
|
|
void CMA_MIPSIV::SWL()
|
|
|
|
{
|
|
|
|
ComputeMemAccessAddr();
|
|
|
|
|
|
|
|
m_pB->PushValueAt(0);
|
|
|
|
m_pB->AndImm(0x00000003);
|
|
|
|
m_pB->PushValueAt(1);
|
|
|
|
m_pB->AndImm(~0x00000003);
|
|
|
|
//2 - BYTE EA
|
|
|
|
//1 - OFFSET
|
|
|
|
//0 - EA
|
|
|
|
|
|
|
|
//Get the reg value
|
|
|
|
m_pB->PushAddr(&m_pCtx->m_State.nGPR[m_nRT].nV[0]);
|
|
|
|
//3 - BYTE EA
|
|
|
|
//2 - OFFSET
|
|
|
|
//1 - EA
|
|
|
|
//0 - REG
|
|
|
|
|
|
|
|
//Get shift the register right
|
|
|
|
m_pB->PushValueAt(2);
|
|
|
|
m_pB->Lookup(m_nSWLShift);
|
|
|
|
m_pB->Srl();
|
|
|
|
//3 - BYTE EA
|
|
|
|
//2 - OFFSET
|
|
|
|
//1 - EA
|
|
|
|
//0 - REG SHIFTED
|
|
|
|
|
|
|
|
//Get the mask for this register
|
|
|
|
m_pB->PushValueAt(2);
|
|
|
|
m_pB->Lookup(m_nSWLMask);
|
|
|
|
//4 - BYTE EA
|
|
|
|
//3 - OFFSET
|
|
|
|
//2 - EA
|
|
|
|
//1 - REG SHIFTED
|
|
|
|
//0 - MASK
|
|
|
|
|
|
|
|
//Obtain the value of memory, mask, or with the value and save
|
|
|
|
m_pB->PushValueAt(2);
|
|
|
|
m_pB->PushRef(m_pCtx);
|
|
|
|
m_pB->Call(reinterpret_cast<void*>(&CCacheBlock::GetWordProxy), 2, true);
|
|
|
|
//5 - BYTE EA
|
|
|
|
//4 - OFFSET
|
|
|
|
//3 - EA
|
|
|
|
//2 - REG SHIFTED
|
|
|
|
//1 - MASK
|
|
|
|
//0 - WORD
|
|
|
|
|
|
|
|
m_pB->And();
|
|
|
|
m_pB->Or();
|
|
|
|
//3 - BYTE EA
|
|
|
|
//2 - OFFSET
|
|
|
|
//1 - EA
|
|
|
|
//0 - WORD VALUE
|
|
|
|
|
|
|
|
m_pB->PushValueAt(1);
|
|
|
|
m_pB->Swap();
|
|
|
|
m_pB->PushRef(m_pCtx);
|
|
|
|
m_pB->Call(reinterpret_cast<void*>(&CCacheBlock::SetWordProxy), 3, false);
|
|
|
|
//2 - BYTE EA
|
|
|
|
//1 - OFFSET
|
|
|
|
//0 - EA
|
|
|
|
|
|
|
|
//Done, free the stack
|
|
|
|
m_pB->Free(3);
|
|
|
|
}
|
|
|
|
|
|
|
|
//2B
|
|
|
|
void CMA_MIPSIV::SW()
|
|
|
|
{
|
|
|
|
CCodeGen::Begin(m_pB);
|
|
|
|
{
|
|
|
|
ComputeMemAccessAddrEx();
|
|
|
|
|
|
|
|
CCodeGen::PushRef(m_pCtx);
|
|
|
|
CCodeGen::PushRel(offsetof(CMIPS, m_State.nGPR[m_nRT].nV[0]));
|
|
|
|
CCodeGen::PushIdx(2);
|
|
|
|
CCodeGen::Call(reinterpret_cast<void*>(&CCacheBlock::SetWordProxy), 3, false);
|
|
|
|
|
|
|
|
CCodeGen::PullTop();
|
|
|
|
}
|
|
|
|
CCodeGen::End();
|
|
|
|
}
|
|
|
|
|
|
|
|
//2C
|
|
|
|
void CMA_MIPSIV::SDL()
|
|
|
|
{
|
|
|
|
ComputeMemAccessAddr();
|
|
|
|
|
|
|
|
m_pB->PushValueAt(0);
|
|
|
|
m_pB->AndImm(0x00000007);
|
|
|
|
m_pB->PushValueAt(1);
|
|
|
|
m_pB->AndImm(~0x00000007);
|
|
|
|
//2 - BYTE EA
|
|
|
|
//1 - OFFSET
|
|
|
|
//0 - EA
|
|
|
|
|
|
|
|
//Get the lo/hi reg values
|
|
|
|
m_pB->PushAddr(&m_pCtx->m_State.nGPR[m_nRT].nV[0]);
|
|
|
|
m_pB->PushAddr(&m_pCtx->m_State.nGPR[m_nRT].nV[1]);
|
|
|
|
//4 - BYTE EA
|
|
|
|
//3 - OFFSET
|
|
|
|
//2 - EA
|
|
|
|
//1 - LOREG
|
|
|
|
//0 - HIREG
|
|
|
|
|
|
|
|
//Get shift the register right
|
|
|
|
m_pB->PushValueAt(3);
|
|
|
|
m_pB->Lookup(m_nSDLShift);
|
|
|
|
m_pB->Srl64();
|
|
|
|
//4 - BYTE EA
|
|
|
|
//3 - OFFSET
|
|
|
|
//2 - EA
|
|
|
|
//1 - LOREG SHIFTED
|
|
|
|
//0 - HIREG SHIFTED
|
|
|
|
|
|
|
|
////////////////////////
|
|
|
|
//Higher 32-bits
|
|
|
|
////////////////////////
|
|
|
|
|
|
|
|
//Get the mask for this register
|
|
|
|
m_pB->PushValueAt(3);
|
|
|
|
m_pB->Lookup(m_nSDLMaskHi);
|
|
|
|
//5 - BYTE EA
|
|
|
|
//4 - OFFSET
|
|
|
|
//3 - EA
|
|
|
|
//2 - LOREG SHIFTED
|
|
|
|
//1 - HIREG SHIFTED
|
|
|
|
//0 - HIMASK
|
|
|
|
|
|
|
|
//Obtain the value of memory, mask, or with the value and save
|
|
|
|
m_pB->PushValueAt(3);
|
|
|
|
m_pB->AddImm(4);
|
|
|
|
m_pB->PushRef(m_pCtx);
|
|
|
|
m_pB->Call(reinterpret_cast<void*>(&CCacheBlock::GetWordProxy), 2, true);
|
|
|
|
//6 - BYTE EA
|
|
|
|
//5 - OFFSET
|
|
|
|
//4 - EA
|
|
|
|
//3 - LOREG SHIFTED
|
|
|
|
//2 - HIREG SHIFTED
|
|
|
|
//1 - HIMASK
|
|
|
|
//0 - HIWORD
|
|
|
|
|
|
|
|
m_pB->And();
|
|
|
|
m_pB->Or();
|
|
|
|
//4 - BYTE EA
|
|
|
|
//3 - OFFSET
|
|
|
|
//2 - EA
|
|
|
|
//1 - LOREG SHIFTED
|
|
|
|
//0 - HIWORD VALUE
|
|
|
|
|
|
|
|
m_pB->PushValueAt(2);
|
|
|
|
m_pB->AddImm(4);
|
|
|
|
m_pB->Swap();
|
|
|
|
m_pB->PushRef(m_pCtx);
|
|
|
|
m_pB->Call(reinterpret_cast<void*>(&CCacheBlock::SetWordProxy), 3, false);
|
|
|
|
//3 - BYTE EA
|
|
|
|
//2 - OFFSET
|
|
|
|
//1 - EA
|
|
|
|
//0 - LOREG SHIFTED
|
|
|
|
|
|
|
|
////////////////////////
|
|
|
|
//Lower 32-bits
|
|
|
|
////////////////////////
|
|
|
|
|
|
|
|
//Get the mask for this register
|
|
|
|
m_pB->PushValueAt(2);
|
|
|
|
m_pB->Lookup(m_nSDLMaskLo);
|
|
|
|
//4 - BYTE EA
|
|
|
|
//3 - OFFSET
|
|
|
|
//2 - EA
|
|
|
|
//1 - LOREG SHIFTED
|
|
|
|
//0 - LOMASK
|
|
|
|
|
|
|
|
//Obtain the value of memory, mask, or with the value and save
|
|
|
|
m_pB->PushValueAt(2);
|
|
|
|
m_pB->PushRef(m_pCtx);
|
|
|
|
m_pB->Call(reinterpret_cast<void*>(&CCacheBlock::GetWordProxy), 2, true);
|
|
|
|
//5 - BYTE EA
|
|
|
|
//4 - OFFSET
|
|
|
|
//3 - EA
|
|
|
|
//2 - LOREG SHIFTED
|
|
|
|
//1 - LOMASK
|
|
|
|
//0 - LOWORD
|
|
|
|
|
|
|
|
m_pB->And();
|
|
|
|
m_pB->Or();
|
|
|
|
//3 - BYTE EA
|
|
|
|
//2 - OFFSET
|
|
|
|
//1 - EA
|
|
|
|
//0 - LOWORD VALUE
|
|
|
|
|
|
|
|
m_pB->PushValueAt(1);
|
|
|
|
m_pB->Swap();
|
|
|
|
m_pB->PushRef(m_pCtx);
|
|
|
|
m_pB->Call(reinterpret_cast<void*>(&CCacheBlock::SetWordProxy), 3, false);
|
|
|
|
//2 - BYTE EA
|
|
|
|
//1 - OFFSET
|
|
|
|
//0 - EA
|
|
|
|
|
|
|
|
//Done, free the stack
|
|
|
|
m_pB->Free(3);
|
|
|
|
}
|
|
|
|
|
|
|
|
//2D
|
|
|
|
void CMA_MIPSIV::SDR()
|
|
|
|
{
|
|
|
|
ComputeMemAccessAddr();
|
|
|
|
|
|
|
|
m_pB->PushValueAt(0);
|
|
|
|
m_pB->AndImm(0x00000007);
|
|
|
|
m_pB->PushValueAt(1);
|
|
|
|
m_pB->AndImm(~0x00000007);
|
|
|
|
//2 - BYTE EA
|
|
|
|
//1 - OFFSET
|
|
|
|
//0 - EA
|
|
|
|
|
|
|
|
//Get the lo/hi reg values
|
|
|
|
m_pB->PushAddr(&m_pCtx->m_State.nGPR[m_nRT].nV[0]);
|
|
|
|
m_pB->PushAddr(&m_pCtx->m_State.nGPR[m_nRT].nV[1]);
|
|
|
|
//4 - BYTE EA
|
|
|
|
//3 - OFFSET
|
|
|
|
//2 - EA
|
|
|
|
//1 - LOREG
|
|
|
|
//0 - HIREG
|
|
|
|
|
|
|
|
//Get shift the register left
|
|
|
|
m_pB->PushValueAt(3);
|
|
|
|
m_pB->Lookup(m_nSDRShift);
|
|
|
|
m_pB->Sll64();
|
|
|
|
//4 - BYTE EA
|
|
|
|
//3 - OFFSET
|
|
|
|
//2 - EA
|
|
|
|
//1 - LOREG SHIFTED
|
|
|
|
//0 - HIREG SHIFTED
|
|
|
|
|
|
|
|
////////////////////////
|
|
|
|
//Higher 32-bits
|
|
|
|
////////////////////////
|
|
|
|
|
|
|
|
//Get the mask for this register
|
|
|
|
m_pB->PushValueAt(3);
|
|
|
|
m_pB->Lookup(m_nSDRMaskHi);
|
|
|
|
//5 - BYTE EA
|
|
|
|
//4 - OFFSET
|
|
|
|
//3 - EA
|
|
|
|
//2 - LOREG SHIFTED
|
|
|
|
//1 - HIREG SHIFTED
|
|
|
|
//0 - HIMASK
|
|
|
|
|
|
|
|
//Obtain the value of memory, mask, or with the value and save
|
|
|
|
m_pB->PushValueAt(3);
|
|
|
|
m_pB->AddImm(4);
|
|
|
|
m_pB->PushRef(m_pCtx);
|
|
|
|
m_pB->Call(reinterpret_cast<void*>(&CCacheBlock::GetWordProxy), 2, true);
|
|
|
|
//6 - BYTE EA
|
|
|
|
//5 - OFFSET
|
|
|
|
//4 - EA
|
|
|
|
//3 - LOREG SHIFTED
|
|
|
|
//2 - HIREG SHIFTED
|
|
|
|
//1 - HIMASK
|
|
|
|
//0 - HIWORD
|
|
|
|
|
|
|
|
m_pB->And();
|
|
|
|
m_pB->Or();
|
|
|
|
//4 - BYTE EA
|
|
|
|
//3 - OFFSET
|
|
|
|
//2 - EA
|
|
|
|
//1 - LOREG SHIFTED
|
|
|
|
//0 - HIWORD VALUE
|
|
|
|
|
|
|
|
m_pB->PushValueAt(2);
|
|
|
|
m_pB->AddImm(4);
|
|
|
|
m_pB->Swap();
|
|
|
|
m_pB->PushRef(m_pCtx);
|
|
|
|
m_pB->Call(reinterpret_cast<void*>(&CCacheBlock::SetWordProxy), 3, false);
|
|
|
|
//3 - BYTE EA
|
|
|
|
//2 - OFFSET
|
|
|
|
//1 - EA
|
|
|
|
//0 - LOREG SHIFTED
|
|
|
|
|
|
|
|
////////////////////////
|
|
|
|
//Lower 32-bits
|
|
|
|
////////////////////////
|
|
|
|
|
|
|
|
//Get the mask for this register
|
|
|
|
m_pB->PushValueAt(2);
|
|
|
|
m_pB->Lookup(m_nSDRMaskLo);
|
|
|
|
//4 - BYTE EA
|
|
|
|
//3 - OFFSET
|
|
|
|
//2 - EA
|
|
|
|
//1 - LOREG SHIFTED
|
|
|
|
//0 - LOMASK
|
|
|
|
|
|
|
|
//Obtain the value of memory, mask, or with the value and save
|
|
|
|
m_pB->PushValueAt(2);
|
|
|
|
m_pB->PushRef(m_pCtx);
|
|
|
|
m_pB->Call(reinterpret_cast<void*>(&CCacheBlock::GetWordProxy), 2, true);
|
|
|
|
//5 - BYTE EA
|
|
|
|
//4 - OFFSET
|
|
|
|
//3 - EA
|
|
|
|
//2 - LOREG SHIFTED
|
|
|
|
//1 - LOMASK
|
|
|
|
//0 - LOWORD
|
|
|
|
|
|
|
|
m_pB->And();
|
|
|
|
m_pB->Or();
|
|
|
|
//3 - BYTE EA
|
|
|
|
//2 - OFFSET
|
|
|
|
//1 - EA
|
|
|
|
//0 - LOWORD VALUE
|
|
|
|
|
|
|
|
m_pB->PushValueAt(1);
|
|
|
|
m_pB->Swap();
|
|
|
|
m_pB->PushRef(m_pCtx);
|
|
|
|
m_pB->Call(reinterpret_cast<void*>(&CCacheBlock::SetWordProxy), 3, false);
|
|
|
|
//2 - BYTE EA
|
|
|
|
//1 - OFFSET
|
|
|
|
//0 - EA
|
|
|
|
|
|
|
|
//Done, free the stack
|
|
|
|
m_pB->Free(3);
|
|
|
|
}
|
|
|
|
|
|
|
|
//2E
|
|
|
|
void CMA_MIPSIV::SWR()
|
|
|
|
{
|
|
|
|
ComputeMemAccessAddr();
|
|
|
|
|
|
|
|
m_pB->PushValueAt(0);
|
|
|
|
m_pB->AndImm(0x00000003);
|
|
|
|
m_pB->PushValueAt(1);
|
|
|
|
m_pB->AndImm(~0x00000003);
|
|
|
|
//2 - BYTE EA
|
|
|
|
//1 - OFFSET
|
|
|
|
//0 - EA
|
|
|
|
|
|
|
|
//Get the reg value
|
|
|
|
m_pB->PushAddr(&m_pCtx->m_State.nGPR[m_nRT].nV[0]);
|
|
|
|
//3 - BYTE EA
|
|
|
|
//2 - OFFSET
|
|
|
|
//1 - EA
|
|
|
|
//0 - REG
|
|
|
|
|
|
|
|
//Get shift the register left
|
|
|
|
m_pB->PushValueAt(2);
|
|
|
|
m_pB->Lookup(m_nSWRShift);
|
|
|
|
m_pB->Sll();
|
|
|
|
//3 - BYTE EA
|
|
|
|
//2 - OFFSET
|
|
|
|
//1 - EA
|
|
|
|
//0 - REG SHIFTED
|
|
|
|
|
|
|
|
//Get the mask for this register
|
|
|
|
m_pB->PushValueAt(2);
|
|
|
|
m_pB->Lookup(m_nSWRMask);
|
|
|
|
//4 - BYTE EA
|
|
|
|
//3 - OFFSET
|
|
|
|
//2 - EA
|
|
|
|
//1 - REG SHIFTED
|
|
|
|
//0 - MASK
|
|
|
|
|
|
|
|
//Obtain the value of memory, mask, or with the value and save
|
|
|
|
m_pB->PushValueAt(2);
|
|
|
|
m_pB->PushRef(m_pCtx);
|
|
|
|
m_pB->Call(reinterpret_cast<void*>(&CCacheBlock::GetWordProxy), 2, true);
|
|
|
|
//5 - BYTE EA
|
|
|
|
//4 - OFFSET
|
|
|
|
//3 - EA
|
|
|
|
//2 - REG SHIFTED
|
|
|
|
//1 - MASK
|
|
|
|
//0 - WORD
|
|
|
|
|
|
|
|
m_pB->And();
|
|
|
|
m_pB->Or();
|
|
|
|
//3 - BYTE EA
|
|
|
|
//2 - OFFSET
|
|
|
|
//1 - EA
|
|
|
|
//0 - WORD VALUE
|
|
|
|
|
|
|
|
m_pB->PushValueAt(1);
|
|
|
|
m_pB->Swap();
|
|
|
|
m_pB->PushRef(m_pCtx);
|
|
|
|
m_pB->Call(reinterpret_cast<void*>(&CCacheBlock::SetWordProxy), 3, false);
|
|
|
|
//2 - BYTE EA
|
|
|
|
//1 - OFFSET
|
|
|
|
//0 - EA
|
|
|
|
|
|
|
|
//Done, free the stack
|
|
|
|
m_pB->Free(3);
|
|
|
|
}
|
|
|
|
|
|
|
|
//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_pB, m_pCtx, false);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Illegal();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//36
|
|
|
|
void CMA_MIPSIV::LDC2()
|
|
|
|
{
|
|
|
|
if(m_pCtx->m_pCOP[2] != NULL)
|
|
|
|
{
|
|
|
|
m_pCtx->m_pCOP[2]->CompileInstruction(m_nAddress, m_pB, m_pCtx, false);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Illegal();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//37
|
|
|
|
void CMA_MIPSIV::LD()
|
|
|
|
{
|
|
|
|
CCodeGen::Begin(m_pB);
|
|
|
|
{
|
|
|
|
ComputeMemAccessAddrEx();
|
|
|
|
|
|
|
|
for(unsigned int i = 0; i < 2; i++)
|
|
|
|
{
|
|
|
|
CCodeGen::PushRef(m_pCtx);
|
|
|
|
CCodeGen::PushIdx(1);
|
|
|
|
CCodeGen::Call(reinterpret_cast<void*>(&CCacheBlock::GetWordProxy), 2, true);
|
|
|
|
|
|
|
|
CCodeGen::PullRel(offsetof(CMIPS, m_State.nGPR[m_nRT].nV[i]));
|
|
|
|
|
|
|
|
if(i != 1)
|
|
|
|
{
|
|
|
|
CCodeGen::PushCst(4);
|
|
|
|
CCodeGen::Add();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
CCodeGen::PullTop();
|
|
|
|
}
|
|
|
|
CCodeGen::End();
|
|
|
|
}
|
|
|
|
|
|
|
|
//39
|
|
|
|
void CMA_MIPSIV::SWC1()
|
|
|
|
{
|
|
|
|
if(m_pCtx->m_pCOP[1] != NULL)
|
|
|
|
{
|
|
|
|
m_pCtx->m_pCOP[1]->CompileInstruction(m_nAddress, m_pB, m_pCtx, false);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Illegal();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//3E
|
|
|
|
void CMA_MIPSIV::SDC2()
|
|
|
|
{
|
|
|
|
if(m_pCtx->m_pCOP[2] != NULL)
|
|
|
|
{
|
|
|
|
m_pCtx->m_pCOP[2]->CompileInstruction(m_nAddress, m_pB, m_pCtx, false);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Illegal();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//3F
|
|
|
|
void CMA_MIPSIV::SD()
|
|
|
|
{
|
|
|
|
CCodeGen::Begin(m_pB);
|
|
|
|
{
|
|
|
|
ComputeMemAccessAddrEx();
|
|
|
|
|
|
|
|
for(unsigned int i = 0; i < 2; i++)
|
|
|
|
{
|
|
|
|
CCodeGen::PushRef(m_pCtx);
|
|
|
|
CCodeGen::PushRel(offsetof(CMIPS, m_State.nGPR[m_nRT].nV[i]));
|
|
|
|
CCodeGen::PushIdx(2);
|
|
|
|
CCodeGen::Call(reinterpret_cast<void*>(&CCacheBlock::SetWordProxy), 3, false);
|
|
|
|
|
|
|
|
if(i != 1)
|
|
|
|
{
|
|
|
|
CCodeGen::PushCst(4);
|
|
|
|
CCodeGen::Add();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
CCodeGen::PullTop();
|
|
|
|
}
|
|
|
|
CCodeGen::End();
|
|
|
|
}
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////
|
|
|
|
//Special Opcodes
|
|
|
|
//////////////////////////////////////////////////
|
|
|
|
|
|
|
|
//00
|
|
|
|
void CMA_MIPSIV::SLL()
|
|
|
|
{
|
|
|
|
Template_ShiftCst32()(&CCodeGen::Shl);
|
|
|
|
}
|
|
|
|
|
|
|
|
//02
|
|
|
|
void CMA_MIPSIV::SRL()
|
|
|
|
{
|
|
|
|
Template_ShiftCst32()(&CCodeGen::Srl);
|
|
|
|
}
|
|
|
|
|
|
|
|
//03
|
|
|
|
void CMA_MIPSIV::SRA()
|
|
|
|
{
|
|
|
|
Template_ShiftCst32()(&CCodeGen::Sra);
|
|
|
|
}
|
|
|
|
|
|
|
|
//04
|
|
|
|
void CMA_MIPSIV::SLLV()
|
|
|
|
{
|
|
|
|
m_pB->PushAddr(&m_pCtx->m_State.nGPR[m_nRT].nV[0]);
|
|
|
|
m_pB->PushAddr(&m_pCtx->m_State.nGPR[m_nRS].nV[0]);
|
|
|
|
m_pB->Sll();
|
|
|
|
SignExtendTop32(m_nRD);
|
|
|
|
m_pB->PullAddr(&m_pCtx->m_State.nGPR[m_nRD].nV[0]);
|
|
|
|
}
|
|
|
|
|
|
|
|
//06
|
|
|
|
void CMA_MIPSIV::SRLV()
|
|
|
|
{
|
|
|
|
m_pB->PushAddr(&m_pCtx->m_State.nGPR[m_nRT].nV[0]);
|
|
|
|
m_pB->PushAddr(&m_pCtx->m_State.nGPR[m_nRS].nV[0]);
|
|
|
|
m_pB->Srl();
|
|
|
|
SignExtendTop32(m_nRD);
|
|
|
|
m_pB->PullAddr(&m_pCtx->m_State.nGPR[m_nRD].nV[0]);
|
|
|
|
}
|
|
|
|
|
|
|
|
//07
|
|
|
|
void CMA_MIPSIV::SRAV()
|
|
|
|
{
|
|
|
|
m_pB->PushAddr(&m_pCtx->m_State.nGPR[m_nRT].nV[0]);
|
|
|
|
m_pB->PushAddr(&m_pCtx->m_State.nGPR[m_nRS].nV[0]);
|
|
|
|
m_pB->Sra();
|
|
|
|
SignExtendTop32(m_nRD);
|
|
|
|
m_pB->PullAddr(&m_pCtx->m_State.nGPR[m_nRD].nV[0]);
|
|
|
|
}
|
|
|
|
|
|
|
|
//08
|
|
|
|
void CMA_MIPSIV::JR()
|
|
|
|
{
|
|
|
|
//TODO: 64-bits addresses
|
|
|
|
CCodeGen::Begin(m_pB);
|
|
|
|
{
|
|
|
|
CCodeGen::PushRel(offsetof(CMIPS, m_State.nGPR[m_nRS].nV[0]));
|
|
|
|
CCodeGen::PullRel(offsetof(CMIPS, m_State.nDelayedJumpAddr));
|
|
|
|
|
|
|
|
m_pB->SetDelayedJumpCheck();
|
|
|
|
}
|
|
|
|
CCodeGen::End();
|
|
|
|
}
|
|
|
|
|
|
|
|
//09
|
|
|
|
void CMA_MIPSIV::JALR()
|
|
|
|
{
|
|
|
|
//TODO: 64-bits addresses
|
|
|
|
|
|
|
|
//Set the jump address
|
|
|
|
m_pB->PushAddr(&m_pCtx->m_State.nGPR[m_nRS].nV[0]);
|
|
|
|
m_pB->PullAddr(&m_pCtx->m_State.nDelayedJumpAddr);
|
|
|
|
|
|
|
|
//Save address in register
|
|
|
|
m_pB->PushAddr(&m_pCtx->m_State.nPC);
|
|
|
|
m_pB->AddImm(4);
|
|
|
|
m_pB->PullAddr(&m_pCtx->m_State.nGPR[m_nRD].nV[0]);
|
|
|
|
|
|
|
|
m_pB->SetDelayedJumpCheck();
|
|
|
|
}
|
|
|
|
|
|
|
|
//0A
|
|
|
|
void CMA_MIPSIV::MOVZ()
|
|
|
|
{
|
|
|
|
m_pB->PushAddr(&m_pCtx->m_State.nGPR[m_nRT].nV[0]);
|
|
|
|
m_pB->PushImm(0);
|
|
|
|
m_pB->Cmp(JCC_CONDITION_EQ);
|
|
|
|
|
|
|
|
m_pB->BeginJcc(true);
|
|
|
|
{
|
|
|
|
m_pB->PushAddr(&m_pCtx->m_State.nGPR[m_nRS].nV[0]);
|
|
|
|
m_pB->PullAddr(&m_pCtx->m_State.nGPR[m_nRD].nV[0]);
|
|
|
|
|
|
|
|
m_pB->PushAddr(&m_pCtx->m_State.nGPR[m_nRS].nV[1]);
|
|
|
|
m_pB->PullAddr(&m_pCtx->m_State.nGPR[m_nRD].nV[1]);
|
|
|
|
}
|
|
|
|
m_pB->EndJcc();
|
|
|
|
}
|
|
|
|
|
|
|
|
//0B
|
|
|
|
void CMA_MIPSIV::MOVN()
|
|
|
|
{
|
|
|
|
m_pB->PushAddr(&m_pCtx->m_State.nGPR[m_nRT].nV[0]);
|
|
|
|
m_pB->PushImm(0);
|
|
|
|
m_pB->Cmp(JCC_CONDITION_EQ);
|
|
|
|
|
|
|
|
m_pB->BeginJcc(false);
|
|
|
|
{
|
|
|
|
m_pB->PushAddr(&m_pCtx->m_State.nGPR[m_nRS].nV[0]);
|
|
|
|
m_pB->PullAddr(&m_pCtx->m_State.nGPR[m_nRD].nV[0]);
|
|
|
|
|
|
|
|
m_pB->PushAddr(&m_pCtx->m_State.nGPR[m_nRS].nV[1]);
|
|
|
|
m_pB->PullAddr(&m_pCtx->m_State.nGPR[m_nRD].nV[1]);
|
|
|
|
}
|
|
|
|
m_pB->EndJcc();
|
|
|
|
}
|
|
|
|
|
|
|
|
//0C
|
|
|
|
void CMA_MIPSIV::SYSCALL()
|
|
|
|
{
|
2007-11-02 21:30:00 +00:00
|
|
|
CCodeGen::Begin(m_pB);
|
|
|
|
{
|
|
|
|
CCodeGen::PushRef(m_pCtx);
|
|
|
|
CCodeGen::Call(reinterpret_cast<void*>(m_pCtx->m_pSysCallHandler), 1, false);
|
|
|
|
m_pB->SetProgramCounterChanged();
|
|
|
|
}
|
|
|
|
CCodeGen::End();
|
|
|
|
|
|
|
|
// m_pB->Call(reinterpret_cast<void*>(m_pCtx->m_pSysCallHandler), 0, false);
|
|
|
|
// m_pB->SetProgramCounterChanged();
|
2007-11-02 03:05:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//0F
|
|
|
|
void CMA_MIPSIV::SYNC()
|
|
|
|
{
|
|
|
|
//NOP
|
|
|
|
}
|
|
|
|
|
|
|
|
//10
|
|
|
|
void CMA_MIPSIV::MFHI()
|
|
|
|
{
|
|
|
|
CCodeGen::Begin(m_pB);
|
|
|
|
{
|
|
|
|
CCodeGen::PushRel(offsetof(CMIPS, m_State.nHI[0]));
|
|
|
|
CCodeGen::PullRel(offsetof(CMIPS, m_State.nGPR[m_nRD].nV[0]));
|
|
|
|
|
|
|
|
CCodeGen::PushRel(offsetof(CMIPS, m_State.nHI[1]));
|
|
|
|
CCodeGen::PullRel(offsetof(CMIPS, m_State.nGPR[m_nRD].nV[1]));
|
|
|
|
}
|
|
|
|
CCodeGen::End();
|
|
|
|
}
|
|
|
|
|
|
|
|
//11
|
|
|
|
void CMA_MIPSIV::MTHI()
|
|
|
|
{
|
|
|
|
m_pB->PushAddr(&m_pCtx->m_State.nGPR[m_nRS].nV[0]);
|
|
|
|
m_pB->PullAddr(&m_pCtx->m_State.nHI[0]);
|
|
|
|
|
|
|
|
m_pB->PushAddr(&m_pCtx->m_State.nGPR[m_nRS].nV[1]);
|
|
|
|
m_pB->PullAddr(&m_pCtx->m_State.nHI[1]);
|
|
|
|
}
|
|
|
|
|
|
|
|
//12
|
|
|
|
void CMA_MIPSIV::MFLO()
|
|
|
|
{
|
|
|
|
CCodeGen::Begin(m_pB);
|
|
|
|
{
|
|
|
|
CCodeGen::PushRel(offsetof(CMIPS, m_State.nLO[0]));
|
|
|
|
CCodeGen::PullRel(offsetof(CMIPS, m_State.nGPR[m_nRD].nV[0]));
|
|
|
|
|
|
|
|
CCodeGen::PushRel(offsetof(CMIPS, m_State.nLO[1]));
|
|
|
|
CCodeGen::PullRel(offsetof(CMIPS, m_State.nGPR[m_nRD].nV[1]));
|
|
|
|
}
|
|
|
|
CCodeGen::End();
|
|
|
|
}
|
|
|
|
|
|
|
|
//13
|
|
|
|
void CMA_MIPSIV::MTLO()
|
|
|
|
{
|
|
|
|
m_pB->PushAddr(&m_pCtx->m_State.nGPR[m_nRS].nV[0]);
|
|
|
|
m_pB->PullAddr(&m_pCtx->m_State.nLO[0]);
|
|
|
|
|
|
|
|
m_pB->PushAddr(&m_pCtx->m_State.nGPR[m_nRS].nV[1]);
|
|
|
|
m_pB->PullAddr(&m_pCtx->m_State.nLO[1]);
|
|
|
|
}
|
|
|
|
|
|
|
|
//14
|
|
|
|
void CMA_MIPSIV::DSLLV()
|
|
|
|
{
|
|
|
|
CCodeGen::Begin(m_pB);
|
|
|
|
{
|
|
|
|
CCodeGen::PushRel(offsetof(CMIPS, m_State.nGPR[m_nRT].nV[0]));
|
|
|
|
CCodeGen::PushRel(offsetof(CMIPS, m_State.nGPR[m_nRT].nV[1]));
|
|
|
|
|
|
|
|
CCodeGen::PushRel(offsetof(CMIPS, m_State.nGPR[m_nRS].nV[0]));
|
|
|
|
|
|
|
|
CCodeGen::Shl64();
|
|
|
|
|
|
|
|
CCodeGen::PullRel(offsetof(CMIPS, m_State.nGPR[m_nRD].nV[1]));
|
|
|
|
CCodeGen::PullRel(offsetof(CMIPS, m_State.nGPR[m_nRD].nV[0]));
|
|
|
|
}
|
|
|
|
CCodeGen::End();
|
|
|
|
}
|
|
|
|
|
|
|
|
//16
|
|
|
|
void CMA_MIPSIV::DSRLV()
|
|
|
|
{
|
|
|
|
CCodeGen::Begin(m_pB);
|
|
|
|
{
|
|
|
|
CCodeGen::PushRel(offsetof(CMIPS, m_State.nGPR[m_nRT].nV[0]));
|
|
|
|
CCodeGen::PushRel(offsetof(CMIPS, m_State.nGPR[m_nRT].nV[1]));
|
|
|
|
|
|
|
|
CCodeGen::PushRel(offsetof(CMIPS, m_State.nGPR[m_nRS].nV[0]));
|
|
|
|
|
|
|
|
CCodeGen::Srl64();
|
|
|
|
|
|
|
|
CCodeGen::PullRel(offsetof(CMIPS, m_State.nGPR[m_nRD].nV[1]));
|
|
|
|
CCodeGen::PullRel(offsetof(CMIPS, m_State.nGPR[m_nRD].nV[0]));
|
|
|
|
}
|
|
|
|
CCodeGen::End();
|
|
|
|
}
|
|
|
|
|
|
|
|
//18
|
|
|
|
void CMA_MIPSIV::MULT()
|
|
|
|
{
|
|
|
|
Template_Mult32()(&CCodeGen::MultS);
|
|
|
|
}
|
|
|
|
|
|
|
|
//19
|
|
|
|
void CMA_MIPSIV::MULTU()
|
|
|
|
{
|
|
|
|
m_pB->PushAddr(&m_pCtx->m_State.nGPR[m_nRS].nV[0]);
|
|
|
|
m_pB->PushAddr(&m_pCtx->m_State.nGPR[m_nRT].nV[0]);
|
|
|
|
m_pB->Mult();
|
|
|
|
|
|
|
|
m_pB->SeX32();
|
|
|
|
m_pB->PullAddr(&m_pCtx->m_State.nLO[1]);
|
|
|
|
m_pB->PullAddr(&m_pCtx->m_State.nLO[0]);
|
|
|
|
|
|
|
|
m_pB->SeX32();
|
|
|
|
m_pB->PullAddr(&m_pCtx->m_State.nHI[1]);
|
|
|
|
m_pB->PullAddr(&m_pCtx->m_State.nHI[0]);
|
|
|
|
|
|
|
|
if(m_nRD != 0)
|
|
|
|
{
|
|
|
|
//Wierd EE MIPS spinoff...
|
|
|
|
m_pB->PushAddr(&m_pCtx->m_State.nLO[0]);
|
|
|
|
SignExtendTop32(m_nRD);
|
|
|
|
m_pB->PullAddr(&m_pCtx->m_State.nGPR[m_nRD].nV[0]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//1A
|
|
|
|
void CMA_MIPSIV::DIV()
|
|
|
|
{
|
|
|
|
m_pB->PushAddr(&m_pCtx->m_State.nGPR[m_nRS].nV[0]);
|
|
|
|
m_pB->PushAddr(&m_pCtx->m_State.nGPR[m_nRT].nV[0]);
|
|
|
|
m_pB->DivS();
|
|
|
|
|
|
|
|
m_pB->SeX32();
|
|
|
|
m_pB->PullAddr(&m_pCtx->m_State.nLO[1]);
|
|
|
|
m_pB->PullAddr(&m_pCtx->m_State.nLO[0]);
|
|
|
|
|
|
|
|
m_pB->SeX32();
|
|
|
|
m_pB->PullAddr(&m_pCtx->m_State.nHI[1]);
|
|
|
|
m_pB->PullAddr(&m_pCtx->m_State.nHI[0]);
|
|
|
|
}
|
|
|
|
|
|
|
|
//1B
|
|
|
|
void CMA_MIPSIV::DIVU()
|
|
|
|
{
|
|
|
|
m_pB->PushAddr(&m_pCtx->m_State.nGPR[m_nRS].nV[0]);
|
|
|
|
m_pB->PushAddr(&m_pCtx->m_State.nGPR[m_nRT].nV[0]);
|
|
|
|
m_pB->Div();
|
|
|
|
|
|
|
|
m_pB->SeX32();
|
|
|
|
m_pB->PullAddr(&m_pCtx->m_State.nLO[1]);
|
|
|
|
m_pB->PullAddr(&m_pCtx->m_State.nLO[0]);
|
|
|
|
|
|
|
|
m_pB->SeX32();
|
|
|
|
m_pB->PullAddr(&m_pCtx->m_State.nHI[1]);
|
|
|
|
m_pB->PullAddr(&m_pCtx->m_State.nHI[0]);
|
|
|
|
}
|
|
|
|
|
|
|
|
//20
|
|
|
|
void CMA_MIPSIV::ADD()
|
|
|
|
{
|
|
|
|
CCodeGen::Begin(m_pB);
|
|
|
|
{
|
|
|
|
CCodeGen::PushVar(&m_pCtx->m_State.nGPR[m_nRS].nV[0]);
|
|
|
|
CCodeGen::PushVar(&m_pCtx->m_State.nGPR[m_nRT].nV[0]);
|
|
|
|
CCodeGen::Add();
|
|
|
|
CCodeGen::SeX();
|
|
|
|
CCodeGen::PullVar(&m_pCtx->m_State.nGPR[m_nRD].nV[1]);
|
|
|
|
CCodeGen::PullVar(&m_pCtx->m_State.nGPR[m_nRD].nV[0]);
|
|
|
|
}
|
|
|
|
CCodeGen::End();
|
|
|
|
}
|
|
|
|
|
|
|
|
//21
|
|
|
|
void CMA_MIPSIV::ADDU()
|
|
|
|
{
|
|
|
|
CCodeGen::Begin(m_pB);
|
|
|
|
{
|
|
|
|
CCodeGen::PushRel(offsetof(CMIPS, m_State.nGPR[m_nRS].nV[0]));
|
|
|
|
CCodeGen::PushRel(offsetof(CMIPS, m_State.nGPR[m_nRT].nV[0]));
|
|
|
|
|
|
|
|
CCodeGen::Add();
|
|
|
|
CCodeGen::SeX();
|
|
|
|
|
|
|
|
CCodeGen::PullRel(offsetof(CMIPS, m_State.nGPR[m_nRD].nV[1]));
|
|
|
|
CCodeGen::PullRel(offsetof(CMIPS, m_State.nGPR[m_nRD].nV[0]));
|
|
|
|
}
|
|
|
|
CCodeGen::End();
|
|
|
|
}
|
|
|
|
|
|
|
|
//23
|
|
|
|
void CMA_MIPSIV::SUBU()
|
|
|
|
{
|
|
|
|
CCodeGen::Begin(m_pB);
|
|
|
|
{
|
|
|
|
CCodeGen::PushRel(offsetof(CMIPS, m_State.nGPR[m_nRS].nV[0]));
|
|
|
|
CCodeGen::PushRel(offsetof(CMIPS, m_State.nGPR[m_nRT].nV[0]));
|
|
|
|
|
|
|
|
CCodeGen::Sub();
|
|
|
|
CCodeGen::SeX();
|
|
|
|
|
|
|
|
CCodeGen::PullRel(offsetof(CMIPS, m_State.nGPR[m_nRD].nV[1]));
|
|
|
|
CCodeGen::PullRel(offsetof(CMIPS, m_State.nGPR[m_nRD].nV[0]));
|
|
|
|
}
|
|
|
|
CCodeGen::End();
|
|
|
|
}
|
|
|
|
|
|
|
|
//24
|
|
|
|
void CMA_MIPSIV::AND()
|
|
|
|
{
|
|
|
|
CCodeGen::Begin(m_pB);
|
|
|
|
{
|
|
|
|
CCodeGen::PushRel(offsetof(CMIPS, m_State.nGPR[m_nRS].nV[0]));
|
|
|
|
CCodeGen::PushRel(offsetof(CMIPS, m_State.nGPR[m_nRS].nV[1]));
|
|
|
|
|
|
|
|
CCodeGen::PushRel(offsetof(CMIPS, m_State.nGPR[m_nRT].nV[0]));
|
|
|
|
CCodeGen::PushRel(offsetof(CMIPS, m_State.nGPR[m_nRT].nV[1]));
|
|
|
|
|
|
|
|
CCodeGen::And64();
|
|
|
|
|
|
|
|
CCodeGen::PullRel(offsetof(CMIPS, m_State.nGPR[m_nRD].nV[1]));
|
|
|
|
CCodeGen::PullRel(offsetof(CMIPS, m_State.nGPR[m_nRD].nV[0]));
|
|
|
|
}
|
|
|
|
CCodeGen::End();
|
|
|
|
}
|
|
|
|
|
|
|
|
//25
|
|
|
|
void CMA_MIPSIV::OR()
|
|
|
|
{
|
|
|
|
//TODO: Use a 64-bits op
|
|
|
|
CCodeGen::Begin(m_pB);
|
|
|
|
{
|
|
|
|
for(unsigned int i = 0; i < 2; i++)
|
|
|
|
{
|
|
|
|
CCodeGen::PushRel(offsetof(CMIPS, m_State.nGPR[m_nRS].nV[i]));
|
|
|
|
CCodeGen::PushRel(offsetof(CMIPS, m_State.nGPR[m_nRT].nV[i]));
|
|
|
|
|
|
|
|
CCodeGen::Or();
|
|
|
|
|
|
|
|
CCodeGen::PullRel(offsetof(CMIPS, m_State.nGPR[m_nRD].nV[i]));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
CCodeGen::End();
|
|
|
|
}
|
|
|
|
|
|
|
|
//26
|
|
|
|
void CMA_MIPSIV::XOR()
|
|
|
|
{
|
|
|
|
m_pB->PushAddr(&m_pCtx->m_State.nGPR[m_nRS].nV[0]);
|
|
|
|
m_pB->PushAddr(&m_pCtx->m_State.nGPR[m_nRT].nV[0]);
|
|
|
|
m_pB->Xor();
|
|
|
|
m_pB->PullAddr(&m_pCtx->m_State.nGPR[m_nRD].nV[0]);
|
|
|
|
|
|
|
|
m_pB->PushAddr(&m_pCtx->m_State.nGPR[m_nRS].nV[1]);
|
|
|
|
m_pB->PushAddr(&m_pCtx->m_State.nGPR[m_nRT].nV[1]);
|
|
|
|
m_pB->Xor();
|
|
|
|
m_pB->PullAddr(&m_pCtx->m_State.nGPR[m_nRD].nV[1]);
|
|
|
|
}
|
|
|
|
|
|
|
|
//27
|
|
|
|
void CMA_MIPSIV::NOR()
|
|
|
|
{
|
|
|
|
m_pB->PushAddr(&m_pCtx->m_State.nGPR[m_nRS].nV[0]);
|
|
|
|
m_pB->PushAddr(&m_pCtx->m_State.nGPR[m_nRT].nV[0]);
|
|
|
|
m_pB->Or();
|
|
|
|
m_pB->Not();
|
|
|
|
m_pB->PullAddr(&m_pCtx->m_State.nGPR[m_nRD].nV[0]);
|
|
|
|
|
|
|
|
m_pB->PushAddr(&m_pCtx->m_State.nGPR[m_nRS].nV[1]);
|
|
|
|
m_pB->PushAddr(&m_pCtx->m_State.nGPR[m_nRT].nV[1]);
|
|
|
|
m_pB->Or();
|
|
|
|
m_pB->Not();
|
|
|
|
m_pB->PullAddr(&m_pCtx->m_State.nGPR[m_nRD].nV[1]);
|
|
|
|
}
|
|
|
|
|
|
|
|
//2A
|
|
|
|
void CMA_MIPSIV::SLT()
|
|
|
|
{
|
|
|
|
CCodeGen::Begin(m_pB);
|
|
|
|
{
|
|
|
|
CCodeGen::PushVar(&m_pCtx->m_State.nGPR[m_nRS].nV[0]);
|
|
|
|
CCodeGen::PushVar(&m_pCtx->m_State.nGPR[m_nRS].nV[1]);
|
|
|
|
|
|
|
|
CCodeGen::PushVar(&m_pCtx->m_State.nGPR[m_nRT].nV[0]);
|
|
|
|
CCodeGen::PushVar(&m_pCtx->m_State.nGPR[m_nRT].nV[1]);
|
|
|
|
|
|
|
|
CCodeGen::Cmp64(CCodeGen::CONDITION_LT);
|
|
|
|
|
|
|
|
CCodeGen::PullVar(&m_pCtx->m_State.nGPR[m_nRD].nV[0]);
|
|
|
|
|
|
|
|
//Clear higher 32-bits
|
|
|
|
CCodeGen::PushCst(0);
|
|
|
|
CCodeGen::PullVar(&m_pCtx->m_State.nGPR[m_nRD].nV[1]);
|
|
|
|
}
|
|
|
|
CCodeGen::End();
|
|
|
|
}
|
|
|
|
|
|
|
|
//2B
|
|
|
|
void CMA_MIPSIV::SLTU()
|
|
|
|
{
|
|
|
|
CCodeGen::Begin(m_pB);
|
|
|
|
{
|
|
|
|
CCodeGen::PushRel(offsetof(CMIPS, m_State.nGPR[m_nRS].nV[0]));
|
|
|
|
CCodeGen::PushRel(offsetof(CMIPS, m_State.nGPR[m_nRS].nV[1]));
|
|
|
|
|
|
|
|
CCodeGen::PushRel(offsetof(CMIPS, m_State.nGPR[m_nRT].nV[0]));
|
|
|
|
CCodeGen::PushRel(offsetof(CMIPS, m_State.nGPR[m_nRT].nV[1]));
|
|
|
|
|
|
|
|
CCodeGen::Cmp64(CCodeGen::CONDITION_BL);
|
|
|
|
|
|
|
|
CCodeGen::PullRel(offsetof(CMIPS, m_State.nGPR[m_nRD].nV[0]));
|
|
|
|
|
|
|
|
//Clear higher 32-bits
|
|
|
|
CCodeGen::PushCst(0);
|
|
|
|
CCodeGen::PullRel(offsetof(CMIPS, m_State.nGPR[m_nRD].nV[1]));
|
|
|
|
}
|
|
|
|
CCodeGen::End();
|
|
|
|
}
|
|
|
|
|
|
|
|
//2D
|
|
|
|
void CMA_MIPSIV::DADDU()
|
|
|
|
{
|
|
|
|
CCodeGen::Begin(m_pB);
|
|
|
|
{
|
|
|
|
CCodeGen::PushRel(offsetof(CMIPS, m_State.nGPR[m_nRS].nV[0]));
|
|
|
|
CCodeGen::PushRel(offsetof(CMIPS, m_State.nGPR[m_nRS].nV[1]));
|
|
|
|
|
|
|
|
CCodeGen::PushRel(offsetof(CMIPS, m_State.nGPR[m_nRT].nV[0]));
|
|
|
|
CCodeGen::PushRel(offsetof(CMIPS, m_State.nGPR[m_nRT].nV[1]));
|
|
|
|
|
|
|
|
CCodeGen::Add64();
|
|
|
|
|
|
|
|
CCodeGen::PullRel(offsetof(CMIPS, m_State.nGPR[m_nRD].nV[1]));
|
|
|
|
CCodeGen::PullRel(offsetof(CMIPS, m_State.nGPR[m_nRD].nV[0]));
|
|
|
|
}
|
|
|
|
CCodeGen::End();
|
|
|
|
}
|
|
|
|
|
|
|
|
//2F
|
|
|
|
void CMA_MIPSIV::DSUBU()
|
|
|
|
{
|
|
|
|
//First 32-bits half
|
|
|
|
m_pB->PushAddr(&m_pCtx->m_State.nGPR[m_nRS].nV[0]);
|
|
|
|
m_pB->PushAddr(&m_pCtx->m_State.nGPR[m_nRT].nV[0]);
|
|
|
|
m_pB->SubC();
|
|
|
|
m_pB->PullAddr(&m_pCtx->m_State.nGPR[m_nRD].nV[0]);
|
|
|
|
|
|
|
|
//2nd 32-bits half
|
|
|
|
m_pB->PushAddr(&m_pCtx->m_State.nGPR[m_nRS].nV[1]);
|
|
|
|
m_pB->PushAddr(&m_pCtx->m_State.nGPR[m_nRT].nV[1]);
|
|
|
|
m_pB->Sub();
|
|
|
|
m_pB->Swap();
|
|
|
|
m_pB->Sub();
|
|
|
|
m_pB->PullAddr(&m_pCtx->m_State.nGPR[m_nRD].nV[1]);
|
|
|
|
}
|
|
|
|
|
|
|
|
//38
|
|
|
|
void CMA_MIPSIV::DSLL()
|
|
|
|
{
|
|
|
|
CCodeGen::Begin(m_pB);
|
|
|
|
{
|
|
|
|
CCodeGen::PushRel(offsetof(CMIPS, m_State.nGPR[m_nRT].nV[0]));
|
|
|
|
CCodeGen::PushRel(offsetof(CMIPS, m_State.nGPR[m_nRT].nV[1]));
|
|
|
|
|
|
|
|
CCodeGen::Shl64(m_nSA);
|
|
|
|
|
|
|
|
CCodeGen::PullRel(offsetof(CMIPS, m_State.nGPR[m_nRD].nV[1]));
|
|
|
|
CCodeGen::PullRel(offsetof(CMIPS, m_State.nGPR[m_nRD].nV[0]));
|
|
|
|
}
|
|
|
|
CCodeGen::End();
|
|
|
|
}
|
|
|
|
|
|
|
|
//3A
|
|
|
|
void CMA_MIPSIV::DSRL()
|
|
|
|
{
|
|
|
|
CCodeGen::Begin(m_pB);
|
|
|
|
{
|
|
|
|
CCodeGen::PushRel(offsetof(CMIPS, m_State.nGPR[m_nRT].nV[0]));
|
|
|
|
CCodeGen::PushRel(offsetof(CMIPS, m_State.nGPR[m_nRT].nV[1]));
|
|
|
|
|
|
|
|
CCodeGen::Srl64(m_nSA);
|
|
|
|
|
|
|
|
CCodeGen::PullRel(offsetof(CMIPS, m_State.nGPR[m_nRD].nV[1]));
|
|
|
|
CCodeGen::PullRel(offsetof(CMIPS, m_State.nGPR[m_nRD].nV[0]));
|
|
|
|
}
|
|
|
|
CCodeGen::End();
|
|
|
|
}
|
|
|
|
|
|
|
|
//3B
|
|
|
|
void CMA_MIPSIV::DSRA()
|
|
|
|
{
|
|
|
|
//TODO: Fix that! Run-time shift algorithm selection is used
|
|
|
|
m_pB->PushAddr(&m_pCtx->m_State.nGPR[m_nRT].nV[0]);
|
|
|
|
m_pB->PushAddr(&m_pCtx->m_State.nGPR[m_nRT].nV[1]);
|
|
|
|
m_pB->PushImm(m_nSA);
|
|
|
|
|
|
|
|
m_pB->Sra64();
|
|
|
|
|
|
|
|
m_pB->PullAddr(&m_pCtx->m_State.nGPR[m_nRD].nV[1]);
|
|
|
|
m_pB->PullAddr(&m_pCtx->m_State.nGPR[m_nRD].nV[0]);
|
|
|
|
}
|
|
|
|
|
|
|
|
//3C
|
|
|
|
void CMA_MIPSIV::DSLL32()
|
|
|
|
{
|
|
|
|
CCodeGen::Begin(m_pB);
|
|
|
|
{
|
|
|
|
CCodeGen::PushRel(offsetof(CMIPS, m_State.nGPR[m_nRT].nV[0]));
|
|
|
|
CCodeGen::PushRel(offsetof(CMIPS, m_State.nGPR[m_nRT].nV[1]));
|
|
|
|
|
|
|
|
CCodeGen::Shl64(m_nSA + 0x20);
|
|
|
|
|
|
|
|
CCodeGen::PullRel(offsetof(CMIPS, m_State.nGPR[m_nRD].nV[1]));
|
|
|
|
CCodeGen::PullRel(offsetof(CMIPS, m_State.nGPR[m_nRD].nV[0]));
|
|
|
|
}
|
|
|
|
CCodeGen::End();
|
|
|
|
}
|
|
|
|
|
|
|
|
//3E
|
|
|
|
void CMA_MIPSIV::DSRL32()
|
|
|
|
{
|
|
|
|
CCodeGen::Begin(m_pB);
|
|
|
|
{
|
|
|
|
CCodeGen::PushRel(offsetof(CMIPS, m_State.nGPR[m_nRT].nV[0]));
|
|
|
|
CCodeGen::PushRel(offsetof(CMIPS, m_State.nGPR[m_nRT].nV[1]));
|
|
|
|
|
|
|
|
CCodeGen::Srl64(m_nSA + 32);
|
|
|
|
|
|
|
|
CCodeGen::PullRel(offsetof(CMIPS, m_State.nGPR[m_nRD].nV[1]));
|
|
|
|
CCodeGen::PullRel(offsetof(CMIPS, m_State.nGPR[m_nRD].nV[0]));
|
|
|
|
}
|
|
|
|
CCodeGen::End();
|
|
|
|
}
|
|
|
|
|
|
|
|
//3F
|
|
|
|
void CMA_MIPSIV::DSRA32()
|
|
|
|
{
|
|
|
|
CCodeGen::Begin(m_pB);
|
|
|
|
{
|
|
|
|
CCodeGen::PushRel(offsetof(CMIPS, m_State.nGPR[m_nRT].nV[0]));
|
|
|
|
CCodeGen::PushRel(offsetof(CMIPS, m_State.nGPR[m_nRT].nV[1]));
|
|
|
|
|
|
|
|
CCodeGen::Sra64(m_nSA + 32);
|
|
|
|
|
|
|
|
CCodeGen::PullRel(offsetof(CMIPS, m_State.nGPR[m_nRD].nV[1]));
|
|
|
|
CCodeGen::PullRel(offsetof(CMIPS, m_State.nGPR[m_nRD].nV[0]));
|
|
|
|
}
|
|
|
|
CCodeGen::End();
|
|
|
|
}
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////
|
|
|
|
//Special2 Opcodes
|
|
|
|
//////////////////////////////////////////////////
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////
|
|
|
|
//RegImm Opcodes
|
|
|
|
//////////////////////////////////////////////////
|
|
|
|
|
|
|
|
//00
|
|
|
|
void CMA_MIPSIV::BLTZ()
|
|
|
|
{
|
|
|
|
m_pB->PushImm(0);
|
|
|
|
m_pB->PushAddr(&m_pCtx->m_State.nGPR[m_nRS].nV[1]);
|
|
|
|
m_pB->AndImm(0x80000000);
|
|
|
|
|
|
|
|
m_pB->Cmp(JCC_CONDITION_EQ);
|
|
|
|
|
|
|
|
Branch(false);
|
|
|
|
}
|
|
|
|
|
|
|
|
//01
|
|
|
|
void CMA_MIPSIV::BGEZ()
|
|
|
|
{
|
|
|
|
CCodeGen::Begin(m_pB);
|
|
|
|
{
|
|
|
|
CCodeGen::PushCst(0);
|
|
|
|
|
|
|
|
CCodeGen::PushRel(offsetof(CMIPS, m_State.nGPR[m_nRS].nV[1]));
|
|
|
|
CCodeGen::PushCst(0x80000000);
|
|
|
|
CCodeGen::And();
|
|
|
|
|
|
|
|
CCodeGen::Cmp(CCodeGen::CONDITION_EQ);
|
|
|
|
|
|
|
|
BranchEx(true);
|
|
|
|
}
|
|
|
|
CCodeGen::End();
|
|
|
|
}
|
|
|
|
|
|
|
|
//02
|
|
|
|
void CMA_MIPSIV::BLTZL()
|
|
|
|
{
|
|
|
|
m_pB->PushImm(0);
|
|
|
|
m_pB->PushAddr(&m_pCtx->m_State.nGPR[m_nRS].nV[1]);
|
|
|
|
m_pB->AndImm(0x80000000);
|
|
|
|
|
|
|
|
m_pB->Cmp(JCC_CONDITION_EQ);
|
|
|
|
|
|
|
|
BranchLikely(false);
|
|
|
|
}
|
|
|
|
|
|
|
|
//03
|
|
|
|
void CMA_MIPSIV::BGEZL()
|
|
|
|
{
|
|
|
|
m_pB->PushImm(0);
|
|
|
|
m_pB->PushAddr(&m_pCtx->m_State.nGPR[m_nRS].nV[1]);
|
|
|
|
m_pB->AndImm(0x80000000);
|
|
|
|
|
|
|
|
m_pB->Cmp(JCC_CONDITION_EQ);
|
|
|
|
|
|
|
|
BranchLikely(true);
|
|
|
|
}
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////
|
|
|
|
//Opcode Tables
|
|
|
|
//////////////////////////////////////////////////
|
|
|
|
|
|
|
|
void (*CMA_MIPSIV::m_pOpGeneral[0x40])() =
|
|
|
|
{
|
|
|
|
//0x00
|
|
|
|
SPECIAL, REGIMM, J, JAL, BEQ, BNE, BLEZ, BGTZ,
|
|
|
|
//0x08
|
|
|
|
ADDI, ADDIU, SLTI, SLTIU, ANDI, ORI, XORI, LUI,
|
|
|
|
//0x10
|
|
|
|
COP0, COP1, COP2, Illegal, BEQL, BNEL, BLEZL, BGTZL,
|
|
|
|
//0x18
|
|
|
|
Illegal, DADDIU, LDL, LDR, SPECIAL2, Illegal, Illegal, Illegal,
|
|
|
|
//0x20
|
|
|
|
LB, LH, LWL, LW, LBU, LHU, LWR, LWU,
|
|
|
|
//0x28
|
|
|
|
SB, SH, SWL, SW, SDL, SDR, SWR, CACHE,
|
|
|
|
//0x30
|
|
|
|
Illegal, LWC1, Illegal, Illegal, Illegal, Illegal, LDC2, LD,
|
|
|
|
//0x38
|
|
|
|
Illegal, SWC1, Illegal, Illegal, Illegal, Illegal, SDC2, SD,
|
|
|
|
};
|
|
|
|
|
|
|
|
void (*CMA_MIPSIV::m_pOpSpecial[0x40])() =
|
|
|
|
{
|
|
|
|
//0x00
|
|
|
|
SLL, Illegal, SRL, SRA, SLLV, Illegal, SRLV, SRAV,
|
|
|
|
//0x08
|
|
|
|
JR, JALR, MOVZ, MOVN, SYSCALL, Illegal, Illegal, SYNC,
|
|
|
|
//0x10
|
|
|
|
MFHI, MTHI, MFLO, MTLO, DSLLV, Illegal, DSRLV, Illegal,
|
|
|
|
//0x18
|
|
|
|
MULT, MULTU, DIV, DIVU, Illegal, Illegal, Illegal, Illegal,
|
|
|
|
//0x20
|
|
|
|
ADD, ADDU, Illegal, SUBU, AND, OR, XOR, NOR,
|
|
|
|
//0x28
|
|
|
|
Illegal, Illegal, SLT, SLTU, Illegal, DADDU, Illegal, DSUBU,
|
|
|
|
//0x30
|
|
|
|
Illegal, Illegal, Illegal, Illegal, Illegal, Illegal, Illegal, Illegal,
|
|
|
|
//0x38
|
|
|
|
DSLL, Illegal, DSRL, DSRA, DSLL32, Illegal, DSRL32, DSRA32,
|
|
|
|
};
|
|
|
|
|
|
|
|
void (*CMA_MIPSIV::m_pOpSpecial2[0x40])() =
|
|
|
|
{
|
|
|
|
//0x00
|
|
|
|
Illegal, Illegal, Illegal, Illegal, Illegal, Illegal, Illegal, Illegal,
|
|
|
|
//0x08
|
|
|
|
Illegal, Illegal, Illegal, Illegal, Illegal, Illegal, Illegal, Illegal,
|
|
|
|
//0x10
|
|
|
|
Illegal, Illegal, Illegal, Illegal, Illegal, Illegal, Illegal, Illegal,
|
|
|
|
//0x18
|
|
|
|
Illegal, Illegal, Illegal, Illegal, Illegal, Illegal, Illegal, Illegal,
|
|
|
|
//0x20
|
|
|
|
Illegal, Illegal, Illegal, Illegal, Illegal, Illegal, Illegal, Illegal,
|
|
|
|
//0x28
|
|
|
|
Illegal, Illegal, Illegal, Illegal, Illegal, Illegal, Illegal, Illegal,
|
|
|
|
//0x30
|
|
|
|
Illegal, Illegal, Illegal, Illegal, Illegal, Illegal, Illegal, Illegal,
|
|
|
|
//0x38
|
|
|
|
Illegal, Illegal, Illegal, Illegal, Illegal, Illegal, Illegal, Illegal,
|
|
|
|
};
|
|
|
|
|
|
|
|
void (*CMA_MIPSIV::m_pOpRegImm[0x20])() =
|
|
|
|
{
|
|
|
|
//0x00
|
|
|
|
BLTZ, BGEZ, BLTZL, BGEZL, Illegal, Illegal, Illegal, Illegal,
|
|
|
|
//0x08
|
|
|
|
Illegal, Illegal, Illegal, Illegal, Illegal, Illegal, Illegal, Illegal,
|
|
|
|
//0x10
|
|
|
|
Illegal, Illegal, Illegal, Illegal, Illegal, Illegal, Illegal, Illegal,
|
|
|
|
//0x18
|
|
|
|
Illegal, Illegal, Illegal, Illegal, Illegal, Illegal, Illegal, Illegal,
|
|
|
|
};
|