Merge pull request #4691 from lioncash/dsptables

DSPTables: Hide/Eliminate some extern variables
This commit is contained in:
Matthew Parlane 2017-01-21 12:39:47 +13:00 committed by GitHub
commit a945b4ea9b
10 changed files with 144 additions and 154 deletions

View File

@ -5,6 +5,7 @@
#include "Core/DSP/DSPAssembler.h" #include "Core/DSP/DSPAssembler.h"
#include <cstddef>
#include <cstdio> #include <cstdio>
#include <cstdlib> #include <cstdlib>
#include <cstring> #include <cstring>
@ -441,29 +442,29 @@ u32 DSPAssembler::GetParams(char* parstr, param_t* par)
return count; return count;
} }
const opc_t* DSPAssembler::FindOpcode(const char* opcode, u32 par_count, const opc_t* const opcod, const opc_t* DSPAssembler::FindOpcode(const char* name, u32 par_count, const opc_t* const opcodes,
int opcod_size) size_t opcodes_size)
{ {
if (opcode[0] == 'C' && opcode[1] == 'W') if (name[0] == 'C' && name[1] == 'W')
return &cw; return &cw;
AliasMap::const_iterator alias_iter = aliases.find(opcode); const auto alias_iter = aliases.find(name);
if (alias_iter != aliases.end()) if (alias_iter != aliases.end())
opcode = alias_iter->second.c_str(); name = alias_iter->second.c_str();
for (int i = 0; i < opcod_size; i++) for (size_t i = 0; i < opcodes_size; i++)
{ {
const opc_t* opc = &opcod[i]; const opc_t* opcode = &opcodes[i];
if (strcmp(opc->name, opcode) == 0) if (strcmp(opcode->name, name) == 0)
{ {
if (par_count < opc->param_count) if (par_count < opcode->param_count)
{ {
ShowError(ERR_NOT_ENOUGH_PARAMETERS); ShowError(ERR_NOT_ENOUGH_PARAMETERS);
} }
if (par_count > opc->param_count) else if (par_count > opcode->param_count)
{ {
ShowError(ERR_TOO_MANY_PARAMETERS); ShowError(ERR_TOO_MANY_PARAMETERS);
} }
return opc; return opcode;
} }
} }
ShowError(ERR_UNKNOWN_OPCODE); ShowError(ERR_UNKNOWN_OPCODE);
@ -478,11 +479,11 @@ static u16 get_mask_shifted_down(u16 mask)
return mask; return mask;
} }
bool DSPAssembler::VerifyParams(const opc_t* opc, param_t* par, int count, bool ext) bool DSPAssembler::VerifyParams(const opc_t* opc, param_t* par, size_t count, bool ext)
{ {
for (int i = 0; i < count; i++) for (size_t i = 0; i < count; i++)
{ {
const int current_param = i + 1; // just for display. const size_t current_param = i + 1; // just for display.
if (opc->params[i].type != par[i].type || (par[i].type & P_REG)) if (opc->params[i].type != par[i].type || (par[i].type & P_REG))
{ {
if (par[i].type == P_VAL && if (par[i].type == P_VAL &&
@ -510,7 +511,7 @@ bool DSPAssembler::VerifyParams(const opc_t* opc, param_t* par, int count, bool
if (ext) if (ext)
fprintf(stderr, "(ext) "); fprintf(stderr, "(ext) ");
fprintf(stderr, "%s (param %i)", cur_line.c_str(), current_param); fprintf(stderr, "%s (param %zu)", cur_line.c_str(), current_param);
ShowError(ERR_INVALID_REGISTER); ShowError(ERR_INVALID_REGISTER);
} }
break; break;
@ -520,7 +521,7 @@ bool DSPAssembler::VerifyParams(const opc_t* opc, param_t* par, int count, bool
if (ext) if (ext)
fprintf(stderr, "(ext) "); fprintf(stderr, "(ext) ");
fprintf(stderr, "%s (param %i)", cur_line.c_str(), current_param); fprintf(stderr, "%s (param %zu)", cur_line.c_str(), current_param);
ShowError(ERR_INVALID_REGISTER); ShowError(ERR_INVALID_REGISTER);
} }
break; break;
@ -534,14 +535,14 @@ bool DSPAssembler::VerifyParams(const opc_t* opc, param_t* par, int count, bool
{ {
fprintf(stderr, "%i : %s ", code_line, cur_line.c_str()); fprintf(stderr, "%i : %s ", code_line, cur_line.c_str());
fprintf(stderr, "WARNING: $ACM%d register used instead of $ACC%d register Line: %d " fprintf(stderr, "WARNING: $ACM%d register used instead of $ACC%d register Line: %d "
"Param: %d Ext: %d\n", "Param: %zu Ext: %d\n",
(par[i].val & 1), (par[i].val & 1), code_line, current_param, ext); (par[i].val & 1), (par[i].val & 1), code_line, current_param, ext);
} }
else if (par[i].val >= 0x1c && par[i].val <= 0x1d) else if (par[i].val >= 0x1c && par[i].val <= 0x1d)
{ {
fprintf( fprintf(
stderr, stderr,
"WARNING: $ACL%d register used instead of $ACC%d register Line: %d Param: %d\n", "WARNING: $ACL%d register used instead of $ACC%d register Line: %d Param: %zu\n",
(par[i].val & 1), (par[i].val & 1), code_line, current_param); (par[i].val & 1), (par[i].val & 1), code_line, current_param);
} }
else else
@ -560,14 +561,14 @@ bool DSPAssembler::VerifyParams(const opc_t* opc, param_t* par, int count, bool
{ {
fprintf( fprintf(
stderr, stderr,
"WARNING: $ACL%d register used instead of $ACM%d register Line: %d Param: %d\n", "WARNING: $ACL%d register used instead of $ACM%d register Line: %d Param: %zu\n",
(par[i].val & 1), (par[i].val & 1), code_line, current_param); (par[i].val & 1), (par[i].val & 1), code_line, current_param);
} }
else if (par[i].val >= 0x20 && par[i].val <= 0x21) else if (par[i].val >= 0x20 && par[i].val <= 0x21)
{ {
fprintf( fprintf(
stderr, stderr,
"WARNING: $ACC%d register used instead of $ACM%d register Line: %d Param: %d\n", "WARNING: $ACC%d register used instead of $ACM%d register Line: %d Param: %zu\n",
(par[i].val & 1), (par[i].val & 1), code_line, current_param); (par[i].val & 1), (par[i].val & 1), code_line, current_param);
} }
else else
@ -588,7 +589,7 @@ bool DSPAssembler::VerifyParams(const opc_t* opc, param_t* par, int count, bool
fprintf(stderr, "%s ", cur_line.c_str()); fprintf(stderr, "%s ", cur_line.c_str());
fprintf( fprintf(
stderr, stderr,
"WARNING: $ACM%d register used instead of $ACL%d register Line: %d Param: %d\n", "WARNING: $ACM%d register used instead of $ACL%d register Line: %d Param: %zu\n",
(par[i].val & 1), (par[i].val & 1), code_line, current_param); (par[i].val & 1), (par[i].val & 1), code_line, current_param);
} }
else if (par[i].val >= 0x20 && par[i].val <= 0x21) else if (par[i].val >= 0x20 && par[i].val <= 0x21)
@ -596,7 +597,7 @@ bool DSPAssembler::VerifyParams(const opc_t* opc, param_t* par, int count, bool
fprintf(stderr, "%s ", cur_line.c_str()); fprintf(stderr, "%s ", cur_line.c_str());
fprintf( fprintf(
stderr, stderr,
"WARNING: $ACC%d register used instead of $ACL%d register Line: %d Param: %d\n", "WARNING: $ACC%d register used instead of $ACL%d register Line: %d Param: %zu\n",
(par[i].val & 1), (par[i].val & 1), code_line, current_param); (par[i].val & 1), (par[i].val & 1), code_line, current_param);
} }
else else
@ -987,7 +988,7 @@ bool DSPAssembler::AssembleFile(const char* fname, int pass)
continue; continue;
} }
const opc_t* opc = FindOpcode(opcode, params_count, opcodes, opcodes_size); const opc_t* opc = FindOpcode(opcode, params_count, opcodes.data(), opcodes.size());
if (!opc) if (!opc)
opc = &cw; opc = &cw;
@ -1001,7 +1002,7 @@ bool DSPAssembler::AssembleFile(const char* fname, int pass)
{ {
if (opcode_ext) if (opcode_ext)
{ {
opc_ext = FindOpcode(opcode_ext, params_count_ext, opcodes_ext, opcodes_ext_size); opc_ext = FindOpcode(opcode_ext, params_count_ext, opcodes_ext.data(), opcodes_ext.size());
VerifyParams(opc_ext, params_ext, params_count_ext, true); VerifyParams(opc_ext, params_ext, params_count_ext, true);
} }
else if (params_count_ext) else if (params_count_ext)

View File

@ -5,6 +5,7 @@
#pragma once #pragma once
#include <cstddef>
#include <map> #include <map>
#include <string> #include <string>
@ -89,9 +90,9 @@ private:
// void ShowWarning(err_t err_code, const char *extra_info = nullptr); // void ShowWarning(err_t err_code, const char *extra_info = nullptr);
char* FindBrackets(char* src, char* dst); char* FindBrackets(char* src, char* dst);
const opc_t* FindOpcode(const char* opcode, u32 par_count, const opc_t* const opcod, const opc_t* FindOpcode(const char* name, u32 par_count, const opc_t* opcodes,
int opcod_size); size_t opcodes_size);
bool VerifyParams(const opc_t* opc, param_t* par, int count, bool ext = false); bool VerifyParams(const opc_t* opc, param_t* par, size_t count, bool ext = false);
void BuildCode(const opc_t* opc, param_t* par, u32 par_count, u16* outbuf); void BuildCode(const opc_t* opc, param_t* par, u32 par_count, u16* outbuf);
char* gdg_buffer; char* gdg_buffer;

View File

@ -186,13 +186,13 @@ bool DSPDisassembler::DisassembleOpcode(const u16* binbuf, int base_addr, int pa
const DSPOPCTemplate* opc_ext = nullptr; const DSPOPCTemplate* opc_ext = nullptr;
// find opcode // find opcode
for (int j = 0; j < opcodes_size; j++) for (const auto& opcode : opcodes)
{ {
u16 mask = opcodes[j].opcode_mask; u16 mask = opcode.opcode_mask;
if ((op1 & mask) == opcodes[j].opcode) if ((op1 & mask) == opcode.opcode)
{ {
opc = &opcodes[j]; opc = &opcode;
break; break;
} }
} }
@ -220,21 +220,21 @@ bool DSPDisassembler::DisassembleOpcode(const u16* binbuf, int base_addr, int pa
{ {
// opcode has an extension // opcode has an extension
// find opcode // find opcode
for (int j = 0; j < opcodes_ext_size; j++) for (const auto& opcode_ext : opcodes_ext)
{ {
if (only7bitext) if (only7bitext)
{ {
if (((op1 & 0x7f) & opcodes_ext[j].opcode_mask) == opcodes_ext[j].opcode) if (((op1 & 0x7f) & opcode_ext.opcode_mask) == opcode_ext.opcode)
{ {
opc_ext = &opcodes_ext[j]; opc_ext = &opcode_ext;
break; break;
} }
} }
else else
{ {
if ((op1 & opcodes_ext[j].opcode_mask) == opcodes_ext[j].opcode) if ((op1 & opcode_ext.opcode_mask) == opcode_ext.opcode)
{ {
opc_ext = &opcodes_ext[j]; opc_ext = &opcode_ext;
break; break;
} }
} }

View File

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

View File

@ -6,6 +6,9 @@
#include "Core/DSP/DSPTables.h" #include "Core/DSP/DSPTables.h"
#include <array>
#include <cstddef>
#include "Common/CommonTypes.h" #include "Common/CommonTypes.h"
#include "Core/DSP/Interpreter/DSPIntExtOps.h" #include "Core/DSP/Interpreter/DSPIntExtOps.h"
@ -17,8 +20,8 @@ namespace DSP
using JIT::x86::DSPEmitter; using JIT::x86::DSPEmitter;
// clang-format off // clang-format off
const DSPOPCTemplate opcodes[] = const std::array<DSPOPCTemplate, 214> opcodes =
{ {{
// # of parameters----+ {type, size, loc, lshift, mask} branch reads PC // instruction approximation // # of parameters----+ {type, size, loc, lshift, mask} branch reads PC // instruction approximation
// name opcode mask interpreter function JIT function size-V V param 1 param 2 param 3 extendable uncond. updates SR // name opcode mask interpreter function JIT function size-V V param 1 param 2 param 3 extendable uncond. updates SR
{"NOP", 0x0000, 0xfffc, Interpreter::nop, &DSPEmitter::nop, 1, 0, {}, false, false, false, false, false}, // no operation {"NOP", 0x0000, 0xfffc, Interpreter::nop, &DSPEmitter::nop, 1, 0, {}, false, false, false, false, false}, // no operation
@ -286,15 +289,15 @@ const DSPOPCTemplate opcodes[] =
{"ADDPAXZ", 0xf800, 0xfc00, Interpreter::addpaxz, &DSPEmitter::addpaxz,1, 2, {{P_ACC, 1, 0, 9, 0x0200}, {P_AX, 1, 0, 8, 0x0100}}, true, false, false, false, true}, // $acD.hm = $prod.hm + $ax.h; $acD.l = 0 {"ADDPAXZ", 0xf800, 0xfc00, Interpreter::addpaxz, &DSPEmitter::addpaxz,1, 2, {{P_ACC, 1, 0, 9, 0x0200}, {P_AX, 1, 0, 8, 0x0100}}, true, false, false, false, true}, // $acD.hm = $prod.hm + $ax.h; $acD.l = 0
{"CLRL", 0xfc00, 0xfe00, Interpreter::clrl, &DSPEmitter::clrl, 1, 1, {{P_ACCL, 1, 0, 11, 0x0800}}, true, false, false, false, true}, // $acR.l = 0 {"CLRL", 0xfc00, 0xfe00, Interpreter::clrl, &DSPEmitter::clrl, 1, 1, {{P_ACCL, 1, 0, 11, 0x0800}}, true, false, false, false, true}, // $acR.l = 0
{"MOVPZ", 0xfe00, 0xfe00, Interpreter::movpz, &DSPEmitter::movpz, 1, 1, {{P_ACC, 1, 0, 8, 0x0100}}, true, false, false, false, true}, // $acD.hm = $prod.hm; $acD.l = 0 {"MOVPZ", 0xfe00, 0xfe00, Interpreter::movpz, &DSPEmitter::movpz, 1, 1, {{P_ACC, 1, 0, 8, 0x0100}}, true, false, false, false, true}, // $acD.hm = $prod.hm; $acD.l = 0
}; }};
const DSPOPCTemplate cw = const DSPOPCTemplate cw =
{"CW", 0x0000, 0x0000, Interpreter::nop, nullptr, 1, 1, {{P_VAL, 2, 0, 0, 0xffff}}, false, false, false, false, false}; {"CW", 0x0000, 0x0000, Interpreter::nop, nullptr, 1, 1, {{P_VAL, 2, 0, 0, 0xffff}}, false, false, false, false, false};
// extended opcodes // extended opcodes
const DSPOPCTemplate opcodes_ext[] = const std::array<DSPOPCTemplate, 25> opcodes_ext =
{ {{
{"XXX", 0x0000, 0x00fc, Interpreter::Ext::nop, &DSPEmitter::nop, 1, 1, {{P_VAL, 1, 0, 0, 0x00ff}}, false, false, false, false, false}, // no operation {"XXX", 0x0000, 0x00fc, Interpreter::Ext::nop, &DSPEmitter::nop, 1, 1, {{P_VAL, 1, 0, 0, 0x00ff}}, false, false, false, false, false}, // no operation
{"DR", 0x0004, 0x00fc, Interpreter::Ext::dr, &DSPEmitter::dr, 1, 1, {{P_REG, 1, 0, 0, 0x0003}}, false, false, false, false, false}, // $arR-- {"DR", 0x0004, 0x00fc, Interpreter::Ext::dr, &DSPEmitter::dr, 1, 1, {{P_REG, 1, 0, 0, 0x0003}}, false, false, false, false, false}, // $arR--
@ -326,13 +329,10 @@ const DSPOPCTemplate opcodes_ext[] =
{"LDN", 0x00c4, 0x00cc, Interpreter::Ext::ldn, &DSPEmitter::ldn, 1, 3, {{P_REGM18, 1, 0, 4, 0x0020}, {P_REGM19, 1, 0, 3, 0x0010}, {P_PRG, 1, 0, 0, 0x0003}}, false, false, false, false, false}, // $ax0.D = MEM[$arS]; $ax1.R = MEM[$ar3++]; $arS += $ixS {"LDN", 0x00c4, 0x00cc, Interpreter::Ext::ldn, &DSPEmitter::ldn, 1, 3, {{P_REGM18, 1, 0, 4, 0x0020}, {P_REGM19, 1, 0, 3, 0x0010}, {P_PRG, 1, 0, 0, 0x0003}}, false, false, false, false, false}, // $ax0.D = MEM[$arS]; $ax1.R = MEM[$ar3++]; $arS += $ixS
{"LDM", 0x00c8, 0x00cc, Interpreter::Ext::ldm, &DSPEmitter::ldm, 1, 3, {{P_REGM18, 1, 0, 4, 0x0020}, {P_REGM19, 1, 0, 3, 0x0010}, {P_PRG, 1, 0, 0, 0x0003}}, false, false, false, false, false}, // $ax0.D = MEM[$arS++]; $ax1.R = MEM[$ar3]; $ar3 += $ix3 {"LDM", 0x00c8, 0x00cc, Interpreter::Ext::ldm, &DSPEmitter::ldm, 1, 3, {{P_REGM18, 1, 0, 4, 0x0020}, {P_REGM19, 1, 0, 3, 0x0010}, {P_PRG, 1, 0, 0, 0x0003}}, false, false, false, false, false}, // $ax0.D = MEM[$arS++]; $ax1.R = MEM[$ar3]; $ar3 += $ix3
{"LDNM", 0x00cc, 0x00cc, Interpreter::Ext::ldnm, &DSPEmitter::ldnm, 1, 3, {{P_REGM18, 1, 0, 4, 0x0020}, {P_REGM19, 1, 0, 3, 0x0010}, {P_PRG, 1, 0, 0, 0x0003}}, false, false, false, false, false}, // $ax0.D = MEM[$arS]; $ax1.R = MEM[$ar3]; $arS += $ixS; $ar3 += $ix3 {"LDNM", 0x00cc, 0x00cc, Interpreter::Ext::ldnm, &DSPEmitter::ldnm, 1, 3, {{P_REGM18, 1, 0, 4, 0x0020}, {P_REGM19, 1, 0, 3, 0x0010}, {P_PRG, 1, 0, 0, 0x0003}}, false, false, false, false, false}, // $ax0.D = MEM[$arS]; $ax1.R = MEM[$ar3]; $arS += $ixS; $ar3 += $ix3
}; }};
const int opcodes_size = sizeof(opcodes) / sizeof(DSPOPCTemplate); const std::array<pdlabel_t, 96> pdlabels =
const int opcodes_ext_size = sizeof(opcodes_ext) / sizeof(DSPOPCTemplate); {{
const pdlabel_t pdlabels[] =
{
{0xffa0, "COEF_A1_0", "COEF_A1_0",}, {0xffa0, "COEF_A1_0", "COEF_A1_0",},
{0xffa1, "COEF_A2_0", "COEF_A2_0",}, {0xffa1, "COEF_A2_0", "COEF_A2_0",},
{0xffa2, "COEF_A1_1", "COEF_A1_1",}, {0xffa2, "COEF_A1_1", "COEF_A1_1",},
@ -434,12 +434,10 @@ const pdlabel_t pdlabels[] =
{0xfffd, "DMBL", "DSP Mailbox L",}, {0xfffd, "DMBL", "DSP Mailbox L",},
{0xfffe, "CMBH", "CPU Mailbox H",}, {0xfffe, "CMBH", "CPU Mailbox H",},
{0xffff, "CMBL", "CPU Mailbox L",}, {0xffff, "CMBL", "CPU Mailbox L",},
}; }};
const u32 pdlabels_size = sizeof(pdlabels) / sizeof(pdlabel_t); const std::array<pdlabel_t, 36> regnames =
{{
const pdlabel_t regnames[] =
{
{0x00, "AR0", "Addr Reg 00",}, {0x00, "AR0", "Addr Reg 00",},
{0x01, "AR1", "Addr Reg 01",}, {0x01, "AR1", "Addr Reg 01",},
{0x02, "AR2", "Addr Reg 02",}, {0x02, "AR2", "Addr Reg 02",},
@ -478,13 +476,11 @@ const pdlabel_t regnames[] =
{0x21, "ACC1", "Accu Full 1",}, {0x21, "ACC1", "Accu Full 1",},
{0x22, "AX0", "Extra Accu 0",}, {0x22, "AX0", "Extra Accu 0",},
{0x23, "AX1", "Extra Accu 1",}, {0x23, "AX1", "Extra Accu 1",},
}; }};
// clang-format on // clang-format on
const DSPOPCTemplate* opTable[OPTABLE_SIZE]; std::array<u16, WRITEBACK_LOG_SIZE> writeBackLog;
const DSPOPCTemplate* extOpTable[EXT_OPTABLE_SIZE]; std::array<int, WRITEBACK_LOG_SIZE> writeBackLogIdx;
u16 writeBackLog[WRITEBACKLOGSIZE];
int writeBackLogIdx[WRITEBACKLOGSIZE];
const char* pdname(u16 val) const char* pdname(u16 val)
{ {
@ -510,9 +506,27 @@ const char* pdregnamelong(int val)
return regnames[val].description; 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 // This function could use the above GetOpTemplate, but then we'd lose the
@ -520,27 +534,27 @@ const DSPOPCTemplate* GetOpTemplate(const UDSPInstruction& inst)
void InitInstructionTable() void InitInstructionTable()
{ {
// ext op table // ext op table
for (int i = 0; i < EXT_OPTABLE_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) for (const DSPOPCTemplate& ext : opcodes_ext)
{ {
u16 mask = ext.opcode_mask; u16 mask = ext.opcode_mask;
if ((mask & i) == ext.opcode) 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 else
{ {
// if the entry already in the table // if the entry already in the table
// is a strict subset, allow it // 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 %d already in use by %s when inserting %s", i, ERROR_LOG(DSPLLE, "opcode ext table place %zu already in use by %s when inserting %s",
extOpTable[i]->name, ext.name); i, s_ext_op_table[i]->name, ext.name);
} }
} }
} }
@ -548,29 +562,23 @@ void InitInstructionTable()
} }
// op table // op table
for (const DSPOPCTemplate*& opcode : opTable) s_op_table.fill(&cw);
{
opcode = &cw;
}
for (int i = 0; i < OPTABLE_SIZE; i++) for (size_t i = 0; i < s_op_table.size(); i++)
{ {
for (const DSPOPCTemplate& opcode : opcodes) for (const DSPOPCTemplate& opcode : opcodes)
{ {
u16 mask = opcode.opcode_mask; u16 mask = opcode.opcode_mask;
if ((mask & i) == opcode.opcode) if ((mask & i) == opcode.opcode)
{ {
if (opTable[i] == &cw) if (s_op_table[i] == &cw)
opTable[i] = &opcode; s_op_table[i] = &opcode;
else else
ERROR_LOG(DSPLLE, "opcode table place %d already in use for %s", i, opcode.name); ERROR_LOG(DSPLLE, "opcode table place %zu already in use for %s", i, opcode.name);
} }
} }
} }
for (int& elem : writeBackLogIdx) writeBackLogIdx.fill(-1);
{
elem = -1;
}
} }
} // namespace DSP } // namespace DSP

View File

@ -6,6 +6,9 @@
#pragma once #pragma once
#include <array>
#include <cstddef>
#include "Core/DSP/DSPCommon.h" #include "Core/DSP/DSPCommon.h"
#include "Core/DSP/Jit/DSPEmitter.h" #include "Core/DSP/Jit/DSPEmitter.h"
@ -53,9 +56,6 @@ enum partype_t
// P_AX_D = P_REG | 0x2280, // P_AX_D = P_REG | 0x2280,
}; };
#define OPTABLE_SIZE 0xffff + 1
#define EXT_OPTABLE_SIZE 0xff + 1
struct param2_t struct param2_t
{ {
partype_t type; partype_t type;
@ -90,18 +90,13 @@ struct DSPOPCTemplate
typedef DSPOPCTemplate opc_t; typedef DSPOPCTemplate opc_t;
// Opcodes // Opcodes
extern const DSPOPCTemplate opcodes[]; extern const std::array<DSPOPCTemplate, 214> opcodes;
extern const int opcodes_size; extern const std::array<DSPOPCTemplate, 25> opcodes_ext;
extern const DSPOPCTemplate opcodes_ext[];
extern const int opcodes_ext_size;
extern const DSPOPCTemplate cw; extern const DSPOPCTemplate cw;
#define WRITEBACKLOGSIZE 5 constexpr size_t WRITEBACK_LOG_SIZE = 5;
extern std::array<u16, WRITEBACK_LOG_SIZE> writeBackLog;
extern const DSPOPCTemplate* opTable[OPTABLE_SIZE]; extern std::array<int, WRITEBACK_LOG_SIZE> writeBackLogIdx;
extern const DSPOPCTemplate* extOpTable[EXT_OPTABLE_SIZE];
extern u16 writeBackLog[WRITEBACKLOGSIZE];
extern int writeBackLogIdx[WRITEBACKLOGSIZE];
// Predefined labels // Predefined labels
struct pdlabel_t struct pdlabel_t
@ -111,9 +106,8 @@ struct pdlabel_t
const char* description; const char* description;
}; };
extern const pdlabel_t regnames[]; extern const std::array<pdlabel_t, 36> regnames;
extern const pdlabel_t pdlabels[]; extern const std::array<pdlabel_t, 96> pdlabels;
extern const u32 pdlabels_size;
const char* pdname(u16 val); const char* pdname(u16 val);
const char* pdregname(int val); const char* pdregname(int val);
@ -124,5 +118,6 @@ void applyWriteBackLog();
void zeroWriteBackLog(); void zeroWriteBackLog();
void zeroWriteBackLogPreserveAcc(u8 acc); void zeroWriteBackLogPreserveAcc(u8 acc);
const DSPOPCTemplate* GetOpTemplate(const UDSPInstruction& inst); const DSPOPCTemplate* GetOpTemplate(UDSPInstruction inst);
const DSPOPCTemplate* GetExtOpTemplate(UDSPInstruction inst);
} // namespace DSP } // namespace DSP

View File

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

View File

@ -105,7 +105,9 @@ bool DSPEmitter::FlagsNeeded() const
void DSPEmitter::FallBackToInterpreter(UDSPInstruction inst) 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 // Increment PC - we shouldn't need to do this for every instruction. only for branches and end
// of block. // of block.
@ -116,68 +118,50 @@ void DSPEmitter::FallBackToInterpreter(UDSPInstruction inst)
// Fall back to interpreter // Fall back to interpreter
gpr.PushRegs(); gpr.PushRegs();
_assert_msg_(DSPLLE, opTable[inst]->intFunc, "No function for %04x", inst); _assert_msg_(DSPLLE, op_template->intFunc, "No function for %04x", inst);
ABI_CallFunctionC16(opTable[inst]->intFunc, inst); ABI_CallFunctionC16(op_template->intFunc, inst);
gpr.PopRegs(); gpr.PopRegs();
} }
void DSPEmitter::EmitInstruction(UDSPInstruction inst) void DSPEmitter::EmitInstruction(UDSPInstruction inst)
{ {
const DSPOPCTemplate* tinst = GetOpTemplate(inst); const DSPOPCTemplate* const op_template = GetOpTemplate(inst);
bool ext_is_jit = false; bool ext_is_jit = false;
// Call extended // 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();
// Fall back to interpreter ABI_CallFunctionC16(ext_op_template->intFunc, inst);
gpr.PushRegs(); gpr.PopRegs();
ABI_CallFunctionC16(extOpTable[inst & 0x7F]->intFunc, inst); INFO_LOG(DSPLLE, "Instruction not JITed(ext part): %04x", inst);
gpr.PopRegs(); ext_is_jit = false;
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;
}
} }
else else
{ {
if (!extOpTable[inst & 0xFF]->jitFunc) (this->*ext_op_template->jitFunc)(inst);
{ ext_is_jit = true;
// 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 // Main instruction
if (!opTable[inst]->jitFunc) if (!op_template->jitFunc)
{ {
FallBackToInterpreter(inst); FallBackToInterpreter(inst);
INFO_LOG(DSPLLE, "Instruction not JITed(main part): %04x", inst); INFO_LOG(DSPLLE, "Instruction not JITed(main part): %04x", inst);
} }
else else
{ {
(this->*opTable[inst]->jitFunc)(inst); (this->*op_template->jitFunc)(inst);
} }
// Backlog // Backlog
if (tinst->extended) if (op_template->extended)
{ {
if (!ext_is_jit) 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 // NOTE: Cannot use FallBackToInterpreter(opc) here because of the need to write branch exit
void DSPEmitter::ifcc(const UDSPInstruction opc) 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); ReJitConditional<r_ifcc>(opc, *this);
WriteBranchExit(*this); WriteBranchExit(*this);
} }
@ -347,8 +350,8 @@ void DSPEmitter::loop(const UDSPInstruction opc)
FixupBranch exit = J(true); FixupBranch exit = J(true);
SetJumpTarget(cnt); SetJumpTarget(cnt);
// dsp_skip_inst(); // 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); WriteBranchExit(*this);
gpr.FlushRegs(c, false); gpr.FlushRegs(c, false);
SetJumpTarget(exit); SetJumpTarget(exit);
@ -380,8 +383,8 @@ void DSPEmitter::loopi(const UDSPInstruction opc)
} }
else else
{ {
// dsp_skip_inst(); // 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); WriteBranchExit(*this);
} }
} }
@ -416,9 +419,9 @@ void DSPEmitter::bloop(const UDSPInstruction opc)
FixupBranch exit = J(true); FixupBranch exit = J(true);
SetJumpTarget(cnt); SetJumpTarget(cnt);
// g_dsp.pc = loop_pc; // g_dsp.pc = loop_pc;
// dsp_skip_inst(); // 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); WriteBranchExit(*this);
gpr.FlushRegs(c, false); gpr.FlushRegs(c, false);
SetJumpTarget(exit); SetJumpTarget(exit);
@ -452,9 +455,9 @@ void DSPEmitter::bloopi(const UDSPInstruction opc)
} }
else else
{ {
// g_dsp.pc = loop_pc; // g_dsp.pc = loop_pc;
// dsp_skip_inst(); // 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); WriteBranchExit(*this);
} }
} }

View File

@ -13,15 +13,16 @@ LabelMap::LabelMap()
void LabelMap::RegisterDefaults() void LabelMap::RegisterDefaults()
{ {
for (int i = 0; i < 0x24; i++) for (const auto& reg_name_label : regnames)
{ {
if (regnames[i].name) if (reg_name_label.name != nullptr)
RegisterLabel(regnames[i].name, regnames[i].addr); RegisterLabel(reg_name_label.name, reg_name_label.addr);
} }
for (int i = 0; i < (int)pdlabels_size; i++)
for (const auto& predefined_label : pdlabels)
{ {
if (pdlabels[i].name) if (predefined_label.name != nullptr)
RegisterLabel(pdlabels[i].name, pdlabels[i].addr); RegisterLabel(predefined_label.name, predefined_label.addr);
} }
} }