From c73f4bd2266c92b1e1b2eee2ebe10627bc7b5e32 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Thu, 19 Jan 2017 14:48:59 -0500 Subject: [PATCH] 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. --- Source/Core/Core/DSP/DSPMemoryMap.cpp | 2 +- Source/Core/Core/DSP/DSPTables.cpp | 44 +++++++++----- Source/Core/Core/DSP/DSPTables.h | 8 +-- .../Core/DSP/Interpreter/DSPInterpreter.cpp | 5 +- Source/Core/Core/DSP/Jit/DSPEmitter.cpp | 58 +++++++------------ Source/Core/Core/DSP/Jit/DSPJitBranch.cpp | 25 ++++---- 6 files changed, 69 insertions(+), 73 deletions(-) diff --git a/Source/Core/Core/DSP/DSPMemoryMap.cpp b/Source/Core/Core/DSP/DSPMemoryMap.cpp index c19d6947f2..19cced93ff 100644 --- a/Source/Core/Core/DSP/DSPMemoryMap.cpp +++ b/Source/Core/Core/DSP/DSPMemoryMap.cpp @@ -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 diff --git a/Source/Core/Core/DSP/DSPTables.cpp b/Source/Core/Core/DSP/DSPTables.cpp index e14a944903..f0bfee47cb 100644 --- a/Source/Core/Core/DSP/DSPTables.cpp +++ b/Source/Core/Core/DSP/DSPTables.cpp @@ -479,8 +479,6 @@ const std::array regnames = }}; // clang-format on -std::array opTable; -std::array extOpTable; std::array writeBackLog; std::array 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 s_op_table; +std::array 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); } diff --git a/Source/Core/Core/DSP/DSPTables.h b/Source/Core/Core/DSP/DSPTables.h index d93c7f0b40..194c7cb0bb 100644 --- a/Source/Core/Core/DSP/DSPTables.h +++ b/Source/Core/Core/DSP/DSPTables.h @@ -94,12 +94,7 @@ extern const std::array opcodes; extern const std::array 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 opTable; -extern std::array extOpTable; extern std::array writeBackLog; extern std::array 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 diff --git a/Source/Core/Core/DSP/Interpreter/DSPInterpreter.cpp b/Source/Core/Core/DSP/Interpreter/DSPInterpreter.cpp index a7a4a2e12d..d874f878bb 100644 --- a/Source/Core/Core/DSP/Interpreter/DSPInterpreter.cpp +++ b/Source/Core/Core/DSP/Interpreter/DSPInterpreter.cpp @@ -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); diff --git a/Source/Core/Core/DSP/Jit/DSPEmitter.cpp b/Source/Core/Core/DSP/Jit/DSPEmitter.cpp index f89c604485..0b11b922a4 100644 --- a/Source/Core/Core/DSP/Jit/DSPEmitter.cpp +++ b/Source/Core/Core/DSP/Jit/DSPEmitter.cpp @@ -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) + const DSPOPCTemplate* const ext_op_template = GetExtOpTemplate(inst); + + if (!ext_op_template->jitFunc) { - if (!extOpTable[inst & 0x7F]->jitFunc) - { - // Fall back to interpreter - gpr.PushRegs(); - ABI_CallFunctionC16(extOpTable[inst & 0x7F]->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); - ext_is_jit = true; - } + // Fall back to interpreter + gpr.PushRegs(); + ABI_CallFunctionC16(ext_op_template->intFunc, inst); + gpr.PopRegs(); + INFO_LOG(DSPLLE, "Instruction not JITed(ext part): %04x", inst); + ext_is_jit = false; } 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; - } + (this->*ext_op_template->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) { diff --git a/Source/Core/Core/DSP/Jit/DSPJitBranch.cpp b/Source/Core/Core/DSP/Jit/DSPJitBranch.cpp index 356bf9731e..e60cbaed64 100644 --- a/Source/Core/Core/DSP/Jit/DSPJitBranch.cpp +++ b/Source/Core/Core/DSP/Jit/DSPJitBranch.cpp @@ -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(opc, *this); WriteBranchExit(*this); } @@ -347,8 +350,8 @@ void DSPEmitter::loop(const UDSPInstruction opc) FixupBranch exit = J(true); SetJumpTarget(cnt); - // dsp_skip_inst(); - MOV(16, M(&g_dsp.pc), Imm16(loop_pc + opTable[dsp_imem_read(loop_pc)]->size)); + // dsp_skip_inst(); + MOV(16, M(&g_dsp.pc), Imm16(loop_pc + GetOpTemplate(dsp_imem_read(loop_pc))->size)); WriteBranchExit(*this); gpr.FlushRegs(c, false); SetJumpTarget(exit); @@ -380,8 +383,8 @@ 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)); + // dsp_skip_inst(); + MOV(16, M(&g_dsp.pc), Imm16(loop_pc + GetOpTemplate(dsp_imem_read(loop_pc))->size)); WriteBranchExit(*this); } } @@ -416,9 +419,9 @@ void DSPEmitter::bloop(const UDSPInstruction opc) FixupBranch exit = J(true); 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)); + // g_dsp.pc = loop_pc; + // dsp_skip_inst(); + MOV(16, M(&g_dsp.pc), Imm16(loop_pc + GetOpTemplate(dsp_imem_read(loop_pc))->size)); WriteBranchExit(*this); gpr.FlushRegs(c, false); SetJumpTarget(exit); @@ -452,9 +455,9 @@ void DSPEmitter::bloopi(const UDSPInstruction opc) } else { - // g_dsp.pc = loop_pc; - // dsp_skip_inst(); - MOV(16, M(&g_dsp.pc), Imm16(loop_pc + opTable[dsp_imem_read(loop_pc)]->size)); + // g_dsp.pc = loop_pc; + // dsp_skip_inst(); + MOV(16, M(&g_dsp.pc), Imm16(loop_pc + GetOpTemplate(dsp_imem_read(loop_pc))->size)); WriteBranchExit(*this); } }