2007-12-27 20:35:09 +00:00
|
|
|
#include <assert.h>
|
|
|
|
#include <stddef.h>
|
|
|
|
#include "MIPSInstructionFactory.h"
|
|
|
|
#include "MIPS.h"
|
|
|
|
#include "offsetof_def.h"
|
2019-04-25 17:58:16 -04:00
|
|
|
#include "BitManip.h"
|
2020-08-04 13:29:59 -04:00
|
|
|
#include "COP_SCU.h"
|
2007-12-27 20:35:09 +00:00
|
|
|
|
2023-02-27 15:08:49 -05:00
|
|
|
extern "C" void TrapHandler(CMIPS* context)
|
|
|
|
{
|
|
|
|
//This is just a way to inspect state when traps are happening
|
|
|
|
assert(false && "Unhandled trap.");
|
|
|
|
}
|
|
|
|
|
2012-03-18 19:45:26 +00:00
|
|
|
CMIPSInstructionFactory::CMIPSInstructionFactory(MIPS_REGSIZE nRegSize)
|
2018-04-30 21:01:23 +01:00
|
|
|
: m_regSize(nRegSize)
|
2007-12-27 20:35:09 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2022-10-18 20:01:20 +01:00
|
|
|
void CMIPSInstructionFactory::SetupQuickVariables(uint32 nAddress, CMipsJitter* codeGen, CMIPS* pCtx, uint32 instrPosition)
|
2007-12-27 20:35:09 +00:00
|
|
|
{
|
2018-04-30 21:01:23 +01:00
|
|
|
m_pCtx = pCtx;
|
|
|
|
m_codeGen = codeGen;
|
|
|
|
m_nAddress = nAddress;
|
2022-10-18 20:01:20 +01:00
|
|
|
m_instrPosition = instrPosition;
|
2007-12-27 20:35:09 +00:00
|
|
|
|
2018-04-30 21:01:23 +01:00
|
|
|
m_nOpcode = m_pCtx->m_pMemoryMap->GetInstruction(m_nAddress);
|
2007-12-27 20:35:09 +00:00
|
|
|
}
|
|
|
|
|
2020-08-04 13:29:59 -04:00
|
|
|
static void HandleTLBException(CMIPS*)
|
|
|
|
{
|
|
|
|
//Will exit CPU execution loop with an exception pending
|
|
|
|
}
|
|
|
|
|
|
|
|
void CMIPSInstructionFactory::CheckTLBExceptions(bool isWrite)
|
|
|
|
{
|
|
|
|
if(m_pCtx->m_pAddrTranslator == &CMIPS::TranslateAddress64) return;
|
|
|
|
if(m_pCtx->m_TLBExceptionChecker == nullptr) return;
|
|
|
|
|
|
|
|
uint8 nRS = (uint8)((m_nOpcode >> 21) & 0x001F);
|
|
|
|
uint16 nImmediate = (uint16)((m_nOpcode >> 0) & 0xFFFF);
|
|
|
|
|
|
|
|
//Push context
|
|
|
|
m_codeGen->PushCtx();
|
|
|
|
|
|
|
|
//Push low part of address
|
|
|
|
m_codeGen->PushRel(offsetof(CMIPS, m_State.nGPR[nRS].nV[0]));
|
|
|
|
if(nImmediate != 0)
|
|
|
|
{
|
|
|
|
m_codeGen->PushCst((int16)nImmediate);
|
|
|
|
m_codeGen->Add();
|
|
|
|
}
|
|
|
|
|
|
|
|
//Push isWrite
|
|
|
|
m_codeGen->PushCst(isWrite ? 1 : 0);
|
|
|
|
|
|
|
|
//Call
|
2024-01-17 17:00:22 -05:00
|
|
|
m_codeGen->Call(reinterpret_cast<void*>(m_pCtx->m_TLBExceptionChecker), 3, Jitter::CJitter::RETURN_VALUE_32);
|
2020-08-04 13:29:59 -04:00
|
|
|
|
|
|
|
m_codeGen->PushCst(MIPS_EXCEPTION_NONE);
|
|
|
|
m_codeGen->BeginIf(Jitter::CONDITION_NE);
|
|
|
|
{
|
2022-10-18 20:01:36 +01:00
|
|
|
m_codeGen->PushRel(offsetof(CMIPS, m_State.nPC));
|
|
|
|
m_codeGen->PushCst(m_instrPosition);
|
|
|
|
m_codeGen->Add();
|
2020-08-04 13:29:59 -04:00
|
|
|
m_codeGen->PullRel(offsetof(CMIPS, m_State.nCOP0[CCOP_SCU::EPC]));
|
|
|
|
m_codeGen->JumpTo(reinterpret_cast<void*>(&HandleTLBException));
|
|
|
|
}
|
|
|
|
m_codeGen->EndIf();
|
|
|
|
}
|
|
|
|
|
2023-02-27 15:08:49 -05:00
|
|
|
void CMIPSInstructionFactory::CheckTrap()
|
|
|
|
{
|
|
|
|
m_codeGen->PushCst(0);
|
|
|
|
m_codeGen->BeginIf(Jitter::CONDITION_NE);
|
|
|
|
{
|
|
|
|
m_codeGen->PushCtx();
|
|
|
|
m_codeGen->Call(reinterpret_cast<void*>(&TrapHandler), 1, Jitter::CJitter::RETURN_VALUE_NONE);
|
|
|
|
}
|
|
|
|
m_codeGen->EndIf();
|
|
|
|
}
|
|
|
|
|
2007-12-27 20:35:09 +00:00
|
|
|
void CMIPSInstructionFactory::ComputeMemAccessAddr()
|
|
|
|
{
|
2018-04-30 21:01:23 +01:00
|
|
|
uint8 nRS = (uint8)((m_nOpcode >> 21) & 0x001F);
|
|
|
|
uint16 nImmediate = (uint16)((m_nOpcode >> 0) & 0xFFFF);
|
2007-12-27 20:35:09 +00:00
|
|
|
|
2010-08-11 03:47:19 +00:00
|
|
|
if(m_pCtx->m_pAddrTranslator == &CMIPS::TranslateAddress64)
|
|
|
|
{
|
|
|
|
m_codeGen->PushRel(offsetof(CMIPS, m_State.nGPR[nRS].nV[0]));
|
|
|
|
if(nImmediate != 0)
|
|
|
|
{
|
|
|
|
m_codeGen->PushCst((int16)nImmediate);
|
|
|
|
m_codeGen->Add();
|
|
|
|
}
|
|
|
|
m_codeGen->PushCst(0x1FFFFFFF);
|
|
|
|
m_codeGen->And();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
//TODO: Compute the complete 64-bit address
|
2007-12-27 20:35:09 +00:00
|
|
|
|
2010-08-11 03:47:19 +00:00
|
|
|
//Translate the address
|
2007-12-27 20:35:09 +00:00
|
|
|
|
2010-08-11 03:47:19 +00:00
|
|
|
//Push context
|
|
|
|
m_codeGen->PushCtx();
|
2007-12-27 20:35:09 +00:00
|
|
|
|
2010-08-11 03:47:19 +00:00
|
|
|
//Push low part of address
|
|
|
|
m_codeGen->PushRel(offsetof(CMIPS, m_State.nGPR[nRS].nV[0]));
|
|
|
|
if(nImmediate != 0)
|
|
|
|
{
|
|
|
|
m_codeGen->PushCst((int16)nImmediate);
|
|
|
|
m_codeGen->Add();
|
|
|
|
}
|
2007-12-27 20:35:09 +00:00
|
|
|
|
2010-08-11 03:47:19 +00:00
|
|
|
//Call
|
2024-01-17 17:00:22 -05:00
|
|
|
m_codeGen->Call(reinterpret_cast<void*>(m_pCtx->m_pAddrTranslator), 2, Jitter::CJitter::RETURN_VALUE_32);
|
2010-08-11 03:47:19 +00:00
|
|
|
}
|
2007-12-27 20:35:09 +00:00
|
|
|
}
|
|
|
|
|
2016-07-16 21:32:23 -04:00
|
|
|
void CMIPSInstructionFactory::ComputeMemAccessAddrNoXlat()
|
|
|
|
{
|
2018-08-27 08:50:35 -04:00
|
|
|
uint8 nRS = (uint8)((m_nOpcode >> 21) & 0x001F);
|
|
|
|
uint16 nImmediate = (uint16)((m_nOpcode >> 0) & 0xFFFF);
|
2016-07-16 21:32:23 -04:00
|
|
|
|
|
|
|
//Push low part of address
|
|
|
|
m_codeGen->PushRel(offsetof(CMIPS, m_State.nGPR[nRS].nV[0]));
|
|
|
|
if(nImmediate != 0)
|
|
|
|
{
|
|
|
|
m_codeGen->PushCst((int16)nImmediate);
|
|
|
|
m_codeGen->Add();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-07-21 16:22:15 -04:00
|
|
|
void CMIPSInstructionFactory::ComputeMemAccessRefIdx(uint32 accessSize)
|
2016-07-16 21:32:23 -04:00
|
|
|
{
|
|
|
|
ComputeMemAccessPageRef();
|
|
|
|
|
2018-08-27 08:50:35 -04:00
|
|
|
auto rs = static_cast<uint8>((m_nOpcode >> 21) & 0x001F);
|
|
|
|
auto immediate = static_cast<uint16>((m_nOpcode >> 0) & 0xFFFF);
|
2016-07-16 21:32:23 -04:00
|
|
|
|
|
|
|
m_codeGen->PushRel(offsetof(CMIPS, m_State.nGPR[rs].nV[0]));
|
|
|
|
m_codeGen->PushCst(static_cast<int16>(immediate));
|
|
|
|
m_codeGen->Add();
|
2019-04-25 17:38:49 -04:00
|
|
|
m_codeGen->PushCst(MIPS_PAGE_SIZE - accessSize);
|
2016-07-16 21:32:23 -04:00
|
|
|
m_codeGen->And();
|
|
|
|
}
|
|
|
|
|
|
|
|
void CMIPSInstructionFactory::ComputeMemAccessPageRef()
|
|
|
|
{
|
2018-08-27 08:50:35 -04:00
|
|
|
auto rs = static_cast<uint8>((m_nOpcode >> 21) & 0x001F);
|
2022-11-11 15:25:51 -05:00
|
|
|
auto immediate = static_cast<int16>((m_nOpcode >> 0) & 0xFFFF);
|
|
|
|
constexpr int32 pageSizeShift = Framework::GetPowerOf2(MIPS_PAGE_SIZE);
|
2019-04-12 13:10:27 -04:00
|
|
|
m_codeGen->PushRelRef(offsetof(CMIPS, m_pageLookup));
|
2016-07-16 21:32:23 -04:00
|
|
|
|
|
|
|
m_codeGen->PushRel(offsetof(CMIPS, m_State.nGPR[rs].nV[0]));
|
2022-11-11 15:25:51 -05:00
|
|
|
m_codeGen->PushCst(immediate);
|
2016-07-16 21:32:23 -04:00
|
|
|
m_codeGen->Add();
|
2023-07-21 14:49:00 -04:00
|
|
|
m_codeGen->Srl(pageSizeShift); //Divide by MIPS_PAGE_SIZE
|
|
|
|
m_codeGen->LoadRefFromRefIdx();
|
2016-07-16 21:32:23 -04:00
|
|
|
}
|
|
|
|
|
2010-08-11 03:47:19 +00:00
|
|
|
void CMIPSInstructionFactory::Branch(Jitter::CONDITION condition)
|
2007-12-27 20:35:09 +00:00
|
|
|
{
|
|
|
|
uint16 nImmediate = (uint16)(m_nOpcode & 0xFFFF);
|
|
|
|
|
|
|
|
m_codeGen->PushCst(MIPS_INVALID_PC);
|
|
|
|
m_codeGen->PullRel(offsetof(CMIPS, m_State.nDelayedJumpAddr));
|
|
|
|
|
2010-08-11 03:47:19 +00:00
|
|
|
m_codeGen->BeginIf(condition);
|
2007-12-27 20:35:09 +00:00
|
|
|
{
|
2022-10-18 20:01:36 +01:00
|
|
|
m_codeGen->PushRel(offsetof(CMIPS, m_State.nPC));
|
|
|
|
m_codeGen->PushCst((m_instrPosition + 4) + CMIPS::GetBranch(nImmediate));
|
|
|
|
m_codeGen->Add();
|
2007-12-27 20:35:09 +00:00
|
|
|
m_codeGen->PullRel(offsetof(CMIPS, m_State.nDelayedJumpAddr));
|
|
|
|
}
|
|
|
|
m_codeGen->EndIf();
|
|
|
|
}
|
|
|
|
|
2010-08-11 03:47:19 +00:00
|
|
|
void CMIPSInstructionFactory::BranchLikely(Jitter::CONDITION condition)
|
2007-12-27 20:35:09 +00:00
|
|
|
{
|
|
|
|
uint16 nImmediate = (uint16)(m_nOpcode & 0xFFFF);
|
|
|
|
|
|
|
|
m_codeGen->PushCst(MIPS_INVALID_PC);
|
|
|
|
m_codeGen->PullRel(offsetof(CMIPS, m_State.nDelayedJumpAddr));
|
|
|
|
|
2010-08-11 03:47:19 +00:00
|
|
|
m_codeGen->BeginIf(condition);
|
2007-12-27 20:35:09 +00:00
|
|
|
{
|
2022-10-18 20:01:36 +01:00
|
|
|
m_codeGen->PushRel(offsetof(CMIPS, m_State.nPC));
|
|
|
|
m_codeGen->PushCst((m_instrPosition + 4) + CMIPS::GetBranch(nImmediate));
|
|
|
|
m_codeGen->Add();
|
2007-12-27 20:35:09 +00:00
|
|
|
m_codeGen->PullRel(offsetof(CMIPS, m_State.nDelayedJumpAddr));
|
|
|
|
}
|
2010-08-11 03:47:19 +00:00
|
|
|
m_codeGen->Else();
|
2007-12-27 20:35:09 +00:00
|
|
|
{
|
2022-11-30 17:25:50 -05:00
|
|
|
m_codeGen->Goto(m_codeGen->GetLastBlockLabel());
|
2007-12-27 20:35:09 +00:00
|
|
|
}
|
|
|
|
m_codeGen->EndIf();
|
|
|
|
}
|
|
|
|
|
|
|
|
void CMIPSInstructionFactory::Illegal()
|
|
|
|
{
|
2015-05-03 03:05:54 -04:00
|
|
|
#ifdef _DEBUG
|
2018-05-02 12:34:49 -04:00
|
|
|
m_codeGen->Break();
|
2015-05-03 03:05:54 -04:00
|
|
|
#endif
|
2007-12-27 20:35:09 +00:00
|
|
|
}
|