DSPTables: Separate interpreter and JIT functions from main info table

This is one of the last things that needed to be done in order to
finally separate the x86-64-specific code from the rest of the common
DSP code. This splits the tables up similar to how it's currently done
for the PowerPC CPU tables.

Now, the tables are split up and within their own relevant source files,
so the main table within the common DSP code acts as the "info" table
that provides specifics about a particular instruction, while the other
tables contain the actual instruction.

With this out of the way, all that's left is to make a general base for
the emitters and we can then replace the x64 JIT pointer in DSPCore with
it, getting all x64 out of the common code once and for all.

While shuffling all the code around, the removal of the DSPEmitter
includes in some places uncovered indirect inclusions, so this also
fixes those as well.
This commit is contained in:
Lioncash
2018-06-21 04:21:44 -04:00
parent 091efcc41d
commit 474c1bb4f7
14 changed files with 1111 additions and 277 deletions
+4 -2
View File
@@ -58,6 +58,7 @@ add_library(core
DSP/Interpreter/DSPIntLoadStore.cpp
DSP/Interpreter/DSPIntMisc.cpp
DSP/Interpreter/DSPIntMultiplier.cpp
DSP/Interpreter/DSPIntTables.cpp
DSP/Jit/x64/DSPEmitter.cpp
DSP/Jit/x64/DSPJitRegCache.cpp
DSP/Jit/x64/DSPJitExtOps.cpp
@@ -65,9 +66,10 @@ add_library(core
DSP/Jit/x64/DSPJitCCUtil.cpp
DSP/Jit/x64/DSPJitArithmetic.cpp
DSP/Jit/x64/DSPJitLoadStore.cpp
DSP/Jit/x64/DSPJitMultiplier.cpp
DSP/Jit/x64/DSPJitUtil.cpp
DSP/Jit/x64/DSPJitMisc.cpp
DSP/Jit/x64/DSPJitMultiplier.cpp
DSP/Jit/x64/DSPJitTables.cpp
DSP/Jit/x64/DSPJitUtil.cpp
FifoPlayer/FifoAnalyzer.cpp
FifoPlayer/FifoDataFile.cpp
FifoPlayer/FifoPlaybackAnalyzer.cpp
+4
View File
@@ -81,6 +81,7 @@
<ClCompile Include="DSP\Interpreter\DSPIntLoadStore.cpp" />
<ClCompile Include="DSP\Interpreter\DSPIntMisc.cpp" />
<ClCompile Include="DSP\Interpreter\DSPIntMultiplier.cpp" />
<ClCompile Include="DSP\Interpreter\DSPIntTables.cpp" />
<ClCompile Include="DSP\Jit\x64\DSPEmitter.cpp" />
<ClCompile Include="DSP\Jit\x64\DSPJitArithmetic.cpp" />
<ClCompile Include="DSP\Jit\x64\DSPJitBranch.cpp" />
@@ -90,6 +91,7 @@
<ClCompile Include="DSP\Jit\x64\DSPJitMisc.cpp" />
<ClCompile Include="DSP\Jit\x64\DSPJitMultiplier.cpp" />
<ClCompile Include="DSP\Jit\x64\DSPJitRegCache.cpp" />
<ClCompile Include="DSP\Jit\x64\DSPJitTables.cpp" />
<ClCompile Include="DSP\Jit\x64\DSPJitUtil.cpp" />
<ClCompile Include="DSP\LabelMap.cpp" />
<ClCompile Include="FifoPlayer\FifoAnalyzer.cpp" />
@@ -341,9 +343,11 @@
<ClInclude Include="DSP\Interpreter\DSPIntCCUtil.h" />
<ClInclude Include="DSP\Interpreter\DSPInterpreter.h" />
<ClInclude Include="DSP\Interpreter\DSPIntExtOps.h" />
<ClInclude Include="DSP\Interpreter\DSPIntTables.h" />
<ClInclude Include="DSP\Interpreter\DSPIntUtil.h" />
<ClInclude Include="DSP\Jit\x64\DSPEmitter.h" />
<ClInclude Include="DSP\Jit\x64\DSPJitRegCache.h" />
<ClInclude Include="DSP\Jit\x64\DSPJitTables.h" />
<ClInclude Include="DSP\LabelMap.h" />
<ClInclude Include="FifoPlayer\FifoAnalyzer.h" />
<ClInclude Include="FifoPlayer\FifoDataFile.h" />
+12
View File
@@ -240,6 +240,9 @@
<ClCompile Include="DSP\Interpreter\DSPIntMultiplier.cpp">
<Filter>DSPCore\Interpreter</Filter>
</ClCompile>
<ClCompile Include="DSP\Interpreter\DSPIntTables.cpp">
<Filter>DSPCore\Interpreter</Filter>
</ClCompile>
<ClCompile Include="DSP\Jit\x64\DSPJitRegCache.cpp">
<Filter>DSPCore\Jit\x64</Filter>
</ClCompile>
@@ -267,6 +270,9 @@
<ClCompile Include="DSP\Jit\x64\DSPEmitter.cpp">
<Filter>DSPCore\Jit\x64</Filter>
</ClCompile>
<ClCompile Include="DSP\Jit\x64\DSPJitTables.cpp">
<Filter>DSPCore\Jit\x64</Filter>
</ClCompile>
<ClCompile Include="DSP\Jit\x64\DSPJitUtil.cpp">
<Filter>DSPCore\Jit\x64</Filter>
</ClCompile>
@@ -960,12 +966,18 @@
<ClInclude Include="DSP\Interpreter\DSPIntExtOps.h">
<Filter>DSPCore\Interpreter</Filter>
</ClInclude>
<ClInclude Include="DSP\Interpreter\DSPIntTables.h">
<Filter>DSPCore\Interpreter</Filter>
</ClInclude>
<ClInclude Include="DSP\Interpreter\DSPIntUtil.h">
<Filter>DSPCore\Interpreter</Filter>
</ClInclude>
<ClInclude Include="DSP\Jit\x64\DSPJitRegCache.h">
<Filter>DSPCore\Jit\x64</Filter>
</ClInclude>
<ClInclude Include="DSP\Jit\x64\DSPJitTables.h">
<Filter>DSPCore\Jit\x64</Filter>
</ClInclude>
<ClInclude Include="DSP\Jit\x64\DSPEmitter.h">
<Filter>DSPCore\Jit\x64</Filter>
</ClInclude>
+1
View File
@@ -12,6 +12,7 @@
#include "Common/CommonTypes.h"
#include "Common/File.h"
#include "Common/FileUtil.h"
#include "Common/MsgHandler.h"
#include "Common/StringUtil.h"
#include "Common/Swap.h"
+3 -3
View File
@@ -11,6 +11,7 @@
#include <vector>
#include "Common/CommonTypes.h"
#include "Common/Logging/Log.h"
#include "Common/StringUtil.h"
#include "Core/DSP/DSPTables.h"
@@ -144,9 +145,8 @@ bool DSPDisassembler::DisassembleOpcode(const u16* binbuf, u16* pc, std::string&
// Find main opcode
const DSPOPCTemplate* opc = FindOpInfoByOpcode(op1);
const DSPOPCTemplate fake_op = {
"CW", 0x0000, 0x0000, nullptr, nullptr, 1, 1, {{P_VAL, 2, 0, 0, 0xffff}},
false, false, false, false, false};
const DSPOPCTemplate fake_op = {"CW", 0x0000, 0x0000, 1, 1, {{P_VAL, 2, 0, 0, 0xffff}},
false, false, false, false, false};
if (!opc)
opc = &fake_op;
File diff suppressed because it is too large Load Diff
-7
View File
@@ -11,7 +11,6 @@
#include <string>
#include "Core/DSP/DSPCommon.h"
#include "Core/DSP/Jit/x64/DSPEmitter.h"
namespace DSP
{
@@ -68,16 +67,10 @@ struct param2_t
struct DSPOPCTemplate
{
using InterpreterFunction = void (*)(UDSPInstruction);
using JITFunction = void (JIT::x64::DSPEmitter::*)(UDSPInstruction);
const char* name;
u16 opcode;
u16 opcode_mask;
InterpreterFunction intFunc;
JITFunction jitFunc;
u8 size;
u8 param_count;
param2_t params[8];
@@ -0,0 +1,389 @@
// Copyright 2018 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.
#include "Core/DSP/Interpreter/DSPIntTables.h"
#include <algorithm>
#include <array>
#include "Common/CommonTypes.h"
#include "Core/DSP/Interpreter/DSPIntExtOps.h"
#include "Core/DSP/Interpreter/DSPInterpreter.h"
namespace DSP::Interpreter
{
struct InterpreterOpInfo
{
u16 opcode;
u16 mask;
InterpreterFunction function;
};
// clang-format off
constexpr std::array<InterpreterOpInfo, 214> s_opcodes
{{
{0x0000, 0xfffc, nop},
{0x0004, 0xfffc, dar},
{0x0008, 0xfffc, iar},
{0x000c, 0xfffc, subarn},
{0x0010, 0xfff0, addarn},
{0x0021, 0xffff, halt},
{0x02d0, 0xffff, ret},
{0x02d1, 0xffff, ret},
{0x02d2, 0xffff, ret},
{0x02d3, 0xffff, ret},
{0x02d4, 0xffff, ret},
{0x02d5, 0xffff, ret},
{0x02d6, 0xffff, ret},
{0x02d7, 0xffff, ret},
{0x02d8, 0xffff, ret},
{0x02d9, 0xffff, ret},
{0x02da, 0xffff, ret},
{0x02db, 0xffff, ret},
{0x02dc, 0xffff, ret},
{0x02dd, 0xffff, ret},
{0x02de, 0xffff, ret},
{0x02df, 0xffff, ret},
{0x02ff, 0xffff, rti},
{0x02b0, 0xffff, call},
{0x02b1, 0xffff, call},
{0x02b2, 0xffff, call},
{0x02b3, 0xffff, call},
{0x02b4, 0xffff, call},
{0x02b5, 0xffff, call},
{0x02b6, 0xffff, call},
{0x02b7, 0xffff, call},
{0x02b8, 0xffff, call},
{0x02b9, 0xffff, call},
{0x02ba, 0xffff, call},
{0x02bb, 0xffff, call},
{0x02bc, 0xffff, call},
{0x02bd, 0xffff, call},
{0x02be, 0xffff, call},
{0x02bf, 0xffff, call},
{0x0270, 0xffff, ifcc},
{0x0271, 0xffff, ifcc},
{0x0272, 0xffff, ifcc},
{0x0273, 0xffff, ifcc},
{0x0274, 0xffff, ifcc},
{0x0275, 0xffff, ifcc},
{0x0276, 0xffff, ifcc},
{0x0277, 0xffff, ifcc},
{0x0278, 0xffff, ifcc},
{0x0279, 0xffff, ifcc},
{0x027a, 0xffff, ifcc},
{0x027b, 0xffff, ifcc},
{0x027c, 0xffff, ifcc},
{0x027d, 0xffff, ifcc},
{0x027e, 0xffff, ifcc},
{0x027f, 0xffff, ifcc},
{0x0290, 0xffff, jcc},
{0x0291, 0xffff, jcc},
{0x0292, 0xffff, jcc},
{0x0293, 0xffff, jcc},
{0x0294, 0xffff, jcc},
{0x0295, 0xffff, jcc},
{0x0296, 0xffff, jcc},
{0x0297, 0xffff, jcc},
{0x0298, 0xffff, jcc},
{0x0299, 0xffff, jcc},
{0x029a, 0xffff, jcc},
{0x029b, 0xffff, jcc},
{0x029c, 0xffff, jcc},
{0x029d, 0xffff, jcc},
{0x029e, 0xffff, jcc},
{0x029f, 0xffff, jcc},
{0x1700, 0xff1f, jmprcc},
{0x1701, 0xff1f, jmprcc},
{0x1702, 0xff1f, jmprcc},
{0x1703, 0xff1f, jmprcc},
{0x1704, 0xff1f, jmprcc},
{0x1705, 0xff1f, jmprcc},
{0x1706, 0xff1f, jmprcc},
{0x1707, 0xff1f, jmprcc},
{0x1708, 0xff1f, jmprcc},
{0x1709, 0xff1f, jmprcc},
{0x170a, 0xff1f, jmprcc},
{0x170b, 0xff1f, jmprcc},
{0x170c, 0xff1f, jmprcc},
{0x170d, 0xff1f, jmprcc},
{0x170e, 0xff1f, jmprcc},
{0x170f, 0xff1f, jmprcc},
{0x1710, 0xff1f, callr},
{0x1711, 0xff1f, callr},
{0x1712, 0xff1f, callr},
{0x1713, 0xff1f, callr},
{0x1714, 0xff1f, callr},
{0x1715, 0xff1f, callr},
{0x1716, 0xff1f, callr},
{0x1717, 0xff1f, callr},
{0x1718, 0xff1f, callr},
{0x1719, 0xff1f, callr},
{0x171a, 0xff1f, callr},
{0x171b, 0xff1f, callr},
{0x171c, 0xff1f, callr},
{0x171d, 0xff1f, callr},
{0x171e, 0xff1f, callr},
{0x171f, 0xff1f, callr},
{0x1200, 0xff00, sbclr},
{0x1300, 0xff00, sbset},
{0x1400, 0xfec0, lsl},
{0x1440, 0xfec0, lsr},
{0x1480, 0xfec0, asl},
{0x14c0, 0xfec0, asr},
// these two were discovered by ector
{0x02ca, 0xffff, lsrn},
{0x02cb, 0xffff, asrn},
{0x0080, 0xffe0, lri},
{0x00c0, 0xffe0, lr},
{0x00e0, 0xffe0, sr},
{0x1c00, 0xfc00, mrr},
{0x1600, 0xff00, si},
{0x0400, 0xfe00, addis},
{0x0600, 0xfe00, cmpis},
{0x0800, 0xf800, lris},
{0x0200, 0xfeff, addi},
{0x0220, 0xfeff, xori},
{0x0240, 0xfeff, andi},
{0x0260, 0xfeff, ori},
{0x0280, 0xfeff, cmpi},
{0x02a0, 0xfeff, andf},
{0x02c0, 0xfeff, andcf},
{0x0210, 0xfefc, ilrr},
{0x0214, 0xfefc, ilrrd},
{0x0218, 0xfefc, ilrri},
{0x021c, 0xfefc, ilrrn},
// LOOPS
{0x0040, 0xffe0, loop},
{0x0060, 0xffe0, bloop},
{0x1000, 0xff00, loopi},
{0x1100, 0xff00, bloopi},
// load and store value pointed by indexing reg and increment; LRR/SRR variants
{0x1800, 0xff80, lrr},
{0x1880, 0xff80, lrrd},
{0x1900, 0xff80, lrri},
{0x1980, 0xff80, lrrn},
{0x1a00, 0xff80, srr},
{0x1a80, 0xff80, srrd},
{0x1b00, 0xff80, srri},
{0x1b80, 0xff80, srrn},
// 2
{0x2000, 0xf800, lrs},
{0x2800, 0xf800, srs},
// opcodes that can be extended
// 3 - main opcode defined by 9 bits, extension defined by last 7 bits!!
{0x3000, 0xfc80, xorr},
{0x3400, 0xfc80, andr},
{0x3800, 0xfc80, orr},
{0x3c00, 0xfe80, andc},
{0x3e00, 0xfe80, orc},
{0x3080, 0xfe80, xorc},
{0x3280, 0xfe80, notc},
{0x3480, 0xfc80, lsrnrx},
{0x3880, 0xfc80, asrnrx},
{0x3c80, 0xfe80, lsrnr},
{0x3e80, 0xfe80, asrnr},
// 4
{0x4000, 0xf800, addr},
{0x4800, 0xfc00, addax},
{0x4c00, 0xfe00, add},
{0x4e00, 0xfe00, addp},
// 5
{0x5000, 0xf800, subr},
{0x5800, 0xfc00, subax},
{0x5c00, 0xfe00, sub},
{0x5e00, 0xfe00, subp},
// 6
{0x6000, 0xf800, movr},
{0x6800, 0xfc00, movax},
{0x6c00, 0xfe00, mov},
{0x6e00, 0xfe00, movp},
// 7
{0x7000, 0xfc00, addaxl},
{0x7400, 0xfe00, incm},
{0x7600, 0xfe00, inc},
{0x7800, 0xfe00, decm},
{0x7a00, 0xfe00, dec},
{0x7c00, 0xfe00, neg},
{0x7e00, 0xfe00, movnp},
// 8
{0x8000, 0xf700, nx},
{0x8100, 0xf700, clr},
{0x8200, 0xff00, cmp},
{0x8300, 0xff00, mulaxh},
{0x8400, 0xff00, clrp},
{0x8500, 0xff00, tstprod},
{0x8600, 0xfe00, tstaxh},
{0x8a00, 0xff00, srbith},
{0x8b00, 0xff00, srbith},
{0x8c00, 0xff00, srbith},
{0x8d00, 0xff00, srbith},
{0x8e00, 0xff00, srbith},
{0x8f00, 0xff00, srbith},
// 9
{0x9000, 0xf700, mul},
{0x9100, 0xf700, asr16},
{0x9200, 0xf600, mulmvz},
{0x9400, 0xf600, mulac},
{0x9600, 0xf600, mulmv},
// A-B
{0xa000, 0xe700, mulx},
{0xa100, 0xf700, abs},
{0xa200, 0xe600, mulxmvz},
{0xa400, 0xe600, mulxac},
{0xa600, 0xe600, mulxmv},
{0xb100, 0xf700, tst},
// C-D
{0xc000, 0xe700, mulc},
{0xc100, 0xe700, cmpar},
{0xc200, 0xe600, mulcmvz},
{0xc400, 0xe600, mulcac},
{0xc600, 0xe600, mulcmv},
// E
{0xe000, 0xfc00, maddx},
{0xe400, 0xfc00, msubx},
{0xe800, 0xfc00, maddc},
{0xec00, 0xfc00, msubc},
// F
{0xf000, 0xfe00, lsl16},
{0xf200, 0xfe00, madd},
{0xf400, 0xfe00, lsr16},
{0xf600, 0xfe00, msub},
{0xf800, 0xfc00, addpaxz},
{0xfc00, 0xfe00, clrl},
{0xfe00, 0xfe00, movpz},
}};
constexpr std::array<InterpreterOpInfo, 25> s_opcodes_ext
{{
{0x0000, 0x00fc, Ext::nop},
{0x0004, 0x00fc, Ext::dr},
{0x0008, 0x00fc, Ext::ir},
{0x000c, 0x00fc, Ext::nr},
{0x0010, 0x00f0, Ext::mv},
{0x0020, 0x00e4, Ext::s},
{0x0024, 0x00e4, Ext::sn},
{0x0040, 0x00c4, Ext::l},
{0x0044, 0x00c4, Ext::ln},
{0x0080, 0x00ce, Ext::ls},
{0x0082, 0x00ce, Ext::sl},
{0x0084, 0x00ce, Ext::lsn},
{0x0086, 0x00ce, Ext::sln},
{0x0088, 0x00ce, Ext::lsm},
{0x008a, 0x00ce, Ext::slm},
{0x008c, 0x00ce, Ext::lsnm},
{0x008e, 0x00ce, Ext::slnm},
{0x00c3, 0x00cf, Ext::ldax},
{0x00c7, 0x00cf, Ext::ldaxn},
{0x00cb, 0x00cf, Ext::ldaxm},
{0x00cf, 0x00cf, Ext::ldaxnm},
{0x00c0, 0x00cc, Ext::ld},
{0x00c4, 0x00cc, Ext::ldn},
{0x00c8, 0x00cc, Ext::ldm},
{0x00cc, 0x00cc, Ext::ldnm},
}};
// clang-format on
namespace
{
std::array<InterpreterFunction, 65536> s_op_table;
std::array<InterpreterFunction, 256> s_ext_op_table;
bool s_tables_initialized = false;
template <size_t N>
auto FindByOpcode(UDSPInstruction opcode, const std::array<InterpreterOpInfo, N>& data)
{
return std::find_if(data.cbegin(), data.cend(),
[opcode](const auto& info) { return (opcode & info.mask) == info.opcode; });
}
} // Anonymous namespace
InterpreterFunction GetOp(UDSPInstruction inst)
{
return s_op_table[inst];
}
InterpreterFunction GetExtOp(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];
}
void InitInstructionTables()
{
if (s_tables_initialized)
return;
// ext op table
for (size_t i = 0; i < s_ext_op_table.size(); i++)
{
s_ext_op_table[i] = nop;
const auto iter = FindByOpcode(static_cast<UDSPInstruction>(i), s_opcodes_ext);
if (iter == s_opcodes_ext.cend())
continue;
s_ext_op_table[i] = iter->function;
}
// op table
for (size_t i = 0; i < s_op_table.size(); i++)
{
s_op_table[i] = nop;
const auto iter = FindByOpcode(static_cast<UDSPInstruction>(i), s_opcodes);
if (iter == s_opcodes.cend())
continue;
s_op_table[i] = iter->function;
}
s_tables_initialized = true;
}
} // namespace DSP::Interpreter
@@ -0,0 +1,16 @@
// Copyright 2018 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.
#pragma once
#include "Core/DSP/DSPCommon.h"
namespace DSP::Interpreter
{
using InterpreterFunction = void (*)(UDSPInstruction);
InterpreterFunction GetOp(UDSPInstruction inst);
InterpreterFunction GetExtOp(UDSPInstruction inst);
void InitInstructionTables();
} // namespace DSP::Interpreter
@@ -12,6 +12,7 @@
#include "Core/DSP/DSPCore.h"
#include "Core/DSP/DSPMemoryMap.h"
#include "Core/DSP/DSPTables.h"
#include "Core/DSP/Interpreter/DSPIntTables.h"
namespace DSP
{
@@ -25,10 +26,10 @@ void ExecuteInstruction(const UDSPInstruction inst)
if (opcode_template->extended)
{
GetExtOpTemplate(inst)->intFunc(inst);
GetExtOp(inst)(inst);
}
opcode_template->intFunc(inst);
GetOp(inst)(inst);
if (opcode_template->extended)
{
+25 -15
View File
@@ -19,6 +19,8 @@
#include "Core/DSP/DSPHost.h"
#include "Core/DSP/DSPMemoryMap.h"
#include "Core/DSP/DSPTables.h"
#include "Core/DSP/Interpreter/DSPIntTables.h"
#include "Core/DSP/Jit/x64/DSPJitTables.h"
using namespace Gen;
@@ -32,6 +34,7 @@ DSPEmitter::DSPEmitter()
: m_compile_status_register{SR_INT_ENABLE | SR_EXT_INT_ENABLE}, m_blocks(MAX_BLOCKS),
m_block_size(MAX_BLOCKS), m_block_links(MAX_BLOCKS)
{
x64::InitInstructionTables();
AllocCodeSpace(COMPILED_CODE_SIZE);
CompileDispatcher();
@@ -139,9 +142,11 @@ void DSPEmitter::FallBackToInterpreter(UDSPInstruction inst)
}
// Fall back to interpreter
const auto interpreter_function = Interpreter::GetOp(inst);
m_gpr.PushRegs();
ASSERT_MSG(DSPLLE, op_template->intFunc, "No function for %04x", inst);
ABI_CallFunctionC16(op_template->intFunc, inst);
ASSERT_MSG(DSPLLE, interpreter_function != nullptr, "No function for %04x", inst);
ABI_CallFunctionC16(interpreter_function, inst);
m_gpr.PopRegs();
}
@@ -153,33 +158,36 @@ void DSPEmitter::EmitInstruction(UDSPInstruction inst)
// Call extended
if (op_template->extended)
{
const DSPOPCTemplate* const ext_op_template = GetExtOpTemplate(inst);
const auto jit_function = GetExtOp(inst);
if (!ext_op_template->jitFunc)
if (jit_function)
{
(this->*jit_function)(inst);
ext_is_jit = true;
}
else
{
// Fall back to interpreter
const auto interpreter_function = Interpreter::GetExtOp(inst);
m_gpr.PushRegs();
ABI_CallFunctionC16(ext_op_template->intFunc, inst);
ABI_CallFunctionC16(interpreter_function, inst);
m_gpr.PopRegs();
INFO_LOG(DSPLLE, "Instruction not JITed(ext part): %04x", inst);
ext_is_jit = false;
}
else
{
(this->*ext_op_template->jitFunc)(inst);
ext_is_jit = true;
}
}
// Main instruction
if (!op_template->jitFunc)
const auto jit_function = GetOp(inst);
if (jit_function)
{
FallBackToInterpreter(inst);
INFO_LOG(DSPLLE, "Instruction not JITed(main part): %04x", inst);
(this->*jit_function)(inst);
}
else
{
(this->*op_template->jitFunc)(inst);
FallBackToInterpreter(inst);
INFO_LOG(DSPLLE, "Instruction not JITed(main part): %04x", inst);
}
// Backlog
@@ -281,7 +289,9 @@ void DSPEmitter::Compile(u16 start_addr)
{
break;
}
else if (!opcode->jitFunc)
const auto jit_function = GetOp(inst);
if (!jit_function)
{
// look at g_dsp.pc if we actually branched
MOV(16, R(AX), M_SDSP_pc());
@@ -0,0 +1,388 @@
// Copyright 2018 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.
#include "Core/DSP/Jit/x64/DSPJitTables.h"
#include <algorithm>
#include <array>
#include "Common/CommonTypes.h"
#include "Core/DSP/Jit/x64/DSPEmitter.h"
namespace DSP::JIT::x64
{
struct JITOpInfo
{
u16 opcode;
u16 mask;
JITFunction function;
};
// clang-format off
const std::array<JITOpInfo, 214> s_opcodes =
{{
{0x0000, 0xfffc, &DSPEmitter::nop},
{0x0004, 0xfffc, &DSPEmitter::dar},
{0x0008, 0xfffc, &DSPEmitter::iar},
{0x000c, 0xfffc, &DSPEmitter::subarn},
{0x0010, 0xfff0, &DSPEmitter::addarn},
{0x0021, 0xffff, &DSPEmitter::halt},
{0x02d0, 0xffff, &DSPEmitter::ret},
{0x02d1, 0xffff, &DSPEmitter::ret},
{0x02d2, 0xffff, &DSPEmitter::ret},
{0x02d3, 0xffff, &DSPEmitter::ret},
{0x02d4, 0xffff, &DSPEmitter::ret},
{0x02d5, 0xffff, &DSPEmitter::ret},
{0x02d6, 0xffff, &DSPEmitter::ret},
{0x02d7, 0xffff, &DSPEmitter::ret},
{0x02d8, 0xffff, &DSPEmitter::ret},
{0x02d9, 0xffff, &DSPEmitter::ret},
{0x02da, 0xffff, &DSPEmitter::ret},
{0x02db, 0xffff, &DSPEmitter::ret},
{0x02dc, 0xffff, &DSPEmitter::ret},
{0x02dd, 0xffff, &DSPEmitter::ret},
{0x02de, 0xffff, &DSPEmitter::ret},
{0x02df, 0xffff, &DSPEmitter::ret},
{0x02ff, 0xffff, &DSPEmitter::rti},
{0x02b0, 0xffff, &DSPEmitter::call},
{0x02b1, 0xffff, &DSPEmitter::call},
{0x02b2, 0xffff, &DSPEmitter::call},
{0x02b3, 0xffff, &DSPEmitter::call},
{0x02b4, 0xffff, &DSPEmitter::call},
{0x02b5, 0xffff, &DSPEmitter::call},
{0x02b6, 0xffff, &DSPEmitter::call},
{0x02b7, 0xffff, &DSPEmitter::call},
{0x02b8, 0xffff, &DSPEmitter::call},
{0x02b9, 0xffff, &DSPEmitter::call},
{0x02ba, 0xffff, &DSPEmitter::call},
{0x02bb, 0xffff, &DSPEmitter::call},
{0x02bc, 0xffff, &DSPEmitter::call},
{0x02bd, 0xffff, &DSPEmitter::call},
{0x02be, 0xffff, &DSPEmitter::call},
{0x02bf, 0xffff, &DSPEmitter::call},
{0x0270, 0xffff, &DSPEmitter::ifcc},
{0x0271, 0xffff, &DSPEmitter::ifcc},
{0x0272, 0xffff, &DSPEmitter::ifcc},
{0x0273, 0xffff, &DSPEmitter::ifcc},
{0x0274, 0xffff, &DSPEmitter::ifcc},
{0x0275, 0xffff, &DSPEmitter::ifcc},
{0x0276, 0xffff, &DSPEmitter::ifcc},
{0x0277, 0xffff, &DSPEmitter::ifcc},
{0x0278, 0xffff, &DSPEmitter::ifcc},
{0x0279, 0xffff, &DSPEmitter::ifcc},
{0x027a, 0xffff, &DSPEmitter::ifcc},
{0x027b, 0xffff, &DSPEmitter::ifcc},
{0x027c, 0xffff, &DSPEmitter::ifcc},
{0x027d, 0xffff, &DSPEmitter::ifcc},
{0x027e, 0xffff, &DSPEmitter::ifcc},
{0x027f, 0xffff, &DSPEmitter::ifcc},
{0x0290, 0xffff, &DSPEmitter::jcc},
{0x0291, 0xffff, &DSPEmitter::jcc},
{0x0292, 0xffff, &DSPEmitter::jcc},
{0x0293, 0xffff, &DSPEmitter::jcc},
{0x0294, 0xffff, &DSPEmitter::jcc},
{0x0295, 0xffff, &DSPEmitter::jcc},
{0x0296, 0xffff, &DSPEmitter::jcc},
{0x0297, 0xffff, &DSPEmitter::jcc},
{0x0298, 0xffff, &DSPEmitter::jcc},
{0x0299, 0xffff, &DSPEmitter::jcc},
{0x029a, 0xffff, &DSPEmitter::jcc},
{0x029b, 0xffff, &DSPEmitter::jcc},
{0x029c, 0xffff, &DSPEmitter::jcc},
{0x029d, 0xffff, &DSPEmitter::jcc},
{0x029e, 0xffff, &DSPEmitter::jcc},
{0x029f, 0xffff, &DSPEmitter::jcc},
{0x1700, 0xff1f, &DSPEmitter::jmprcc},
{0x1701, 0xff1f, &DSPEmitter::jmprcc},
{0x1702, 0xff1f, &DSPEmitter::jmprcc},
{0x1703, 0xff1f, &DSPEmitter::jmprcc},
{0x1704, 0xff1f, &DSPEmitter::jmprcc},
{0x1705, 0xff1f, &DSPEmitter::jmprcc},
{0x1706, 0xff1f, &DSPEmitter::jmprcc},
{0x1707, 0xff1f, &DSPEmitter::jmprcc},
{0x1708, 0xff1f, &DSPEmitter::jmprcc},
{0x1709, 0xff1f, &DSPEmitter::jmprcc},
{0x170a, 0xff1f, &DSPEmitter::jmprcc},
{0x170b, 0xff1f, &DSPEmitter::jmprcc},
{0x170c, 0xff1f, &DSPEmitter::jmprcc},
{0x170d, 0xff1f, &DSPEmitter::jmprcc},
{0x170e, 0xff1f, &DSPEmitter::jmprcc},
{0x170f, 0xff1f, &DSPEmitter::jmprcc},
{0x1710, 0xff1f, &DSPEmitter::callr},
{0x1711, 0xff1f, &DSPEmitter::callr},
{0x1712, 0xff1f, &DSPEmitter::callr},
{0x1713, 0xff1f, &DSPEmitter::callr},
{0x1714, 0xff1f, &DSPEmitter::callr},
{0x1715, 0xff1f, &DSPEmitter::callr},
{0x1716, 0xff1f, &DSPEmitter::callr},
{0x1717, 0xff1f, &DSPEmitter::callr},
{0x1718, 0xff1f, &DSPEmitter::callr},
{0x1719, 0xff1f, &DSPEmitter::callr},
{0x171a, 0xff1f, &DSPEmitter::callr},
{0x171b, 0xff1f, &DSPEmitter::callr},
{0x171c, 0xff1f, &DSPEmitter::callr},
{0x171d, 0xff1f, &DSPEmitter::callr},
{0x171e, 0xff1f, &DSPEmitter::callr},
{0x171f, 0xff1f, &DSPEmitter::callr},
{0x1200, 0xff00, &DSPEmitter::sbclr},
{0x1300, 0xff00, &DSPEmitter::sbset},
{0x1400, 0xfec0, &DSPEmitter::lsl},
{0x1440, 0xfec0, &DSPEmitter::lsr},
{0x1480, 0xfec0, &DSPEmitter::asl},
{0x14c0, 0xfec0, &DSPEmitter::asr},
// These two were discovered by ector
{0x02ca, 0xffff, &DSPEmitter::lsrn},
{0x02cb, 0xffff, &DSPEmitter::asrn},
{0x0080, 0xffe0, &DSPEmitter::lri},
{0x00c0, 0xffe0, &DSPEmitter::lr},
{0x00e0, 0xffe0, &DSPEmitter::sr},
{0x1c00, 0xfc00, &DSPEmitter::mrr},
{0x1600, 0xff00, &DSPEmitter::si},
{0x0400, 0xfe00, &DSPEmitter::addis},
{0x0600, 0xfe00, &DSPEmitter::cmpis},
{0x0800, 0xf800, &DSPEmitter::lris},
{0x0200, 0xfeff, &DSPEmitter::addi},
{0x0220, 0xfeff, &DSPEmitter::xori},
{0x0240, 0xfeff, &DSPEmitter::andi},
{0x0260, 0xfeff, &DSPEmitter::ori},
{0x0280, 0xfeff, &DSPEmitter::cmpi},
{0x02a0, 0xfeff, &DSPEmitter::andf},
{0x02c0, 0xfeff, &DSPEmitter::andcf},
{0x0210, 0xfefc, &DSPEmitter::ilrr},
{0x0214, 0xfefc, &DSPEmitter::ilrrd},
{0x0218, 0xfefc, &DSPEmitter::ilrri},
{0x021c, 0xfefc, &DSPEmitter::ilrrn},
// LOOPS
{0x0040, 0xffe0, &DSPEmitter::loop},
{0x0060, 0xffe0, &DSPEmitter::bloop},
{0x1000, 0xff00, &DSPEmitter::loopi},
{0x1100, 0xff00, &DSPEmitter::bloopi},
// Load and store value pointed by indexing reg and increment; LRR/SRR variants
{0x1800, 0xff80, &DSPEmitter::lrr},
{0x1880, 0xff80, &DSPEmitter::lrrd},
{0x1900, 0xff80, &DSPEmitter::lrri},
{0x1980, 0xff80, &DSPEmitter::lrrn},
{0x1a00, 0xff80, &DSPEmitter::srr},
{0x1a80, 0xff80, &DSPEmitter::srrd},
{0x1b00, 0xff80, &DSPEmitter::srri},
{0x1b80, 0xff80, &DSPEmitter::srrn},
// 2
{0x2000, 0xf800, &DSPEmitter::lrs},
{0x2800, 0xf800, &DSPEmitter::srs},
// opcodes that can be extended
// 3 - main opcode defined by 9 bits, extension defined by last 7 bits!!
{0x3000, 0xfc80, &DSPEmitter::xorr},
{0x3400, 0xfc80, &DSPEmitter::andr},
{0x3800, 0xfc80, &DSPEmitter::orr},
{0x3c00, 0xfe80, &DSPEmitter::andc},
{0x3e00, 0xfe80, &DSPEmitter::orc},
{0x3080, 0xfe80, &DSPEmitter::xorc},
{0x3280, 0xfe80, &DSPEmitter::notc},
{0x3480, 0xfc80, &DSPEmitter::lsrnrx},
{0x3880, 0xfc80, &DSPEmitter::asrnrx},
{0x3c80, 0xfe80, &DSPEmitter::lsrnr},
{0x3e80, 0xfe80, &DSPEmitter::asrnr},
// 4
{0x4000, 0xf800, &DSPEmitter::addr},
{0x4800, 0xfc00, &DSPEmitter::addax},
{0x4c00, 0xfe00, &DSPEmitter::add},
{0x4e00, 0xfe00, &DSPEmitter::addp},
// 5
{0x5000, 0xf800, &DSPEmitter::subr},
{0x5800, 0xfc00, &DSPEmitter::subax},
{0x5c00, 0xfe00, &DSPEmitter::sub},
{0x5e00, 0xfe00, &DSPEmitter::subp},
// 6
{0x6000, 0xf800, &DSPEmitter::movr},
{0x6800, 0xfc00, &DSPEmitter::movax},
{0x6c00, 0xfe00, &DSPEmitter::mov},
{0x6e00, 0xfe00, &DSPEmitter::movp},
// 7
{0x7000, 0xfc00, &DSPEmitter::addaxl},
{0x7400, 0xfe00, &DSPEmitter::incm},
{0x7600, 0xfe00, &DSPEmitter::inc},
{0x7800, 0xfe00, &DSPEmitter::decm},
{0x7a00, 0xfe00, &DSPEmitter::dec},
{0x7c00, 0xfe00, &DSPEmitter::neg},
{0x7e00, 0xfe00, &DSPEmitter::movnp},
// 8
{0x8000, 0xf700, &DSPEmitter::nx},
{0x8100, 0xf700, &DSPEmitter::clr},
{0x8200, 0xff00, &DSPEmitter::cmp},
{0x8300, 0xff00, &DSPEmitter::mulaxh},
{0x8400, 0xff00, &DSPEmitter::clrp},
{0x8500, 0xff00, &DSPEmitter::tstprod},
{0x8600, 0xfe00, &DSPEmitter::tstaxh},
{0x8a00, 0xff00, &DSPEmitter::srbith},
{0x8b00, 0xff00, &DSPEmitter::srbith},
{0x8c00, 0xff00, &DSPEmitter::srbith},
{0x8d00, 0xff00, &DSPEmitter::srbith},
{0x8e00, 0xff00, &DSPEmitter::srbith},
{0x8f00, 0xff00, &DSPEmitter::srbith},
// 9
{0x9000, 0xf700, &DSPEmitter::mul},
{0x9100, 0xf700, &DSPEmitter::asr16},
{0x9200, 0xf600, &DSPEmitter::mulmvz},
{0x9400, 0xf600, &DSPEmitter::mulac},
{0x9600, 0xf600, &DSPEmitter::mulmv},
// A-B
{0xa000, 0xe700, &DSPEmitter::mulx},
{0xa100, 0xf700, &DSPEmitter::abs},
{0xa200, 0xe600, &DSPEmitter::mulxmvz},
{0xa400, 0xe600, &DSPEmitter::mulxac},
{0xa600, 0xe600, &DSPEmitter::mulxmv},
{0xb100, 0xf700, &DSPEmitter::tst},
// C-D
{0xc000, 0xe700, &DSPEmitter::mulc},
{0xc100, 0xe700, &DSPEmitter::cmpar},
{0xc200, 0xe600, &DSPEmitter::mulcmvz},
{0xc400, 0xe600, &DSPEmitter::mulcac},
{0xc600, 0xe600, &DSPEmitter::mulcmv},
// E
{0xe000, 0xfc00, &DSPEmitter::maddx},
{0xe400, 0xfc00, &DSPEmitter::msubx},
{0xe800, 0xfc00, &DSPEmitter::maddc},
{0xec00, 0xfc00, &DSPEmitter::msubc},
// F
{0xf000, 0xfe00, &DSPEmitter::lsl16},
{0xf200, 0xfe00, &DSPEmitter::madd},
{0xf400, 0xfe00, &DSPEmitter::lsr16},
{0xf600, 0xfe00, &DSPEmitter::msub},
{0xf800, 0xfc00, &DSPEmitter::addpaxz},
{0xfc00, 0xfe00, &DSPEmitter::clrl},
{0xfe00, 0xfe00, &DSPEmitter::movpz},
}};
constexpr std::array<JITOpInfo, 25> s_opcodes_ext
{{
{0x0000, 0x00fc, &DSPEmitter::nop},
{0x0004, 0x00fc, &DSPEmitter::dr},
{0x0008, 0x00fc, &DSPEmitter::ir},
{0x000c, 0x00fc, &DSPEmitter::nr},
{0x0010, 0x00f0, &DSPEmitter::mv},
{0x0020, 0x00e4, &DSPEmitter::s},
{0x0024, 0x00e4, &DSPEmitter::sn},
{0x0040, 0x00c4, &DSPEmitter::l},
{0x0044, 0x00c4, &DSPEmitter::ln},
{0x0080, 0x00ce, &DSPEmitter::ls},
{0x0082, 0x00ce, &DSPEmitter::sl},
{0x0084, 0x00ce, &DSPEmitter::lsn},
{0x0086, 0x00ce, &DSPEmitter::sln},
{0x0088, 0x00ce, &DSPEmitter::lsm},
{0x008a, 0x00ce, &DSPEmitter::slm},
{0x008c, 0x00ce, &DSPEmitter::lsnm},
{0x008e, 0x00ce, &DSPEmitter::slnm},
{0x00c3, 0x00cf, &DSPEmitter::ldax},
{0x00c7, 0x00cf, &DSPEmitter::ldaxn},
{0x00cb, 0x00cf, &DSPEmitter::ldaxm},
{0x00cf, 0x00cf, &DSPEmitter::ldaxnm},
{0x00c0, 0x00cc, &DSPEmitter::ld},
{0x00c4, 0x00cc, &DSPEmitter::ldn},
{0x00c8, 0x00cc, &DSPEmitter::ldm},
{0x00cc, 0x00cc, &DSPEmitter::ldnm},
}};
// clang-format on
namespace
{
std::array<JITFunction, 65536> s_op_table;
std::array<JITFunction, 256> s_ext_op_table;
bool s_tables_initialized = false;
template <size_t N>
auto FindByOpcode(UDSPInstruction opcode, const std::array<JITOpInfo, N>& data)
{
return std::find_if(data.cbegin(), data.cend(),
[opcode](const auto& info) { return (opcode & info.mask) == info.opcode; });
}
} // Anonymous namespace
JITFunction GetOp(UDSPInstruction inst)
{
return s_op_table[inst];
}
JITFunction GetExtOp(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];
}
void InitInstructionTables()
{
if (s_tables_initialized)
return;
// ext op table
for (size_t i = 0; i < s_ext_op_table.size(); i++)
{
s_ext_op_table[i] = nullptr;
const auto iter = FindByOpcode(static_cast<UDSPInstruction>(i), s_opcodes_ext);
if (iter == s_opcodes_ext.cend())
continue;
s_ext_op_table[i] = iter->function;
}
// op table
for (size_t i = 0; i < s_op_table.size(); i++)
{
s_op_table[i] = nullptr;
const auto iter = FindByOpcode(static_cast<UDSPInstruction>(i), s_opcodes);
if (iter == s_opcodes.cend())
continue;
s_op_table[i] = iter->function;
}
s_tables_initialized = true;
}
} // namespace DSP::JIT::x64
@@ -0,0 +1,18 @@
// Copyright 2018 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.
#pragma once
#include "Core/DSP/DSPCommon.h"
namespace DSP::JIT::x64
{
class DSPEmitter;
using JITFunction = void (DSPEmitter::*)(UDSPInstruction);
JITFunction GetOp(UDSPInstruction inst);
JITFunction GetExtOp(UDSPInstruction inst);
void InitInstructionTables();
} // namespace DSP::JIT::x64
+1
View File
@@ -25,6 +25,7 @@
#include "Core/DSP/DSPHost.h"
#include "Core/DSP/DSPTables.h"
#include "Core/DSP/Interpreter/DSPInterpreter.h"
#include "Core/DSP/Jit/x64/DSPEmitter.h"
#include "Core/HW/DSPLLE/DSPLLEGlobals.h"
#include "Core/HW/Memmap.h"
#include "Core/Host.h"