project64/Source/Project64-rsp-core/Recompiler/RspRecompilerOps-x64.cpp

1197 lines
31 KiB
C++

#if defined(__amd64__) || defined(_M_X64)
#include "RspRecompilerOps-x64.h"
#include <Common/StdString.h>
#include <Project64-rsp-core/Recompiler/RspAssembler.h>
#include <Project64-rsp-core/Recompiler/RspCodeBlock.h>
#include <Project64-rsp-core/Recompiler/RspProfiling.h>
#include <Project64-rsp-core/cpu/RSPInstruction.h>
#include <Project64-rsp-core/cpu/RspSystem.h>
#include <Settings/Settings.h>
extern p_Recompfunc RSP_Recomp_RegImm[32];
extern p_Recompfunc RSP_Recomp_Special[64];
extern p_Recompfunc RSP_Recomp_Cop0[32];
extern p_Recompfunc RSP_Recomp_Cop2[32];
extern p_Recompfunc RSP_Recomp_Vector[64];
extern p_Recompfunc RSP_Recomp_Lc2[32];
extern p_Recompfunc RSP_Recomp_Sc2[32];
uint32_t BranchCompare = 0;
CRSPRecompilerOps::CRSPRecompilerOps(CRSPSystem & System, CRSPRecompiler & Recompiler) :
m_System(System),
m_Recompiler(Recompiler),
m_OpCode(Recompiler.m_OpCode),
m_CompilePC(Recompiler.m_CompilePC),
m_CurrentBlock(Recompiler.m_CurrentBlock),
m_NextInstruction(Recompiler.m_NextInstruction),
m_Reg(System.m_Reg),
m_GPR(System.m_Reg.m_GPR),
m_Assembler(Recompiler.m_Assembler),
m_DelayAffectBranch(false)
{
}
void CRSPRecompilerOps::Cheat_r4300iOpcode(RSPOp::Func FunctAddress, const char * FunctName)
{
m_Recompiler.Log(" %X %s", m_CompilePC, RSPInstruction(m_CompilePC, m_OpCode.Value).NameAndParam().c_str());
m_Assembler->MoveConstToVariable(&m_System.m_OpCode.Value, "m_OpCode.Value", m_OpCode.Value);
m_Assembler->CallThis(&RSPSystem.m_Op, AddressOf(FunctAddress), FunctName);
}
// Opcode functions
void CRSPRecompilerOps::SPECIAL(void)
{
(this->*RSP_Recomp_Special[m_OpCode.funct])();
}
void CRSPRecompilerOps::REGIMM(void)
{
(this->*RSP_Recomp_RegImm[m_OpCode.rt])();
}
void CRSPRecompilerOps::J(void)
{
if (m_NextInstruction == RSPPIPELINE_NORMAL)
{
m_Recompiler.Log(" %X %s", m_CompilePC, RSPInstruction(m_CompilePC, m_OpCode.Value).NameAndParam().c_str());
m_NextInstruction = RSPPIPELINE_DO_DELAY_SLOT;
}
else if (m_NextInstruction == RSPPIPELINE_DELAY_SLOT_DONE)
{
uint32_t Target = (m_OpCode.target << 2) & 0x1FFC;
asmjit::Label Jump;
if (m_CurrentBlock->IsEnd(m_CompilePC) && m_CurrentBlock->CodeType() == RspCodeType_TASK)
{
m_Assembler->MoveConstToVariable(m_System.m_SP_PC_REG, "RSP PC", Target);
ExitCodeBlock();
}
else if (m_Recompiler.FindBranchJump(Target, Jump))
{
m_Assembler->JmpLabel(stdstr_f("0x%X", Target).c_str(), Jump);
}
else
{
g_Notify->BreakPoint(__FILE__, __LINE__);
}
#ifdef tofix
#if defined(__amd64__) || defined(_M_X64)
if (CRSPSettings::CPUMethod() == RSPCpuMethod::RecompilerTasks && m_OpCode.Value == EndHleTaskOp::J_0x1118)
{
m_NextInstruction = RSPPIPELINE_DO_DELAY_SLOT_TASK_EXIT;
}
#endif
JmpLabel32("BranchToJump", 0);
m_Recompiler.Branch_AddRef((m_OpCode.target << 2) & 0xFFC, (uint32_t *)(RecompPos - 4));
m_NextInstruction = RSPPIPELINE_FINISH_SUB_BLOCK;
#endif
}
else if (m_NextInstruction == RSPPIPELINE_DELAY_SLOT_EXIT_DONE || m_NextInstruction == RSPPIPELINE_DELAY_SLOT_TASK_EXIT_DONE)
{
g_Notify->BreakPoint(__FILE__, __LINE__);
#ifdef tofix
MoveConstToVariable((m_OpCode.target << 2) & 0xFFC, m_System.m_SP_PC_REG, "RSP PC");
m_NextInstruction = m_NextInstruction == RSPPIPELINE_DELAY_SLOT_EXIT_DONE ? RSPPIPELINE_FINISH_SUB_BLOCK : RSPPIPELINE_FINISH_TASK_SUB_BLOCK;
Ret();
#endif
}
else
{
g_Notify->BreakPoint(__FILE__, __LINE__);
#ifdef tofix
CompilerWarning(stdstr_f("J error\nWeird Delay Slot.\n\nNextInstruction = %X\nEmulation will now stop", m_NextInstruction).c_str());
BreakPoint();
#endif
}
}
void CRSPRecompilerOps::JAL(void)
{
if (m_NextInstruction == RSPPIPELINE_NORMAL)
{
m_Recompiler.Log(" %X %s", m_CompilePC, RSPInstruction(m_CompilePC, m_OpCode.Value).NameAndParam().c_str());
m_Assembler->MoveConstToVariable(&m_GPR[31].UW, "RA.W", (m_CompilePC + 8) & 0x1FFC);
m_NextInstruction = RSPPIPELINE_DO_DELAY_SLOT;
}
else if (m_NextInstruction == RSPPIPELINE_DELAY_SLOT_DONE)
{
uint32_t targetAddress = (m_OpCode.target << 2) & 0x1FFC;
const RspCodeBlock * FunctionBlock = m_CurrentBlock ? m_CurrentBlock->GetFunctionBlock(targetAddress) : nullptr;
if (FunctionBlock != nullptr)
{
m_Assembler->CallFunc(FunctionBlock->GetCompiledLocation(), stdstr_f("0x%X", targetAddress).c_str());
}
else
{
g_Notify->BreakPoint(__FILE__, __LINE__);
}
}
else
{
g_Notify->BreakPoint(__FILE__, __LINE__);
//CompilerWarning(stdstr_f("J error\nWeird Delay Slot.\n\nNextInstruction = %X\nEmulation will now stop", m_NextInstruction).c_str());
//BreakPoint();
}
}
void CRSPRecompilerOps::BEQ(void)
{
if (m_NextInstruction == RSPPIPELINE_NORMAL)
{
RSPInstruction Instruction(m_CompilePC, m_OpCode.Value);
m_Recompiler.Log(" %X %s", m_CompilePC, Instruction.NameAndParam().c_str());
m_DelayAffectBranch = Instruction.DelaySlotAffectBranch();
if (!m_DelayAffectBranch)
{
m_NextInstruction = RSPPIPELINE_DO_DELAY_SLOT;
return;
}
if (m_OpCode.rt == 0)
{
m_Assembler->CompConstToVariable(&m_GPR[m_OpCode.rs].W, GPR_Name(m_OpCode.rs), 0);
}
else if (m_OpCode.rs == 0)
{
m_Assembler->CompConstToVariable(&m_GPR[m_OpCode.rt].W, GPR_Name(m_OpCode.rt), 0);
}
else
{
m_Assembler->MoveVariableToX86reg(asmjit::x86::r11, &m_GPR[m_OpCode.rt].W, GPR_Name(m_OpCode.rt));
m_Assembler->CompX86regToVariable(&m_GPR[m_OpCode.rs].W, GPR_Name(m_OpCode.rs), asmjit::x86::r11);
}
m_Assembler->SetzVariable(&BranchCompare, "BranchCompare");
m_NextInstruction = RSPPIPELINE_DO_DELAY_SLOT;
}
else if (m_NextInstruction == RSPPIPELINE_DELAY_SLOT_DONE)
{
uint32_t Target = (m_CompilePC + ((short)m_OpCode.offset << 2) + 4) & 0x1FFC;
if (m_OpCode.rs == 0 && m_OpCode.rt == 0)
{
g_Notify->BreakPoint(__FILE__, __LINE__);
#ifdef tofix
JmpLabel32("BranchToJump", 0);
m_Recompiler.Branch_AddRef(Target, (uint32_t *)(RecompPos - 4));
m_NextInstruction = RSPPIPELINE_FINISH_SUB_BLOCK;
#endif
return;
}
if (m_OpCode.rs == 0 && m_OpCode.rt == 0)
{
return;
}
if (!m_DelayAffectBranch)
{
if (m_OpCode.rt == 0)
{
m_Assembler->CompConstToVariable(&m_GPR[m_OpCode.rs].W, GPR_Name(m_OpCode.rs), 0);
}
else if (m_OpCode.rs == 0)
{
m_Assembler->CompConstToVariable(&m_GPR[m_OpCode.rt].W, GPR_Name(m_OpCode.rt), 0);
}
else
{
g_Notify->BreakPoint(__FILE__, __LINE__);
#ifdef tofix
m_Assembler->MoveVariableToX86reg(&m_GPR[m_OpCode.rt].W, GPR_Name(m_OpCode.rt), x86_EAX);
m_Assembler->CompX86regToVariable(x86_EAX, &m_GPR[m_OpCode.rs].W, GPR_Name(m_OpCode.rs));
#endif
}
if (Target == m_CurrentBlock->GetEndBlockAddress())
{
asmjit::Label ContinueLabel = m_Assembler->newLabel();
m_Assembler->JneLabel(stdstr_f("Continue-%X", m_CompilePC).c_str(), ContinueLabel);
m_Assembler->MoveConstToVariable(m_System.m_SP_PC_REG, "RSP PC", Target);
ExitCodeBlock();
m_Assembler->bind(ContinueLabel);
}
else
{
asmjit::Label Jump;
if (!m_Recompiler.FindBranchJump(Target, Jump))
{
g_Notify->BreakPoint(__FILE__, __LINE__);
}
m_Assembler->JeLabel(stdstr_f("0x%X", Target).c_str(), Jump);
}
}
else
{
asmjit::Label Jump;
if (!m_Recompiler.FindBranchJump(Target, Jump))
{
g_Notify->BreakPoint(__FILE__, __LINE__);
}
m_Assembler->CompConstToVariable(&BranchCompare, "BranchCompare", true);
m_Assembler->JeLabel(stdstr_f("0x%X", Target).c_str(), Jump);
}
}
else if (m_NextInstruction == RSPPIPELINE_DELAY_SLOT_EXIT_DONE)
{
g_Notify->BreakPoint(__FILE__, __LINE__);
#ifdef tofix
uint32_t Target = (m_CompilePC + ((short)m_OpCode.offset << 2) + 4) & 0xFFC;
CompileBranchExit(Target, m_CompilePC + 8);
#endif
}
else
{
g_Notify->BreakPoint(__FILE__, __LINE__);
#ifdef tofix
CompilerWarning(stdstr_f("BNE error\nWeird Delay Slot.\n\nNextInstruction = %X\nEmulation will now stop", m_NextInstruction).c_str());
BreakPoint();
#endif
}
}
void CRSPRecompilerOps::BNE(void)
{
if (m_NextInstruction == RSPPIPELINE_NORMAL)
{
RSPInstruction Instruction(m_CompilePC, m_OpCode.Value);
m_Recompiler.Log(" %X %s", m_CompilePC, Instruction.NameAndParam().c_str());
m_DelayAffectBranch = Instruction.DelaySlotAffectBranch();
if (!m_DelayAffectBranch)
{
m_NextInstruction = RSPPIPELINE_DO_DELAY_SLOT;
return;
}
g_Notify->BreakPoint(__FILE__, __LINE__);
#ifdef tofix
if (m_OpCode.rs == 0 && m_OpCode.rt == 0)
{
MoveConstByteToVariable(0, &BranchCompare, "BranchCompare");
m_NextInstruction = RSPPIPELINE_DO_DELAY_SLOT;
return;
}
if (m_OpCode.rt == 0)
{
CompConstToVariable(0, &m_GPR[m_OpCode.rs].W, GPR_Name(m_OpCode.rs));
}
else if (m_OpCode.rs == 0)
{
CompConstToVariable(0, &m_GPR[m_OpCode.rt].W, GPR_Name(m_OpCode.rt));
}
else
{
MoveVariableToX86reg(&m_GPR[m_OpCode.rt].W, GPR_Name(m_OpCode.rt), x86_EAX);
CompX86regToVariable(x86_EAX, &m_GPR[m_OpCode.rs].W, GPR_Name(m_OpCode.rs));
}
SetnzVariable(&BranchCompare, "BranchCompare");
m_NextInstruction = RSPPIPELINE_DO_DELAY_SLOT;
#endif
}
else if (m_NextInstruction == RSPPIPELINE_DELAY_SLOT_DONE)
{
uint32_t Target = (m_CompilePC + ((short)m_OpCode.offset << 2) + 4) & 0x1FFC;
if (m_OpCode.rs == 0 && m_OpCode.rt == 0)
{
return;
}
if (!m_DelayAffectBranch)
{
if (m_OpCode.rt == 0)
{
m_Assembler->CompConstToVariable(&m_GPR[m_OpCode.rs].W, GPR_Name(m_OpCode.rs), 0);
}
else if (m_OpCode.rs == 0)
{
m_Assembler->CompConstToVariable(&m_GPR[m_OpCode.rt].W, GPR_Name(m_OpCode.rt), 0);
}
else
{
g_Notify->BreakPoint(__FILE__, __LINE__);
#ifdef tofix
MoveVariableToX86reg(&m_GPR[m_OpCode.rt].W, GPR_Name(m_OpCode.rt), x86_EAX);
CompX86regToVariable(x86_EAX, &m_GPR[m_OpCode.rs].W, GPR_Name(m_OpCode.rs));
#endif
}
asmjit::Label Jump;
if (!m_Recompiler.FindBranchJump(Target, Jump))
{
g_Notify->BreakPoint(__FILE__, __LINE__);
}
m_Assembler->JneLabel(stdstr_f("0x%X", Target).c_str(), Jump);
}
else
{
g_Notify->BreakPoint(__FILE__, __LINE__);
#ifdef tofix
// Take a look at the branch compare variable
CompConstToVariable(true, &BranchCompare, "BranchCompare");
JeLabel32("BranchNotEqual", 0);
#endif
}
}
else if (m_NextInstruction == RSPPIPELINE_DELAY_SLOT_EXIT_DONE)
{
g_Notify->BreakPoint(__FILE__, __LINE__);
#ifdef tofix
uint32_t Target = (m_CompilePC + ((short)m_OpCode.offset << 2) + 4) & 0xFFC;
CompileBranchExit(Target, m_CompilePC + 8);
#endif
}
else
{
g_Notify->BreakPoint(__FILE__, __LINE__);
#ifdef tofix
CompilerWarning(stdstr_f("BNE error\nWeird Delay Slot.\n\nNextInstruction = %X\nEmulation will now stop", m_NextInstruction).c_str());
BreakPoint();
#endif
}
}
void CRSPRecompilerOps::BLEZ(void)
{
if (m_NextInstruction == RSPPIPELINE_NORMAL)
{
RSPInstruction Instruction(m_CompilePC, m_OpCode.Value);
m_Recompiler.Log(" %X %s", m_CompilePC, Instruction.NameAndParam().c_str());
if (m_OpCode.rs == 0)
{
m_DelayAffectBranch = false;
m_NextInstruction = RSPPIPELINE_DO_DELAY_SLOT;
return;
}
m_DelayAffectBranch = Instruction.DelaySlotAffectBranch();
if (!m_DelayAffectBranch)
{
m_NextInstruction = RSPPIPELINE_DO_DELAY_SLOT;
return;
}
g_Notify->BreakPoint(__FILE__, __LINE__);
#ifdef tofix
CompConstToVariable(0, &m_GPR[m_OpCode.rs].W, GPR_Name(m_OpCode.rs));
SetleVariable(&BranchCompare, "BranchCompare");
m_NextInstruction = RSPPIPELINE_DO_DELAY_SLOT;
#endif
}
else if (m_NextInstruction == RSPPIPELINE_DELAY_SLOT_DONE)
{
uint32_t Target = (m_CompilePC + ((short)m_OpCode.offset << 2) + 4) & 0x1FFC;
if (m_OpCode.rs == 0)
{
g_Notify->BreakPoint(__FILE__, __LINE__);
#ifdef tofix
JmpLabel32("BranchToJump", 0);
m_Recompiler.Branch_AddRef(Target, (uint32_t *)(RecompPos - 4));
m_NextInstruction = RSPPIPELINE_FINISH_SUB_BLOCK;
#endif
return;
}
if (!m_DelayAffectBranch)
{
m_Assembler->CompConstToVariable(&m_GPR[m_OpCode.rs].W, GPR_Name(m_OpCode.rs), 0);
asmjit::Label Jump;
if (!m_Recompiler.FindBranchJump(Target, Jump))
{
g_Notify->BreakPoint(__FILE__, __LINE__);
}
m_Assembler->JleLabel(stdstr_f("0x%X", Target).c_str(), Jump);
}
else
{
// Take a look at the branch compare variable
g_Notify->BreakPoint(__FILE__, __LINE__);
#ifdef tofix
CompConstToVariable(true, &BranchCompare, "BranchCompare");
JeLabel32("BranchLessEqual", 0);
#endif
}
}
else if (m_NextInstruction == RSPPIPELINE_DELAY_SLOT_EXIT_DONE)
{
g_Notify->BreakPoint(__FILE__, __LINE__);
#ifdef tofix
uint32_t Target = (m_CompilePC + ((short)m_OpCode.offset << 2) + 4) & 0xFFC;
CompileBranchExit(Target, m_CompilePC + 8);
#endif
}
else
{
g_Notify->BreakPoint(__FILE__, __LINE__);
#ifdef tofix
CompilerWarning(stdstr_f("BGTZ error\nWeird Delay Slot.\n\nNextInstruction = %X\nEmulation will now stop", m_NextInstruction).c_str());
BreakPoint();
#endif
}
}
void CRSPRecompilerOps::BGTZ(void)
{
if (m_NextInstruction == RSPPIPELINE_NORMAL)
{
RSPInstruction Instruction(m_CompilePC, m_OpCode.Value);
m_Recompiler.Log(" %X %s", m_CompilePC, Instruction.NameAndParam().c_str());
if (m_OpCode.rs == 0)
{
m_DelayAffectBranch = false;
m_NextInstruction = RSPPIPELINE_DO_DELAY_SLOT;
return;
}
m_DelayAffectBranch = Instruction.DelaySlotAffectBranch();
if (!m_DelayAffectBranch)
{
m_NextInstruction = RSPPIPELINE_DO_DELAY_SLOT;
return;
}
m_Assembler->CompConstToVariable(&m_GPR[m_OpCode.rs].W, GPR_Name(m_OpCode.rs), 0);
m_Assembler->SetgVariable(&BranchCompare, "BranchCompare");
m_NextInstruction = RSPPIPELINE_DO_DELAY_SLOT;
}
else if (m_NextInstruction == RSPPIPELINE_DELAY_SLOT_DONE)
{
uint32_t Target = (m_CompilePC + ((short)m_OpCode.offset << 2) + 4) & 0x1FFC;
if (m_OpCode.rs == 0)
{
g_Notify->BreakPoint(__FILE__, __LINE__);
#ifdef tofix
m_NextInstruction = RSPPIPELINE_FINISH_SUB_BLOCK;
#endif
return;
}
asmjit::Label Jump;
if (!m_Recompiler.FindBranchJump(Target, Jump))
{
g_Notify->BreakPoint(__FILE__, __LINE__);
}
if (!m_DelayAffectBranch)
{
m_Assembler->CompConstToVariable(&m_GPR[m_OpCode.rs].W, GPR_Name(m_OpCode.rs), 0);
m_Assembler->JgLabel(stdstr_f("0x%X", Target).c_str(), Jump);
}
else
{
m_Assembler->CompConstToVariable(&BranchCompare, "BranchCompare", true);
m_Assembler->JeLabel(stdstr_f("0x%X", Target).c_str(), Jump);
}
}
else if (m_NextInstruction == RSPPIPELINE_DELAY_SLOT_EXIT_DONE)
{
g_Notify->BreakPoint(__FILE__, __LINE__);
#ifdef tofix
uint32_t Target = (m_CompilePC + ((short)m_OpCode.offset << 2) + 4) & 0xFFC;
CompileBranchExit(Target, m_CompilePC + 8);
#endif
}
else
{
g_Notify->BreakPoint(__FILE__, __LINE__);
#ifdef tofix
CompilerWarning(stdstr_f("BGTZ error\nWeird Delay Slot.\n\nNextInstruction = %X\nEmulation will now stop", m_NextInstruction).c_str());
BreakPoint();
#endif
}
}
void CRSPRecompilerOps::ADDI(void)
{
Cheat_r4300iOpcode(&RSPOp::ADDI, "RSPOp::ADDI");
}
void CRSPRecompilerOps::ADDIU(void)
{
g_Notify->BreakPoint(__FILE__, __LINE__);
}
void CRSPRecompilerOps::SLTI(void)
{
g_Notify->BreakPoint(__FILE__, __LINE__);
}
void CRSPRecompilerOps::SLTIU(void)
{
g_Notify->BreakPoint(__FILE__, __LINE__);
}
void CRSPRecompilerOps::ANDI(void)
{
Cheat_r4300iOpcode(&RSPOp::ANDI, "RSPOp::ANDI");
}
void CRSPRecompilerOps::ORI(void)
{
Cheat_r4300iOpcode(&RSPOp::ORI, "RSPOp::ORI");
}
void CRSPRecompilerOps::XORI(void)
{
g_Notify->BreakPoint(__FILE__, __LINE__);
}
void CRSPRecompilerOps::LUI(void)
{
Cheat_r4300iOpcode(&RSPOp::LUI, "RSPOp::LUI");
}
void CRSPRecompilerOps::COP0(void)
{
(this->*RSP_Recomp_Cop0[m_OpCode.rs])();
}
void CRSPRecompilerOps::COP2(void)
{
(this->*RSP_Recomp_Cop2[m_OpCode.rs])();
}
void CRSPRecompilerOps::LB(void)
{
g_Notify->BreakPoint(__FILE__, __LINE__);
}
void CRSPRecompilerOps::LH(void)
{
Cheat_r4300iOpcode(&RSPOp::LH, "RSPOp::LH");
}
void CRSPRecompilerOps::LW(void)
{
Cheat_r4300iOpcode(&RSPOp::LW, "RSPOp::LW");
}
void CRSPRecompilerOps::LBU(void)
{
Cheat_r4300iOpcode(&RSPOp::LBU, "RSPOp::LBU");
}
void CRSPRecompilerOps::LHU(void)
{
Cheat_r4300iOpcode(&RSPOp::LHU, "RSPOp::LHU");
}
void CRSPRecompilerOps::LWU(void)
{
g_Notify->BreakPoint(__FILE__, __LINE__);
}
void CRSPRecompilerOps::SB(void)
{
g_Notify->BreakPoint(__FILE__, __LINE__);
}
void CRSPRecompilerOps::SH(void)
{
Cheat_r4300iOpcode(&RSPOp::SH, "RSPOp::SH");
}
void CRSPRecompilerOps::SW(void)
{
Cheat_r4300iOpcode(&RSPOp::SW, "RSPOp::SW");
}
void CRSPRecompilerOps::LC2(void)
{
(this->*RSP_Recomp_Lc2[m_OpCode.rd])();
}
void CRSPRecompilerOps::SC2(void)
{
(this->*RSP_Recomp_Sc2[m_OpCode.rd])();
}
// R4300i Opcodes: Special
void CRSPRecompilerOps::Special_SLL(void)
{
if (m_OpCode.rd == 0)
{
m_Recompiler.Log(" %X %s", m_CompilePC, RSPInstruction(m_CompilePC, m_OpCode.Value).NameAndParam().c_str());
return;
}
Cheat_r4300iOpcode(&RSPOp::Special_SLL, "RSPOp::Special_SLL");
}
void CRSPRecompilerOps::Special_SRL(void)
{
Cheat_r4300iOpcode(&RSPOp::Special_SRL, "RSPOp::Special_SRL");
}
void CRSPRecompilerOps::Special_SRA(void)
{
g_Notify->BreakPoint(__FILE__, __LINE__);
}
void CRSPRecompilerOps::Special_SLLV(void)
{
g_Notify->BreakPoint(__FILE__, __LINE__);
}
void CRSPRecompilerOps::Special_SRLV(void)
{
Cheat_r4300iOpcode(&RSPOp::Special_SRLV, "RSPOp::Special_SRLV");
}
void CRSPRecompilerOps::Special_SRAV(void)
{
g_Notify->BreakPoint(__FILE__, __LINE__);
}
void CRSPRecompilerOps::Special_JR(void)
{
//uint8_t * Jump = nullptr;
if (m_NextInstruction == RSPPIPELINE_NORMAL)
{
m_Recompiler.Log(" %X %s", m_CompilePC, RSPInstruction(m_CompilePC, m_OpCode.Value).NameAndParam().c_str());
m_Assembler->MoveVariableToX86reg(asmjit::x86::eax, &m_GPR[m_OpCode.rs].W, GPR_Name(m_OpCode.rs));
m_Assembler->and_(asmjit::x86::eax, 0x1FFC);
m_Assembler->MoveX86regToVariable(m_System.m_SP_PC_REG, "RSP PC", asmjit::x86::eax);
m_NextInstruction = RSPPIPELINE_DO_DELAY_SLOT;
}
else if (m_NextInstruction == RSPPIPELINE_DELAY_SLOT_DONE)
{
if (m_CurrentBlock && m_CurrentBlock->CodeType() == RspCodeType_SUBROUTINE)
{
ExitCodeBlock();
}
else
{
g_Notify->BreakPoint(__FILE__, __LINE__);
}
#ifdef tofix
MoveVariableToX86reg(m_System.m_SP_PC_REG, "RSP PC", x86_EAX);
AddVariableToX86reg(x86_EAX, &JumpTable, "JumpTable");
MoveX86regPointerToX86reg(x86_EAX, x86_EAX);
TestX86RegToX86Reg(x86_EAX, x86_EAX);
JeLabel8("Null", 0);
Jump = RecompPos - 1;
JumpX86Reg(x86_EAX);
x86_SetBranch8b(Jump, RecompPos);
CPU_Message(" Null:");
if (CRSPSettings::CPUMethod() == RSPCpuMethod::HighLevelEmulation)
{
BreakPoint();
}
Ret();
ChangedPC = false;
m_NextInstruction = RSPPIPELINE_FINISH_SUB_BLOCK;
#endif
}
else if (m_NextInstruction == RSPPIPELINE_DELAY_SLOT_EXIT_DONE)
{
g_Notify->BreakPoint(__FILE__, __LINE__);
#ifdef tofix
m_NextInstruction = RSPPIPELINE_FINISH_SUB_BLOCK;
Ret();
#endif
}
else
{
g_Notify->BreakPoint(__FILE__, __LINE__);
#ifdef tofix
CompilerWarning(stdstr_f("WTF\n\nJR\nNextInstruction = %X", m_NextInstruction).c_str());
BreakPoint();
#endif
}
}
void CRSPRecompilerOps::Special_JALR(void)
{
g_Notify->BreakPoint(__FILE__, __LINE__);
}
void CRSPRecompilerOps::Special_BREAK(void)
{
g_Notify->BreakPoint(__FILE__, __LINE__);
}
void CRSPRecompilerOps::Special_ADD(void)
{
Cheat_r4300iOpcode(&RSPOp::Special_ADD, "RSPOp::Special_ADD");
}
void CRSPRecompilerOps::Special_ADDU(void)
{
g_Notify->BreakPoint(__FILE__, __LINE__);
}
void CRSPRecompilerOps::Special_SUB(void)
{
Cheat_r4300iOpcode(&RSPOp::Special_SUB, "RSPOp::Special_SUB");
}
void CRSPRecompilerOps::Special_SUBU(void)
{
g_Notify->BreakPoint(__FILE__, __LINE__);
}
void CRSPRecompilerOps::Special_AND(void)
{
Cheat_r4300iOpcode(&RSPOp::Special_AND, "RSPOp::Special_AND");
}
void CRSPRecompilerOps::Special_OR(void)
{
g_Notify->BreakPoint(__FILE__, __LINE__);
}
void CRSPRecompilerOps::Special_XOR(void)
{
g_Notify->BreakPoint(__FILE__, __LINE__);
}
void CRSPRecompilerOps::Special_NOR(void)
{
g_Notify->BreakPoint(__FILE__, __LINE__);
}
void CRSPRecompilerOps::Special_SLT(void)
{
g_Notify->BreakPoint(__FILE__, __LINE__);
}
void CRSPRecompilerOps::Special_SLTU(void)
{
g_Notify->BreakPoint(__FILE__, __LINE__);
}
// R4300i Opcodes: RegImm
void CRSPRecompilerOps::RegImm_BLTZ(void)
{
g_Notify->BreakPoint(__FILE__, __LINE__);
}
void CRSPRecompilerOps::RegImm_BGEZ(void)
{
g_Notify->BreakPoint(__FILE__, __LINE__);
}
void CRSPRecompilerOps::RegImm_BLTZAL(void)
{
g_Notify->BreakPoint(__FILE__, __LINE__);
}
void CRSPRecompilerOps::RegImm_BGEZAL(void)
{
g_Notify->BreakPoint(__FILE__, __LINE__);
}
// COP0 functions
void CRSPRecompilerOps::Cop0_MF(void)
{
Cheat_r4300iOpcode(&RSPOp::Cop0_MF, "RSPOp::Cop0_MF");
}
void CRSPRecompilerOps::Cop0_MT(void)
{
Cheat_r4300iOpcode(&RSPOp::Cop0_MT, "RSPOp::Cop0_MT");
}
// COP2 functions
void CRSPRecompilerOps::Cop2_MF(void)
{
Cheat_r4300iOpcode(&RSPOp::Cop2_MF, "RSPOp::Cop2_MF");
}
void CRSPRecompilerOps::Cop2_CF(void)
{
g_Notify->BreakPoint(__FILE__, __LINE__);
}
void CRSPRecompilerOps::Cop2_MT(void)
{
Cheat_r4300iOpcode(&RSPOp::Cop2_MT, "RSPOp::Cop2_MT");
}
void CRSPRecompilerOps::Cop2_CT(void)
{
g_Notify->BreakPoint(__FILE__, __LINE__);
}
void CRSPRecompilerOps::COP2_VECTOR(void)
{
(this->*RSP_Recomp_Vector[m_OpCode.funct])();
}
// Vector functions
void CRSPRecompilerOps::Vector_VMULF(void)
{
Cheat_r4300iOpcode(&RSPOp::Vector_VMULF, "RSPOp::Vector_VMULF");
}
void CRSPRecompilerOps::Vector_VMULU(void)
{
g_Notify->BreakPoint(__FILE__, __LINE__);
}
void CRSPRecompilerOps::Vector_VRNDN(void)
{
g_Notify->BreakPoint(__FILE__, __LINE__);
}
void CRSPRecompilerOps::Vector_VRNDP(void)
{
g_Notify->BreakPoint(__FILE__, __LINE__);
}
void CRSPRecompilerOps::Vector_VMULQ(void)
{
g_Notify->BreakPoint(__FILE__, __LINE__);
}
void CRSPRecompilerOps::Vector_VMUDL(void)
{
Cheat_r4300iOpcode(&RSPOp::Vector_VMUDL, "RSPOp::Vector_VMUDL");
}
void CRSPRecompilerOps::Vector_VMUDM(void)
{
Cheat_r4300iOpcode(&RSPOp::Vector_VMUDM, "RSPOp::Vector_VMUDM");
}
void CRSPRecompilerOps::Vector_VMUDN(void)
{
Cheat_r4300iOpcode(&RSPOp::Vector_VMUDN, "RSPOp::Vector_VMUDN");
}
void CRSPRecompilerOps::Vector_VMUDH(void)
{
Cheat_r4300iOpcode(&RSPOp::Vector_VMUDH, "RSPOp::Vector_VMUDH");
}
void CRSPRecompilerOps::Vector_VMACF(void)
{
Cheat_r4300iOpcode(&RSPOp::Vector_VMACF, "RSPOp::Vector_VMACF");
}
void CRSPRecompilerOps::Vector_VMACU(void)
{
g_Notify->BreakPoint(__FILE__, __LINE__);
}
void CRSPRecompilerOps::Vector_VMACQ(void)
{
g_Notify->BreakPoint(__FILE__, __LINE__);
}
void CRSPRecompilerOps::Vector_VMADL(void)
{
g_Notify->BreakPoint(__FILE__, __LINE__);
}
void CRSPRecompilerOps::Vector_VMADM(void)
{
Cheat_r4300iOpcode(&RSPOp::Vector_VMADM, "RSPOp::Vector_VMADM");
}
void CRSPRecompilerOps::Vector_VMADN(void)
{
Cheat_r4300iOpcode(&RSPOp::Vector_VMADN, "RSPOp::Vector_VMADN");
}
void CRSPRecompilerOps::Vector_VMADH(void)
{
Cheat_r4300iOpcode(&RSPOp::Vector_VMADH, "RSPOp::Vector_VMADH");
}
void CRSPRecompilerOps::Vector_VADD(void)
{
Cheat_r4300iOpcode(&RSPOp::Vector_VADD, "RSPOp::Vector_VADD");
}
void CRSPRecompilerOps::Vector_VSUB(void)
{
Cheat_r4300iOpcode(&RSPOp::Vector_VSUB, "RSPOp::Vector_VSUB");
}
void CRSPRecompilerOps::Vector_VABS(void)
{
g_Notify->BreakPoint(__FILE__, __LINE__);
}
void CRSPRecompilerOps::Vector_VADDC(void)
{
g_Notify->BreakPoint(__FILE__, __LINE__);
}
void CRSPRecompilerOps::Vector_VSUBC(void)
{
Cheat_r4300iOpcode(&RSPOp::Vector_VSUBC, "RSPOp::Vector_VSUBC");
}
void CRSPRecompilerOps::Vector_VSAW(void)
{
Cheat_r4300iOpcode(&RSPOp::Vector_VSAW, "RSPOp::Vector_VSAW");
}
void CRSPRecompilerOps::Vector_VLT(void)
{
g_Notify->BreakPoint(__FILE__, __LINE__);
}
void CRSPRecompilerOps::Vector_VEQ(void)
{
g_Notify->BreakPoint(__FILE__, __LINE__);
}
void CRSPRecompilerOps::Vector_VNE(void)
{
g_Notify->BreakPoint(__FILE__, __LINE__);
}
void CRSPRecompilerOps::Vector_VGE(void)
{
Cheat_r4300iOpcode(&RSPOp::Vector_VGE, "RSPOp::Vector_VGE");
}
void CRSPRecompilerOps::Vector_VCL(void)
{
Cheat_r4300iOpcode(&RSPOp::Vector_VCL, "RSPOp::Vector_VCL");
}
void CRSPRecompilerOps::Vector_VCH(void)
{
g_Notify->BreakPoint(__FILE__, __LINE__);
}
void CRSPRecompilerOps::Vector_VCR(void)
{
g_Notify->BreakPoint(__FILE__, __LINE__);
}
void CRSPRecompilerOps::Vector_VMRG(void)
{
g_Notify->BreakPoint(__FILE__, __LINE__);
}
void CRSPRecompilerOps::Vector_VAND(void)
{
Cheat_r4300iOpcode(&RSPOp::Vector_VAND, "RSPOp::Vector_VAND");
}
void CRSPRecompilerOps::Vector_VNAND(void)
{
g_Notify->BreakPoint(__FILE__, __LINE__);
}
void CRSPRecompilerOps::Vector_VOR(void)
{
g_Notify->BreakPoint(__FILE__, __LINE__);
}
void CRSPRecompilerOps::Vector_VNOR(void)
{
g_Notify->BreakPoint(__FILE__, __LINE__);
}
void CRSPRecompilerOps::Vector_VXOR(void)
{
Cheat_r4300iOpcode(&RSPOp::Vector_VXOR, "RSPOp::Vector_VXOR");
}
void CRSPRecompilerOps::Vector_VNXOR(void)
{
g_Notify->BreakPoint(__FILE__, __LINE__);
}
void CRSPRecompilerOps::Vector_VRCP(void)
{
g_Notify->BreakPoint(__FILE__, __LINE__);
}
void CRSPRecompilerOps::Vector_VRCPL(void)
{
g_Notify->BreakPoint(__FILE__, __LINE__);
}
void CRSPRecompilerOps::Vector_VRCPH(void)
{
g_Notify->BreakPoint(__FILE__, __LINE__);
}
void CRSPRecompilerOps::Vector_VMOV(void)
{
g_Notify->BreakPoint(__FILE__, __LINE__);
}
void CRSPRecompilerOps::Vector_VRSQ(void)
{
g_Notify->BreakPoint(__FILE__, __LINE__);
}
void CRSPRecompilerOps::Vector_VRSQL(void)
{
g_Notify->BreakPoint(__FILE__, __LINE__);
}
void CRSPRecompilerOps::Vector_VRSQH(void)
{
g_Notify->BreakPoint(__FILE__, __LINE__);
}
void CRSPRecompilerOps::Vector_VNOOP(void)
{
}
void CRSPRecompilerOps::Vector_Reserved(void)
{
g_Notify->BreakPoint(__FILE__, __LINE__);
}
// LC2 functions
void CRSPRecompilerOps::Opcode_LBV(void)
{
g_Notify->BreakPoint(__FILE__, __LINE__);
}
void CRSPRecompilerOps::Opcode_LSV(void)
{
Cheat_r4300iOpcode(&RSPOp::LSV, "RSPOp::LSV");
}
void CRSPRecompilerOps::Opcode_LLV(void)
{
g_Notify->BreakPoint(__FILE__, __LINE__);
}
void CRSPRecompilerOps::Opcode_LDV(void)
{
Cheat_r4300iOpcode(&RSPOp::LDV, "RSPOp::LDV");
}
void CRSPRecompilerOps::Opcode_LQV(void)
{
Cheat_r4300iOpcode(&RSPOp::LQV, "RSPOp::LQV");
}
void CRSPRecompilerOps::Opcode_LRV(void)
{
Cheat_r4300iOpcode(&RSPOp::LRV, "RSPOp::LRV");
}
void CRSPRecompilerOps::Opcode_LPV(void)
{
g_Notify->BreakPoint(__FILE__, __LINE__);
}
void CRSPRecompilerOps::Opcode_LUV(void)
{
g_Notify->BreakPoint(__FILE__, __LINE__);
}
void CRSPRecompilerOps::Opcode_LHV(void)
{
g_Notify->BreakPoint(__FILE__, __LINE__);
}
void CRSPRecompilerOps::Opcode_LFV(void)
{
g_Notify->BreakPoint(__FILE__, __LINE__);
}
void CRSPRecompilerOps::Opcode_LWV(void)
{
g_Notify->BreakPoint(__FILE__, __LINE__);
}
void CRSPRecompilerOps::Opcode_LTV(void)
{
g_Notify->BreakPoint(__FILE__, __LINE__);
}
// SC2 functions
void CRSPRecompilerOps::Opcode_SBV(void)
{
g_Notify->BreakPoint(__FILE__, __LINE__);
}
void CRSPRecompilerOps::Opcode_SSV(void)
{
Cheat_r4300iOpcode(&RSPOp::SSV, "RSPOp::SSV");
}
void CRSPRecompilerOps::Opcode_SLV(void)
{
Cheat_r4300iOpcode(&RSPOp::SLV, "RSPOp::SLV");
}
void CRSPRecompilerOps::Opcode_SDV(void)
{
Cheat_r4300iOpcode(&RSPOp::SDV, "RSPOp::SDV");
}
void CRSPRecompilerOps::Opcode_SQV(void)
{
Cheat_r4300iOpcode(&RSPOp::SQV, "RSPOp::SQV");
}
void CRSPRecompilerOps::Opcode_SRV(void)
{
g_Notify->BreakPoint(__FILE__, __LINE__);
}
void CRSPRecompilerOps::Opcode_SPV(void)
{
g_Notify->BreakPoint(__FILE__, __LINE__);
}
void CRSPRecompilerOps::Opcode_SUV(void)
{
g_Notify->BreakPoint(__FILE__, __LINE__);
}
void CRSPRecompilerOps::Opcode_SHV(void)
{
g_Notify->BreakPoint(__FILE__, __LINE__);
}
void CRSPRecompilerOps::Opcode_SFV(void)
{
g_Notify->BreakPoint(__FILE__, __LINE__);
}
void CRSPRecompilerOps::Opcode_STV(void)
{
g_Notify->BreakPoint(__FILE__, __LINE__);
}
void CRSPRecompilerOps::Opcode_SWV(void)
{
g_Notify->BreakPoint(__FILE__, __LINE__);
}
// Other functions
void CRSPRecompilerOps::UnknownOpcode(void)
{
g_Notify->BreakPoint(__FILE__, __LINE__);
}
void CRSPRecompilerOps::EnterCodeBlock(void)
{
m_Assembler->sub(asmjit::x86::rsp, 40);
if (Profiling && m_CurrentBlock->CodeType() == RspCodeType_TASK)
{
m_Assembler->mov(asmjit::x86::rcx, asmjit::imm((uintptr_t)m_CompilePC));
m_Assembler->CallFunc(AddressOf(&StartTimer), "StartTimer");
}
}
void CRSPRecompilerOps::ExitCodeBlock(void)
{
if (Profiling && m_CurrentBlock->CodeType() == RspCodeType_TASK)
{
m_Assembler->CallFunc(AddressOf(&StopTimer), "StopTimer");
}
m_Assembler->add(asmjit::x86::rsp, 40);
m_Assembler->ret();
}
#endif