Merge pull request #4691 from lioncash/dsptables
DSPTables: Hide/Eliminate some extern variables
This commit is contained in:
commit
a945b4ea9b
|
@ -5,6 +5,7 @@
|
|||
|
||||
#include "Core/DSP/DSPAssembler.h"
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
|
@ -441,29 +442,29 @@ u32 DSPAssembler::GetParams(char* parstr, param_t* par)
|
|||
return count;
|
||||
}
|
||||
|
||||
const opc_t* DSPAssembler::FindOpcode(const char* opcode, u32 par_count, const opc_t* const opcod,
|
||||
int opcod_size)
|
||||
const opc_t* DSPAssembler::FindOpcode(const char* name, u32 par_count, const opc_t* const opcodes,
|
||||
size_t opcodes_size)
|
||||
{
|
||||
if (opcode[0] == 'C' && opcode[1] == 'W')
|
||||
if (name[0] == 'C' && name[1] == 'W')
|
||||
return &cw;
|
||||
|
||||
AliasMap::const_iterator alias_iter = aliases.find(opcode);
|
||||
const auto alias_iter = aliases.find(name);
|
||||
if (alias_iter != aliases.end())
|
||||
opcode = alias_iter->second.c_str();
|
||||
for (int i = 0; i < opcod_size; i++)
|
||||
name = alias_iter->second.c_str();
|
||||
for (size_t i = 0; i < opcodes_size; i++)
|
||||
{
|
||||
const opc_t* opc = &opcod[i];
|
||||
if (strcmp(opc->name, opcode) == 0)
|
||||
const opc_t* opcode = &opcodes[i];
|
||||
if (strcmp(opcode->name, name) == 0)
|
||||
{
|
||||
if (par_count < opc->param_count)
|
||||
if (par_count < opcode->param_count)
|
||||
{
|
||||
ShowError(ERR_NOT_ENOUGH_PARAMETERS);
|
||||
}
|
||||
if (par_count > opc->param_count)
|
||||
else if (par_count > opcode->param_count)
|
||||
{
|
||||
ShowError(ERR_TOO_MANY_PARAMETERS);
|
||||
}
|
||||
return opc;
|
||||
return opcode;
|
||||
}
|
||||
}
|
||||
ShowError(ERR_UNKNOWN_OPCODE);
|
||||
|
@ -478,11 +479,11 @@ static u16 get_mask_shifted_down(u16 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 (par[i].type == P_VAL &&
|
||||
|
@ -510,7 +511,7 @@ bool DSPAssembler::VerifyParams(const opc_t* opc, param_t* par, int count, bool
|
|||
if (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);
|
||||
}
|
||||
break;
|
||||
|
@ -520,7 +521,7 @@ bool DSPAssembler::VerifyParams(const opc_t* opc, param_t* par, int count, bool
|
|||
if (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);
|
||||
}
|
||||
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, "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);
|
||||
}
|
||||
else if (par[i].val >= 0x1c && par[i].val <= 0x1d)
|
||||
{
|
||||
fprintf(
|
||||
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);
|
||||
}
|
||||
else
|
||||
|
@ -560,14 +561,14 @@ bool DSPAssembler::VerifyParams(const opc_t* opc, param_t* par, int count, bool
|
|||
{
|
||||
fprintf(
|
||||
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);
|
||||
}
|
||||
else if (par[i].val >= 0x20 && par[i].val <= 0x21)
|
||||
{
|
||||
fprintf(
|
||||
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);
|
||||
}
|
||||
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,
|
||||
"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);
|
||||
}
|
||||
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,
|
||||
"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);
|
||||
}
|
||||
else
|
||||
|
@ -987,7 +988,7 @@ bool DSPAssembler::AssembleFile(const char* fname, int pass)
|
|||
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)
|
||||
opc = &cw;
|
||||
|
||||
|
@ -1001,7 +1002,7 @@ bool DSPAssembler::AssembleFile(const char* fname, int pass)
|
|||
{
|
||||
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);
|
||||
}
|
||||
else if (params_count_ext)
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <cstddef>
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
|
@ -89,9 +90,9 @@ private:
|
|||
// void ShowWarning(err_t err_code, const char *extra_info = nullptr);
|
||||
|
||||
char* FindBrackets(char* src, char* dst);
|
||||
const opc_t* FindOpcode(const char* opcode, u32 par_count, const opc_t* const opcod,
|
||||
int opcod_size);
|
||||
bool VerifyParams(const opc_t* opc, param_t* par, int count, bool ext = false);
|
||||
const opc_t* FindOpcode(const char* name, u32 par_count, const opc_t* opcodes,
|
||||
size_t opcodes_size);
|
||||
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);
|
||||
|
||||
char* gdg_buffer;
|
||||
|
|
|
@ -186,13 +186,13 @@ bool DSPDisassembler::DisassembleOpcode(const u16* binbuf, int base_addr, int pa
|
|||
const DSPOPCTemplate* opc_ext = nullptr;
|
||||
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
|
@ -220,21 +220,21 @@ bool DSPDisassembler::DisassembleOpcode(const u16* binbuf, int base_addr, int pa
|
|||
{
|
||||
// opcode has an extension
|
||||
// find opcode
|
||||
for (int j = 0; j < opcodes_ext_size; j++)
|
||||
for (const auto& opcode_ext : opcodes_ext)
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -6,6 +6,9 @@
|
|||
|
||||
#include "Core/DSP/DSPTables.h"
|
||||
|
||||
#include <array>
|
||||
#include <cstddef>
|
||||
|
||||
#include "Common/CommonTypes.h"
|
||||
|
||||
#include "Core/DSP/Interpreter/DSPIntExtOps.h"
|
||||
|
@ -17,8 +20,8 @@ namespace DSP
|
|||
using JIT::x86::DSPEmitter;
|
||||
|
||||
// clang-format off
|
||||
const DSPOPCTemplate opcodes[] =
|
||||
{
|
||||
const std::array<DSPOPCTemplate, 214> opcodes =
|
||||
{{
|
||||
// # 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
|
||||
{"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
|
||||
{"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
|
||||
};
|
||||
}};
|
||||
|
||||
const DSPOPCTemplate cw =
|
||||
{"CW", 0x0000, 0x0000, Interpreter::nop, nullptr, 1, 1, {{P_VAL, 2, 0, 0, 0xffff}}, false, false, false, false, false};
|
||||
|
||||
// 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
|
||||
|
||||
{"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
|
||||
{"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
|
||||
};
|
||||
}};
|
||||
|
||||
const int opcodes_size = sizeof(opcodes) / sizeof(DSPOPCTemplate);
|
||||
const int opcodes_ext_size = sizeof(opcodes_ext) / sizeof(DSPOPCTemplate);
|
||||
|
||||
const pdlabel_t pdlabels[] =
|
||||
{
|
||||
const std::array<pdlabel_t, 96> pdlabels =
|
||||
{{
|
||||
{0xffa0, "COEF_A1_0", "COEF_A1_0",},
|
||||
{0xffa1, "COEF_A2_0", "COEF_A2_0",},
|
||||
{0xffa2, "COEF_A1_1", "COEF_A1_1",},
|
||||
|
@ -434,12 +434,10 @@ const pdlabel_t pdlabels[] =
|
|||
{0xfffd, "DMBL", "DSP Mailbox L",},
|
||||
{0xfffe, "CMBH", "CPU Mailbox H",},
|
||||
{0xffff, "CMBL", "CPU Mailbox L",},
|
||||
};
|
||||
}};
|
||||
|
||||
const u32 pdlabels_size = sizeof(pdlabels) / sizeof(pdlabel_t);
|
||||
|
||||
const pdlabel_t regnames[] =
|
||||
{
|
||||
const std::array<pdlabel_t, 36> regnames =
|
||||
{{
|
||||
{0x00, "AR0", "Addr Reg 00",},
|
||||
{0x01, "AR1", "Addr Reg 01",},
|
||||
{0x02, "AR2", "Addr Reg 02",},
|
||||
|
@ -478,13 +476,11 @@ const pdlabel_t regnames[] =
|
|||
{0x21, "ACC1", "Accu Full 1",},
|
||||
{0x22, "AX0", "Extra Accu 0",},
|
||||
{0x23, "AX1", "Extra Accu 1",},
|
||||
};
|
||||
}};
|
||||
// clang-format on
|
||||
|
||||
const DSPOPCTemplate* opTable[OPTABLE_SIZE];
|
||||
const DSPOPCTemplate* extOpTable[EXT_OPTABLE_SIZE];
|
||||
u16 writeBackLog[WRITEBACKLOGSIZE];
|
||||
int writeBackLogIdx[WRITEBACKLOGSIZE];
|
||||
std::array<u16, WRITEBACK_LOG_SIZE> writeBackLog;
|
||||
std::array<int, WRITEBACK_LOG_SIZE> writeBackLogIdx;
|
||||
|
||||
const char* pdname(u16 val)
|
||||
{
|
||||
|
@ -510,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
|
||||
|
@ -520,27 +534,27 @@ const DSPOPCTemplate* GetOpTemplate(const UDSPInstruction& inst)
|
|||
void InitInstructionTable()
|
||||
{
|
||||
// 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)
|
||||
{
|
||||
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 %d already in use by %s when inserting %s", i,
|
||||
extOpTable[i]->name, ext.name);
|
||||
ERROR_LOG(DSPLLE, "opcode ext table place %zu already in use by %s when inserting %s",
|
||||
i, s_ext_op_table[i]->name, ext.name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -548,29 +562,23 @@ void InitInstructionTable()
|
|||
}
|
||||
|
||||
// op table
|
||||
for (const DSPOPCTemplate*& opcode : opTable)
|
||||
{
|
||||
opcode = &cw;
|
||||
}
|
||||
s_op_table.fill(&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)
|
||||
{
|
||||
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 %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)
|
||||
{
|
||||
elem = -1;
|
||||
}
|
||||
writeBackLogIdx.fill(-1);
|
||||
}
|
||||
} // namespace DSP
|
||||
|
|
|
@ -6,6 +6,9 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include <cstddef>
|
||||
|
||||
#include "Core/DSP/DSPCommon.h"
|
||||
#include "Core/DSP/Jit/DSPEmitter.h"
|
||||
|
||||
|
@ -53,9 +56,6 @@ enum partype_t
|
|||
// P_AX_D = P_REG | 0x2280,
|
||||
};
|
||||
|
||||
#define OPTABLE_SIZE 0xffff + 1
|
||||
#define EXT_OPTABLE_SIZE 0xff + 1
|
||||
|
||||
struct param2_t
|
||||
{
|
||||
partype_t type;
|
||||
|
@ -90,18 +90,13 @@ struct DSPOPCTemplate
|
|||
typedef DSPOPCTemplate opc_t;
|
||||
|
||||
// Opcodes
|
||||
extern const DSPOPCTemplate opcodes[];
|
||||
extern const int opcodes_size;
|
||||
extern const DSPOPCTemplate opcodes_ext[];
|
||||
extern const int opcodes_ext_size;
|
||||
extern const std::array<DSPOPCTemplate, 214> opcodes;
|
||||
extern const std::array<DSPOPCTemplate, 25> opcodes_ext;
|
||||
extern const DSPOPCTemplate cw;
|
||||
|
||||
#define WRITEBACKLOGSIZE 5
|
||||
|
||||
extern const DSPOPCTemplate* opTable[OPTABLE_SIZE];
|
||||
extern const DSPOPCTemplate* extOpTable[EXT_OPTABLE_SIZE];
|
||||
extern u16 writeBackLog[WRITEBACKLOGSIZE];
|
||||
extern int writeBackLogIdx[WRITEBACKLOGSIZE];
|
||||
constexpr size_t WRITEBACK_LOG_SIZE = 5;
|
||||
extern std::array<u16, WRITEBACK_LOG_SIZE> writeBackLog;
|
||||
extern std::array<int, WRITEBACK_LOG_SIZE> writeBackLogIdx;
|
||||
|
||||
// Predefined labels
|
||||
struct pdlabel_t
|
||||
|
@ -111,9 +106,8 @@ struct pdlabel_t
|
|||
const char* description;
|
||||
};
|
||||
|
||||
extern const pdlabel_t regnames[];
|
||||
extern const pdlabel_t pdlabels[];
|
||||
extern const u32 pdlabels_size;
|
||||
extern const std::array<pdlabel_t, 36> regnames;
|
||||
extern const std::array<pdlabel_t, 96> pdlabels;
|
||||
|
||||
const char* pdname(u16 val);
|
||||
const char* pdregname(int val);
|
||||
|
@ -124,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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,15 +13,16 @@ LabelMap::LabelMap()
|
|||
|
||||
void LabelMap::RegisterDefaults()
|
||||
{
|
||||
for (int i = 0; i < 0x24; i++)
|
||||
for (const auto& reg_name_label : regnames)
|
||||
{
|
||||
if (regnames[i].name)
|
||||
RegisterLabel(regnames[i].name, regnames[i].addr);
|
||||
if (reg_name_label.name != nullptr)
|
||||
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)
|
||||
RegisterLabel(pdlabels[i].name, pdlabels[i].addr);
|
||||
if (predefined_label.name != nullptr)
|
||||
RegisterLabel(predefined_label.name, predefined_label.addr);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue