DSPTables: Hide main opcode tables

Hides the opcode tables that the interpreter and JIT interface with to
execute instructions.

This does not, however, hide the read-only tables that the assembler and
disassembler use.
This commit is contained in:
Lioncash 2017-01-19 14:48:59 -05:00
parent 2b5b21f2a4
commit c73f4bd226
6 changed files with 69 additions and 73 deletions

View File

@ -82,6 +82,6 @@ u16 dsp_peek_code()
void dsp_skip_inst()
{
g_dsp.pc += opTable[dsp_peek_code()]->size;
g_dsp.pc += GetOpTemplate(dsp_peek_code())->size;
}
} // namespace DSP

View File

@ -479,8 +479,6 @@ const std::array<pdlabel_t, 36> regnames =
}};
// clang-format on
std::array<const DSPOPCTemplate*, OPTABLE_SIZE> opTable;
std::array<const DSPOPCTemplate*, EXT_OPTABLE_SIZE> extOpTable;
std::array<u16, WRITEBACK_LOG_SIZE> writeBackLog;
std::array<int, WRITEBACK_LOG_SIZE> writeBackLogIdx;
@ -508,9 +506,27 @@ const char* pdregnamelong(int val)
return regnames[val].description;
}
const DSPOPCTemplate* GetOpTemplate(const UDSPInstruction& inst)
namespace
{
return opTable[inst];
constexpr size_t OPTABLE_SIZE = 0xffff + 1;
constexpr size_t EXT_OPTABLE_SIZE = 0xff + 1;
std::array<const DSPOPCTemplate*, OPTABLE_SIZE> s_op_table;
std::array<const DSPOPCTemplate*, EXT_OPTABLE_SIZE> s_ext_op_table;
} // Anonymous namespace
const DSPOPCTemplate* GetOpTemplate(UDSPInstruction inst)
{
return s_op_table[inst];
}
const DSPOPCTemplate* GetExtOpTemplate(UDSPInstruction inst)
{
const bool has_seven_bit_extension = (inst >> 12) == 0x3;
if (has_seven_bit_extension)
return s_ext_op_table[inst & 0x7F];
return s_ext_op_table[inst & 0xFF];
}
// This function could use the above GetOpTemplate, but then we'd lose the
@ -518,27 +534,27 @@ const DSPOPCTemplate* GetOpTemplate(const UDSPInstruction& inst)
void InitInstructionTable()
{
// ext op table
for (size_t i = 0; i < extOpTable.size(); i++)
for (size_t i = 0; i < s_ext_op_table.size(); i++)
{
extOpTable[i] = &cw;
s_ext_op_table[i] = &cw;
for (const DSPOPCTemplate& ext : opcodes_ext)
{
u16 mask = ext.opcode_mask;
if ((mask & i) == ext.opcode)
{
if (extOpTable[i] == &cw)
if (s_ext_op_table[i] == &cw)
{
extOpTable[i] = &ext;
s_ext_op_table[i] = &ext;
}
else
{
// if the entry already in the table
// is a strict subset, allow it
if ((extOpTable[i]->opcode_mask | ext.opcode_mask) != extOpTable[i]->opcode_mask)
if ((s_ext_op_table[i]->opcode_mask | ext.opcode_mask) != s_ext_op_table[i]->opcode_mask)
{
ERROR_LOG(DSPLLE, "opcode ext table place %zu already in use by %s when inserting %s",
i, extOpTable[i]->name, ext.name);
i, s_ext_op_table[i]->name, ext.name);
}
}
}
@ -546,17 +562,17 @@ void InitInstructionTable()
}
// op table
opTable.fill(&cw);
s_op_table.fill(&cw);
for (size_t i = 0; i < opTable.size(); i++)
for (size_t i = 0; i < s_op_table.size(); i++)
{
for (const DSPOPCTemplate& opcode : opcodes)
{
u16 mask = opcode.opcode_mask;
if ((mask & i) == opcode.opcode)
{
if (opTable[i] == &cw)
opTable[i] = &opcode;
if (s_op_table[i] == &cw)
s_op_table[i] = &opcode;
else
ERROR_LOG(DSPLLE, "opcode table place %zu already in use for %s", i, opcode.name);
}

View File

@ -94,12 +94,7 @@ extern const std::array<DSPOPCTemplate, 214> opcodes;
extern const std::array<DSPOPCTemplate, 25> opcodes_ext;
extern const DSPOPCTemplate cw;
constexpr size_t OPTABLE_SIZE = 0xffff + 1;
constexpr size_t EXT_OPTABLE_SIZE = 0xff + 1;
constexpr size_t WRITEBACK_LOG_SIZE = 5;
extern std::array<const DSPOPCTemplate*, OPTABLE_SIZE> opTable;
extern std::array<const DSPOPCTemplate*, EXT_OPTABLE_SIZE> extOpTable;
extern std::array<u16, WRITEBACK_LOG_SIZE> writeBackLog;
extern std::array<int, WRITEBACK_LOG_SIZE> writeBackLogIdx;
@ -123,5 +118,6 @@ void applyWriteBackLog();
void zeroWriteBackLog();
void zeroWriteBackLogPreserveAcc(u8 acc);
const DSPOPCTemplate* GetOpTemplate(const UDSPInstruction& inst);
const DSPOPCTemplate* GetOpTemplate(UDSPInstruction inst);
const DSPOPCTemplate* GetExtOpTemplate(UDSPInstruction inst);
} // namespace DSP

View File

@ -25,10 +25,7 @@ void ExecuteInstruction(const UDSPInstruction inst)
if (opcode_template->extended)
{
if ((inst >> 12) == 0x3)
extOpTable[inst & 0x7F]->intFunc(inst);
else
extOpTable[inst & 0xFF]->intFunc(inst);
GetExtOpTemplate(inst)->intFunc(inst);
}
opcode_template->intFunc(inst);

View File

@ -105,7 +105,9 @@ bool DSPEmitter::FlagsNeeded() const
void DSPEmitter::FallBackToInterpreter(UDSPInstruction inst)
{
if (opTable[inst]->reads_pc)
const DSPOPCTemplate* const op_template = GetOpTemplate(inst);
if (op_template->reads_pc)
{
// Increment PC - we shouldn't need to do this for every instruction. only for branches and end
// of block.
@ -116,68 +118,50 @@ void DSPEmitter::FallBackToInterpreter(UDSPInstruction inst)
// Fall back to interpreter
gpr.PushRegs();
_assert_msg_(DSPLLE, opTable[inst]->intFunc, "No function for %04x", inst);
ABI_CallFunctionC16(opTable[inst]->intFunc, inst);
_assert_msg_(DSPLLE, op_template->intFunc, "No function for %04x", inst);
ABI_CallFunctionC16(op_template->intFunc, inst);
gpr.PopRegs();
}
void DSPEmitter::EmitInstruction(UDSPInstruction inst)
{
const DSPOPCTemplate* tinst = GetOpTemplate(inst);
const DSPOPCTemplate* const op_template = GetOpTemplate(inst);
bool ext_is_jit = false;
// Call extended
if (tinst->extended)
if (op_template->extended)
{
if ((inst >> 12) == 0x3)
{
if (!extOpTable[inst & 0x7F]->jitFunc)
const DSPOPCTemplate* const ext_op_template = GetExtOpTemplate(inst);
if (!ext_op_template->jitFunc)
{
// Fall back to interpreter
gpr.PushRegs();
ABI_CallFunctionC16(extOpTable[inst & 0x7F]->intFunc, inst);
ABI_CallFunctionC16(ext_op_template->intFunc, inst);
gpr.PopRegs();
INFO_LOG(DSPLLE, "Instruction not JITed(ext part): %04x", inst);
ext_is_jit = false;
}
else
{
(this->*extOpTable[inst & 0x7F]->jitFunc)(inst);
(this->*ext_op_template->jitFunc)(inst);
ext_is_jit = true;
}
}
else
{
if (!extOpTable[inst & 0xFF]->jitFunc)
{
// Fall back to interpreter
gpr.PushRegs();
ABI_CallFunctionC16(extOpTable[inst & 0xFF]->intFunc, inst);
gpr.PopRegs();
INFO_LOG(DSPLLE, "Instruction not JITed(ext part): %04x", inst);
ext_is_jit = false;
}
else
{
(this->*extOpTable[inst & 0xFF]->jitFunc)(inst);
ext_is_jit = true;
}
}
}
// Main instruction
if (!opTable[inst]->jitFunc)
if (!op_template->jitFunc)
{
FallBackToInterpreter(inst);
INFO_LOG(DSPLLE, "Instruction not JITed(main part): %04x", inst);
}
else
{
(this->*opTable[inst]->jitFunc)(inst);
(this->*op_template->jitFunc)(inst);
}
// Backlog
if (tinst->extended)
if (op_template->extended)
{
if (!ext_is_jit)
{

View File

@ -232,7 +232,10 @@ static void r_ifcc(const UDSPInstruction opc, DSPEmitter& emitter)
// NOTE: Cannot use FallBackToInterpreter(opc) here because of the need to write branch exit
void DSPEmitter::ifcc(const UDSPInstruction opc)
{
MOV(16, M(&g_dsp.pc), Imm16((compilePC + 1) + opTable[dsp_imem_read(compilePC + 1)]->size));
const u16 address = compilePC + 1;
const DSPOPCTemplate* const op_template = GetOpTemplate(dsp_imem_read(address));
MOV(16, M(&g_dsp.pc), Imm16(address + op_template->size));
ReJitConditional<r_ifcc>(opc, *this);
WriteBranchExit(*this);
}
@ -348,7 +351,7 @@ void DSPEmitter::loop(const UDSPInstruction opc)
SetJumpTarget(cnt);
// dsp_skip_inst();
MOV(16, M(&g_dsp.pc), Imm16(loop_pc + opTable[dsp_imem_read(loop_pc)]->size));
MOV(16, M(&g_dsp.pc), Imm16(loop_pc + GetOpTemplate(dsp_imem_read(loop_pc))->size));
WriteBranchExit(*this);
gpr.FlushRegs(c, false);
SetJumpTarget(exit);
@ -381,7 +384,7 @@ void DSPEmitter::loopi(const UDSPInstruction opc)
else
{
// dsp_skip_inst();
MOV(16, M(&g_dsp.pc), Imm16(loop_pc + opTable[dsp_imem_read(loop_pc)]->size));
MOV(16, M(&g_dsp.pc), Imm16(loop_pc + GetOpTemplate(dsp_imem_read(loop_pc))->size));
WriteBranchExit(*this);
}
}
@ -418,7 +421,7 @@ void DSPEmitter::bloop(const UDSPInstruction opc)
SetJumpTarget(cnt);
// g_dsp.pc = loop_pc;
// dsp_skip_inst();
MOV(16, M(&g_dsp.pc), Imm16(loop_pc + opTable[dsp_imem_read(loop_pc)]->size));
MOV(16, M(&g_dsp.pc), Imm16(loop_pc + GetOpTemplate(dsp_imem_read(loop_pc))->size));
WriteBranchExit(*this);
gpr.FlushRegs(c, false);
SetJumpTarget(exit);
@ -454,7 +457,7 @@ void DSPEmitter::bloopi(const UDSPInstruction opc)
{
// g_dsp.pc = loop_pc;
// dsp_skip_inst();
MOV(16, M(&g_dsp.pc), Imm16(loop_pc + opTable[dsp_imem_read(loop_pc)]->size));
MOV(16, M(&g_dsp.pc), Imm16(loop_pc + GetOpTemplate(dsp_imem_read(loop_pc))->size));
WriteBranchExit(*this);
}
}