Split PPCTables from Interpreter_Tables

This also allows use of constexpr in both places. Some additional work was needed in PPCTables due to mutable data associated with each opcode.
This commit is contained in:
Pokechu22 committed 2023-03-16 18:36:25 -07:00
1 parent cd627d1232
commit 164ea57790
12 files changed
+1077 -574

No files matched your search

@@ -34,14 +34,6 @@ u32 last_pc;
bool Interpreter::m_end_block;
// function tables
std::array<Interpreter::Instruction, 64> Interpreter::m_op_table;
std::array<Interpreter::Instruction, 1024> Interpreter::m_op_table4;
std::array<Interpreter::Instruction, 1024> Interpreter::m_op_table19;
std::array<Interpreter::Instruction, 1024> Interpreter::m_op_table31;
std::array<Interpreter::Instruction, 32> Interpreter::m_op_table59;
std::array<Interpreter::Instruction, 1024> Interpreter::m_op_table63;
namespace
{
// Determines whether or not the given instruction is one where its execution
@@ -79,30 +71,8 @@ void UpdatePC()
}
} // Anonymous namespace
void Interpreter::RunTable4(UGeckoInstruction inst)
{
m_op_table4[inst.SUBOP10](inst);
}
void Interpreter::RunTable19(UGeckoInstruction inst)
{
m_op_table19[inst.SUBOP10](inst);
}
void Interpreter::RunTable31(UGeckoInstruction inst)
{
m_op_table31[inst.SUBOP10](inst);
}
void Interpreter::RunTable59(UGeckoInstruction inst)
{
m_op_table59[inst.SUBOP5](inst);
}
void Interpreter::RunTable63(UGeckoInstruction inst)
{
m_op_table63[inst.SUBOP10](inst);
}
void Interpreter::Init()
{
InitializeInstructionTables();
m_end_block = false;
}
@@ -150,7 +120,7 @@ int Interpreter::SingleStepInner()
if (HandleFunctionHooking(PowerPC::ppcState.pc))
{
UpdatePC();
return PPCTables::GetOpInfo(m_prev_inst)->numCycles;
return PPCTables::GetOpInfo(m_prev_inst)->num_cycles;
}
PowerPC::ppcState.npc = PowerPC::ppcState.pc + sizeof(UGeckoInstruction);
@@ -181,7 +151,7 @@ int Interpreter::SingleStepInner()
}
else if (PowerPC::ppcState.msr.FP)
{
m_op_table[m_prev_inst.OPCD](m_prev_inst);
RunInterpreterOp(m_prev_inst);
if ((PowerPC::ppcState.Exceptions & EXCEPTION_DSI) != 0)
{
CheckExceptions();
@@ -197,7 +167,7 @@ int Interpreter::SingleStepInner()
}
else
{
m_op_table[m_prev_inst.OPCD](m_prev_inst);
RunInterpreterOp(m_prev_inst);
if ((PowerPC::ppcState.Exceptions & EXCEPTION_DSI) != 0)
{
CheckExceptions();
@@ -214,9 +184,9 @@ int Interpreter::SingleStepInner()
UpdatePC();
const GekkoOPInfo* opinfo = PPCTables::GetOpInfo(m_prev_inst);
PowerPC::UpdatePerformanceMonitor(opinfo->numCycles, (opinfo->flags & FL_LOADSTORE) != 0,
PowerPC::UpdatePerformanceMonitor(opinfo->num_cycles, (opinfo->flags & FL_LOADSTORE) != 0,
(opinfo->flags & FL_USE_FPU) != 0, PowerPC::ppcState);
return opinfo->numCycles;
return opinfo->num_cycles;
}
void Interpreter::SingleStep()
@@ -262,12 +262,9 @@ public:
static void isync(UGeckoInstruction inst);
using Instruction = void (*)(UGeckoInstruction inst);
static std::array<Instruction, 64> m_op_table;
static std::array<Instruction, 1024> m_op_table4;
static std::array<Instruction, 1024> m_op_table19;
static std::array<Instruction, 1024> m_op_table31;
static std::array<Instruction, 32> m_op_table59;
static std::array<Instruction, 1024> m_op_table63;
static Instruction GetInterpreterOp(UGeckoInstruction inst);
static void RunInterpreterOp(UGeckoInstruction inst);
// singleton
static Interpreter* getInstance();
@@ -283,8 +280,6 @@ public:
private:
void CheckExceptions();
static void InitializeInstructionTables();
static bool HandleFunctionHooking(u32 address);
// flag helper
@@ -5,492 +5,492 @@
#include <array>
#include "Common/Assert.h"
#include "Common/TypeUtils.h"
#include "Core/PowerPC/Gekko.h"
#include "Core/PowerPC/PPCTables.h"
namespace
{
struct GekkoOPTemplate
struct InterpreterOpTemplate
{
int opcode;
Interpreter::Instruction Inst;
GekkoOPInfo opinfo;
u32 opcode;
Interpreter::Instruction fn;
};
} // namespace
// clang-format off
static GekkoOPInfo unknownopinfo = { "unknown_instruction", OpType::Unknown, FL_ENDBLOCK, 0, 0, 0, 0 };
constexpr std::array<InterpreterOpTemplate, 54> s_primary_table{{
{4, Interpreter::RunTable4}, // RunTable4
{19, Interpreter::RunTable19}, // RunTable19
{31, Interpreter::RunTable31}, // RunTable31
{59, Interpreter::RunTable59}, // RunTable59
{63, Interpreter::RunTable63}, // RunTable63
static std::array<GekkoOPTemplate, 54> primarytable =
{{
{4, Interpreter::RunTable4, {"RunTable4", OpType::Subtable, 0, 0, 0, 0, 0}},
{19, Interpreter::RunTable19, {"RunTable19", OpType::Subtable, 0, 0, 0, 0, 0}},
{31, Interpreter::RunTable31, {"RunTable31", OpType::Subtable, 0, 0, 0, 0, 0}},
{59, Interpreter::RunTable59, {"RunTable59", OpType::Subtable, 0, 0, 0, 0, 0}},
{63, Interpreter::RunTable63, {"RunTable63", OpType::Subtable, 0, 0, 0, 0, 0}},
{16, Interpreter::bcx}, // bcx
{18, Interpreter::bx}, // bx
{16, Interpreter::bcx, {"bcx", OpType::Branch, FL_ENDBLOCK | FL_READ_CR_BI, 1, 0, 0, 0}},
{18, Interpreter::bx, {"bx", OpType::Branch, FL_ENDBLOCK, 1, 0, 0, 0}},
{3, Interpreter::twi}, // twi
{17, Interpreter::sc}, // sc
{3, Interpreter::twi, {"twi", OpType::System, FL_IN_A | FL_ENDBLOCK, 1, 0, 0, 0}},
{17, Interpreter::sc, {"sc", OpType::System, FL_ENDBLOCK, 2, 0, 0, 0}},
{7, Interpreter::mulli}, // mulli
{8, Interpreter::subfic}, // subfic
{10, Interpreter::cmpli}, // cmpli
{11, Interpreter::cmpi}, // cmpi
{12, Interpreter::addic}, // addic
{13, Interpreter::addic_rc}, // addic_rc
{14, Interpreter::addi}, // addi
{15, Interpreter::addis}, // addis
{7, Interpreter::mulli, {"mulli", OpType::Integer, FL_OUT_D | FL_IN_A, 3, 0, 0, 0}},
{8, Interpreter::subfic, {"subfic", OpType::Integer, FL_OUT_D | FL_IN_A | FL_SET_CA, 1, 0, 0, 0}},
{10, Interpreter::cmpli, {"cmpli", OpType::Integer, FL_IN_A | FL_SET_CRn, 1, 0, 0, 0}},
{11, Interpreter::cmpi, {"cmpi", OpType::Integer, FL_IN_A | FL_SET_CRn, 1, 0, 0, 0}},
{12, Interpreter::addic, {"addic", OpType::Integer, FL_OUT_D | FL_IN_A | FL_SET_CA, 1, 0, 0, 0}},
{13, Interpreter::addic_rc, {"addic_rc", OpType::Integer, FL_OUT_D | FL_IN_A | FL_SET_CA | FL_SET_CR0, 1, 0, 0, 0}},
{14, Interpreter::addi, {"addi", OpType::Integer, FL_OUT_D | FL_IN_A0, 1, 0, 0, 0}},
{15, Interpreter::addis, {"addis", OpType::Integer, FL_OUT_D | FL_IN_A0, 1, 0, 0, 0}},
{20, Interpreter::rlwimix}, // rlwimix
{21, Interpreter::rlwinmx}, // rlwinmx
{23, Interpreter::rlwnmx}, // rlwnmx
{20, Interpreter::rlwimix, {"rlwimix", OpType::Integer, FL_OUT_A | FL_IN_A | FL_IN_S | FL_RC_BIT, 1, 0, 0, 0}},
{21, Interpreter::rlwinmx, {"rlwinmx", OpType::Integer, FL_OUT_A | FL_IN_S | FL_RC_BIT, 1, 0, 0, 0}},
{23, Interpreter::rlwnmx, {"rlwnmx", OpType::Integer, FL_OUT_A | FL_IN_SB | FL_RC_BIT, 1, 0, 0, 0}},
{24, Interpreter::ori}, // ori
{25, Interpreter::oris}, // oris
{26, Interpreter::xori}, // xori
{27, Interpreter::xoris}, // xoris
{28, Interpreter::andi_rc}, // andi_rc
{29, Interpreter::andis_rc}, // andis_rc
{24, Interpreter::ori, {"ori", OpType::Integer, FL_OUT_A | FL_IN_S, 1, 0, 0, 0}},
{25, Interpreter::oris, {"oris", OpType::Integer, FL_OUT_A | FL_IN_S, 1, 0, 0, 0}},
{26, Interpreter::xori, {"xori", OpType::Integer, FL_OUT_A | FL_IN_S, 1, 0, 0, 0}},
{27, Interpreter::xoris, {"xoris", OpType::Integer, FL_OUT_A | FL_IN_S, 1, 0, 0, 0}},
{28, Interpreter::andi_rc, {"andi_rc", OpType::Integer, FL_OUT_A | FL_IN_S | FL_SET_CR0, 1, 0, 0, 0}},
{29, Interpreter::andis_rc, {"andis_rc", OpType::Integer, FL_OUT_A | FL_IN_S | FL_SET_CR0, 1, 0, 0, 0}},
{32, Interpreter::lwz}, // lwz
{33, Interpreter::lwzu}, // lwzu
{34, Interpreter::lbz}, // lbz
{35, Interpreter::lbzu}, // lbzu
{40, Interpreter::lhz}, // lhz
{41, Interpreter::lhzu}, // lhzu
{32, Interpreter::lwz, {"lwz", OpType::Load, FL_OUT_D | FL_IN_A0 | FL_LOADSTORE, 1, 0, 0, 0}},
{33, Interpreter::lwzu, {"lwzu", OpType::Load, FL_OUT_D | FL_OUT_A | FL_IN_A | FL_LOADSTORE, 1, 0, 0, 0}},
{34, Interpreter::lbz, {"lbz", OpType::Load, FL_OUT_D | FL_IN_A0 | FL_LOADSTORE, 1, 0, 0, 0}},
{35, Interpreter::lbzu, {"lbzu", OpType::Load, FL_OUT_D | FL_OUT_A | FL_IN_A | FL_LOADSTORE, 1, 0, 0, 0}},
{40, Interpreter::lhz, {"lhz", OpType::Load, FL_OUT_D | FL_IN_A0 | FL_LOADSTORE, 1, 0, 0, 0}},
{41, Interpreter::lhzu, {"lhzu", OpType::Load, FL_OUT_D | FL_OUT_A | FL_IN_A | FL_LOADSTORE, 1, 0, 0, 0}},
{42, Interpreter::lha}, // lha
{43, Interpreter::lhau}, // lhau
{42, Interpreter::lha, {"lha", OpType::Load, FL_OUT_D | FL_IN_A0 | FL_LOADSTORE, 1, 0, 0, 0}},
{43, Interpreter::lhau, {"lhau", OpType::Load, FL_OUT_D | FL_OUT_A | FL_IN_A | FL_LOADSTORE, 1, 0, 0, 0}},
{44, Interpreter::sth}, // sth
{45, Interpreter::sthu}, // sthu
{36, Interpreter::stw}, // stw
{37, Interpreter::stwu}, // stwu
{38, Interpreter::stb}, // stb
{39, Interpreter::stbu}, // stbu
{44, Interpreter::sth, {"sth", OpType::Store, FL_IN_A0 | FL_IN_S | FL_LOADSTORE, 1, 0, 0, 0}},
{45, Interpreter::sthu, {"sthu", OpType::Store, FL_OUT_A | FL_IN_A | FL_IN_S | FL_LOADSTORE, 1, 0, 0, 0}},
{36, Interpreter::stw, {"stw", OpType::Store, FL_IN_A0 | FL_IN_S | FL_LOADSTORE, 1, 0, 0, 0}},
{37, Interpreter::stwu, {"stwu", OpType::Store, FL_OUT_A | FL_IN_A | FL_IN_S | FL_LOADSTORE, 1, 0, 0, 0}},
{38, Interpreter::stb, {"stb", OpType::Store, FL_IN_A0 | FL_IN_S | FL_LOADSTORE, 1, 0, 0, 0}},
{39, Interpreter::stbu, {"stbu", OpType::Store, FL_OUT_A | FL_IN_A | FL_IN_S | FL_LOADSTORE, 1, 0, 0, 0}},
{46, Interpreter::lmw}, // lmw
{47, Interpreter::stmw}, // stmw
{46, Interpreter::lmw, {"lmw", OpType::System, FL_EVIL | FL_IN_A0 | FL_LOADSTORE, 11, 0, 0, 0}},
{47, Interpreter::stmw, {"stmw", OpType::System, FL_EVIL | FL_IN_A0 | FL_LOADSTORE, 11, 0, 0, 0}},
{48, Interpreter::lfs}, // lfs
{49, Interpreter::lfsu}, // lfsu
{50, Interpreter::lfd}, // lfd
{51, Interpreter::lfdu}, // lfdu
{48, Interpreter::lfs, {"lfs", OpType::LoadFP, FL_OUT_FLOAT_D | FL_IN_A | FL_USE_FPU | FL_LOADSTORE, 1, 0, 0, 0}},
{49, Interpreter::lfsu, {"lfsu", OpType::LoadFP, FL_OUT_FLOAT_D | FL_OUT_A | FL_IN_A | FL_USE_FPU | FL_LOADSTORE, 1, 0, 0, 0}},
{50, Interpreter::lfd, {"lfd", OpType::LoadFP, FL_INOUT_FLOAT_D | FL_IN_A | FL_USE_FPU | FL_LOADSTORE, 1, 0, 0, 0}},
{51, Interpreter::lfdu, {"lfdu", OpType::LoadFP, FL_INOUT_FLOAT_D | FL_OUT_A | FL_IN_A | FL_USE_FPU | FL_LOADSTORE, 1, 0, 0, 0}},
{52, Interpreter::stfs}, // stfs
{53, Interpreter::stfsu}, // stfsu
{54, Interpreter::stfd}, // stfd
{55, Interpreter::stfdu}, // stfdu
{52, Interpreter::stfs, {"stfs", OpType::StoreFP, FL_IN_FLOAT_S | FL_IN_A0 | FL_USE_FPU | FL_LOADSTORE, 1, 0, 0, 0}},
{53, Interpreter::stfsu, {"stfsu", OpType::StoreFP, FL_IN_FLOAT_S | FL_OUT_A | FL_IN_A | FL_USE_FPU | FL_LOADSTORE, 1, 0, 0, 0}},
{54, Interpreter::stfd, {"stfd", OpType::StoreFP, FL_IN_FLOAT_S | FL_IN_A0 | FL_USE_FPU | FL_LOADSTORE, 1, 0, 0, 0}},
{55, Interpreter::stfdu, {"stfdu", OpType::StoreFP, FL_IN_FLOAT_S | FL_OUT_A | FL_IN_A | FL_USE_FPU | FL_LOADSTORE, 1, 0, 0, 0}},
{56, Interpreter::psq_l}, // psq_l
{57, Interpreter::psq_lu}, // psq_lu
{60, Interpreter::psq_st}, // psq_st
{61, Interpreter::psq_stu}, // psq_stu
{56, Interpreter::psq_l, {"psq_l", OpType::LoadPS, FL_OUT_FLOAT_D | FL_IN_A0 | FL_USE_FPU | FL_LOADSTORE | FL_PROGRAMEXCEPTION, 1, 0, 0, 0}},
{57, Interpreter::psq_lu, {"psq_lu", OpType::LoadPS, FL_OUT_FLOAT_D | FL_OUT_A | FL_IN_A | FL_USE_FPU | FL_LOADSTORE | FL_PROGRAMEXCEPTION, 1, 0, 0, 0}},
{60, Interpreter::psq_st, {"psq_st", OpType::StorePS, FL_IN_FLOAT_S | FL_IN_A0 | FL_USE_FPU | FL_LOADSTORE | FL_PROGRAMEXCEPTION, 1, 0, 0, 0}},
{61, Interpreter::psq_stu, {"psq_stu", OpType::StorePS, FL_IN_FLOAT_S | FL_OUT_A | FL_IN_A | FL_USE_FPU | FL_LOADSTORE | FL_PROGRAMEXCEPTION, 1, 0, 0, 0}},
//missing: 0, 1, 2, 5, 6, 9, 22, 30, 62, 58
// missing: 0, 1, 2, 5, 6, 9, 22, 30, 62, 58
}};
static std::array<GekkoOPTemplate, 13> table4 =
{{ //SUBOP10
{0, Interpreter::ps_cmpu0, {"ps_cmpu0", OpType::PS, FL_IN_FLOAT_AB | FL_SET_CRn | FL_USE_FPU | FL_READ_FPRF | FL_SET_FPRF | FL_PROGRAMEXCEPTION | FL_FLOAT_EXCEPTION, 1, 0, 0, 0}},
{32, Interpreter::ps_cmpo0, {"ps_cmpo0", OpType::PS, FL_IN_FLOAT_AB | FL_SET_CRn | FL_USE_FPU | FL_READ_FPRF | FL_SET_FPRF | FL_PROGRAMEXCEPTION | FL_FLOAT_EXCEPTION, 1, 0, 0, 0}},
{40, Interpreter::ps_neg, {"ps_neg", OpType::PS, FL_OUT_FLOAT_D | FL_IN_FLOAT_B | FL_IN_FLOAT_B_BITEXACT | FL_RC_BIT_F | FL_USE_FPU | FL_PROGRAMEXCEPTION, 1, 0, 0, 0}},
{136, Interpreter::ps_nabs, {"ps_nabs", OpType::PS, FL_OUT_FLOAT_D | FL_IN_FLOAT_B | FL_IN_FLOAT_B_BITEXACT | FL_RC_BIT_F | FL_USE_FPU | FL_PROGRAMEXCEPTION, 1, 0, 0, 0}},
{264, Interpreter::ps_abs, {"ps_abs", OpType::PS, FL_OUT_FLOAT_D | FL_IN_FLOAT_B | FL_IN_FLOAT_B_BITEXACT | FL_RC_BIT_F | FL_USE_FPU | FL_PROGRAMEXCEPTION, 1, 0, 0, 0}},
{64, Interpreter::ps_cmpu1, {"ps_cmpu1", OpType::PS, FL_IN_FLOAT_AB | FL_SET_CRn | FL_USE_FPU | FL_READ_FPRF | FL_SET_FPRF | FL_PROGRAMEXCEPTION | FL_FLOAT_EXCEPTION, 1, 0, 0, 0}},
{72, Interpreter::ps_mr, {"ps_mr", OpType::PS, FL_OUT_FLOAT_D | FL_IN_FLOAT_B | FL_IN_FLOAT_B_BITEXACT | FL_RC_BIT_F | FL_USE_FPU | FL_PROGRAMEXCEPTION, 1, 0, 0, 0}},
{96, Interpreter::ps_cmpo1, {"ps_cmpo1", OpType::PS, FL_IN_FLOAT_AB | FL_SET_CRn | FL_USE_FPU | FL_READ_FPRF | FL_SET_FPRF | FL_PROGRAMEXCEPTION | FL_FLOAT_EXCEPTION, 1, 0, 0, 0}},
{528, Interpreter::ps_merge00, {"ps_merge00", OpType::PS, FL_OUT_FLOAT_D | FL_IN_FLOAT_AB | FL_IN_FLOAT_AB_BITEXACT | FL_RC_BIT_F | FL_USE_FPU | FL_PROGRAMEXCEPTION, 1, 0, 0, 0}},
{560, Interpreter::ps_merge01, {"ps_merge01", OpType::PS, FL_OUT_FLOAT_D | FL_IN_FLOAT_AB | FL_IN_FLOAT_AB_BITEXACT | FL_RC_BIT_F | FL_USE_FPU | FL_PROGRAMEXCEPTION, 1, 0, 0, 0}},
{592, Interpreter::ps_merge10, {"ps_merge10", OpType::PS, FL_OUT_FLOAT_D | FL_IN_FLOAT_AB | FL_IN_FLOAT_AB_BITEXACT | FL_RC_BIT_F | FL_USE_FPU | FL_PROGRAMEXCEPTION, 1, 0, 0, 0}},
{624, Interpreter::ps_merge11, {"ps_merge11", OpType::PS, FL_OUT_FLOAT_D | FL_IN_FLOAT_AB | FL_IN_FLOAT_AB_BITEXACT | FL_RC_BIT_F | FL_USE_FPU | FL_PROGRAMEXCEPTION, 1, 0, 0, 0}},
constexpr std::array<InterpreterOpTemplate, 13> s_table4{{
// SUBOP10
{0, Interpreter::ps_cmpu0}, // ps_cmpu0
{32, Interpreter::ps_cmpo0}, // ps_cmpo0
{40, Interpreter::ps_neg}, // ps_neg
{136, Interpreter::ps_nabs}, // ps_nabs
{264, Interpreter::ps_abs}, // ps_abs
{64, Interpreter::ps_cmpu1}, // ps_cmpu1
{72, Interpreter::ps_mr}, // ps_mr
{96, Interpreter::ps_cmpo1}, // ps_cmpo1
{528, Interpreter::ps_merge00}, // ps_merge00
{560, Interpreter::ps_merge01}, // ps_merge01
{592, Interpreter::ps_merge10}, // ps_merge10
{624, Interpreter::ps_merge11}, // ps_merge11
{1014, Interpreter::dcbz_l, {"dcbz_l", OpType::System, FL_IN_A0B | FL_LOADSTORE | FL_PROGRAMEXCEPTION, 1, 0, 0, 0}},
{1014, Interpreter::dcbz_l}, // dcbz_l
}};
static std::array<GekkoOPTemplate, 17> table4_2 =
{{
{10, Interpreter::ps_sum0, {"ps_sum0", OpType::PS, FL_OUT_FLOAT_D | FL_IN_FLOAT_ABC | FL_RC_BIT_F | FL_USE_FPU | FL_SET_FPRF | FL_PROGRAMEXCEPTION | FL_FLOAT_EXCEPTION, 1, 0, 0, 0}},
{11, Interpreter::ps_sum1, {"ps_sum1", OpType::PS, FL_OUT_FLOAT_D | FL_IN_FLOAT_ABC | FL_RC_BIT_F | FL_USE_FPU | FL_SET_FPRF | FL_PROGRAMEXCEPTION | FL_FLOAT_EXCEPTION, 1, 0, 0, 0}},
{12, Interpreter::ps_muls0, {"ps_muls0", OpType::PS, FL_OUT_FLOAT_D | FL_IN_FLOAT_AC | FL_RC_BIT_F | FL_USE_FPU | FL_SET_FPRF | FL_PROGRAMEXCEPTION | FL_FLOAT_EXCEPTION, 1, 0, 0, 0}},
{13, Interpreter::ps_muls1, {"ps_muls1", OpType::PS, FL_OUT_FLOAT_D | FL_IN_FLOAT_AC | FL_RC_BIT_F | FL_USE_FPU | FL_SET_FPRF | FL_PROGRAMEXCEPTION | FL_FLOAT_EXCEPTION, 1, 0, 0, 0}},
{14, Interpreter::ps_madds0, {"ps_madds0", OpType::PS, FL_OUT_FLOAT_D | FL_IN_FLOAT_ABC | FL_RC_BIT_F | FL_USE_FPU | FL_SET_FPRF | FL_PROGRAMEXCEPTION | FL_FLOAT_EXCEPTION, 1, 0, 0, 0}},
{15, Interpreter::ps_madds1, {"ps_madds1", OpType::PS, FL_OUT_FLOAT_D | FL_IN_FLOAT_ABC | FL_RC_BIT_F | FL_USE_FPU | FL_SET_FPRF | FL_PROGRAMEXCEPTION | FL_FLOAT_EXCEPTION, 1, 0, 0, 0}},
{18, Interpreter::ps_div, {"ps_div", OpType::PS, FL_OUT_FLOAT_D | FL_IN_FLOAT_AB | FL_RC_BIT_F | FL_USE_FPU | FL_SET_FPRF | FL_PROGRAMEXCEPTION | FL_FLOAT_EXCEPTION | FL_FLOAT_DIV, 17, 0, 0, 0}},
{20, Interpreter::ps_sub, {"ps_sub", OpType::PS, FL_OUT_FLOAT_D | FL_IN_FLOAT_AB | FL_RC_BIT_F | FL_USE_FPU | FL_SET_FPRF | FL_PROGRAMEXCEPTION | FL_FLOAT_EXCEPTION, 1, 0, 0, 0}},
{21, Interpreter::ps_add, {"ps_add", OpType::PS, FL_OUT_FLOAT_D | FL_IN_FLOAT_AB | FL_RC_BIT_F | FL_USE_FPU | FL_SET_FPRF | FL_PROGRAMEXCEPTION | FL_FLOAT_EXCEPTION, 1, 0, 0, 0}},
{23, Interpreter::ps_sel, {"ps_sel", OpType::PS, FL_OUT_FLOAT_D | FL_IN_FLOAT_ABC | FL_IN_FLOAT_BC_BITEXACT | FL_RC_BIT_F | FL_USE_FPU | FL_PROGRAMEXCEPTION, 1, 0, 0, 0}},
{24, Interpreter::ps_res, {"ps_res", OpType::PS, FL_OUT_FLOAT_D | FL_IN_FLOAT_B | FL_RC_BIT_F | FL_USE_FPU | FL_SET_FPRF | FL_PROGRAMEXCEPTION | FL_FLOAT_EXCEPTION | FL_FLOAT_DIV, 1, 0, 0, 0}},
{25, Interpreter::ps_mul, {"ps_mul", OpType::PS, FL_OUT_FLOAT_D | FL_IN_FLOAT_AC | FL_RC_BIT_F | FL_USE_FPU | FL_SET_FPRF | FL_PROGRAMEXCEPTION | FL_FLOAT_EXCEPTION, 1, 0, 0, 0}},
{26, Interpreter::ps_rsqrte, {"ps_rsqrte", OpType::PS, FL_OUT_FLOAT_D | FL_IN_FLOAT_B | FL_RC_BIT_F | FL_USE_FPU | FL_SET_FPRF | FL_PROGRAMEXCEPTION | FL_FLOAT_EXCEPTION | FL_FLOAT_DIV, 2, 0, 0, 0}},
{28, Interpreter::ps_msub, {"ps_msub", OpType::PS, FL_OUT_FLOAT_D | FL_IN_FLOAT_ABC | FL_RC_BIT_F | FL_USE_FPU | FL_SET_FPRF | FL_PROGRAMEXCEPTION | FL_FLOAT_EXCEPTION, 1, 0, 0, 0}},
{29, Interpreter::ps_madd, {"ps_madd", OpType::PS, FL_OUT_FLOAT_D | FL_IN_FLOAT_ABC | FL_RC_BIT_F | FL_USE_FPU | FL_SET_FPRF | FL_PROGRAMEXCEPTION | FL_FLOAT_EXCEPTION, 1, 0, 0, 0}},
{30, Interpreter::ps_nmsub, {"ps_nmsub", OpType::PS, FL_OUT_FLOAT_D | FL_IN_FLOAT_ABC | FL_RC_BIT_F | FL_USE_FPU | FL_SET_FPRF | FL_PROGRAMEXCEPTION | FL_FLOAT_EXCEPTION, 1, 0, 0, 0}},
{31, Interpreter::ps_nmadd, {"ps_nmadd", OpType::PS, FL_OUT_FLOAT_D | FL_IN_FLOAT_ABC | FL_RC_BIT_F | FL_USE_FPU | FL_SET_FPRF | FL_PROGRAMEXCEPTION | FL_FLOAT_EXCEPTION, 1, 0, 0, 0}},
constexpr std::array<InterpreterOpTemplate, 17> s_table4_2{{
{10, Interpreter::ps_sum0}, // ps_sum0
{11, Interpreter::ps_sum1}, // ps_sum1
{12, Interpreter::ps_muls0}, // ps_muls0
{13, Interpreter::ps_muls1}, // ps_muls1
{14, Interpreter::ps_madds0}, // ps_madds0
{15, Interpreter::ps_madds1}, // ps_madds1
{18, Interpreter::ps_div}, // ps_div
{20, Interpreter::ps_sub}, // ps_sub
{21, Interpreter::ps_add}, // ps_add
{23, Interpreter::ps_sel}, // ps_sel
{24, Interpreter::ps_res}, // ps_res
{25, Interpreter::ps_mul}, // ps_mul
{26, Interpreter::ps_rsqrte}, // ps_rsqrte
{28, Interpreter::ps_msub}, // ps_msub
{29, Interpreter::ps_madd}, // ps_madd
{30, Interpreter::ps_nmsub}, // ps_nmsub
{31, Interpreter::ps_nmadd}, // ps_nmadd
}};
static std::array<GekkoOPTemplate, 4> table4_3 =
{{
{6, Interpreter::psq_lx, {"psq_lx", OpType::LoadPS, FL_OUT_FLOAT_D | FL_IN_A0B | FL_USE_FPU | FL_LOADSTORE, 1, 0, 0, 0}},
{7, Interpreter::psq_stx, {"psq_stx", OpType::StorePS, FL_IN_FLOAT_S | FL_IN_A0B | FL_USE_FPU | FL_LOADSTORE, 1, 0, 0, 0}},
{38, Interpreter::psq_lux, {"psq_lux", OpType::LoadPS, FL_OUT_FLOAT_D | FL_OUT_A | FL_IN_AB | FL_USE_FPU | FL_LOADSTORE, 1, 0, 0, 0}},
{39, Interpreter::psq_stux, {"psq_stux", OpType::StorePS, FL_IN_FLOAT_S | FL_OUT_A | FL_IN_AB | FL_USE_FPU | FL_LOADSTORE, 1, 0, 0, 0}},
constexpr std::array<InterpreterOpTemplate, 4> s_table4_3{{
{6, Interpreter::psq_lx}, // psq_lx
{7, Interpreter::psq_stx}, // psq_stx
{38, Interpreter::psq_lux}, // psq_lux
{39, Interpreter::psq_stux}, // psq_stux
}};
static std::array<GekkoOPTemplate, 13> table19 =
{{
{528, Interpreter::bcctrx, {"bcctrx", OpType::Branch, FL_ENDBLOCK | FL_READ_CR_BI, 1, 0, 0, 0}},
{16, Interpreter::bclrx, {"bclrx", OpType::Branch, FL_ENDBLOCK | FL_READ_CR_BI, 1, 0, 0, 0}},
{257, Interpreter::crand, {"crand", OpType::CR, FL_EVIL, 1, 0, 0, 0}},
{129, Interpreter::crandc, {"crandc", OpType::CR, FL_EVIL, 1, 0, 0, 0}},
{289, Interpreter::creqv, {"creqv", OpType::CR, FL_EVIL, 1, 0, 0, 0}},
{225, Interpreter::crnand, {"crnand", OpType::CR, FL_EVIL, 1, 0, 0, 0}},
{33, Interpreter::crnor, {"crnor", OpType::CR, FL_EVIL, 1, 0, 0, 0}},
{449, Interpreter::cror, {"cror", OpType::CR, FL_EVIL, 1, 0, 0, 0}},
{417, Interpreter::crorc, {"crorc", OpType::CR, FL_EVIL, 1, 0, 0, 0}},
{193, Interpreter::crxor, {"crxor", OpType::CR, FL_EVIL, 1, 0, 0, 0}},
constexpr std::array<InterpreterOpTemplate, 13> s_table19{{
{528, Interpreter::bcctrx}, // bcctrx
{16, Interpreter::bclrx}, // bclrx
{257, Interpreter::crand}, // crand
{129, Interpreter::crandc}, // crandc
{289, Interpreter::creqv}, // creqv
{225, Interpreter::crnand}, // crnand
{33, Interpreter::crnor}, // crnor
{449, Interpreter::cror}, // cror
{417, Interpreter::crorc}, // crorc
{193, Interpreter::crxor}, // crxor
{150, Interpreter::isync, {"isync", OpType::InstructionCache, FL_EVIL, 1, 0, 0, 0}},
{0, Interpreter::mcrf, {"mcrf", OpType::System, FL_EVIL | FL_SET_CRn | FL_READ_CRn, 1, 0, 0, 0}},
{150, Interpreter::isync}, // isync
{0, Interpreter::mcrf}, // mcrf
{50, Interpreter::rfi, {"rfi", OpType::System, FL_ENDBLOCK | FL_CHECKEXCEPTIONS | FL_PROGRAMEXCEPTION, 2, 0, 0, 0}},
{50, Interpreter::rfi}, // rfi
}};
static std::array<GekkoOPTemplate, 107> table31 =
{{
{266, Interpreter::addx, {"addx", OpType::Integer, FL_OUT_D | FL_IN_AB | FL_RC_BIT, 1, 0, 0, 0}},
{778, Interpreter::addx, {"addox", OpType::Integer, FL_OUT_D | FL_IN_AB | FL_RC_BIT | FL_SET_OE, 1, 0, 0, 0}},
{10, Interpreter::addcx, {"addcx", OpType::Integer, FL_OUT_D | FL_IN_AB | FL_SET_CA | FL_RC_BIT, 1, 0, 0, 0}},
{522, Interpreter::addcx, {"addcox", OpType::Integer, FL_OUT_D | FL_IN_AB | FL_SET_CA | FL_RC_BIT | FL_SET_OE, 1, 0, 0, 0}},
{138, Interpreter::addex, {"addex", OpType::Integer, FL_OUT_D | FL_IN_AB | FL_READ_CA | FL_SET_CA | FL_RC_BIT, 1, 0, 0, 0}},
{650, Interpreter::addex, {"addeox", OpType::Integer, FL_OUT_D | FL_IN_AB | FL_READ_CA | FL_SET_CA | FL_RC_BIT | FL_SET_OE, 1, 0, 0, 0}},
{234, Interpreter::addmex, {"addmex", OpType::Integer, FL_OUT_D | FL_IN_A | FL_READ_CA | FL_SET_CA | FL_RC_BIT, 1, 0, 0, 0}},
{746, Interpreter::addmex, {"addmeox", OpType::Integer, FL_OUT_D | FL_IN_A | FL_READ_CA | FL_SET_CA | FL_RC_BIT | FL_SET_OE, 1, 0, 0, 0}},
{202, Interpreter::addzex, {"addzex", OpType::Integer, FL_OUT_D | FL_IN_A | FL_READ_CA | FL_SET_CA | FL_RC_BIT, 1, 0, 0, 0}},
{714, Interpreter::addzex, {"addzeox", OpType::Integer, FL_OUT_D | FL_IN_A | FL_READ_CA | FL_SET_CA | FL_RC_BIT | FL_SET_OE, 1, 0, 0, 0}},
{491, Interpreter::divwx, {"divwx", OpType::Integer, FL_OUT_D | FL_IN_AB | FL_RC_BIT, 40, 0, 0, 0}},
{1003, Interpreter::divwx, {"divwox", OpType::Integer, FL_OUT_D | FL_IN_AB | FL_RC_BIT | FL_SET_OE, 40, 0, 0, 0}},
{459, Interpreter::divwux, {"divwux", OpType::Integer, FL_OUT_D | FL_IN_AB | FL_RC_BIT, 40, 0, 0, 0}},
{971, Interpreter::divwux, {"divwuox", OpType::Integer, FL_OUT_D | FL_IN_AB | FL_RC_BIT | FL_SET_OE, 40, 0, 0, 0}},
{75, Interpreter::mulhwx, {"mulhwx", OpType::Integer, FL_OUT_D | FL_IN_AB | FL_RC_BIT, 5, 0, 0, 0}},
{11, Interpreter::mulhwux, {"mulhwux", OpType::Integer, FL_OUT_D | FL_IN_AB | FL_RC_BIT, 5, 0, 0, 0}},
{235, Interpreter::mullwx, {"mullwx", OpType::Integer, FL_OUT_D | FL_IN_AB | FL_RC_BIT, 5, 0, 0, 0}},
{747, Interpreter::mullwx, {"mullwox", OpType::Integer, FL_OUT_D | FL_IN_AB | FL_RC_BIT | FL_SET_OE, 5, 0, 0, 0}},
{104, Interpreter::negx, {"negx", OpType::Integer, FL_OUT_D | FL_IN_A | FL_RC_BIT, 1, 0, 0, 0}},
{616, Interpreter::negx, {"negox", OpType::Integer, FL_OUT_D | FL_IN_A | FL_RC_BIT | FL_SET_OE, 1, 0, 0, 0}},
{40, Interpreter::subfx, {"subfx", OpType::Integer, FL_OUT_D | FL_IN_AB | FL_RC_BIT, 1, 0, 0, 0}},
{552, Interpreter::subfx, {"subfox", OpType::Integer, FL_OUT_D | FL_IN_AB | FL_RC_BIT | FL_SET_OE, 1, 0, 0, 0}},
{8, Interpreter::subfcx, {"subfcx", OpType::Integer, FL_OUT_D | FL_IN_AB | FL_SET_CA | FL_RC_BIT, 1, 0, 0, 0}},
{520, Interpreter::subfcx, {"subfcox", OpType::Integer, FL_OUT_D | FL_IN_AB | FL_SET_CA | FL_RC_BIT | FL_SET_OE, 1, 0, 0, 0}},
{136, Interpreter::subfex, {"subfex", OpType::Integer, FL_OUT_D | FL_IN_AB | FL_READ_CA | FL_SET_CA | FL_RC_BIT, 1, 0, 0, 0}},
{648, Interpreter::subfex, {"subfeox", OpType::Integer, FL_OUT_D | FL_IN_AB | FL_READ_CA | FL_SET_CA | FL_RC_BIT | FL_SET_OE, 1, 0, 0, 0}},
{232, Interpreter::subfmex, {"subfmex", OpType::Integer, FL_OUT_D | FL_IN_A | FL_READ_CA | FL_SET_CA | FL_RC_BIT, 1, 0, 0, 0}},
{744, Interpreter::subfmex, {"subfmeox",OpType::Integer, FL_OUT_D | FL_IN_A | FL_READ_CA | FL_SET_CA | FL_RC_BIT | FL_SET_OE, 1, 0, 0, 0}},
{200, Interpreter::subfzex, {"subfzex", OpType::Integer, FL_OUT_D | FL_IN_A | FL_READ_CA | FL_SET_CA | FL_RC_BIT, 1, 0, 0, 0}},
{712, Interpreter::subfzex, {"subfzeox",OpType::Integer, FL_OUT_D | FL_IN_A | FL_READ_CA | FL_SET_CA | FL_RC_BIT | FL_SET_OE, 1, 0, 0, 0}},
constexpr std::array<InterpreterOpTemplate, 107> s_table31{{
{266, Interpreter::addx}, // addx
{778, Interpreter::addx}, // addox
{10, Interpreter::addcx}, // addcx
{522, Interpreter::addcx}, // addcox
{138, Interpreter::addex}, // addex
{650, Interpreter::addex}, // addeox
{234, Interpreter::addmex}, // addmex
{746, Interpreter::addmex}, // addmeox
{202, Interpreter::addzex}, // addzex
{714, Interpreter::addzex}, // addzeox
{491, Interpreter::divwx}, // divwx
{1003, Interpreter::divwx}, // divwox
{459, Interpreter::divwux}, // divwux
{971, Interpreter::divwux}, // divwuox
{75, Interpreter::mulhwx}, // mulhwx
{11, Interpreter::mulhwux}, // mulhwux
{235, Interpreter::mullwx}, // mullwx
{747, Interpreter::mullwx}, // mullwox
{104, Interpreter::negx}, // negx
{616, Interpreter::negx}, // negox
{40, Interpreter::subfx}, // subfx
{552, Interpreter::subfx}, // subfox
{8, Interpreter::subfcx}, // subfcx
{520, Interpreter::subfcx}, // subfcox
{136, Interpreter::subfex}, // subfex
{648, Interpreter::subfex}, // subfeox
{232, Interpreter::subfmex}, // subfmex
{744, Interpreter::subfmex}, // subfmeox
{200, Interpreter::subfzex}, // subfzex
{712, Interpreter::subfzex}, // subfzeox
{28, Interpreter::andx, {"andx", OpType::Integer, FL_OUT_A | FL_IN_SB | FL_RC_BIT, 1, 0, 0, 0}},
{60, Interpreter::andcx, {"andcx", OpType::Integer, FL_OUT_A | FL_IN_SB | FL_RC_BIT, 1, 0, 0, 0}},
{444, Interpreter::orx, {"orx", OpType::Integer, FL_OUT_A | FL_IN_SB | FL_RC_BIT, 1, 0, 0, 0}},
{124, Interpreter::norx, {"norx", OpType::Integer, FL_OUT_A | FL_IN_SB | FL_RC_BIT, 1, 0, 0, 0}},
{316, Interpreter::xorx, {"xorx", OpType::Integer, FL_OUT_A | FL_IN_SB | FL_RC_BIT, 1, 0, 0, 0}},
{412, Interpreter::orcx, {"orcx", OpType::Integer, FL_OUT_A | FL_IN_SB | FL_RC_BIT, 1, 0, 0, 0}},
{476, Interpreter::nandx, {"nandx", OpType::Integer, FL_OUT_A | FL_IN_SB | FL_RC_BIT, 1, 0, 0, 0}},
{284, Interpreter::eqvx, {"eqvx", OpType::Integer, FL_OUT_A | FL_IN_SB | FL_RC_BIT, 1, 0, 0, 0}},
{0, Interpreter::cmp, {"cmp", OpType::Integer, FL_IN_AB | FL_SET_CRn, 1, 0, 0, 0}},
{32, Interpreter::cmpl, {"cmpl", OpType::Integer, FL_IN_AB | FL_SET_CRn, 1, 0, 0, 0}},
{26, Interpreter::cntlzwx, {"cntlzwx",OpType::Integer, FL_OUT_A | FL_IN_S | FL_RC_BIT, 1, 0, 0, 0}},
{922, Interpreter::extshx, {"extshx", OpType::Integer, FL_OUT_A | FL_IN_S | FL_RC_BIT, 1, 0, 0, 0}},
{954, Interpreter::extsbx, {"extsbx", OpType::Integer, FL_OUT_A | FL_IN_S | FL_RC_BIT, 1, 0, 0, 0}},
{536, Interpreter::srwx, {"srwx", OpType::Integer, FL_OUT_A | FL_IN_SB | FL_RC_BIT, 1, 0, 0, 0}},
{792, Interpreter::srawx, {"srawx", OpType::Integer, FL_OUT_A | FL_IN_SB | FL_SET_CA | FL_RC_BIT, 1, 0, 0, 0}},
{824, Interpreter::srawix, {"srawix", OpType::Integer, FL_OUT_A | FL_IN_S | FL_SET_CA | FL_RC_BIT, 1, 0, 0, 0}},
{24, Interpreter::slwx, {"slwx", OpType::Integer, FL_OUT_A | FL_IN_SB | FL_RC_BIT, 1, 0, 0, 0}},
{28, Interpreter::andx}, // andx
{60, Interpreter::andcx}, // andcx
{444, Interpreter::orx}, // orx
{124, Interpreter::norx}, // norx
{316, Interpreter::xorx}, // xorx
{412, Interpreter::orcx}, // orcx
{476, Interpreter::nandx}, // nandx
{284, Interpreter::eqvx}, // eqvx
{0, Interpreter::cmp}, // cmp
{32, Interpreter::cmpl}, // cmpl
{26, Interpreter::cntlzwx}, // cntlzwx
{922, Interpreter::extshx}, // extshx
{954, Interpreter::extsbx}, // extsbx
{536, Interpreter::srwx}, // srwx
{792, Interpreter::srawx}, // srawx
{824, Interpreter::srawix}, // srawix
{24, Interpreter::slwx}, // slwx
{54, Interpreter::dcbst, {"dcbst", OpType::DataCache, FL_IN_A0B | FL_LOADSTORE, 5, 0, 0, 0}},
{86, Interpreter::dcbf, {"dcbf", OpType::DataCache, FL_IN_A0B | FL_LOADSTORE, 5, 0, 0, 0}},
{246, Interpreter::dcbtst, {"dcbtst", OpType::DataCache, 0, 2, 0, 0, 0}},
{278, Interpreter::dcbt, {"dcbt", OpType::DataCache, 0, 2, 0, 0, 0}},
{470, Interpreter::dcbi, {"dcbi", OpType::DataCache, FL_IN_A0B | FL_LOADSTORE | FL_PROGRAMEXCEPTION, 5, 0, 0, 0}},
{758, Interpreter::dcba, {"dcba", OpType::DataCache, 0, 5, 0, 0, 0}},
{1014, Interpreter::dcbz, {"dcbz", OpType::DataCache, FL_IN_A0B | FL_LOADSTORE, 5, 0, 0, 0}},
{54, Interpreter::dcbst}, // dcbst
{86, Interpreter::dcbf}, // dcbf
{246, Interpreter::dcbtst}, // dcbtst
{278, Interpreter::dcbt}, // dcbt
{470, Interpreter::dcbi}, // dcbi
{758, Interpreter::dcba}, // dcba
{1014, Interpreter::dcbz}, // dcbz
//load word
{23, Interpreter::lwzx, {"lwzx", OpType::Load, FL_OUT_D | FL_IN_A0B | FL_LOADSTORE, 1, 0, 0, 0}},
{55, Interpreter::lwzux, {"lwzux", OpType::Load, FL_OUT_D | FL_OUT_A | FL_IN_AB | FL_LOADSTORE, 1, 0, 0, 0}},
// load word
{23, Interpreter::lwzx}, // lwzx
{55, Interpreter::lwzux}, // lwzux
//load halfword
{279, Interpreter::lhzx, {"lhzx", OpType::Load, FL_OUT_D | FL_IN_A0B | FL_LOADSTORE, 1, 0, 0, 0}},
{311, Interpreter::lhzux, {"lhzux", OpType::Load, FL_OUT_D | FL_OUT_A | FL_IN_AB | FL_LOADSTORE, 1, 0, 0, 0}},
// load halfword
{279, Interpreter::lhzx}, // lhzx
{311, Interpreter::lhzux}, // lhzux
//load halfword signextend
{343, Interpreter::lhax, {"lhax", OpType::Load, FL_OUT_D | FL_IN_A0B | FL_LOADSTORE, 1, 0, 0, 0}},
{375, Interpreter::lhaux, {"lhaux", OpType::Load, FL_OUT_D | FL_OUT_A | FL_IN_AB | FL_LOADSTORE, 1, 0, 0, 0}},
// load halfword signextend
{343, Interpreter::lhax}, // lhax
{375, Interpreter::lhaux}, // lhaux
//load byte
{87, Interpreter::lbzx, {"lbzx", OpType::Load, FL_OUT_D | FL_IN_A0B | FL_LOADSTORE, 1, 0, 0, 0}},
{119, Interpreter::lbzux, {"lbzux", OpType::Load, FL_OUT_D | FL_OUT_A | FL_IN_AB | FL_LOADSTORE, 1, 0, 0, 0}},
// load byte
{87, Interpreter::lbzx}, // lbzx
{119, Interpreter::lbzux}, // lbzux
//load byte reverse
{534, Interpreter::lwbrx, {"lwbrx", OpType::Load, FL_OUT_D | FL_IN_A0B | FL_LOADSTORE, 1, 0, 0, 0}},
{790, Interpreter::lhbrx, {"lhbrx", OpType::Load, FL_OUT_D | FL_IN_A0B | FL_LOADSTORE, 1, 0, 0, 0}},
// load byte reverse
{534, Interpreter::lwbrx}, // lwbrx
{790, Interpreter::lhbrx}, // lhbrx
// Conditional load/store (Wii SMP)
{150, Interpreter::stwcxd, {"stwcxd", OpType::Store, FL_EVIL | FL_IN_S | FL_IN_A0B | FL_SET_CR0 | FL_LOADSTORE, 1, 0, 0, 0}},
{20, Interpreter::lwarx, {"lwarx", OpType::Load, FL_EVIL | FL_OUT_D | FL_IN_A0B | FL_SET_CR0 | FL_LOADSTORE, 1, 0, 0, 0}},
// Conditional load/store (Wii SMP)
{150, Interpreter::stwcxd}, // stwcxd
{20, Interpreter::lwarx}, // lwarx
//load string (Inst these)
{533, Interpreter::lswx, {"lswx", OpType::Load, FL_EVIL | FL_IN_A0B | FL_OUT_D | FL_LOADSTORE, 1, 0, 0, 0}},
{597, Interpreter::lswi, {"lswi", OpType::Load, FL_EVIL | FL_IN_A0 | FL_OUT_D | FL_LOADSTORE, 1, 0, 0, 0}},
// load string (Inst these)
{533, Interpreter::lswx}, // lswx
{597, Interpreter::lswi}, // lswi
//store word
{151, Interpreter::stwx, {"stwx", OpType::Store, FL_IN_S | FL_IN_A0B | FL_LOADSTORE, 1, 0, 0, 0}},
{183, Interpreter::stwux, {"stwux", OpType::Store, FL_IN_S | FL_OUT_A | FL_IN_AB | FL_LOADSTORE, 1, 0, 0, 0}},
// store word
{151, Interpreter::stwx}, // stwx
{183, Interpreter::stwux}, // stwux
//store halfword
{407, Interpreter::sthx, {"sthx", OpType::Store, FL_IN_S | FL_IN_A0B | FL_LOADSTORE, 1, 0, 0, 0}},
{439, Interpreter::sthux, {"sthux", OpType::Store, FL_IN_S | FL_OUT_A | FL_IN_AB | FL_LOADSTORE, 1, 0, 0, 0}},
// store halfword
{407, Interpreter::sthx}, // sthx
{439, Interpreter::sthux}, // sthux
//store byte
{215, Interpreter::stbx, {"stbx", OpType::Store, FL_IN_S | FL_IN_A0B | FL_LOADSTORE, 1, 0, 0, 0}},
{247, Interpreter::stbux, {"stbux", OpType::Store, FL_IN_S | FL_OUT_A | FL_IN_AB | FL_LOADSTORE, 1, 0, 0, 0}},
// store byte
{215, Interpreter::stbx}, // stbx
{247, Interpreter::stbux}, // stbux
//store bytereverse
{662, Interpreter::stwbrx, {"stwbrx", OpType::Store, FL_IN_S | FL_IN_A0B | FL_LOADSTORE, 1, 0, 0, 0}},
{918, Interpreter::sthbrx, {"sthbrx", OpType::Store, FL_IN_S | FL_IN_A0B | FL_LOADSTORE, 1, 0, 0, 0}},
// store bytereverse
{662, Interpreter::stwbrx}, // stwbrx
{918, Interpreter::sthbrx}, // sthbrx
{661, Interpreter::stswx, {"stswx", OpType::Store, FL_EVIL | FL_IN_A0B | FL_LOADSTORE, 1, 0, 0, 0}},
{725, Interpreter::stswi, {"stswi", OpType::Store, FL_EVIL | FL_IN_A0 | FL_LOADSTORE, 1, 0, 0, 0}},
{661, Interpreter::stswx}, // stswx
{725, Interpreter::stswi}, // stswi
// fp load/store
{535, Interpreter::lfsx, {"lfsx", OpType::LoadFP, FL_OUT_FLOAT_D | FL_IN_A0B | FL_USE_FPU | FL_LOADSTORE, 1, 0, 0, 0}},
{567, Interpreter::lfsux, {"lfsux", OpType::LoadFP, FL_OUT_FLOAT_D | FL_IN_AB | FL_OUT_A | FL_USE_FPU | FL_LOADSTORE, 1, 0, 0, 0}},
{599, Interpreter::lfdx, {"lfdx", OpType::LoadFP, FL_INOUT_FLOAT_D | FL_IN_A0B | FL_USE_FPU | FL_LOADSTORE, 1, 0, 0, 0}},
{631, Interpreter::lfdux, {"lfdux", OpType::LoadFP, FL_INOUT_FLOAT_D | FL_IN_AB | FL_OUT_A | FL_USE_FPU | FL_LOADSTORE, 1, 0, 0, 0}},
// fp load/store
{535, Interpreter::lfsx}, // lfsx
{567, Interpreter::lfsux}, // lfsux
{599, Interpreter::lfdx}, // lfdx
{631, Interpreter::lfdux}, // lfdux
{663, Interpreter::stfsx, {"stfsx", OpType::StoreFP, FL_IN_FLOAT_S | FL_IN_A0B | FL_USE_FPU | FL_LOADSTORE, 1, 0, 0, 0}},
{695, Interpreter::stfsux, {"stfsux", OpType::StoreFP, FL_IN_FLOAT_S | FL_IN_AB | FL_OUT_A | FL_USE_FPU | FL_LOADSTORE, 1, 0, 0, 0}},
{727, Interpreter::stfdx, {"stfdx", OpType::StoreFP, FL_IN_FLOAT_S | FL_IN_A0B | FL_USE_FPU | FL_LOADSTORE, 1, 0, 0, 0}},
{759, Interpreter::stfdux, {"stfdux", OpType::StoreFP, FL_IN_FLOAT_S | FL_IN_AB | FL_OUT_A | FL_USE_FPU | FL_LOADSTORE, 1, 0, 0, 0}},
{983, Interpreter::stfiwx, {"stfiwx", OpType::StoreFP, FL_IN_FLOAT_S | FL_IN_A0B | FL_USE_FPU | FL_LOADSTORE, 1, 0, 0, 0}},
{663, Interpreter::stfsx}, // stfsx
{695, Interpreter::stfsux}, // stfsux
{727, Interpreter::stfdx}, // stfdx
{759, Interpreter::stfdux}, // stfdux
{983, Interpreter::stfiwx}, // stfiwx
{19, Interpreter::mfcr, {"mfcr", OpType::System, FL_OUT_D | FL_READ_ALL_CR, 1, 0, 0, 0}},
{83, Interpreter::mfmsr, {"mfmsr", OpType::System, FL_OUT_D | FL_PROGRAMEXCEPTION, 1, 0, 0, 0}},
{144, Interpreter::mtcrf, {"mtcrf", OpType::System, FL_IN_S | FL_SET_ALL_CR | FL_READ_ALL_CR, 1, 0, 0, 0}},
{146, Interpreter::mtmsr, {"mtmsr", OpType::System, FL_IN_S | FL_ENDBLOCK | FL_PROGRAMEXCEPTION | FL_FLOAT_EXCEPTION, 1, 0, 0, 0}},
{210, Interpreter::mtsr, {"mtsr", OpType::System, FL_IN_S | FL_PROGRAMEXCEPTION, 1, 0, 0, 0}},
{242, Interpreter::mtsrin, {"mtsrin", OpType::System, FL_IN_SB | FL_PROGRAMEXCEPTION, 1, 0, 0, 0}},
{339, Interpreter::mfspr, {"mfspr", OpType::SPR, FL_OUT_D | FL_PROGRAMEXCEPTION, 1, 0, 0, 0}},
{467, Interpreter::mtspr, {"mtspr", OpType::SPR, FL_IN_S | FL_PROGRAMEXCEPTION, 2, 0, 0, 0}},
{371, Interpreter::mftb, {"mftb", OpType::System, FL_OUT_D | FL_TIMER | FL_PROGRAMEXCEPTION, 1, 0, 0, 0}},
{512, Interpreter::mcrxr, {"mcrxr", OpType::System, FL_SET_CRn | FL_READ_CA | FL_SET_CA, 1, 0, 0, 0}},
{595, Interpreter::mfsr, {"mfsr", OpType::System, FL_OUT_D | FL_PROGRAMEXCEPTION, 3, 0, 0, 0}},
{659, Interpreter::mfsrin, {"mfsrin", OpType::System, FL_OUT_D | FL_IN_B | FL_PROGRAMEXCEPTION, 3, 0, 0, 0}},
{19, Interpreter::mfcr}, // mfcr
{83, Interpreter::mfmsr}, // mfmsr
{144, Interpreter::mtcrf}, // mtcrf
{146, Interpreter::mtmsr}, // mtmsr
{210, Interpreter::mtsr}, // mtsr
{242, Interpreter::mtsrin}, // mtsrin
{339, Interpreter::mfspr}, // mfspr
{467, Interpreter::mtspr}, // mtspr
{371, Interpreter::mftb}, // mftb
{512, Interpreter::mcrxr}, // mcrxr
{595, Interpreter::mfsr}, // mfsr
{659, Interpreter::mfsrin}, // mfsrin
{4, Interpreter::tw, {"tw", OpType::System, FL_IN_AB | FL_ENDBLOCK, 2, 0, 0, 0}},
{598, Interpreter::sync, {"sync", OpType::System, 0, 3, 0, 0, 0}},
{982, Interpreter::icbi, {"icbi", OpType::System, FL_IN_A0B | FL_ENDBLOCK | FL_LOADSTORE, 4, 0, 0, 0}},
{4, Interpreter::tw}, // tw
{598, Interpreter::sync}, // sync
{982, Interpreter::icbi}, // icbi
// Unused instructions on GC
{310, Interpreter::eciwx, {"eciwx", OpType::System, FL_IN_A0B | FL_OUT_D | FL_LOADSTORE, 1, 0, 0, 0}},
{438, Interpreter::ecowx, {"ecowx", OpType::System, FL_IN_A0B | FL_IN_S | FL_LOADSTORE, 1, 0, 0, 0}},
{854, Interpreter::eieio, {"eieio", OpType::System, 0, 1, 0, 0, 0}},
{306, Interpreter::tlbie, {"tlbie", OpType::System, FL_IN_B | FL_PROGRAMEXCEPTION, 1, 0, 0, 0}},
{566, Interpreter::tlbsync, {"tlbsync", OpType::System, FL_PROGRAMEXCEPTION, 1, 0, 0, 0}},
// Unused instructions on GC
{310, Interpreter::eciwx}, // eciwx
{438, Interpreter::ecowx}, // ecowx
{854, Interpreter::eieio}, // eieio
{306, Interpreter::tlbie}, // tlbie
{566, Interpreter::tlbsync}, // tlbsync
}};
static std::array<GekkoOPTemplate, 9> table59 =
{{
{18, Interpreter::fdivsx, {"fdivsx", OpType::SingleFP, FL_OUT_FLOAT_D | FL_IN_FLOAT_AB | FL_RC_BIT_F | FL_USE_FPU | FL_SET_FPRF | FL_FLOAT_EXCEPTION | FL_FLOAT_DIV, 17, 0, 0, 0}}, // TODO
{20, Interpreter::fsubsx, {"fsubsx", OpType::SingleFP, FL_OUT_FLOAT_D | FL_IN_FLOAT_AB | FL_RC_BIT_F | FL_USE_FPU | FL_SET_FPRF | FL_FLOAT_EXCEPTION, 1, 0, 0, 0}},
{21, Interpreter::faddsx, {"faddsx", OpType::SingleFP, FL_OUT_FLOAT_D | FL_IN_FLOAT_AB | FL_RC_BIT_F | FL_USE_FPU | FL_SET_FPRF | FL_FLOAT_EXCEPTION, 1, 0, 0, 0}},
{24, Interpreter::fresx, {"fresx", OpType::SingleFP, FL_OUT_FLOAT_D | FL_IN_FLOAT_B | FL_RC_BIT_F | FL_USE_FPU | FL_SET_FPRF | FL_FLOAT_EXCEPTION | FL_FLOAT_DIV, 1, 0, 0, 0}},
{25, Interpreter::fmulsx, {"fmulsx", OpType::SingleFP, FL_OUT_FLOAT_D | FL_IN_FLOAT_AC | FL_RC_BIT_F | FL_USE_FPU | FL_SET_FPRF | FL_FLOAT_EXCEPTION, 1, 0, 0, 0}},
{28, Interpreter::fmsubsx, {"fmsubsx", OpType::SingleFP, FL_OUT_FLOAT_D | FL_IN_FLOAT_ABC | FL_RC_BIT_F | FL_USE_FPU | FL_SET_FPRF | FL_FLOAT_EXCEPTION, 1, 0, 0, 0}},
{29, Interpreter::fmaddsx, {"fmaddsx", OpType::SingleFP, FL_OUT_FLOAT_D | FL_IN_FLOAT_ABC | FL_RC_BIT_F | FL_USE_FPU | FL_SET_FPRF | FL_FLOAT_EXCEPTION, 1, 0, 0, 0}},
{30, Interpreter::fnmsubsx, {"fnmsubsx", OpType::SingleFP, FL_OUT_FLOAT_D | FL_IN_FLOAT_ABC | FL_RC_BIT_F | FL_USE_FPU | FL_SET_FPRF | FL_FLOAT_EXCEPTION, 1, 0, 0, 0}},
{31, Interpreter::fnmaddsx, {"fnmaddsx", OpType::SingleFP, FL_OUT_FLOAT_D | FL_IN_FLOAT_ABC | FL_RC_BIT_F | FL_USE_FPU | FL_SET_FPRF | FL_FLOAT_EXCEPTION, 1, 0, 0, 0}},
constexpr std::array<InterpreterOpTemplate, 9> s_table59{{
{18, Interpreter::fdivsx}, // fdivsx // TODO
{20, Interpreter::fsubsx}, // fsubsx
{21, Interpreter::faddsx}, // faddsx
{24, Interpreter::fresx}, // fresx
{25, Interpreter::fmulsx}, // fmulsx
{28, Interpreter::fmsubsx}, // fmsubsx
{29, Interpreter::fmaddsx}, // fmaddsx
{30, Interpreter::fnmsubsx}, // fnmsubsx
{31, Interpreter::fnmaddsx}, // fnmaddsx
}};
static std::array<GekkoOPTemplate, 15> table63 =
{{
{264, Interpreter::fabsx, {"fabsx", OpType::DoubleFP, FL_INOUT_FLOAT_D | FL_IN_FLOAT_B | FL_IN_FLOAT_B_BITEXACT | FL_RC_BIT_F | FL_USE_FPU, 1, 0, 0, 0}},
constexpr std::array<InterpreterOpTemplate, 15> s_table63{{
{264, Interpreter::fabsx}, // fabsx
{32, Interpreter::fcmpo}, // fcmpo
{0, Interpreter::fcmpu}, // fcmpu
{14, Interpreter::fctiwx}, // fctiwx
{15, Interpreter::fctiwzx}, // fctiwzx
{72, Interpreter::fmrx}, // fmrx
{136, Interpreter::fnabsx}, // fnabsx
{40, Interpreter::fnegx}, // fnegx
{12, Interpreter::frspx}, // frspx
// FIXME: fcmp modifies the FPRF flags, but if the flags are clobbered later,
// we don't actually need to calculate or store them here. So FL_READ_FPRF and FL_SET_FPRF is not
// an ideal representation of fcmp's effect on FPRF flags and might result in
// slightly sub-optimal code.
{32, Interpreter::fcmpo, {"fcmpo", OpType::DoubleFP, FL_IN_FLOAT_AB | FL_SET_CRn | FL_USE_FPU | FL_READ_FPRF | FL_SET_FPRF | FL_FLOAT_EXCEPTION, 1, 0, 0, 0}},
{0, Interpreter::fcmpu, {"fcmpu", OpType::DoubleFP, FL_IN_FLOAT_AB | FL_SET_CRn | FL_USE_FPU | FL_READ_FPRF | FL_SET_FPRF | FL_FLOAT_EXCEPTION, 1, 0, 0, 0}},
{14, Interpreter::fctiwx, {"fctiwx", OpType::DoubleFP, FL_INOUT_FLOAT_D | FL_IN_FLOAT_B | FL_RC_BIT_F | FL_USE_FPU | FL_FLOAT_EXCEPTION, 1, 0, 0, 0}},
{15, Interpreter::fctiwzx, {"fctiwzx", OpType::DoubleFP, FL_INOUT_FLOAT_D | FL_IN_FLOAT_B | FL_RC_BIT_F | FL_USE_FPU | FL_FLOAT_EXCEPTION, 1, 0, 0, 0}},
{72, Interpreter::fmrx, {"fmrx", OpType::DoubleFP, FL_INOUT_FLOAT_D | FL_IN_FLOAT_B | FL_IN_FLOAT_B_BITEXACT | FL_RC_BIT_F | FL_USE_FPU, 1, 0, 0, 0}},
{136, Interpreter::fnabsx, {"fnabsx", OpType::DoubleFP, FL_INOUT_FLOAT_D | FL_IN_FLOAT_B | FL_RC_BIT_F | FL_IN_FLOAT_B_BITEXACT | FL_USE_FPU, 1, 0, 0, 0}},
{40, Interpreter::fnegx, {"fnegx", OpType::DoubleFP, FL_INOUT_FLOAT_D | FL_IN_FLOAT_B | FL_RC_BIT_F | FL_IN_FLOAT_B_BITEXACT | FL_USE_FPU, 1, 0, 0, 0}},
{12, Interpreter::frspx, {"frspx", OpType::DoubleFP, FL_OUT_FLOAT_D | FL_IN_FLOAT_B | FL_RC_BIT_F | FL_USE_FPU | FL_SET_FPRF | FL_FLOAT_EXCEPTION, 1, 0, 0, 0}},
{64, Interpreter::mcrfs, {"mcrfs", OpType::SystemFP, FL_SET_CRn | FL_USE_FPU | FL_READ_FPRF, 1, 0, 0, 0}},
{583, Interpreter::mffsx, {"mffsx", OpType::SystemFP, FL_RC_BIT_F | FL_INOUT_FLOAT_D | FL_USE_FPU | FL_READ_FPRF, 1, 0, 0, 0}},
{70, Interpreter::mtfsb0x, {"mtfsb0x", OpType::SystemFP, FL_RC_BIT_F | FL_USE_FPU | FL_READ_FPRF | FL_SET_FPRF, 3, 0, 0, 0}},
{38, Interpreter::mtfsb1x, {"mtfsb1x", OpType::SystemFP, FL_RC_BIT_F | FL_USE_FPU | FL_READ_FPRF | FL_SET_FPRF | FL_FLOAT_EXCEPTION, 3, 0, 0, 0}},
{134, Interpreter::mtfsfix, {"mtfsfix", OpType::SystemFP, FL_RC_BIT_F | FL_USE_FPU | FL_READ_FPRF | FL_SET_FPRF | FL_FLOAT_EXCEPTION, 3, 0, 0, 0}},
{711, Interpreter::mtfsfx, {"mtfsfx", OpType::SystemFP, FL_RC_BIT_F | FL_IN_FLOAT_B | FL_USE_FPU | FL_READ_FPRF | FL_SET_FPRF | FL_FLOAT_EXCEPTION, 3, 0, 0, 0}},
{64, Interpreter::mcrfs}, // mcrfs
{583, Interpreter::mffsx}, // mffsx
{70, Interpreter::mtfsb0x}, // mtfsb0x
{38, Interpreter::mtfsb1x}, // mtfsb1x
{134, Interpreter::mtfsfix}, // mtfsfix
{711, Interpreter::mtfsfx}, // mtfsfx
}};
static std::array<GekkoOPTemplate, 10> table63_2 =
{{
{18, Interpreter::fdivx, {"fdivx", OpType::DoubleFP, FL_INOUT_FLOAT_D | FL_IN_FLOAT_AB | FL_RC_BIT_F | FL_USE_FPU | FL_SET_FPRF | FL_FLOAT_EXCEPTION | FL_FLOAT_DIV, 31, 0, 0, 0}},
{20, Interpreter::fsubx, {"fsubx", OpType::DoubleFP, FL_INOUT_FLOAT_D | FL_IN_FLOAT_AB | FL_RC_BIT_F | FL_USE_FPU | FL_SET_FPRF | FL_FLOAT_EXCEPTION, 1, 0, 0, 0}},
{21, Interpreter::faddx, {"faddx", OpType::DoubleFP, FL_INOUT_FLOAT_D | FL_IN_FLOAT_AB | FL_RC_BIT_F | FL_USE_FPU | FL_SET_FPRF | FL_FLOAT_EXCEPTION, 1, 0, 0, 0}},
{23, Interpreter::fselx, {"fselx", OpType::DoubleFP, FL_INOUT_FLOAT_D | FL_IN_FLOAT_ABC | FL_IN_FLOAT_BC_BITEXACT | FL_RC_BIT_F | FL_USE_FPU, 1, 0, 0, 0}},
{25, Interpreter::fmulx, {"fmulx", OpType::DoubleFP, FL_INOUT_FLOAT_D | FL_IN_FLOAT_AC | FL_RC_BIT_F | FL_USE_FPU | FL_SET_FPRF | FL_FLOAT_EXCEPTION, 1, 0, 0, 0}},
{26, Interpreter::frsqrtex, {"frsqrtex", OpType::DoubleFP, FL_INOUT_FLOAT_D | FL_IN_FLOAT_B | FL_RC_BIT_F | FL_USE_FPU | FL_SET_FPRF | FL_FLOAT_EXCEPTION | FL_FLOAT_DIV, 1, 0, 0, 0}},
{28, Interpreter::fmsubx, {"fmsubx", OpType::DoubleFP, FL_INOUT_FLOAT_D | FL_IN_FLOAT_ABC | FL_RC_BIT_F | FL_USE_FPU | FL_SET_FPRF | FL_FLOAT_EXCEPTION, 1, 0, 0, 0}},
{29, Interpreter::fmaddx, {"fmaddx", OpType::DoubleFP, FL_INOUT_FLOAT_D | FL_IN_FLOAT_ABC | FL_RC_BIT_F | FL_USE_FPU | FL_SET_FPRF | FL_FLOAT_EXCEPTION, 1, 0, 0, 0}},
{30, Interpreter::fnmsubx, {"fnmsubx", OpType::DoubleFP, FL_INOUT_FLOAT_D | FL_IN_FLOAT_ABC | FL_RC_BIT_F | FL_USE_FPU | FL_SET_FPRF | FL_FLOAT_EXCEPTION, 1, 0, 0, 0}},
{31, Interpreter::fnmaddx, {"fnmaddx", OpType::DoubleFP, FL_INOUT_FLOAT_D | FL_IN_FLOAT_ABC | FL_RC_BIT_F | FL_USE_FPU | FL_SET_FPRF | FL_FLOAT_EXCEPTION, 1, 0, 0, 0}},
constexpr std::array<InterpreterOpTemplate, 10> s_table63_2{{
{18, Interpreter::fdivx}, // fdivx
{20, Interpreter::fsubx}, // fsubx
{21, Interpreter::faddx}, // faddx
{23, Interpreter::fselx}, // fselx
{25, Interpreter::fmulx}, // fmulx
{26, Interpreter::frsqrtex}, // frsqrtex
{28, Interpreter::fmsubx}, // fmsubx
{29, Interpreter::fmaddx}, // fmaddx
{30, Interpreter::fnmsubx}, // fnmsubx
{31, Interpreter::fnmaddx}, // fnmaddx
}};
// clang-format on
constexpr size_t TotalInstructionFunctionCount()
constexpr std::array<Interpreter::Instruction, 64> s_interpreter_op_table = []() consteval
{
return primarytable.size() + table4_2.size() + table4_3.size() + table4.size() + table31.size() +
table19.size() + table59.size() + table63.size() + table63_2.size();
std::array<Interpreter::Instruction, 64> table{};
Common::Fill(table, Interpreter::unknown_instruction);
for (auto& tpl : s_primary_table)
{
ASSERT(table[tpl.opcode] == Interpreter::unknown_instruction);
table[tpl.opcode] = tpl.fn;
};
return table;
}
();
constexpr std::array<Interpreter::Instruction, 1024> s_interpreter_op_table4 = []() consteval
{
std::array<Interpreter::Instruction, 1024> table{};
Common::Fill(table, Interpreter::unknown_instruction);
for (u32 i = 0; i < 32; i++)
{
const u32 fill = i << 5;
for (const auto& tpl : s_table4_2)
{
const u32 op = fill + tpl.opcode;
ASSERT(table[op] == Interpreter::unknown_instruction);
table[op] = tpl.fn;
}
}
for (u32 i = 0; i < 16; i++)
{
const u32 fill = i << 6;
for (const auto& tpl : s_table4_3)
{
const u32 op = fill + tpl.opcode;
ASSERT(table[op] == Interpreter::unknown_instruction);
table[op] = tpl.fn;
}
}
for (const auto& tpl : s_table4)
{
const u32 op = tpl.opcode;
ASSERT(table[op] == Interpreter::unknown_instruction);
table[op] = tpl.fn;
}
return table;
}
();
constexpr std::array<Interpreter::Instruction, 1024> s_interpreter_op_table19 = []() consteval
{
std::array<Interpreter::Instruction, 1024> table{};
Common::Fill(table, Interpreter::unknown_instruction);
for (auto& tpl : s_table19)
{
ASSERT(table[tpl.opcode] == Interpreter::unknown_instruction);
table[tpl.opcode] = tpl.fn;
};
return table;
}
();
constexpr std::array<Interpreter::Instruction, 1024> s_interpreter_op_table31 = []() consteval
{
std::array<Interpreter::Instruction, 1024> table{};
Common::Fill(table, Interpreter::unknown_instruction);
for (auto& tpl : s_table31)
{
ASSERT(table[tpl.opcode] == Interpreter::unknown_instruction);
table[tpl.opcode] = tpl.fn;
};
return table;
}
();
constexpr std::array<Interpreter::Instruction, 32> s_interpreter_op_table59 = []() consteval
{
std::array<Interpreter::Instruction, 32> table{};
Common::Fill(table, Interpreter::unknown_instruction);
for (auto& tpl : s_table59)
{
ASSERT(table[tpl.opcode] == Interpreter::unknown_instruction);
table[tpl.opcode] = tpl.fn;
};
return table;
}
();
constexpr std::array<Interpreter::Instruction, 1024> s_interpreter_op_table63 = []() consteval
{
std::array<Interpreter::Instruction, 1024> table{};
Common::Fill(table, Interpreter::unknown_instruction);
for (auto& tpl : s_table63)
{
ASSERT(table[tpl.opcode] == Interpreter::unknown_instruction);
table[tpl.opcode] = tpl.fn;
};
for (u32 i = 0; i < 32; i++)
{
const u32 fill = i << 5;
for (const auto& tpl : s_table63_2)
{
const u32 op = fill + tpl.opcode;
ASSERT(table[op] == Interpreter::unknown_instruction);
table[op] = tpl.fn;
}
}
return table;
}
();
Interpreter::Instruction Interpreter::GetInterpreterOp(UGeckoInstruction inst)
{
// Check for the appropriate subtable ahead of time.
// (This is used by the cached interpreter and JIT, and called once per instruction, so spending a
// bit of extra time to optimise is worthwhile)
Interpreter::Instruction result = s_interpreter_op_table[inst.OPCD];
if (result == Interpreter::RunTable4)
return s_interpreter_op_table4[inst.SUBOP10];
else if (result == Interpreter::RunTable19)
return s_interpreter_op_table19[inst.SUBOP10];
else if (result == Interpreter::RunTable31)
return s_interpreter_op_table31[inst.SUBOP10];
else if (result == Interpreter::RunTable59)
return s_interpreter_op_table59[inst.SUBOP5];
else if (result == Interpreter::RunTable63)
return s_interpreter_op_table63[inst.SUBOP10];
else
return result;
}
static_assert(TotalInstructionFunctionCount() < m_allInstructions.size(),
"m_allInstructions is too small");
void Interpreter::InitializeInstructionTables()
void Interpreter::RunInterpreterOp(UGeckoInstruction inst)
{
// once initialized, tables are read-only
static bool initialized = false;
if (initialized)
return;
// clear
for (int i = 0; i < 64; i++)
{
m_op_table[i] = Interpreter::unknown_instruction;
m_infoTable[i] = &unknownopinfo;
}
for (int i = 0; i < 32; i++)
{
m_op_table59[i] = Interpreter::unknown_instruction;
m_infoTable59[i] = &unknownopinfo;
}
for (int i = 0; i < 1024; i++)
{
m_op_table4[i] = Interpreter::unknown_instruction;
m_op_table19[i] = Interpreter::unknown_instruction;
m_op_table31[i] = Interpreter::unknown_instruction;
m_op_table63[i] = Interpreter::unknown_instruction;
m_infoTable4[i] = &unknownopinfo;
m_infoTable19[i] = &unknownopinfo;
m_infoTable31[i] = &unknownopinfo;
m_infoTable63[i] = &unknownopinfo;
}
for (auto& tpl : primarytable)
{
m_op_table[tpl.opcode] = tpl.Inst;
m_infoTable[tpl.opcode] = &tpl.opinfo;
}
for (int i = 0; i < 32; i++)
{
int fill = i << 5;
for (auto& tpl : table4_2)
{
int op = fill + tpl.opcode;
m_op_table4[op] = tpl.Inst;
m_infoTable4[op] = &tpl.opinfo;
}
}
for (int i = 0; i < 16; i++)
{
int fill = i << 6;
for (auto& tpl : table4_3)
{
int op = fill + tpl.opcode;
m_op_table4[op] = tpl.Inst;
m_infoTable4[op] = &tpl.opinfo;
}
}
for (auto& tpl : table4)
{
int op = tpl.opcode;
m_op_table4[op] = tpl.Inst;
m_infoTable4[op] = &tpl.opinfo;
}
for (auto& tpl : table31)
{
int op = tpl.opcode;
m_op_table31[op] = tpl.Inst;
m_infoTable31[op] = &tpl.opinfo;
}
for (auto& tpl : table19)
{
int op = tpl.opcode;
m_op_table19[op] = tpl.Inst;
m_infoTable19[op] = &tpl.opinfo;
}
for (auto& tpl : table59)
{
int op = tpl.opcode;
m_op_table59[op] = tpl.Inst;
m_infoTable59[op] = &tpl.opinfo;
}
for (auto& tpl : table63)
{
int op = tpl.opcode;
m_op_table63[op] = tpl.Inst;
m_infoTable63[op] = &tpl.opinfo;
}
for (int i = 0; i < 32; i++)
{
int fill = i << 5;
for (auto& tpl : table63_2)
{
int op = fill + tpl.opcode;
m_op_table63[op] = tpl.Inst;
m_infoTable63[op] = &tpl.opinfo;
}
}
m_numInstructions = 0;
for (auto& tpl : primarytable)
m_allInstructions[m_numInstructions++] = &tpl.opinfo;
for (auto& tpl : table4_2)
m_allInstructions[m_numInstructions++] = &tpl.opinfo;
for (auto& tpl : table4_3)
m_allInstructions[m_numInstructions++] = &tpl.opinfo;
for (auto& tpl : table4)
m_allInstructions[m_numInstructions++] = &tpl.opinfo;
for (auto& tpl : table31)
m_allInstructions[m_numInstructions++] = &tpl.opinfo;
for (auto& tpl : table19)
m_allInstructions[m_numInstructions++] = &tpl.opinfo;
for (auto& tpl : table59)
m_allInstructions[m_numInstructions++] = &tpl.opinfo;
for (auto& tpl : table63)
m_allInstructions[m_numInstructions++] = &tpl.opinfo;
for (auto& tpl : table63_2)
m_allInstructions[m_numInstructions++] = &tpl.opinfo;
initialized = true;
// Will handle subtables using RunTable4 etc.
s_interpreter_op_table[inst.OPCD](inst);
}
void Interpreter::RunTable4(UGeckoInstruction inst)
{
s_interpreter_op_table4[inst.SUBOP10](inst);
}
void Interpreter::RunTable19(UGeckoInstruction inst)
{
s_interpreter_op_table19[inst.SUBOP10](inst);
}
void Interpreter::RunTable31(UGeckoInstruction inst)
{
s_interpreter_op_table31[inst.SUBOP10](inst);
}
void Interpreter::RunTable59(UGeckoInstruction inst)
{
s_interpreter_op_table59[inst.SUBOP5](inst);
}
void Interpreter::RunTable63(UGeckoInstruction inst)
{
s_interpreter_op_table63[inst.SUBOP10](inst);
}