summaryrefslogtreecommitdiff
path: root/Source/Core
diff options
context:
space:
mode:
Diffstat (limited to 'Source/Core')
-rw-r--r--Source/Core/Common/x64Emitter.h25
-rw-r--r--Source/Core/Core/CMakeLists.txt7
-rw-r--r--Source/Core/Core/Core.vcxproj7
-rw-r--r--Source/Core/Core/Core.vcxproj.filters21
-rw-r--r--Source/Core/Core/DSP/DSPAnalyzer.cpp16
-rw-r--r--Source/Core/Core/DSP/DSPAnalyzer.h7
-rw-r--r--Source/Core/Core/DSP/DSPCore.cpp516
-rw-r--r--Source/Core/Core/DSP/DSPCore.h328
-rw-r--r--Source/Core/Core/DSP/DSPHWInterface.cpp269
-rw-r--r--Source/Core/Core/DSP/DSPHWInterface.h27
-rw-r--r--Source/Core/Core/DSP/DSPHost.h9
-rw-r--r--Source/Core/Core/DSP/DSPMemoryMap.cpp53
-rw-r--r--Source/Core/Core/DSP/DSPMemoryMap.h19
-rw-r--r--Source/Core/Core/DSP/DSPStacks.cpp34
-rw-r--r--Source/Core/Core/DSP/DSPStacks.h16
-rw-r--r--Source/Core/Core/DSP/DSPTables.cpp8
-rw-r--r--Source/Core/Core/DSP/DSPTables.h7
-rw-r--r--Source/Core/Core/DSP/Interpreter/DSPIntArithmetic.cpp674
-rw-r--r--Source/Core/Core/DSP/Interpreter/DSPIntBranch.cpp184
-rw-r--r--Source/Core/Core/DSP/Interpreter/DSPIntCCUtil.cpp183
-rw-r--r--Source/Core/Core/DSP/Interpreter/DSPIntCCUtil.h25
-rw-r--r--Source/Core/Core/DSP/Interpreter/DSPIntExtOps.cpp473
-rw-r--r--Source/Core/Core/DSP/Interpreter/DSPIntExtOps.h41
-rw-r--r--Source/Core/Core/DSP/Interpreter/DSPIntLoadStore.cpp225
-rw-r--r--Source/Core/Core/DSP/Interpreter/DSPIntMisc.cpp102
-rw-r--r--Source/Core/Core/DSP/Interpreter/DSPIntMultiplier.cpp446
-rw-r--r--Source/Core/Core/DSP/Interpreter/DSPIntTables.cpp315
-rw-r--r--Source/Core/Core/DSP/Interpreter/DSPIntTables.h4
-rw-r--r--Source/Core/Core/DSP/Interpreter/DSPIntUtil.h355
-rw-r--r--Source/Core/Core/DSP/Interpreter/DSPInterpreter.cpp787
-rw-r--r--Source/Core/Core/DSP/Interpreter/DSPInterpreter.h374
-rw-r--r--Source/Core/Core/DSP/Jit/DSPEmitterBase.cpp4
-rw-r--r--Source/Core/Core/DSP/Jit/DSPEmitterBase.h7
-rw-r--r--Source/Core/Core/DSP/Jit/x64/DSPEmitter.cpp56
-rw-r--r--Source/Core/Core/DSP/Jit/x64/DSPEmitter.h7
-rw-r--r--Source/Core/Core/DSP/Jit/x64/DSPJitArithmetic.cpp29
-rw-r--r--Source/Core/Core/DSP/Jit/x64/DSPJitBranch.cpp30
-rw-r--r--Source/Core/Core/DSP/Jit/x64/DSPJitLoadStore.cpp17
-rw-r--r--Source/Core/Core/DSP/Jit/x64/DSPJitMisc.cpp5
-rw-r--r--Source/Core/Core/DSP/Jit/x64/DSPJitRegCache.cpp1
-rw-r--r--Source/Core/Core/DSP/Jit/x64/DSPJitUtil.cpp45
-rw-r--r--Source/Core/Core/HW/DSPLLE/DSPDebugInterface.cpp323
-rw-r--r--Source/Core/Core/HW/DSPLLE/DSPDebugInterface.h85
-rw-r--r--Source/Core/Core/HW/DSPLLE/DSPHost.cpp24
-rw-r--r--Source/Core/Core/HW/DSPLLE/DSPLLE.cpp131
-rw-r--r--Source/Core/Core/HW/DSPLLE/DSPLLE.h6
-rw-r--r--Source/Core/Core/HW/DSPLLE/DSPSymbols.cpp4
-rw-r--r--Source/Core/Core/HW/DSPLLE/DSPSymbols.h7
-rw-r--r--Source/Core/Core/State.cpp2
49 files changed, 3145 insertions, 3195 deletions
diff --git a/Source/Core/Common/x64Emitter.h b/Source/Core/Common/x64Emitter.h
index 6e675e2958..97874dd72c 100644
--- a/Source/Core/Common/x64Emitter.h
+++ b/Source/Core/Common/x64Emitter.h
@@ -1097,6 +1097,13 @@ public:
}
template <typename FunctionPointer>
+ void ABI_CallFunctionP(FunctionPointer func, const void* param1)
+ {
+ MOV(64, R(ABI_PARAM1), Imm64(reinterpret_cast<u64>(param1)));
+ ABI_CallFunction(func);
+ }
+
+ template <typename FunctionPointer>
void ABI_CallFunctionPC(FunctionPointer func, const void* param1, u32 param2)
{
MOV(64, R(ABI_PARAM1), Imm64(reinterpret_cast<u64>(param1)));
@@ -1122,6 +1129,15 @@ public:
ABI_CallFunction(func);
}
+ // Pass a pointer and register as a parameter.
+ template <typename FunctionPointer>
+ void ABI_CallFunctionPR(FunctionPointer func, const void* ptr, X64Reg reg1)
+ {
+ MOV(64, R(ABI_PARAM2), R(reg1));
+ MOV(64, R(ABI_PARAM1), Imm64(reinterpret_cast<u64>(ptr)));
+ ABI_CallFunction(func);
+ }
+
// Pass two registers as parameters.
template <typename FunctionPointer>
void ABI_CallFunctionRR(FunctionPointer func, X64Reg reg1, X64Reg reg2)
@@ -1130,6 +1146,15 @@ public:
ABI_CallFunction(func);
}
+ // Pass a pointer and two registers as parameters.
+ template <typename FunctionPointer>
+ void ABI_CallFunctionPRR(FunctionPointer func, const void* ptr, X64Reg reg1, X64Reg reg2)
+ {
+ MOVTwo(64, ABI_PARAM2, reg1, 0, ABI_PARAM3, reg2);
+ MOV(64, R(ABI_PARAM1), Imm64(reinterpret_cast<u64>(ptr)));
+ ABI_CallFunction(func);
+ }
+
template <typename FunctionPointer>
void ABI_CallFunctionAC(int bits, FunctionPointer func, const Gen::OpArg& arg1, u32 param2)
{
diff --git a/Source/Core/Core/CMakeLists.txt b/Source/Core/Core/CMakeLists.txt
index ccdc3268ae..715945a319 100644
--- a/Source/Core/Core/CMakeLists.txt
+++ b/Source/Core/Core/CMakeLists.txt
@@ -111,23 +111,18 @@ add_library(core
DSP/DSPDisassembler.cpp
DSP/DSPDisassembler.h
DSP/DSPHWInterface.cpp
- DSP/DSPHWInterface.h
DSP/DSPMemoryMap.cpp
- DSP/DSPMemoryMap.h
DSP/DSPStacks.cpp
- DSP/DSPStacks.h
DSP/DSPTables.cpp
DSP/DSPTables.h
DSP/LabelMap.cpp
DSP/LabelMap.h
DSP/Interpreter/DSPIntArithmetic.cpp
DSP/Interpreter/DSPIntBranch.cpp
- DSP/Interpreter/DSPIntCCUtil.cpp
DSP/Interpreter/DSPIntCCUtil.h
DSP/Interpreter/DSPInterpreter.cpp
DSP/Interpreter/DSPInterpreter.h
DSP/Interpreter/DSPIntExtOps.cpp
- DSP/Interpreter/DSPIntExtOps.h
DSP/Interpreter/DSPIntLoadStore.cpp
DSP/Interpreter/DSPIntMisc.cpp
DSP/Interpreter/DSPIntMultiplier.cpp
@@ -186,8 +181,6 @@ add_library(core
HW/DSPHLE/MailHandler.h
HW/DSPHLE/DSPHLE.cpp
HW/DSPHLE/DSPHLE.h
- HW/DSPLLE/DSPDebugInterface.cpp
- HW/DSPLLE/DSPDebugInterface.h
HW/DSPLLE/DSPHost.cpp
HW/DSPLLE/DSPSymbols.cpp
HW/DSPLLE/DSPSymbols.h
diff --git a/Source/Core/Core/Core.vcxproj b/Source/Core/Core/Core.vcxproj
index c772229835..b2cc380db8 100644
--- a/Source/Core/Core/Core.vcxproj
+++ b/Source/Core/Core/Core.vcxproj
@@ -58,7 +58,6 @@
<ClCompile Include="DSP\DSPTables.cpp" />
<ClCompile Include="DSP\Interpreter\DSPIntArithmetic.cpp" />
<ClCompile Include="DSP\Interpreter\DSPIntBranch.cpp" />
- <ClCompile Include="DSP\Interpreter\DSPIntCCUtil.cpp" />
<ClCompile Include="DSP\Interpreter\DSPInterpreter.cpp" />
<ClCompile Include="DSP\Interpreter\DSPIntExtOps.cpp" />
<ClCompile Include="DSP\Interpreter\DSPIntLoadStore.cpp" />
@@ -107,7 +106,6 @@
<ClCompile Include="HW\DSPHLE\UCodes\INIT.cpp" />
<ClCompile Include="HW\DSPHLE\UCodes\ROM.cpp" />
<ClCompile Include="HW\DSPHLE\UCodes\Zelda.cpp" />
- <ClCompile Include="HW\DSPLLE\DSPDebugInterface.cpp" />
<ClCompile Include="HW\DSPLLE\DSPHost.cpp" />
<ClCompile Include="HW\DSPLLE\DSPLLE.cpp" />
<ClCompile Include="HW\DSPLLE\DSPLLEGlobals.cpp" />
@@ -420,13 +418,9 @@
<ClInclude Include="DSP\DSPCore.h" />
<ClInclude Include="DSP\DSPDisassembler.h" />
<ClInclude Include="DSP\DSPHost.h" />
- <ClInclude Include="DSP\DSPHWInterface.h" />
- <ClInclude Include="DSP\DSPMemoryMap.h" />
- <ClInclude Include="DSP\DSPStacks.h" />
<ClInclude Include="DSP\DSPTables.h" />
<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\DSPEmitterBase.h" />
@@ -466,7 +460,6 @@
<ClInclude Include="HW\DSPHLE\UCodes\INIT.h" />
<ClInclude Include="HW\DSPHLE\UCodes\ROM.h" />
<ClInclude Include="HW\DSPHLE\UCodes\Zelda.h" />
- <ClInclude Include="HW\DSPLLE\DSPDebugInterface.h" />
<ClInclude Include="HW\DSPLLE\DSPLLE.h" />
<ClInclude Include="HW\DSPLLE\DSPLLEGlobals.h" />
<ClInclude Include="HW\DSPLLE\DSPSymbols.h" />
diff --git a/Source/Core/Core/Core.vcxproj.filters b/Source/Core/Core/Core.vcxproj.filters
index ae2205c989..fb6d0dd27c 100644
--- a/Source/Core/Core/Core.vcxproj.filters
+++ b/Source/Core/Core/Core.vcxproj.filters
@@ -233,9 +233,6 @@
<ClCompile Include="DSP\Interpreter\DSPIntBranch.cpp">
<Filter>DSPCore\Interpreter</Filter>
</ClCompile>
- <ClCompile Include="DSP\Interpreter\DSPIntCCUtil.cpp">
- <Filter>DSPCore\Interpreter</Filter>
- </ClCompile>
<ClCompile Include="DSP\Interpreter\DSPInterpreter.cpp">
<Filter>DSPCore\Interpreter</Filter>
</ClCompile>
@@ -416,9 +413,6 @@
<ClCompile Include="HW\DSPHLE\MailHandler.cpp">
<Filter>HW %28Flipper/Hollywood%29\DSP Interface + HLE\HLE</Filter>
</ClCompile>
- <ClCompile Include="HW\DSPLLE\DSPDebugInterface.cpp">
- <Filter>HW %28Flipper/Hollywood%29\DSP Interface + HLE\LLE</Filter>
- </ClCompile>
<ClCompile Include="HW\DSPLLE\DSPHost.cpp">
<Filter>HW %28Flipper/Hollywood%29\DSP Interface + HLE\LLE</Filter>
</ClCompile>
@@ -1070,9 +1064,6 @@
<ClInclude Include="DSP\Interpreter\DSPInterpreter.h">
<Filter>DSPCore\Interpreter</Filter>
</ClInclude>
- <ClInclude Include="DSP\Interpreter\DSPIntExtOps.h">
- <Filter>DSPCore\Interpreter</Filter>
- </ClInclude>
<ClInclude Include="DSP\Interpreter\DSPIntTables.h">
<Filter>DSPCore\Interpreter</Filter>
</ClInclude>
@@ -1199,9 +1190,6 @@
<ClInclude Include="HW\DSPHLE\MailHandler.h">
<Filter>HW %28Flipper/Hollywood%29\DSP Interface + HLE\HLE</Filter>
</ClInclude>
- <ClInclude Include="HW\DSPLLE\DSPDebugInterface.h">
- <Filter>HW %28Flipper/Hollywood%29\DSP Interface + HLE\LLE</Filter>
- </ClInclude>
<ClInclude Include="DSP\DSPHost.h">
<Filter>HW %28Flipper/Hollywood%29\DSP Interface + HLE\LLE</Filter>
</ClInclude>
@@ -1388,15 +1376,6 @@
<ClInclude Include="DSPEmulator.h">
<Filter>DSPCore</Filter>
</ClInclude>
- <ClInclude Include="DSP\DSPHWInterface.h">
- <Filter>DSPCore</Filter>
- </ClInclude>
- <ClInclude Include="DSP\DSPMemoryMap.h">
- <Filter>DSPCore</Filter>
- </ClInclude>
- <ClInclude Include="DSP\DSPStacks.h">
- <Filter>DSPCore</Filter>
- </ClInclude>
<ClInclude Include="DSP\DSPTables.h">
<Filter>DSPCore</Filter>
</ClInclude>
diff --git a/Source/Core/Core/DSP/DSPAnalyzer.cpp b/Source/Core/Core/DSP/DSPAnalyzer.cpp
index 9f0b232182..7a88b99773 100644
--- a/Source/Core/Core/DSP/DSPAnalyzer.cpp
+++ b/Source/Core/Core/DSP/DSPAnalyzer.cpp
@@ -9,7 +9,7 @@
#include "Common/Logging/Log.h"
-#include "Core/DSP/DSPMemoryMap.h"
+#include "Core/DSP/DSPCore.h"
#include "Core/DSP/DSPTables.h"
namespace DSP::Analyzer
@@ -72,7 +72,7 @@ void Reset()
code_flags.fill(0);
}
-void AnalyzeRange(u16 start_addr, u16 end_addr)
+void AnalyzeRange(const SDSP& dsp, u16 start_addr, u16 end_addr)
{
// First we run an extremely simplified version of a disassembler to find
// where all instructions start.
@@ -82,7 +82,7 @@ void AnalyzeRange(u16 start_addr, u16 end_addr)
u16 last_arithmetic = 0;
for (u16 addr = start_addr; addr < end_addr;)
{
- UDSPInstruction inst = dsp_imem_read(addr);
+ const UDSPInstruction inst = dsp.ReadIMEM(addr);
const DSPOPCTemplate* opcode = GetOpTemplate(inst);
if (!opcode)
{
@@ -94,7 +94,7 @@ void AnalyzeRange(u16 start_addr, u16 end_addr)
if ((inst & 0xffe0) == 0x0060 || (inst & 0xff00) == 0x1100)
{
// BLOOP, BLOOPI
- u16 loop_end = dsp_imem_read(addr + 1);
+ const u16 loop_end = dsp.ReadIMEM(addr + 1);
code_flags[addr] |= CODE_LOOP_START;
code_flags[loop_end] |= CODE_LOOP_END;
}
@@ -139,7 +139,7 @@ void AnalyzeRange(u16 start_addr, u16 end_addr)
found = true;
if (idle_skip_sigs[s][i] == 0xFFFF)
continue;
- if (idle_skip_sigs[s][i] != dsp_imem_read(static_cast<u16>(addr + i)))
+ if (idle_skip_sigs[s][i] != dsp.ReadIMEM(static_cast<u16>(addr + i)))
break;
}
if (found)
@@ -153,11 +153,11 @@ void AnalyzeRange(u16 start_addr, u16 end_addr)
}
} // Anonymous namespace
-void Analyze()
+void Analyze(const SDSP& dsp)
{
Reset();
- AnalyzeRange(0x0000, 0x1000); // IRAM
- AnalyzeRange(0x8000, 0x9000); // IROM
+ AnalyzeRange(dsp, 0x0000, 0x1000); // IRAM
+ AnalyzeRange(dsp, 0x8000, 0x9000); // IROM
}
u8 GetCodeFlags(u16 address)
diff --git a/Source/Core/Core/DSP/DSPAnalyzer.h b/Source/Core/Core/DSP/DSPAnalyzer.h
index 9d25c2167b..dab41baadc 100644
--- a/Source/Core/Core/DSP/DSPAnalyzer.h
+++ b/Source/Core/Core/DSP/DSPAnalyzer.h
@@ -6,6 +6,11 @@
#include "Common/CommonTypes.h"
+namespace DSP
+{
+struct SDSP;
+}
+
// Basic code analysis.
namespace DSP::Analyzer
{
@@ -28,7 +33,7 @@ enum
// all old analysis away. Luckily the entire address space is only 64K code
// words and the actual code space 8K instructions in total, so we can do
// some pretty expensive analysis if necessary.
-void Analyze();
+void Analyze(const SDSP& dsp);
// Retrieves the flags set during analysis for code in memory.
u8 GetCodeFlags(u16 address);
diff --git a/Source/Core/Core/DSP/DSPCore.cpp b/Source/Core/Core/DSP/DSPCore.cpp
index 7f31720604..39618d5621 100644
--- a/Source/Core/Core/DSP/DSPCore.cpp
+++ b/Source/Core/Core/DSP/DSPCore.cpp
@@ -10,6 +10,7 @@
#include <memory>
#include <type_traits>
+#include "Common/ChunkFile.h"
#include "Common/CommonTypes.h"
#include "Common/Event.h"
#include "Common/Hash.h"
@@ -18,24 +19,18 @@
#include "Core/DSP/DSPAccelerator.h"
#include "Core/DSP/DSPAnalyzer.h"
-#include "Core/DSP/DSPHWInterface.h"
#include "Core/DSP/DSPHost.h"
-#include "Core/DSP/Interpreter/DSPIntUtil.h"
#include "Core/DSP/Interpreter/DSPInterpreter.h"
#include "Core/DSP/Jit/DSPEmitterBase.h"
namespace DSP
{
-SDSP g_dsp;
-DSPBreakpoints g_dsp_breakpoints;
-static State core_state = State::Stopped;
-bool g_init_hax = false;
-std::unique_ptr<JIT::DSPEmitter> g_dsp_jit;
-std::unique_ptr<DSPCaptureLogger> g_dsp_cap;
-static Common::Event step_event;
+// not needed for game ucodes (it slows down interpreter/dspjit32 + easier to compare int VS
+// dspjit64 without it)
+//#define PRECISE_BACKLOG
// Returns false if the hash fails and the user hits "Yes"
-static bool VerifyRoms()
+static bool VerifyRoms(const SDSP& dsp)
{
struct DspRomHashes
{
@@ -64,8 +59,10 @@ static bool VerifyRoms()
{0x128ea7a2, 0xa4a575f5},
}};
- const u32 hash_irom = Common::HashAdler32(reinterpret_cast<u8*>(g_dsp.irom), DSP_IROM_BYTE_SIZE);
- const u32 hash_drom = Common::HashAdler32(reinterpret_cast<u8*>(g_dsp.coef), DSP_COEF_BYTE_SIZE);
+ const u32 hash_irom =
+ Common::HashAdler32(reinterpret_cast<const u8*>(dsp.irom), DSP_IROM_BYTE_SIZE);
+ const u32 hash_drom =
+ Common::HashAdler32(reinterpret_cast<const u8*>(dsp.coef), DSP_COEF_BYTE_SIZE);
int rom_idx = -1;
for (size_t i = 0; i < known_roms.size(); ++i)
@@ -104,151 +101,141 @@ static bool VerifyRoms()
return true;
}
-static void DSPCore_FreeMemoryPages()
-{
- Common::FreeMemoryPages(g_dsp.irom, DSP_IROM_BYTE_SIZE);
- Common::FreeMemoryPages(g_dsp.iram, DSP_IRAM_BYTE_SIZE);
- Common::FreeMemoryPages(g_dsp.dram, DSP_DRAM_BYTE_SIZE);
- Common::FreeMemoryPages(g_dsp.coef, DSP_COEF_BYTE_SIZE);
- g_dsp.irom = g_dsp.iram = g_dsp.dram = g_dsp.coef = nullptr;
-}
-
class LLEAccelerator final : public Accelerator
{
+public:
+ explicit LLEAccelerator(SDSP& dsp) : m_dsp{dsp} {}
+
protected:
u8 ReadMemory(u32 address) override { return Host::ReadHostMemory(address); }
void WriteMemory(u32 address, u8 value) override { Host::WriteHostMemory(value, address); }
- void OnEndException() override { DSPCore_SetException(ExceptionType::AcceleratorOverflow); }
+ void OnEndException() override { m_dsp.SetException(ExceptionType::AcceleratorOverflow); }
+
+private:
+ SDSP& m_dsp;
};
-bool DSPCore_Init(const DSPInitOptions& opts)
+SDSP::SDSP(DSPCore& core) : m_dsp_core{core}
{
- g_dsp.step_counter = 0;
- g_init_hax = false;
+}
- g_dsp.accelerator = std::make_unique<LLEAccelerator>();
+SDSP::~SDSP() = default;
- g_dsp.irom = static_cast<u16*>(Common::AllocateMemoryPages(DSP_IROM_BYTE_SIZE));
- g_dsp.iram = static_cast<u16*>(Common::AllocateMemoryPages(DSP_IRAM_BYTE_SIZE));
- g_dsp.dram = static_cast<u16*>(Common::AllocateMemoryPages(DSP_DRAM_BYTE_SIZE));
- g_dsp.coef = static_cast<u16*>(Common::AllocateMemoryPages(DSP_COEF_BYTE_SIZE));
+bool SDSP::Initialize(const DSPInitOptions& opts)
+{
+ step_counter = 0;
+ accelerator = std::make_unique<LLEAccelerator>(*this);
- memcpy(g_dsp.irom, opts.irom_contents.data(), DSP_IROM_BYTE_SIZE);
- memcpy(g_dsp.coef, opts.coef_contents.data(), DSP_COEF_BYTE_SIZE);
+ irom = static_cast<u16*>(Common::AllocateMemoryPages(DSP_IROM_BYTE_SIZE));
+ iram = static_cast<u16*>(Common::AllocateMemoryPages(DSP_IRAM_BYTE_SIZE));
+ dram = static_cast<u16*>(Common::AllocateMemoryPages(DSP_DRAM_BYTE_SIZE));
+ coef = static_cast<u16*>(Common::AllocateMemoryPages(DSP_COEF_BYTE_SIZE));
+
+ std::memcpy(irom, opts.irom_contents.data(), DSP_IROM_BYTE_SIZE);
+ std::memcpy(coef, opts.coef_contents.data(), DSP_COEF_BYTE_SIZE);
// Try to load real ROM contents.
- if (!VerifyRoms())
+ if (!VerifyRoms(*this))
{
- DSPCore_FreeMemoryPages();
+ FreeMemoryPages();
return false;
}
- memset(&g_dsp.r, 0, sizeof(g_dsp.r));
+ std::memset(&r, 0, sizeof(r));
- std::fill(std::begin(g_dsp.reg_stack_ptrs), std::end(g_dsp.reg_stack_ptrs), 0);
+ std::fill(std::begin(reg_stack_ptrs), std::end(reg_stack_ptrs), 0);
- for (auto& stack : g_dsp.reg_stacks)
+ for (auto& stack : reg_stacks)
std::fill(std::begin(stack), std::end(stack), 0);
// Fill IRAM with HALT opcodes.
- std::fill(g_dsp.iram, g_dsp.iram + DSP_IRAM_SIZE, 0x0021);
+ std::fill(iram, iram + DSP_IRAM_SIZE, 0x0021);
// Just zero out DRAM.
- std::fill(g_dsp.dram, g_dsp.dram + DSP_DRAM_SIZE, 0);
+ std::fill(dram, dram + DSP_DRAM_SIZE, 0);
// Copied from a real console after the custom UCode has been loaded.
// These are the indexing wrapping registers.
- std::fill(std::begin(g_dsp.r.wr), std::end(g_dsp.r.wr), 0xffff);
+ std::fill(std::begin(r.wr), std::end(r.wr), 0xffff);
- g_dsp.r.sr |= SR_INT_ENABLE;
- g_dsp.r.sr |= SR_EXT_INT_ENABLE;
+ r.sr |= SR_INT_ENABLE;
+ r.sr |= SR_EXT_INT_ENABLE;
- g_dsp.cr = 0x804;
- gdsp_ifx_init();
+ cr = 0x804;
+ InitializeIFX();
// Mostly keep IRAM write protected. We unprotect only when DMA-ing
// in new ucodes.
- Common::WriteProtectMemory(g_dsp.iram, DSP_IRAM_BYTE_SIZE, false);
-
- // Initialize JIT, if necessary
- if (opts.core_type == DSPInitOptions::CoreType::JIT64)
- g_dsp_jit = JIT::CreateDSPEmitter();
-
- g_dsp_cap.reset(opts.capture_logger);
-
- core_state = State::Running;
+ Common::WriteProtectMemory(iram, DSP_IRAM_BYTE_SIZE, false);
return true;
}
-void DSPCore_Shutdown()
+void SDSP::Reset()
{
- if (core_state == State::Stopped)
- return;
-
- core_state = State::Stopped;
-
- g_dsp_jit.reset();
-
- DSPCore_FreeMemoryPages();
-
- g_dsp_cap.reset();
+ pc = DSP_RESET_VECTOR;
+ std::fill(std::begin(r.wr), std::end(r.wr), 0xffff);
}
-void DSPCore_Reset()
+void SDSP::Shutdown()
{
- g_dsp.pc = DSP_RESET_VECTOR;
-
- std::fill(std::begin(g_dsp.r.wr), std::end(g_dsp.r.wr), 0xffff);
+ FreeMemoryPages();
+}
- Analyzer::Analyze();
+void SDSP::FreeMemoryPages()
+{
+ Common::FreeMemoryPages(irom, DSP_IROM_BYTE_SIZE);
+ Common::FreeMemoryPages(iram, DSP_IRAM_BYTE_SIZE);
+ Common::FreeMemoryPages(dram, DSP_DRAM_BYTE_SIZE);
+ Common::FreeMemoryPages(coef, DSP_COEF_BYTE_SIZE);
+ irom = nullptr;
+ iram = nullptr;
+ dram = nullptr;
+ coef = nullptr;
}
-void DSPCore_SetException(ExceptionType exception)
+void SDSP::SetException(ExceptionType exception)
{
- g_dsp.exceptions |= 1 << static_cast<std::underlying_type_t<ExceptionType>>(exception);
+ exceptions |= 1 << static_cast<std::underlying_type_t<ExceptionType>>(exception);
}
-// Notify that an external interrupt is pending (used by thread mode)
-void DSPCore_SetExternalInterrupt(bool val)
+void SDSP::SetExternalInterrupt(bool val)
{
- g_dsp.external_interrupt_waiting = val;
+ external_interrupt_waiting = val;
}
-// Coming from the CPU
-void DSPCore_CheckExternalInterrupt()
+void SDSP::CheckExternalInterrupt()
{
- if (!Interpreter::dsp_SR_is_flag_set(SR_EXT_INT_ENABLE))
+ if (!IsSRFlagSet(SR_EXT_INT_ENABLE))
return;
// Signal the SPU about new mail
- DSPCore_SetException(ExceptionType::ExternalInterrupt);
+ SetException(ExceptionType::ExternalInterrupt);
- g_dsp.cr &= ~CR_EXTERNAL_INT;
+ cr &= ~CR_EXTERNAL_INT;
}
-void DSPCore_CheckExceptions()
+void SDSP::CheckExceptions()
{
// Early out to skip the loop in the common case.
- if (g_dsp.exceptions == 0)
+ if (exceptions == 0)
return;
for (int i = 7; i > 0; i--)
{
// Seems exp int are not masked by sr_int_enable
- if (g_dsp.exceptions & (1 << i))
+ if ((exceptions & (1U << i)) != 0)
{
- if (Interpreter::dsp_SR_is_flag_set(SR_INT_ENABLE) ||
- i == static_cast<int>(ExceptionType::ExternalInterrupt))
+ if (IsSRFlagSet(SR_INT_ENABLE) || i == static_cast<int>(ExceptionType::ExternalInterrupt))
{
// store pc and sr until RTI
- dsp_reg_store_stack(StackRegister::Call, g_dsp.pc);
- dsp_reg_store_stack(StackRegister::Data, g_dsp.r.sr);
+ StoreStack(StackRegister::Call, pc);
+ StoreStack(StackRegister::Data, r.sr);
- g_dsp.pc = i * 2;
- g_dsp.exceptions &= ~(1 << i);
+ pc = static_cast<u16>(i * 2);
+ exceptions &= ~(1 << i);
if (i == 7)
- g_dsp.r.sr &= ~SR_EXT_INT_ENABLE;
+ r.sr &= ~SR_EXT_INT_ENABLE;
else
- g_dsp.r.sr &= ~SR_INT_ENABLE;
+ r.sr &= ~SR_INT_ENABLE;
break;
}
else
@@ -261,68 +248,7 @@ void DSPCore_CheckExceptions()
}
}
-// Delegate to JIT or interpreter as appropriate.
-// Handle state changes and stepping.
-int DSPCore_RunCycles(int cycles)
-{
- if (g_dsp_jit)
- {
- return g_dsp_jit->RunCycles(static_cast<u16>(cycles));
- }
-
- while (cycles > 0)
- {
- switch (core_state)
- {
- case State::Running:
-// Seems to slow things down
-#if defined(_DEBUG) || defined(DEBUGFAST)
- cycles = Interpreter::RunCyclesDebug(cycles);
-#else
- cycles = Interpreter::RunCycles(cycles);
-#endif
- break;
-
- case State::Stepping:
- step_event.Wait();
- if (core_state != State::Stepping)
- continue;
-
- Interpreter::Step();
- cycles--;
-
- Host::UpdateDebugger();
- break;
- case State::Stopped:
- break;
- }
- }
- return cycles;
-}
-
-void DSPCore_SetState(State new_state)
-{
- core_state = new_state;
-
- // kick the event, in case we are waiting
- if (new_state == State::Running)
- step_event.Set();
-
- Host::UpdateDebugger();
-}
-
-State DSPCore_GetState()
-{
- return core_state;
-}
-
-void DSPCore_Step()
-{
- if (core_state == State::Stepping)
- step_event.Set();
-}
-
-u16 DSPCore_ReadRegister(size_t reg)
+u16 SDSP::ReadRegister(size_t reg) const
{
switch (reg)
{
@@ -330,56 +256,56 @@ u16 DSPCore_ReadRegister(size_t reg)
case DSP_REG_AR1:
case DSP_REG_AR2:
case DSP_REG_AR3:
- return g_dsp.r.ar[reg - DSP_REG_AR0];
+ return r.ar[reg - DSP_REG_AR0];
case DSP_REG_IX0:
case DSP_REG_IX1:
case DSP_REG_IX2:
case DSP_REG_IX3:
- return g_dsp.r.ix[reg - DSP_REG_IX0];
+ return r.ix[reg - DSP_REG_IX0];
case DSP_REG_WR0:
case DSP_REG_WR1:
case DSP_REG_WR2:
case DSP_REG_WR3:
- return g_dsp.r.wr[reg - DSP_REG_WR0];
+ return r.wr[reg - DSP_REG_WR0];
case DSP_REG_ST0:
case DSP_REG_ST1:
case DSP_REG_ST2:
case DSP_REG_ST3:
- return g_dsp.r.st[reg - DSP_REG_ST0];
+ return r.st[reg - DSP_REG_ST0];
case DSP_REG_ACH0:
case DSP_REG_ACH1:
- return g_dsp.r.ac[reg - DSP_REG_ACH0].h;
+ return r.ac[reg - DSP_REG_ACH0].h;
case DSP_REG_CR:
- return g_dsp.r.cr;
+ return r.cr;
case DSP_REG_SR:
- return g_dsp.r.sr;
+ return r.sr;
case DSP_REG_PRODL:
- return g_dsp.r.prod.l;
+ return r.prod.l;
case DSP_REG_PRODM:
- return g_dsp.r.prod.m;
+ return r.prod.m;
case DSP_REG_PRODH:
- return g_dsp.r.prod.h;
+ return r.prod.h;
case DSP_REG_PRODM2:
- return g_dsp.r.prod.m2;
+ return r.prod.m2;
case DSP_REG_AXL0:
case DSP_REG_AXL1:
- return g_dsp.r.ax[reg - DSP_REG_AXL0].l;
+ return r.ax[reg - DSP_REG_AXL0].l;
case DSP_REG_AXH0:
case DSP_REG_AXH1:
- return g_dsp.r.ax[reg - DSP_REG_AXH0].h;
+ return r.ax[reg - DSP_REG_AXH0].h;
case DSP_REG_ACL0:
case DSP_REG_ACL1:
- return g_dsp.r.ac[reg - DSP_REG_ACL0].l;
+ return r.ac[reg - DSP_REG_ACL0].l;
case DSP_REG_ACM0:
case DSP_REG_ACM1:
- return g_dsp.r.ac[reg - DSP_REG_ACM0].m;
+ return r.ac[reg - DSP_REG_ACM0].m;
default:
ASSERT_MSG(DSP_CORE, 0, "cannot happen");
return 0;
}
}
-void DSPCore_WriteRegister(size_t reg, u16 val)
+void SDSP::WriteRegister(size_t reg, u16 val)
{
switch (reg)
{
@@ -387,64 +313,288 @@ void DSPCore_WriteRegister(size_t reg, u16 val)
case DSP_REG_AR1:
case DSP_REG_AR2:
case DSP_REG_AR3:
- g_dsp.r.ar[reg - DSP_REG_AR0] = val;
+ r.ar[reg - DSP_REG_AR0] = val;
break;
case DSP_REG_IX0:
case DSP_REG_IX1:
case DSP_REG_IX2:
case DSP_REG_IX3:
- g_dsp.r.ix[reg - DSP_REG_IX0] = val;
+ r.ix[reg - DSP_REG_IX0] = val;
break;
case DSP_REG_WR0:
case DSP_REG_WR1:
case DSP_REG_WR2:
case DSP_REG_WR3:
- g_dsp.r.wr[reg - DSP_REG_WR0] = val;
+ r.wr[reg - DSP_REG_WR0] = val;
break;
case DSP_REG_ST0:
case DSP_REG_ST1:
case DSP_REG_ST2:
case DSP_REG_ST3:
- g_dsp.r.st[reg - DSP_REG_ST0] = val;
+ r.st[reg - DSP_REG_ST0] = val;
break;
case DSP_REG_ACH0:
case DSP_REG_ACH1:
- g_dsp.r.ac[reg - DSP_REG_ACH0].h = val;
+ r.ac[reg - DSP_REG_ACH0].h = val;
break;
case DSP_REG_CR:
- g_dsp.r.cr = val;
+ r.cr = val;
break;
case DSP_REG_SR:
- g_dsp.r.sr = val;
+ r.sr = val;
break;
case DSP_REG_PRODL:
- g_dsp.r.prod.l = val;
+ r.prod.l = val;
break;
case DSP_REG_PRODM:
- g_dsp.r.prod.m = val;
+ r.prod.m = val;
break;
case DSP_REG_PRODH:
- g_dsp.r.prod.h = val;
+ r.prod.h = val;
break;
case DSP_REG_PRODM2:
- g_dsp.r.prod.m2 = val;
+ r.prod.m2 = val;
break;
case DSP_REG_AXL0:
case DSP_REG_AXL1:
- g_dsp.r.ax[reg - DSP_REG_AXL0].l = val;
+ r.ax[reg - DSP_REG_AXL0].l = val;
break;
case DSP_REG_AXH0:
case DSP_REG_AXH1:
- g_dsp.r.ax[reg - DSP_REG_AXH0].h = val;
+ r.ax[reg - DSP_REG_AXH0].h = val;
break;
case DSP_REG_ACL0:
case DSP_REG_ACL1:
- g_dsp.r.ac[reg - DSP_REG_ACL0].l = val;
+ r.ac[reg - DSP_REG_ACL0].l = val;
break;
case DSP_REG_ACM0:
case DSP_REG_ACM1:
- g_dsp.r.ac[reg - DSP_REG_ACM0].m = val;
+ r.ac[reg - DSP_REG_ACM0].m = val;
break;
}
}
+
+void SDSP::DoState(PointerWrap& p)
+{
+ p.Do(r);
+ p.Do(pc);
+ p.Do(cr);
+ p.Do(reg_stack_ptrs);
+ p.Do(exceptions);
+ p.Do(external_interrupt_waiting);
+
+ for (auto& stack : reg_stacks)
+ {
+ p.Do(stack);
+ }
+
+ p.Do(step_counter);
+ p.DoArray(ifx_regs);
+ accelerator->DoState(p);
+ p.Do(mbox[0]);
+ p.Do(mbox[1]);
+ Common::UnWriteProtectMemory(iram, DSP_IRAM_BYTE_SIZE, false);
+ p.DoArray(iram, DSP_IRAM_SIZE);
+ Common::WriteProtectMemory(iram, DSP_IRAM_BYTE_SIZE, false);
+ // TODO: This uses the wrong endianness (producing bad disassembly)
+ // and a bogus byte count (producing bad hashes)
+ if (p.GetMode() == PointerWrap::MODE_READ)
+ Host::CodeLoaded(m_dsp_core, reinterpret_cast<const u8*>(iram), DSP_IRAM_BYTE_SIZE);
+ p.DoArray(dram, DSP_DRAM_SIZE);
+}
+
+DSPCore::DSPCore()
+ : m_dsp{*this}, m_dsp_interpreter{std::make_unique<Interpreter::Interpreter>(*this)}
+{
+}
+
+DSPCore::~DSPCore() = default;
+
+bool DSPCore::Initialize(const DSPInitOptions& opts)
+{
+ if (!m_dsp.Initialize(opts))
+ return false;
+
+ m_init_hax = false;
+
+ // Initialize JIT, if necessary
+ if (opts.core_type == DSPInitOptions::CoreType::JIT64)
+ m_dsp_jit = JIT::CreateDSPEmitter(*this);
+
+ m_dsp_cap.reset(opts.capture_logger);
+
+ m_core_state = State::Running;
+ return true;
+}
+
+void DSPCore::Shutdown()
+{
+ if (m_core_state == State::Stopped)
+ return;
+
+ m_core_state = State::Stopped;
+
+ m_dsp_jit.reset();
+ m_dsp.Shutdown();
+ m_dsp_cap.reset();
+}
+
+// Delegate to JIT or interpreter as appropriate.
+// Handle state changes and stepping.
+int DSPCore::RunCycles(int cycles)
+{
+ if (m_dsp_jit)
+ {
+ return m_dsp_jit->RunCycles(static_cast<u16>(cycles));
+ }
+
+ while (cycles > 0)
+ {
+ switch (m_core_state)
+ {
+ case State::Running:
+// Seems to slow things down
+#if defined(_DEBUG) || defined(DEBUGFAST)
+ cycles = m_dsp_interpreter->RunCyclesDebug(cycles);
+#else
+ cycles = m_dsp_interpreter->RunCycles(cycles);
+#endif
+ break;
+
+ case State::Stepping:
+ m_step_event.Wait();
+ if (m_core_state != State::Stepping)
+ continue;
+
+ m_dsp_interpreter->Step();
+ cycles--;
+
+ Host::UpdateDebugger();
+ break;
+ case State::Stopped:
+ break;
+ }
+ }
+ return cycles;
+}
+
+void DSPCore::Step()
+{
+ if (m_core_state == State::Stepping)
+ m_step_event.Set();
+}
+
+void DSPCore::Reset()
+{
+ m_dsp.Reset();
+ Analyzer::Analyze(m_dsp);
+}
+
+void DSPCore::ClearIRAM()
+{
+ if (!m_dsp_jit)
+ return;
+
+ m_dsp_jit->ClearIRAM();
+}
+
+void DSPCore::SetState(State new_state)
+{
+ m_core_state = new_state;
+
+ // kick the event, in case we are waiting
+ if (new_state == State::Running)
+ m_step_event.Set();
+
+ Host::UpdateDebugger();
+}
+
+State DSPCore::GetState() const
+{
+ return m_core_state;
+}
+
+void DSPCore::SetException(ExceptionType exception)
+{
+ m_dsp.SetException(exception);
+}
+
+void DSPCore::SetExternalInterrupt(bool val)
+{
+ m_dsp.SetExternalInterrupt(val);
+}
+
+void DSPCore::CheckExternalInterrupt()
+{
+ m_dsp.CheckExternalInterrupt();
+}
+
+void DSPCore::CheckExceptions()
+{
+ m_dsp.CheckExceptions();
+}
+
+u16 DSPCore::ReadRegister(size_t reg) const
+{
+ return m_dsp.ReadRegister(reg);
+}
+
+void DSPCore::WriteRegister(size_t reg, u16 val)
+{
+ m_dsp.WriteRegister(reg, val);
+}
+
+u32 DSPCore::PeekMailbox(Mailbox mailbox) const
+{
+ return m_dsp.PeekMailbox(mailbox);
+}
+
+u16 DSPCore::ReadMailboxLow(Mailbox mailbox)
+{
+ return m_dsp.ReadMailboxLow(mailbox);
+}
+
+u16 DSPCore::ReadMailboxHigh(Mailbox mailbox)
+{
+ return m_dsp.ReadMailboxHigh(mailbox);
+}
+
+void DSPCore::WriteMailboxLow(Mailbox mailbox, u16 value)
+{
+ m_dsp.WriteMailboxLow(mailbox, value);
+}
+
+void DSPCore::WriteMailboxHigh(Mailbox mailbox, u16 value)
+{
+ m_dsp.WriteMailboxHigh(mailbox, value);
+}
+
+void DSPCore::LogIFXRead(u16 address, u16 read_value)
+{
+ m_dsp_cap->LogIFXRead(address, read_value);
+}
+
+void DSPCore::LogIFXWrite(u16 address, u16 written_value)
+{
+ m_dsp_cap->LogIFXWrite(address, written_value);
+}
+
+void DSPCore::LogDMA(u16 control, u32 gc_address, u16 dsp_address, u16 length, const u8* data)
+{
+ m_dsp_cap->LogDMA(control, gc_address, dsp_address, length, data);
+}
+
+bool DSPCore::IsJITCreated() const
+{
+ return m_dsp_jit != nullptr;
+}
+
+void DSPCore::DoState(PointerWrap& p)
+{
+ m_dsp.DoState(p);
+ p.Do(m_init_hax);
+
+ if (m_dsp_jit)
+ m_dsp_jit->DoState(p);
+}
} // namespace DSP
diff --git a/Source/Core/Core/DSP/DSPCore.h b/Source/Core/Core/DSP/DSPCore.h
index a3f61d1e96..719e6a02c8 100644
--- a/Source/Core/Core/DSP/DSPCore.h
+++ b/Source/Core/Core/DSP/DSPCore.h
@@ -11,12 +11,21 @@
#include <memory>
#include <string>
+#include "Common/Event.h"
#include "Core/DSP/DSPBreakpoints.h"
#include "Core/DSP/DSPCaptureLogger.h"
+class PointerWrap;
+
namespace DSP
{
class Accelerator;
+class DSPCore;
+
+namespace Interpreter
+{
+class Interpreter;
+}
namespace JIT
{
@@ -216,6 +225,12 @@ enum class ExceptionType
ExternalInterrupt = 7 // 0x000e external int (message from CPU)
};
+enum Mailbox : int
+{
+ MAILBOX_CPU,
+ MAILBOX_DSP
+};
+
struct DSP_Regs
{
u16 ar[4];
@@ -259,26 +274,141 @@ struct DSP_Regs
} ac[2];
};
+struct DSPInitOptions
+{
+ // DSP IROM blob, which is where the DSP boots from. Embedded into the DSP.
+ std::array<u16, DSP_IROM_SIZE> irom_contents;
+
+ // DSP DROM blob, which contains resampling coefficients.
+ std::array<u16, DSP_COEF_SIZE> coef_contents;
+
+ // Core used to emulate the DSP.
+ // Default: JIT64.
+ enum class CoreType
+ {
+ Interpreter,
+ JIT64,
+ };
+ CoreType core_type = CoreType::JIT64;
+
+ // Optional capture logger used to log internal DSP data transfers.
+ // Default: dummy implementation, does nothing.
+ DSPCaptureLogger* capture_logger;
+
+ DSPInitOptions() : capture_logger(new DefaultDSPCaptureLogger()) {}
+};
+
// All the state of the DSP should be in this struct. Any DSP state that is not filled on init
// should be moved here.
struct SDSP
{
- DSP_Regs r;
- u16 pc;
-#if PROFILE
- u16 err_pc;
-#endif
+ explicit SDSP(DSPCore& core);
+ ~SDSP();
+
+ SDSP(const SDSP&) = delete;
+ SDSP& operator=(const SDSP&) = delete;
+
+ SDSP(SDSP&&) = delete;
+ SDSP& operator=(SDSP&&) = delete;
+
+ // Initializes overall state.
+ bool Initialize(const DSPInitOptions& opts);
+
+ // Shuts down any necessary DSP state.
+ void Shutdown();
+
+ // Resets DSP state as if the reset exception vector has been taken.
+ void Reset();
+
+ // Initializes the IFX registers.
+ void InitializeIFX();
+
+ // Writes to IFX registers.
+ void WriteIFX(u32 address, u16 value);
+
+ // Reads from IFX registers.
+ u16 ReadIFX(u16 address);
+
+ // Checks the whole value within a mailbox.
+ u32 PeekMailbox(Mailbox mailbox) const;
+
+ // Reads the low part of the value in the specified mailbox.
+ u16 ReadMailboxLow(Mailbox mailbox);
+
+ // Reads the high part of the value in the specified mailbox.
+ u16 ReadMailboxHigh(Mailbox mailbox);
+
+ // Writes to the low part of the mailbox.
+ void WriteMailboxLow(Mailbox mailbox, u16 value);
+
+ // Writes to the high part of the mailbox.
+ void WriteMailboxHigh(Mailbox mailbox, u16 value);
+
+ // Reads from instruction memory.
+ u16 ReadIMEM(u16 address) const;
+
+ // Reads from data memory.
+ u16 ReadDMEM(u16 address);
+
+ // Write to data memory.
+ void WriteDMEM(u16 address, u16 value);
+
+ // Fetches the next instruction and increments the PC.
+ u16 FetchInstruction();
+
+ // Fetches the instruction at the PC address, but doesn't increment the PC.
+ u16 PeekInstruction() const;
+
+ // Skips over the next instruction in memory.
+ void SkipInstruction();
+
+ // Sets the given flags in the SR register.
+ void SetSRFlag(u16 flag) { r.sr |= flag; }
+
+ // Whether or not the given flag is set in the SR register.
+ bool IsSRFlagSet(u16 flag) const { return (r.sr & flag) != 0; }
+
+ // Indicates that a particular exception has occurred
+ // and sets a flag in the pending exception register.
+ void SetException(ExceptionType exception);
+
+ // Checks if any exceptions occurred an updates the DSP state as appropriate.
+ void CheckExceptions();
+
+ // Notify that an external interrupt is pending (used by thread mode)
+ void SetExternalInterrupt(bool val);
+
+ // Coming from the CPU
+ void CheckExternalInterrupt();
+
+ // Stores a value into the specified stack
+ void StoreStack(StackRegister stack_reg, u16 val);
+
+ // Pops a value off of the specified stack
+ u16 PopStack(StackRegister stack_reg);
+
+ // Reads the current value from a particular register.
+ u16 ReadRegister(size_t reg) const;
+
+ // Writes a value to a given register.
+ void WriteRegister(size_t reg, u16 val);
+
+ // Saves and loads any necessary state.
+ void DoState(PointerWrap& p);
+
+ DSP_Regs r{};
+ u16 pc = 0;
// This is NOT the same cr as r.cr.
// This register is shared with the main emulation, see DSP.cpp
// The engine has control over 0x0C07 of this reg.
// Bits are defined in a struct in DSP.cpp.
- u16 cr;
+ u16 cr = 0;
- u8 reg_stack_ptrs[4];
- u8 exceptions; // pending exceptions
- volatile bool external_interrupt_waiting;
- bool reset_dspjit_codespace;
+ u8 reg_stack_ptrs[4]{};
+ u8 exceptions = 0; // pending exceptions
+ volatile bool external_interrupt_waiting = false;
+ bool reset_dspjit_codespace = false;
// DSP hardware stacks. They're mapped to a bunch of registers, such that writes
// to them push and reads pop.
@@ -286,87 +416,157 @@ struct SDSP
// The real DSP has different depths for the different stacks, but it would
// be strange if any ucode relied on stack overflows since on the DSP, when
// the stack overflows, you're screwed.
- u16 reg_stacks[4][DSP_STACK_DEPTH];
+ u16 reg_stacks[4][DSP_STACK_DEPTH]{};
// For debugging.
- u32 iram_crc;
- u64 step_counter;
+ u32 iram_crc = 0;
+ u64 step_counter = 0;
// Mailbox.
std::atomic<u32> mbox[2];
// Accelerator / DMA / other hardware registers. Not GPRs.
- std::array<u16, 256> ifx_regs;
+ std::array<u16, 256> ifx_regs{};
std::unique_ptr<Accelerator> accelerator;
// When state saving, all of the above can just be memcpy'd into the save state.
// The below needs special handling.
- u16* iram;
- u16* dram;
- u16* irom;
- u16* coef;
+ u16* iram = nullptr;
+ u16* dram = nullptr;
+ u16* irom = nullptr;
+ u16* coef = nullptr;
+
+private:
+ void FreeMemoryPages();
+
+ void DoDMA();
+ const u8* DDMAIn(u16 dsp_addr, u32 addr, u32 size);
+ const u8* DDMAOut(u16 dsp_addr, u32 addr, u32 size);
+ const u8* IDMAIn(u16 dsp_addr, u32 addr, u32 size);
+ const u8* IDMAOut(u16 dsp_addr, u32 addr, u32 size);
+
+ u16 ReadIFXImpl(u16 address);
+
+ DSPCore& m_dsp_core;
};
-extern SDSP g_dsp;
-extern DSPBreakpoints g_dsp_breakpoints;
-extern bool g_init_hax;
-extern std::unique_ptr<JIT::DSPEmitter> g_dsp_jit;
-extern std::unique_ptr<DSPCaptureLogger> g_dsp_cap;
+enum class State
+{
+ Stopped,
+ Running,
+ Stepping,
+};
-struct DSPInitOptions
+class DSPCore
{
- // DSP IROM blob, which is where the DSP boots from. Embedded into the DSP.
- std::array<u16, DSP_IROM_SIZE> irom_contents;
+public:
+ DSPCore();
+ ~DSPCore();
- // DSP DROM blob, which contains resampling coefficients.
- std::array<u16, DSP_COEF_SIZE> coef_contents;
+ DSPCore(const DSPCore&) = delete;
+ DSPCore& operator=(const DSPCore&) = delete;
- // Core used to emulate the DSP.
- // Default: JIT64.
- enum class CoreType
- {
- Interpreter,
- JIT64,
- };
- CoreType core_type = CoreType::JIT64;
+ DSPCore(DSPCore&&) = delete;
+ DSPCore& operator=(DSPCore&&) = delete;
- // Optional capture logger used to log internal DSP data transfers.
- // Default: dummy implementation, does nothing.
- DSPCaptureLogger* capture_logger;
+ // Initializes the DSP emulator using the provided options. Takes ownership of
+ // all the pointers contained in the options structure.
+ bool Initialize(const DSPInitOptions& opts);
- DSPInitOptions() : capture_logger(new DefaultDSPCaptureLogger()) {}
-};
+ // Shuts down the DSP core and cleans up any necessary state.
+ void Shutdown();
-// Initializes the DSP emulator using the provided options. Takes ownership of
-// all the pointers contained in the options structure.
-bool DSPCore_Init(const DSPInitOptions& opts);
+ // Delegates to JIT or interpreter as appropriate.
+ // Handle state changes and stepping.
+ int RunCycles(int cycles);
-void DSPCore_Reset();
-void DSPCore_Shutdown(); // Frees all allocated memory.
+ // Steps the DSP by a single instruction.
+ void Step();
-void DSPCore_CheckExternalInterrupt();
-void DSPCore_CheckExceptions();
-void DSPCore_SetExternalInterrupt(bool val);
+ // Resets DSP state as if the reset exception vector has been taken.
+ void Reset();
-// sets a flag in the pending exception register.
-void DSPCore_SetException(ExceptionType exception);
+ // Clears the DSP instruction RAM.
+ void ClearIRAM();
-enum class State
-{
- Stopped,
- Running,
- Stepping,
-};
+ // Dictates whether or not the DSP is currently stopped, running or stepping
+ // through instructions.
+ void SetState(State new_state);
+
+ // Retrieves the current execution state of the DSP.
+ State GetState() const;
+
+ // Indicates that a particular exception has occurred
+ // and sets a flag in the pending exception register.
+ void SetException(ExceptionType exception);
+
+ // Notify that an external interrupt is pending (used by thread mode)
+ void SetExternalInterrupt(bool val);
+
+ // Coming from the CPU
+ void CheckExternalInterrupt();
+
+ // Checks if any exceptions occurred an updates the DSP state as appropriate.
+ void CheckExceptions();
-int DSPCore_RunCycles(int cycles);
+ // Reads the current value from a particular register.
+ u16 ReadRegister(size_t reg) const;
-// These are meant to be called from the UI thread.
-void DSPCore_SetState(State new_state);
-State DSPCore_GetState();
+ // Writes a value to a given register.
+ void WriteRegister(size_t reg, u16 val);
-void DSPCore_Step();
+ // Checks the value within a mailbox.
+ u32 PeekMailbox(Mailbox mailbox) const;
-u16 DSPCore_ReadRegister(size_t reg);
-void DSPCore_WriteRegister(size_t reg, u16 val);
+ // Reads the low part of the specified mailbox register.
+ u16 ReadMailboxLow(Mailbox mailbox);
+
+ // Reads the high part of the specified mailbox register.
+ u16 ReadMailboxHigh(Mailbox mailbox);
+
+ // Writes to the low part of the mailbox register.
+ void WriteMailboxLow(Mailbox mailbox, u16 value);
+
+ // Writes to the high part of the mailbox register.
+ void WriteMailboxHigh(Mailbox mailbox, u16 value);
+
+ // Logs an IFX register read.
+ void LogIFXRead(u16 address, u16 read_value);
+
+ // Logs an IFX register write.
+ void LogIFXWrite(u16 address, u16 written_value);
+
+ // Logs a DMA operation
+ void LogDMA(u16 control, u32 gc_address, u16 dsp_address, u16 length, const u8* data);
+
+ // Whether or not the JIT has been created.
+ bool IsJITCreated() const;
+
+ // Writes or loads state for savestates.
+ void DoState(PointerWrap& p);
+
+ // Accessors for the DSP breakpoint facilities.
+ DSPBreakpoints& BreakPoints() { return m_dsp_breakpoints; }
+ const DSPBreakpoints& BreakPoints() const { return m_dsp_breakpoints; }
+
+ SDSP& DSPState() { return m_dsp; }
+ const SDSP& DSPState() const { return m_dsp; }
+
+ Interpreter::Interpreter& GetInterpreter() { return *m_dsp_interpreter; }
+ const Interpreter::Interpreter& GetInterpreter() const { return *m_dsp_interpreter; }
+
+ bool GetInitHax() const { return m_init_hax; }
+ void SetInitHax(bool value) { m_init_hax = value; }
+
+private:
+ SDSP m_dsp;
+ DSPBreakpoints m_dsp_breakpoints;
+ State m_core_state = State::Stopped;
+ bool m_init_hax = false;
+ std::unique_ptr<Interpreter::Interpreter> m_dsp_interpreter;
+ std::unique_ptr<JIT::DSPEmitter> m_dsp_jit;
+ std::unique_ptr<DSPCaptureLogger> m_dsp_cap;
+ Common::Event m_step_event;
+};
} // namespace DSP
diff --git a/Source/Core/Core/DSP/DSPHWInterface.cpp b/Source/Core/Core/DSP/DSPHWInterface.cpp
index 7e81da0a4d..0733cc4e22 100644
--- a/Source/Core/Core/DSP/DSPHWInterface.cpp
+++ b/Source/Core/Core/DSP/DSPHWInterface.cpp
@@ -3,8 +3,6 @@
// Licensed under GPLv2+
// Refer to the license.txt file included.
-#include "Core/DSP/DSPHWInterface.h"
-
#include <atomic>
#include <cstddef>
#include <cstring>
@@ -23,349 +21,346 @@
namespace DSP
{
-static void gdsp_do_dma();
-
-void gdsp_ifx_init()
+void SDSP::InitializeIFX()
{
- g_dsp.ifx_regs.fill(0);
+ ifx_regs.fill(0);
- g_dsp.mbox[MAILBOX_CPU].store(0);
- g_dsp.mbox[MAILBOX_DSP].store(0);
-}
-
-u32 gdsp_mbox_peek(Mailbox mbx)
-{
- return g_dsp.mbox[mbx].load();
+ mbox[MAILBOX_CPU].store(0);
+ mbox[MAILBOX_DSP].store(0);
}
-void gdsp_mbox_write_h(Mailbox mbx, u16 val)
+u32 SDSP::PeekMailbox(Mailbox mailbox) const
{
- const u32 old_value = g_dsp.mbox[mbx].load(std::memory_order_acquire);
- const u32 new_value = (old_value & 0xffff) | (val << 16);
-
- g_dsp.mbox[mbx].store(new_value & ~0x80000000, std::memory_order_release);
+ return mbox[mailbox].load();
}
-void gdsp_mbox_write_l(Mailbox mbx, u16 val)
+u16 SDSP::ReadMailboxLow(Mailbox mailbox)
{
- const u32 old_value = g_dsp.mbox[mbx].load(std::memory_order_acquire);
- const u32 new_value = (old_value & ~0xffff) | val;
+ const u32 value = mbox[mailbox].load(std::memory_order_acquire);
+ mbox[mailbox].store(value & ~0x80000000, std::memory_order_release);
- g_dsp.mbox[mbx].store(new_value | 0x80000000, std::memory_order_release);
+ if (m_dsp_core.GetInitHax() && mailbox == MAILBOX_DSP)
+ {
+ m_dsp_core.SetInitHax(false);
+ m_dsp_core.Reset();
+ return 0x4348;
+ }
#if defined(_DEBUG) || defined(DEBUGFAST)
- const char* const type = mbx == MAILBOX_DSP ? "DSP" : "CPU";
- DEBUG_LOG_FMT(DSP_MAIL, "{}(WM) B:{} M:{:#010x} (pc={:#06x})", type, mbx, gdsp_mbox_peek(mbx),
- g_dsp.pc);
+ const char* const type = mailbox == MAILBOX_DSP ? "DSP" : "CPU";
+ DEBUG_LOG_FMT(DSP_MAIL, "{}(RM) B:{} M:0x{:#010x} (pc={:#06x})", type, mailbox,
+ PeekMailbox(mailbox), pc);
#endif
+
+ return static_cast<u16>(value);
}
-u16 gdsp_mbox_read_h(Mailbox mbx)
+u16 SDSP::ReadMailboxHigh(Mailbox mailbox)
{
- if (g_init_hax && mbx == MAILBOX_DSP)
+ if (m_dsp_core.GetInitHax() && mailbox == MAILBOX_DSP)
{
return 0x8054;
}
- return (u16)(g_dsp.mbox[mbx].load() >> 16); // TODO: mask away the top bit?
+ // TODO: mask away the top bit?
+ return static_cast<u16>(PeekMailbox(mailbox) >> 16);
}
-u16 gdsp_mbox_read_l(Mailbox mbx)
+void SDSP::WriteMailboxLow(Mailbox mailbox, u16 value)
{
- const u32 value = g_dsp.mbox[mbx].load(std::memory_order_acquire);
- g_dsp.mbox[mbx].store(value & ~0x80000000, std::memory_order_release);
+ const u32 old_value = mbox[mailbox].load(std::memory_order_acquire);
+ const u32 new_value = (old_value & ~0xffff) | value;
- if (g_init_hax && mbx == MAILBOX_DSP)
- {
- g_init_hax = false;
- DSPCore_Reset();
- return 0x4348;
- }
+ mbox[mailbox].store(new_value | 0x80000000, std::memory_order_release);
#if defined(_DEBUG) || defined(DEBUGFAST)
- const char* const type = mbx == MAILBOX_DSP ? "DSP" : "CPU";
- DEBUG_LOG_FMT(DSP_MAIL, "{}(RM) B:{} M:0x{:#010x} (pc={:#06x})", type, mbx, gdsp_mbox_peek(mbx),
- g_dsp.pc);
+ const char* const type = mailbox == MAILBOX_DSP ? "DSP" : "CPU";
+ DEBUG_LOG_FMT(DSP_MAIL, "{}(WM) B:{} M:{:#010x} (pc={:#06x})", type, mailbox,
+ PeekMailbox(mailbox), pc);
#endif
+}
- return (u16)value;
+void SDSP::WriteMailboxHigh(Mailbox mailbox, u16 value)
+{
+ const u32 old_value = mbox[mailbox].load(std::memory_order_acquire);
+ const u32 new_value = (old_value & 0xffff) | (value << 16);
+
+ mbox[mailbox].store(new_value & ~0x80000000, std::memory_order_release);
}
-void gdsp_ifx_write(u32 addr, u16 val)
+void SDSP::WriteIFX(u32 address, u16 value)
{
- g_dsp_cap->LogIFXWrite(addr, val);
+ m_dsp_core.LogIFXWrite(address, value);
- switch (addr & 0xff)
+ switch (address & 0xff)
{
case DSP_DIRQ:
- if ((val & 1) != 0)
+ if ((value & 1) != 0)
Host::InterruptRequest();
else
- WARN_LOG_FMT(DSPLLE, "Unknown Interrupt Request pc={:#06x} ({:#06x})", g_dsp.pc, val);
+ WARN_LOG_FMT(DSPLLE, "Unknown Interrupt Request pc={:#06x} ({:#06x})", pc, value);
break;
case DSP_DMBH:
- gdsp_mbox_write_h(MAILBOX_DSP, val);
+ WriteMailboxHigh(MAILBOX_DSP, value);
break;
case DSP_DMBL:
- gdsp_mbox_write_l(MAILBOX_DSP, val);
+ WriteMailboxLow(MAILBOX_DSP, value);
break;
case DSP_CMBH:
- return gdsp_mbox_write_h(MAILBOX_CPU, val);
+ WriteMailboxHigh(MAILBOX_CPU, value);
+ break;
case DSP_CMBL:
- return gdsp_mbox_write_l(MAILBOX_CPU, val);
+ WriteMailboxLow(MAILBOX_CPU, value);
+ break;
case DSP_DSBL:
- g_dsp.ifx_regs[DSP_DSBL] = val;
- g_dsp.ifx_regs[DSP_DSCR] |= 4; // Doesn't really matter since we do DMA instantly
- if (!g_dsp.ifx_regs[DSP_AMDM])
- gdsp_do_dma();
+ ifx_regs[DSP_DSBL] = value;
+ ifx_regs[DSP_DSCR] |= 4; // Doesn't really matter since we do DMA instantly
+ if (!ifx_regs[DSP_AMDM])
+ DoDMA();
else
NOTICE_LOG_FMT(DSPLLE, "Masked DMA skipped");
- g_dsp.ifx_regs[DSP_DSCR] &= ~4;
- g_dsp.ifx_regs[DSP_DSBL] = 0;
+ ifx_regs[DSP_DSCR] &= ~4;
+ ifx_regs[DSP_DSBL] = 0;
break;
case DSP_GAIN:
- if (val != 0)
+ if (value != 0)
{
- DEBUG_LOG_FMT(DSPLLE, "Gain Written: {:#06x}", val);
+ DEBUG_LOG_FMT(DSPLLE, "Gain Written: {:#06x}", value);
}
[[fallthrough]];
case DSP_DSPA:
case DSP_DSMAH:
case DSP_DSMAL:
case DSP_DSCR:
- g_dsp.ifx_regs[addr & 0xFF] = val;
+ ifx_regs[address & 0xFF] = value;
break;
case DSP_ACSAH:
- g_dsp.accelerator->SetStartAddress(val << 16 |
- static_cast<u16>(g_dsp.accelerator->GetStartAddress()));
+ accelerator->SetStartAddress(value << 16 | static_cast<u16>(accelerator->GetStartAddress()));
break;
case DSP_ACSAL:
- g_dsp.accelerator->SetStartAddress(
- static_cast<u16>(g_dsp.accelerator->GetStartAddress() >> 16) << 16 | val);
+ accelerator->SetStartAddress(static_cast<u16>(accelerator->GetStartAddress() >> 16) << 16 |
+ value);
break;
case DSP_ACEAH:
- g_dsp.accelerator->SetEndAddress(val << 16 |
- static_cast<u16>(g_dsp.accelerator->GetEndAddress()));
+ accelerator->SetEndAddress(value << 16 | static_cast<u16>(accelerator->GetEndAddress()));
break;
case DSP_ACEAL:
- g_dsp.accelerator->SetEndAddress(
- static_cast<u16>(g_dsp.accelerator->GetEndAddress() >> 16) << 16 | val);
+ accelerator->SetEndAddress(static_cast<u16>(accelerator->GetEndAddress() >> 16) << 16 | value);
break;
case DSP_ACCAH:
- g_dsp.accelerator->SetCurrentAddress(val << 16 |
- static_cast<u16>(g_dsp.accelerator->GetCurrentAddress()));
+ accelerator->SetCurrentAddress(value << 16 |
+ static_cast<u16>(accelerator->GetCurrentAddress()));
break;
case DSP_ACCAL:
- g_dsp.accelerator->SetCurrentAddress(
- static_cast<u16>(g_dsp.accelerator->GetCurrentAddress() >> 16) << 16 | val);
+ accelerator->SetCurrentAddress(static_cast<u16>(accelerator->GetCurrentAddress() >> 16) << 16 |
+ value);
break;
case DSP_FORMAT:
- g_dsp.accelerator->SetSampleFormat(val);
+ accelerator->SetSampleFormat(value);
break;
case DSP_YN1:
- g_dsp.accelerator->SetYn1(val);
+ accelerator->SetYn1(value);
break;
case DSP_YN2:
- g_dsp.accelerator->SetYn2(val);
+ accelerator->SetYn2(value);
break;
case DSP_PRED_SCALE:
- g_dsp.accelerator->SetPredScale(val);
+ accelerator->SetPredScale(value);
break;
case DSP_ACDATA1: // Accelerator write (Zelda type) - "UnkZelda"
- g_dsp.accelerator->WriteD3(val);
+ accelerator->WriteD3(value);
break;
default:
- if ((addr & 0xff) >= 0xa0)
+ if ((address & 0xff) >= 0xa0)
{
- const u32 index = (addr & 0xFF) - 0xa0;
+ const u32 index = (address & 0xFF) - 0xa0;
const auto& label = pdlabels[index];
if (label.name && label.description)
{
- DEBUG_LOG_FMT(DSPLLE, "{:04x} MW {} ({:04x})", g_dsp.pc, label.name, val);
+ DEBUG_LOG_FMT(DSPLLE, "{:04x} MW {} ({:04x})", pc, label.name, value);
}
else
{
- ERROR_LOG_FMT(DSPLLE, "{:04x} MW {:04x} ({:04x})", g_dsp.pc, addr, val);
+ ERROR_LOG_FMT(DSPLLE, "{:04x} MW {:04x} ({:04x})", pc, address, value);
}
}
else
{
- ERROR_LOG_FMT(DSPLLE, "{:04x} MW {:04x} ({:04x})", g_dsp.pc, addr, val);
+ ERROR_LOG_FMT(DSPLLE, "{:04x} MW {:04x} ({:04x})", pc, address, value);
}
- g_dsp.ifx_regs[addr & 0xFF] = val;
+ ifx_regs[address & 0xFF] = value;
break;
}
}
-static u16 _gdsp_ifx_read(u16 addr)
+u16 SDSP::ReadIFXImpl(u16 address)
{
- switch (addr & 0xff)
+ switch (address & 0xff)
{
case DSP_DMBH:
- return gdsp_mbox_read_h(MAILBOX_DSP);
+ return ReadMailboxHigh(MAILBOX_DSP);
case DSP_DMBL:
- return gdsp_mbox_read_l(MAILBOX_DSP);
+ return ReadMailboxLow(MAILBOX_DSP);
case DSP_CMBH:
- return gdsp_mbox_read_h(MAILBOX_CPU);
+ return ReadMailboxHigh(MAILBOX_CPU);
case DSP_CMBL:
- return gdsp_mbox_read_l(MAILBOX_CPU);
+ return ReadMailboxLow(MAILBOX_CPU);
case DSP_DSCR:
- return g_dsp.ifx_regs[addr & 0xFF];
+ return ifx_regs[address & 0xFF];
case DSP_ACSAH:
- return static_cast<u16>(g_dsp.accelerator->GetStartAddress() >> 16);
+ return static_cast<u16>(accelerator->GetStartAddress() >> 16);
case DSP_ACSAL:
- return static_cast<u16>(g_dsp.accelerator->GetStartAddress());
+ return static_cast<u16>(accelerator->GetStartAddress());
case DSP_ACEAH:
- return static_cast<u16>(g_dsp.accelerator->GetEndAddress() >> 16);
+ return static_cast<u16>(accelerator->GetEndAddress() >> 16);
case DSP_ACEAL:
- return static_cast<u16>(g_dsp.accelerator->GetEndAddress());
+ return static_cast<u16>(accelerator->GetEndAddress());
case DSP_ACCAH:
- return static_cast<u16>(g_dsp.accelerator->GetCurrentAddress() >> 16);
+ return static_cast<u16>(accelerator->GetCurrentAddress() >> 16);
case DSP_ACCAL:
- return static_cast<u16>(g_dsp.accelerator->GetCurrentAddress());
+ return static_cast<u16>(accelerator->GetCurrentAddress());
case DSP_FORMAT:
- return g_dsp.accelerator->GetSampleFormat();
+ return accelerator->GetSampleFormat();
case DSP_YN1:
- return g_dsp.accelerator->GetYn1();
+ return accelerator->GetYn1();
case DSP_YN2:
- return g_dsp.accelerator->GetYn2();
+ return accelerator->GetYn2();
case DSP_PRED_SCALE:
- return g_dsp.accelerator->GetPredScale();
+ return accelerator->GetPredScale();
case DSP_ACCELERATOR: // ADPCM Accelerator reads
- return g_dsp.accelerator->Read(reinterpret_cast<s16*>(&g_dsp.ifx_regs[DSP_COEF_A1_0]));
+ return accelerator->Read(reinterpret_cast<s16*>(&ifx_regs[DSP_COEF_A1_0]));
case DSP_ACDATA1: // Accelerator reads (Zelda type) - "UnkZelda"
- return g_dsp.accelerator->ReadD3();
+ return accelerator->ReadD3();
default:
{
- const u16 ifx_reg = g_dsp.ifx_regs[addr & 0xFF];
+ const u16 ifx_reg = ifx_regs[address & 0xFF];
- if ((addr & 0xff) >= 0xa0)
+ if ((address & 0xff) >= 0xa0)
{
- const u32 index = (addr & 0xFF) - 0xa0;
+ const u32 index = (address & 0xFF) - 0xa0;
const auto& label = pdlabels[index];
if (label.name && label.description)
{
- DEBUG_LOG_FMT(DSPLLE, "{:04x} MR {} ({:04x})", g_dsp.pc, label.name, ifx_reg);
+ DEBUG_LOG_FMT(DSPLLE, "{:04x} MR {} ({:04x})", pc, label.name, ifx_reg);
}
else
{
- ERROR_LOG_FMT(DSPLLE, "{:04x} MR {:04x} ({:04x})", g_dsp.pc, addr, ifx_reg);
+ ERROR_LOG_FMT(DSPLLE, "{:04x} MR {:04x} ({:04x})", pc, address, ifx_reg);
}
}
else
{
- ERROR_LOG_FMT(DSPLLE, "{:04x} MR {:04x} ({:04x})", g_dsp.pc, addr, ifx_reg);
+ ERROR_LOG_FMT(DSPLLE, "{:04x} MR {:04x} ({:04x})", pc, address, ifx_reg);
}
return ifx_reg;
}
}
}
-u16 gdsp_ifx_read(u16 addr)
+u16 SDSP::ReadIFX(u16 address)
{
- u16 retval = _gdsp_ifx_read(addr);
- g_dsp_cap->LogIFXRead(addr, retval);
+ const u16 retval = ReadIFXImpl(address);
+ m_dsp_core.LogIFXRead(address, retval);
return retval;
}
-static const u8* gdsp_idma_in(u16 dsp_addr, u32 addr, u32 size)
+const u8* SDSP::IDMAIn(u16 dsp_addr, u32 addr, u32 size)
{
- Common::UnWriteProtectMemory(g_dsp.iram, DSP_IRAM_BYTE_SIZE, false);
- Host::DMAToDSP(g_dsp.iram + dsp_addr / 2, addr, size);
- Common::WriteProtectMemory(g_dsp.iram, DSP_IRAM_BYTE_SIZE, false);
+ Common::UnWriteProtectMemory(iram, DSP_IRAM_BYTE_SIZE, false);
+ Host::DMAToDSP(iram + dsp_addr / 2, addr, size);
+ Common::WriteProtectMemory(iram, DSP_IRAM_BYTE_SIZE, false);
- Host::CodeLoaded(addr, size);
+ Host::CodeLoaded(m_dsp_core, addr, size);
NOTICE_LOG_FMT(DSPLLE, "*** Copy new UCode from {:#010x} to {:#06x} (crc: {:#08x})", addr,
- dsp_addr, g_dsp.iram_crc);
+ dsp_addr, iram_crc);
- return reinterpret_cast<u8*>(g_dsp.iram) + dsp_addr;
+ return reinterpret_cast<const u8*>(iram) + dsp_addr;
}
-static const u8* gdsp_idma_out(u16 dsp_addr, u32 addr, u32 size)
+const u8* SDSP::IDMAOut(u16 dsp_addr, u32 addr, u32 size)
{
ERROR_LOG_FMT(DSPLLE, "*** idma_out IRAM_DSP ({:#06x}) -> RAM ({:#010x}) : size ({:#010x})",
dsp_addr / 2, addr, size);
-
return nullptr;
}
// TODO: These should eat clock cycles.
-static const u8* gdsp_ddma_in(u16 dsp_addr, u32 addr, u32 size)
+const u8* SDSP::DDMAIn(u16 dsp_addr, u32 addr, u32 size)
{
- Host::DMAToDSP(g_dsp.dram + dsp_addr / 2, addr, size);
+ Host::DMAToDSP(dram + dsp_addr / 2, addr, size);
DEBUG_LOG_FMT(DSPLLE, "*** ddma_in RAM ({:#010x}) -> DRAM_DSP ({:#06x}) : size ({:#010x})", addr,
dsp_addr / 2, size);
- return reinterpret_cast<u8*>(g_dsp.dram) + dsp_addr;
+ return reinterpret_cast<const u8*>(dram) + dsp_addr;
}
-static const u8* gdsp_ddma_out(u16 dsp_addr, u32 addr, u32 size)
+const u8* SDSP::DDMAOut(u16 dsp_addr, u32 addr, u32 size)
{
- Host::DMAFromDSP(g_dsp.dram + dsp_addr / 2, addr, size);
+ Host::DMAFromDSP(dram + dsp_addr / 2, addr, size);
DEBUG_LOG_FMT(DSPLLE, "*** ddma_out DRAM_DSP ({:#06x}) -> RAM ({:#010x}) : size ({:#010x})",
dsp_addr / 2, addr, size);
- return reinterpret_cast<const u8*>(g_dsp.dram) + dsp_addr;
+ return reinterpret_cast<const u8*>(dram) + dsp_addr;
}
-static void gdsp_do_dma()
+void SDSP::DoDMA()
{
- const u32 addr = (g_dsp.ifx_regs[DSP_DSMAH] << 16) | g_dsp.ifx_regs[DSP_DSMAL];
- const u16 ctl = g_dsp.ifx_regs[DSP_DSCR];
- const u16 dsp_addr = g_dsp.ifx_regs[DSP_DSPA] * 2;
- const u16 len = g_dsp.ifx_regs[DSP_DSBL];
+ const u32 addr = (ifx_regs[DSP_DSMAH] << 16) | ifx_regs[DSP_DSMAL];
+ const u16 ctl = ifx_regs[DSP_DSCR];
+ const u16 dsp_addr = ifx_regs[DSP_DSPA] * 2;
+ const u16 len = ifx_regs[DSP_DSBL];
if (len > 0x4000)
{
ERROR_LOG_FMT(DSPLLE,
"DMA ERROR: PC: {:04x}, Control: {:04x}, Address: {:08x}, DSP Address: {:04x}, "
"Size: {:04x}",
- g_dsp.pc, ctl, addr, dsp_addr, len);
+ pc, ctl, addr, dsp_addr, len);
std::exit(0);
}
#if defined(_DEBUG) || defined(DEBUGFAST)
DEBUG_LOG_FMT(
DSPLLE, "DMA pc: {:04x}, Control: {:04x}, Address: {:08x}, DSP Address: {:04x}, Size: {:04x}",
- g_dsp.pc, ctl, addr, dsp_addr, len);
+ pc, ctl, addr, dsp_addr, len);
#endif
const u8* copied_data_ptr = nullptr;
switch (ctl & 0x3)
{
case (DSP_CR_DMEM | DSP_CR_TO_CPU):
- copied_data_ptr = gdsp_ddma_out(dsp_addr, addr, len);
+ copied_data_ptr = DDMAOut(dsp_addr, addr, len);
break;
case (DSP_CR_DMEM | DSP_CR_FROM_CPU):
- copied_data_ptr = gdsp_ddma_in(dsp_addr, addr, len);
+ copied_data_ptr = DDMAIn(dsp_addr, addr, len);
break;
case (DSP_CR_IMEM | DSP_CR_TO_CPU):
- copied_data_ptr = gdsp_idma_out(dsp_addr, addr, len);
+ copied_data_ptr = IDMAOut(dsp_addr, addr, len);
break;
case (DSP_CR_IMEM | DSP_CR_FROM_CPU):
- copied_data_ptr = gdsp_idma_in(dsp_addr, addr, len);
+ copied_data_ptr = IDMAIn(dsp_addr, addr, len);
break;
}
if (copied_data_ptr)
- g_dsp_cap->LogDMA(ctl, addr, dsp_addr, len, copied_data_ptr);
+ m_dsp_core.LogDMA(ctl, addr, dsp_addr, len, copied_data_ptr);
}
} // namespace DSP
diff --git a/Source/Core/Core/DSP/DSPHWInterface.h b/Source/Core/Core/DSP/DSPHWInterface.h
deleted file mode 100644
index 8c68e1c834..0000000000
--- a/Source/Core/Core/DSP/DSPHWInterface.h
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright 2008 Dolphin Emulator Project
-// Copyright 2004 Duddie & Tratax
-// Licensed under GPLv2+
-// Refer to the license.txt file included.
-
-#pragma once
-
-#include "Common/CommonTypes.h"
-
-namespace DSP
-{
-enum Mailbox
-{
- MAILBOX_CPU,
- MAILBOX_DSP
-};
-
-u32 gdsp_mbox_peek(Mailbox mbx);
-void gdsp_mbox_write_h(Mailbox mbx, u16 val);
-void gdsp_mbox_write_l(Mailbox mbx, u16 val);
-u16 gdsp_mbox_read_h(Mailbox mbx);
-u16 gdsp_mbox_read_l(Mailbox mbx);
-
-void gdsp_ifx_init();
-void gdsp_ifx_write(u32 addr, u16 val);
-u16 gdsp_ifx_read(u16 addr);
-} // namespace DSP
diff --git a/Source/Core/Core/DSP/DSPHost.h b/Source/Core/Core/DSP/DSPHost.h
index 2f47dfe0e4..04ba3ed317 100644
--- a/Source/Core/Core/DSP/DSPHost.h
+++ b/Source/Core/Core/DSP/DSPHost.h
@@ -13,6 +13,11 @@
// core isn't used, for example in an asm/disasm tool, then most of these
// can be stubbed out.
+namespace DSP
+{
+class DSPCore;
+}
+
namespace DSP::Host
{
u8 ReadHostMemory(u32 addr);
@@ -23,7 +28,7 @@ void OSD_AddMessage(std::string str, u32 ms);
bool OnThread();
bool IsWiiHost();
void InterruptRequest();
-void CodeLoaded(u32 addr, size_t size);
-void CodeLoaded(const u8* ptr, size_t size);
+void CodeLoaded(DSPCore& dsp, u32 addr, size_t size);
+void CodeLoaded(DSPCore& dsp, const u8* ptr, size_t size);
void UpdateDebugger();
} // namespace DSP::Host
diff --git a/Source/Core/Core/DSP/DSPMemoryMap.cpp b/Source/Core/Core/DSP/DSPMemoryMap.cpp
index 6bbe109795..fe14a557c5 100644
--- a/Source/Core/Core/DSP/DSPMemoryMap.cpp
+++ b/Source/Core/Core/DSP/DSPMemoryMap.cpp
@@ -3,86 +3,81 @@
// Licensed under GPLv2+
// Refer to the license.txt file included.
-#include "Core/DSP/DSPMemoryMap.h"
-
#include "Common/Logging/Log.h"
#include "Core/DSP/DSPCore.h"
-#include "Core/DSP/DSPHWInterface.h"
#include "Core/DSP/DSPTables.h"
namespace DSP
{
-u16 dsp_imem_read(u16 addr)
+u16 SDSP::ReadIMEM(u16 address) const
{
- switch (addr >> 12)
+ switch (address >> 12)
{
case 0: // 0xxx IRAM
- return g_dsp.iram[addr & DSP_IRAM_MASK];
+ return iram[address & DSP_IRAM_MASK];
case 8: // 8xxx IROM - contains code to receive code for IRAM, and a bunch of mixing loops.
- return g_dsp.irom[addr & DSP_IROM_MASK];
+ return irom[address & DSP_IROM_MASK];
default: // Unmapped/non-existing memory
- ERROR_LOG_FMT(DSPLLE, "{:04x} DSP ERROR: Executing from invalid ({:04x}) memory", g_dsp.pc,
- addr);
+ ERROR_LOG_FMT(DSPLLE, "{:04x} DSP ERROR: Executing from invalid ({:04x}) memory", pc, address);
return 0;
}
}
-u16 dsp_dmem_read(u16 addr)
+u16 SDSP::ReadDMEM(u16 address)
{
- switch (addr >> 12)
+ switch (address >> 12)
{
case 0x0: // 0xxx DRAM
- return g_dsp.dram[addr & DSP_DRAM_MASK];
+ return dram[address & DSP_DRAM_MASK];
case 0x1: // 1xxx COEF
- DEBUG_LOG_FMT(DSPLLE, "{:04x} : Coefficient Read @ {:04x}", g_dsp.pc, addr);
- return g_dsp.coef[addr & DSP_COEF_MASK];
+ DEBUG_LOG_FMT(DSPLLE, "{:04x} : Coefficient Read @ {:04x}", pc, address);
+ return coef[address & DSP_COEF_MASK];
case 0xf: // Fxxx HW regs
- return gdsp_ifx_read(addr);
+ return ReadIFX(address);
default: // Unmapped/non-existing memory
- ERROR_LOG_FMT(DSPLLE, "{:04x} DSP ERROR: Read from UNKNOWN ({:04x}) memory", g_dsp.pc, addr);
+ ERROR_LOG_FMT(DSPLLE, "{:04x} DSP ERROR: Read from UNKNOWN ({:04x}) memory", pc, address);
return 0;
}
}
-void dsp_dmem_write(u16 addr, u16 val)
+void SDSP::WriteDMEM(u16 address, u16 value)
{
- switch (addr >> 12)
+ switch (address >> 12)
{
case 0x0: // 0xxx DRAM
- g_dsp.dram[addr & DSP_DRAM_MASK] = val;
+ dram[address & DSP_DRAM_MASK] = value;
break;
case 0xf: // Fxxx HW regs
- gdsp_ifx_write(addr, val);
+ WriteIFX(address, value);
break;
default: // Unmapped/non-existing memory
- ERROR_LOG_FMT(DSPLLE, "{:04x} DSP ERROR: Write to UNKNOWN ({:04x}) memory", g_dsp.pc, addr);
+ ERROR_LOG_FMT(DSPLLE, "{:04x} DSP ERROR: Write to UNKNOWN ({:04x}) memory", pc, address);
break;
}
}
-u16 dsp_fetch_code()
+u16 SDSP::FetchInstruction()
{
- u16 opc = dsp_imem_read(g_dsp.pc);
-
- g_dsp.pc++;
+ const u16 opc = PeekInstruction();
+ pc++;
return opc;
}
-u16 dsp_peek_code()
+u16 SDSP::PeekInstruction() const
{
- return dsp_imem_read(g_dsp.pc);
+ return ReadIMEM(pc);
}
-void dsp_skip_inst()
+void SDSP::SkipInstruction()
{
- g_dsp.pc += GetOpTemplate(dsp_peek_code())->size;
+ pc += GetOpTemplate(PeekInstruction())->size;
}
} // namespace DSP
diff --git a/Source/Core/Core/DSP/DSPMemoryMap.h b/Source/Core/Core/DSP/DSPMemoryMap.h
deleted file mode 100644
index 118949f5d9..0000000000
--- a/Source/Core/Core/DSP/DSPMemoryMap.h
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright 2008 Dolphin Emulator Project
-// Copyright 2004 Duddie & Tratax
-// Licensed under GPLv2+
-// Refer to the license.txt file included.
-
-#pragma once
-
-#include "Common/CommonTypes.h"
-
-namespace DSP
-{
-u16 dsp_imem_read(u16 addr);
-void dsp_dmem_write(u16 addr, u16 val);
-u16 dsp_dmem_read(u16 addr);
-
-u16 dsp_fetch_code();
-u16 dsp_peek_code();
-void dsp_skip_inst();
-} // namespace DSP
diff --git a/Source/Core/Core/DSP/DSPStacks.cpp b/Source/Core/Core/DSP/DSPStacks.cpp
index e7d8afed25..ebe3f20612 100644
--- a/Source/Core/Core/DSP/DSPStacks.cpp
+++ b/Source/Core/Core/DSP/DSPStacks.cpp
@@ -3,8 +3,6 @@
// Licensed under GPLv2+
// Refer to the license.txt file included.
-#include "Core/DSP/DSPStacks.h"
-
#include <cstddef>
#include "Common/CommonTypes.h"
@@ -13,34 +11,26 @@
// Stacks. The stacks are outside the DSP RAM, in dedicated hardware.
namespace DSP
{
-static void dsp_reg_stack_push(size_t stack_reg)
-{
- g_dsp.reg_stack_ptrs[stack_reg]++;
- g_dsp.reg_stack_ptrs[stack_reg] &= DSP_STACK_MASK;
- g_dsp.reg_stacks[stack_reg][g_dsp.reg_stack_ptrs[stack_reg]] = g_dsp.r.st[stack_reg];
-}
-
-static void dsp_reg_stack_pop(size_t stack_reg)
-{
- g_dsp.r.st[stack_reg] = g_dsp.reg_stacks[stack_reg][g_dsp.reg_stack_ptrs[stack_reg]];
- g_dsp.reg_stack_ptrs[stack_reg]--;
- g_dsp.reg_stack_ptrs[stack_reg] &= DSP_STACK_MASK;
-}
-
-void dsp_reg_store_stack(StackRegister stack_reg, u16 val)
+void SDSP::StoreStack(StackRegister stack_reg, u16 val)
{
const auto reg_index = static_cast<size_t>(stack_reg);
- dsp_reg_stack_push(reg_index);
- g_dsp.r.st[reg_index] = val;
+ reg_stack_ptrs[reg_index]++;
+ reg_stack_ptrs[reg_index] &= DSP_STACK_MASK;
+ reg_stacks[reg_index][reg_stack_ptrs[reg_index]] = r.st[reg_index];
+
+ r.st[reg_index] = val;
}
-u16 dsp_reg_load_stack(StackRegister stack_reg)
+u16 SDSP::PopStack(StackRegister stack_reg)
{
const auto reg_index = static_cast<size_t>(stack_reg);
+ const u16 val = r.st[reg_index];
+
+ r.st[reg_index] = reg_stacks[reg_index][reg_stack_ptrs[reg_index]];
+ reg_stack_ptrs[reg_index]--;
+ reg_stack_ptrs[reg_index] &= DSP_STACK_MASK;
- const u16 val = g_dsp.r.st[reg_index];
- dsp_reg_stack_pop(reg_index);
return val;
}
} // namespace DSP
diff --git a/Source/Core/Core/DSP/DSPStacks.h b/Source/Core/Core/DSP/DSPStacks.h
deleted file mode 100644
index c793c475cf..0000000000
--- a/Source/Core/Core/DSP/DSPStacks.h
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright 2008 Dolphin Emulator Project
-// Copyright 2004 Duddie & Tratax
-// Licensed under GPLv2+
-// Refer to the license.txt file included.
-
-#pragma once
-
-#include "Common/CommonTypes.h"
-
-namespace DSP
-{
-enum class StackRegister;
-
-void dsp_reg_store_stack(StackRegister stack_reg, u16 val);
-u16 dsp_reg_load_stack(StackRegister stack_reg);
-} // namespace DSP
diff --git a/Source/Core/Core/DSP/DSPTables.cpp b/Source/Core/Core/DSP/DSPTables.cpp
index 113d8c4eb0..f518b24c81 100644
--- a/Source/Core/Core/DSP/DSPTables.cpp
+++ b/Source/Core/Core/DSP/DSPTables.cpp
@@ -477,9 +477,6 @@ const std::array<pdlabel_t, 36> regnames =
}};
// clang-format on
-std::array<u16, WRITEBACK_LOG_SIZE> writeBackLog;
-std::array<int, WRITEBACK_LOG_SIZE> writeBackLogIdx;
-
const char* pdname(u16 val)
{
static char tmpstr[12]; // nasty
@@ -612,10 +609,5 @@ void InitInstructionTable()
else
ERROR_LOG_FMT(DSPLLE, "opcode table place {} already in use for {}", i, iter->name);
}
-
- writeBackLogIdx.fill(-1);
-
- // Ensure the interpreter tables are all set up, as JITs also rely on them.
- Interpreter::InitInstructionTables();
}
} // namespace DSP
diff --git a/Source/Core/Core/DSP/DSPTables.h b/Source/Core/Core/DSP/DSPTables.h
index 40004da3fc..ac8fc3080e 100644
--- a/Source/Core/Core/DSP/DSPTables.h
+++ b/Source/Core/Core/DSP/DSPTables.h
@@ -85,10 +85,6 @@ struct DSPOPCTemplate
// Opcodes
extern const DSPOPCTemplate cw;
-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
{
@@ -105,9 +101,6 @@ const char* pdregname(int val);
const char* pdregnamelong(int val);
void InitInstructionTable();
-void ApplyWriteBackLog();
-void ZeroWriteBackLog();
-void ZeroWriteBackLogPreserveAcc(u8 acc);
// Used by the assembler and disassembler for info retrieval.
const DSPOPCTemplate* FindOpInfoByOpcode(UDSPInstruction opcode);
diff --git a/Source/Core/Core/DSP/Interpreter/DSPIntArithmetic.cpp b/Source/Core/Core/DSP/Interpreter/DSPIntArithmetic.cpp
index 54c36b449c..f0614aaab5 100644
--- a/Source/Core/Core/DSP/Interpreter/DSPIntArithmetic.cpp
+++ b/Source/Core/Core/DSP/Interpreter/DSPIntArithmetic.cpp
@@ -4,8 +4,6 @@
//
// Additional copyrights go to Duddie and Tratax (c) 2004
-#include "Core/DSP/DSPMemoryMap.h"
-#include "Core/DSP/DSPTables.h"
#include "Core/DSP/Interpreter/DSPIntCCUtil.h"
#include "Core/DSP/Interpreter/DSPIntUtil.h"
#include "Core/DSP/Interpreter/DSPInterpreter.h"
@@ -19,12 +17,12 @@ namespace DSP::Interpreter
// Clears accumulator $acR
//
// flags out: --10 0100
-void clr(const UDSPInstruction opc)
+void Interpreter::clr(const UDSPInstruction opc)
{
- u8 reg = (opc >> 11) & 0x1;
+ const u8 reg = (opc >> 11) & 0x1;
- dsp_set_long_acc(reg, 0);
- Update_SR_Register64(0);
+ SetLongAcc(reg, 0);
+ UpdateSR64(0);
ZeroWriteBackLog();
}
@@ -33,15 +31,15 @@ void clr(const UDSPInstruction opc)
// Clears (and rounds!) $acR.l - low 16 bits of accumulator $acR.
//
// flags out: --xx xx00
-void clrl(const UDSPInstruction opc)
+void Interpreter::clrl(const UDSPInstruction opc)
{
- u8 reg = (opc >> 8) & 0x1;
- s64 acc = dsp_round_long_acc(dsp_get_long_acc(reg));
+ const u8 reg = (opc >> 8) & 0x1;
+ const s64 acc = dsp_round_long_acc(GetLongAcc(reg));
ZeroWriteBackLog();
- dsp_set_long_acc(reg, acc);
- Update_SR_Register64(acc);
+ SetLongAcc(reg, acc);
+ UpdateSR64(acc);
}
//----
@@ -53,13 +51,13 @@ void clrl(const UDSPInstruction opc)
// accumulator mid part $acD.m with immediate value I is equal I.
//
// flags out: -x-- ----
-void andcf(const UDSPInstruction opc)
+void Interpreter::andcf(const UDSPInstruction opc)
{
- u8 reg = (opc >> 8) & 0x1;
+ const u8 reg = (opc >> 8) & 0x1;
+ const u16 imm = m_dsp_core.DSPState().FetchInstruction();
+ const u16 val = GetAccMid(reg);
- u16 imm = dsp_fetch_code();
- u16 val = dsp_get_acc_m(reg);
- Update_SR_LZ(((val & imm) == imm) ? true : false);
+ UpdateSRLogicZero((val & imm) == imm);
}
// ANDF $acD.m, #I
@@ -70,13 +68,13 @@ void andcf(const UDSPInstruction opc)
// immediate value 0.
//
// flags out: -x-- ----
-void andf(const UDSPInstruction opc)
+void Interpreter::andf(const UDSPInstruction opc)
{
- u8 reg = (opc >> 8) & 0x1;
+ const u8 reg = (opc >> 8) & 0x1;
+ const u16 imm = m_dsp_core.DSPState().FetchInstruction();
+ const u16 val = GetAccMid(reg);
- u16 imm = dsp_fetch_code();
- u16 val = dsp_get_acc_m(reg);
- Update_SR_LZ(((val & imm) == 0) ? true : false);
+ UpdateSRLogicZero((val & imm) == 0);
}
//----
@@ -86,12 +84,12 @@ void andf(const UDSPInstruction opc)
// Test accumulator %acR.
//
// flags out: --xx xx00
-void tst(const UDSPInstruction opc)
+void Interpreter::tst(const UDSPInstruction opc)
{
- u8 reg = (opc >> 11) & 0x1;
+ const u8 reg = (opc >> 11) & 0x1;
+ const s64 acc = GetLongAcc(reg);
- s64 acc = dsp_get_long_acc(reg);
- Update_SR_Register64(acc);
+ UpdateSR64(acc);
ZeroWriteBackLog();
}
@@ -100,12 +98,12 @@ void tst(const UDSPInstruction opc)
// Test high part of secondary accumulator $axR.h.
//
// flags out: --x0 xx00
-void tstaxh(const UDSPInstruction opc)
+void Interpreter::tstaxh(const UDSPInstruction opc)
{
- u8 reg = (opc >> 8) & 0x1;
+ const u8 reg = (opc >> 8) & 0x1;
+ const s16 val = GetAXHigh(reg);
- s16 val = dsp_get_ax_h(reg);
- Update_SR_Register16(val);
+ UpdateSR16(val);
ZeroWriteBackLog();
}
@@ -116,14 +114,14 @@ void tstaxh(const UDSPInstruction opc)
// Compares accumulator $ac0 with accumulator $ac1.
//
// flags out: x-xx xxxx
-void cmp(const UDSPInstruction opc)
+void Interpreter::cmp(const UDSPInstruction)
{
- s64 acc0 = dsp_get_long_acc(0);
- s64 acc1 = dsp_get_long_acc(1);
- s64 res = dsp_convert_long_acc(acc0 - acc1);
+ const s64 acc0 = GetLongAcc(0);
+ const s64 acc1 = GetLongAcc(1);
+ const s64 res = dsp_convert_long_acc(acc0 - acc1);
- Update_SR_Register64(res, isCarry2(acc0, res),
- isOverflow(acc0, -acc1, res)); // CF -> influence on ABS/0xa100
+ UpdateSR64(res, isCarry2(acc0, res),
+ isOverflow(acc0, -acc1, res)); // CF -> influence on ABS/0xa100
ZeroWriteBackLog();
}
@@ -133,17 +131,17 @@ void cmp(const UDSPInstruction opc)
// Not described by Duddie's doc - at least not as a separate instruction.
//
// flags out: x-xx xxxx
-void cmpar(const UDSPInstruction opc)
+void Interpreter::cmpar(const UDSPInstruction opc)
{
- u8 rreg = (opc >> 12) & 0x1;
- u8 sreg = (opc >> 11) & 0x1;
+ const u8 rreg = (opc >> 12) & 0x1;
+ const u8 sreg = (opc >> 11) & 0x1;
- s64 sr = dsp_get_long_acc(sreg);
- s64 rr = (s16)g_dsp.r.ax[rreg].h;
+ const s64 sr = GetLongAcc(sreg);
+ s64 rr = GetAXHigh(rreg);
rr <<= 16;
- s64 res = dsp_convert_long_acc(sr - rr);
+ const s64 res = dsp_convert_long_acc(sr - rr);
- Update_SR_Register64(res, isCarry2(sr, res), isOverflow(sr, -rr, res));
+ UpdateSR64(res, isCarry2(sr, res), isOverflow(sr, -rr, res));
ZeroWriteBackLog();
}
@@ -154,16 +152,17 @@ void cmpar(const UDSPInstruction opc)
// Although flags are being set regarding whole accumulator register.
//
// flags out: x-xx xxxx
-void cmpi(const UDSPInstruction opc)
+void Interpreter::cmpi(const UDSPInstruction opc)
{
- u8 reg = (opc >> 8) & 0x1;
+ const u8 reg = (opc >> 8) & 0x1;
+ auto& state = m_dsp_core.DSPState();
- s64 val = dsp_get_long_acc(reg);
- s64 imm = (s64)(s16)dsp_fetch_code()
- << 16; // Immediate is considered to be at M level in the 40-bit accumulator.
- s64 res = dsp_convert_long_acc(val - imm);
+ const s64 val = GetLongAcc(reg);
+ // Immediate is considered to be at M level in the 40-bit accumulator.
+ const s64 imm = (s64)(s16)state.FetchInstruction() << 16;
+ const s64 res = dsp_convert_long_acc(val - imm);
- Update_SR_Register64(res, isCarry2(val, res), isOverflow(val, -imm, res));
+ UpdateSR64(res, isCarry2(val, res), isOverflow(val, -imm, res));
}
// CMPIS $acD, #I
@@ -173,16 +172,16 @@ void cmpi(const UDSPInstruction opc)
// $acD.hm and computing flags based on whole accumulator $acD.
//
// flags out: x-xx xxxx
-void cmpis(const UDSPInstruction opc)
+void Interpreter::cmpis(const UDSPInstruction opc)
{
- u8 areg = (opc >> 8) & 0x1;
+ const u8 areg = (opc >> 8) & 0x1;
- s64 acc = dsp_get_long_acc(areg);
+ const s64 acc = GetLongAcc(areg);
s64 val = (s8)opc;
val <<= 16;
- s64 res = dsp_convert_long_acc(acc - val);
+ const s64 res = dsp_convert_long_acc(acc - val);
- Update_SR_Register64(res, isCarry2(acc, res), isOverflow(acc, -val, res));
+ UpdateSR64(res, isCarry2(acc, res), isOverflow(acc, -val, res));
}
//----
@@ -194,16 +193,17 @@ void cmpis(const UDSPInstruction opc)
// x = extension (7 bits!!)
//
// flags out: --xx xx00
-void xorr(const UDSPInstruction opc)
+void Interpreter::xorr(const UDSPInstruction opc)
{
- u8 dreg = (opc >> 8) & 0x1;
- u8 sreg = (opc >> 9) & 0x1;
- u16 accm = g_dsp.r.ac[dreg].m ^ g_dsp.r.ax[sreg].h;
+ const u8 dreg = (opc >> 8) & 0x1;
+ const u8 sreg = (opc >> 9) & 0x1;
+ auto& state = m_dsp_core.DSPState();
+ const u16 accm = state.r.ac[dreg].m ^ state.r.ax[sreg].h;
ZeroWriteBackLogPreserveAcc(dreg);
- g_dsp.r.ac[dreg].m = accm;
- Update_SR_Register16((s16)accm, false, false, isOverS32(dsp_get_long_acc(dreg)));
+ state.r.ac[dreg].m = accm;
+ UpdateSR16(static_cast<s16>(accm), false, false, isOverS32(GetLongAcc(dreg)));
}
// ANDR $acD.m, $axS.h
@@ -213,16 +213,17 @@ void xorr(const UDSPInstruction opc)
// x = extension (7 bits!!)
//
// flags out: --xx xx00
-void andr(const UDSPInstruction opc)
+void Interpreter::andr(const UDSPInstruction opc)
{
- u8 dreg = (opc >> 8) & 0x1;
- u8 sreg = (opc >> 9) & 0x1;
- u16 accm = g_dsp.r.ac[dreg].m & g_dsp.r.ax[sreg].h;
+ const u8 dreg = (opc >> 8) & 0x1;
+ const u8 sreg = (opc >> 9) & 0x1;
+ auto& state = m_dsp_core.DSPState();
+ const u16 accm = state.r.ac[dreg].m & state.r.ax[sreg].h;
ZeroWriteBackLogPreserveAcc(dreg);
- g_dsp.r.ac[dreg].m = accm;
- Update_SR_Register16((s16)accm, false, false, isOverS32(dsp_get_long_acc(dreg)));
+ state.r.ac[dreg].m = accm;
+ UpdateSR16(static_cast<s16>(accm), false, false, isOverS32(GetLongAcc(dreg)));
}
// ORR $acD.m, $axS.h
@@ -232,16 +233,17 @@ void andr(const UDSPInstruction opc)
// x = extension (7 bits!!)
//
// flags out: --xx xx00
-void orr(const UDSPInstruction opc)
+void Interpreter::orr(const UDSPInstruction opc)
{
- u8 dreg = (opc >> 8) & 0x1;
- u8 sreg = (opc >> 9) & 0x1;
- u16 accm = g_dsp.r.ac[dreg].m | g_dsp.r.ax[sreg].h;
+ const u8 dreg = (opc >> 8) & 0x1;
+ const u8 sreg = (opc >> 9) & 0x1;
+ auto& state = m_dsp_core.DSPState();
+ const u16 accm = state.r.ac[dreg].m | state.r.ax[sreg].h;
ZeroWriteBackLogPreserveAcc(dreg);
- g_dsp.r.ac[dreg].m = accm;
- Update_SR_Register16((s16)accm, false, false, isOverS32(dsp_get_long_acc(dreg)));
+ state.r.ac[dreg].m = accm;
+ UpdateSR16(static_cast<s16>(accm), false, false, isOverS32(GetLongAcc(dreg)));
}
// ANDC $acD.m, $ac(1-D).m
@@ -251,15 +253,16 @@ void orr(const UDSPInstruction opc)
// x = extension (7 bits!!)
//
// flags out: --xx xx00
-void andc(const UDSPInstruction opc)
+void Interpreter::andc(const UDSPInstruction opc)
{
- u8 dreg = (opc >> 8) & 0x1;
- u16 accm = g_dsp.r.ac[dreg].m & g_dsp.r.ac[1 - dreg].m;
+ auto& state = m_dsp_core.DSPState();
+ const u8 dreg = (opc >> 8) & 0x1;
+ const u16 accm = state.r.ac[dreg].m & state.r.ac[1 - dreg].m;
ZeroWriteBackLogPreserveAcc(dreg);
- g_dsp.r.ac[dreg].m = accm;
- Update_SR_Register16((s16)accm, false, false, isOverS32(dsp_get_long_acc(dreg)));
+ state.r.ac[dreg].m = accm;
+ UpdateSR16(static_cast<s16>(accm), false, false, isOverS32(GetLongAcc(dreg)));
}
// ORC $acD.m, $ac(1-D).m
@@ -269,15 +272,16 @@ void andc(const UDSPInstruction opc)
// x = extension (7 bits!!)
//
// flags out: --xx xx00
-void orc(const UDSPInstruction opc)
+void Interpreter::orc(const UDSPInstruction opc)
{
- u8 dreg = (opc >> 8) & 0x1;
- u16 accm = g_dsp.r.ac[dreg].m | g_dsp.r.ac[1 - dreg].m;
+ auto& state = m_dsp_core.DSPState();
+ const u8 dreg = (opc >> 8) & 0x1;
+ const u16 accm = state.r.ac[dreg].m | state.r.ac[1 - dreg].m;
ZeroWriteBackLogPreserveAcc(dreg);
- g_dsp.r.ac[dreg].m = accm;
- Update_SR_Register16((s16)accm, false, false, isOverS32(dsp_get_long_acc(dreg)));
+ state.r.ac[dreg].m = accm;
+ UpdateSR16(static_cast<s16>(accm), false, false, isOverS32(GetLongAcc(dreg)));
}
// XORC $acD.m
@@ -286,15 +290,16 @@ void orc(const UDSPInstruction opc)
// x = extension (7 bits!!)
//
// flags out: --xx xx00
-void xorc(const UDSPInstruction opc)
+void Interpreter::xorc(const UDSPInstruction opc)
{
- u8 dreg = (opc >> 8) & 0x1;
- u16 accm = g_dsp.r.ac[dreg].m ^ g_dsp.r.ac[1 - dreg].m;
+ auto& state = m_dsp_core.DSPState();
+ const u8 dreg = (opc >> 8) & 0x1;
+ const u16 accm = state.r.ac[dreg].m ^ state.r.ac[1 - dreg].m;
ZeroWriteBackLogPreserveAcc(dreg);
- g_dsp.r.ac[dreg].m = accm;
- Update_SR_Register16((s16)accm, false, false, isOverS32(dsp_get_long_acc(dreg)));
+ state.r.ac[dreg].m = accm;
+ UpdateSR16(static_cast<s16>(accm), false, false, isOverS32(GetLongAcc(dreg)));
}
// NOT $acD.m
@@ -303,15 +308,16 @@ void xorc(const UDSPInstruction opc)
// x = extension (7 bits!!)
//
// flags out: --xx xx00
-void notc(const UDSPInstruction opc)
+void Interpreter::notc(const UDSPInstruction opc)
{
- u8 dreg = (opc >> 8) & 0x1;
- u16 accm = g_dsp.r.ac[dreg].m ^ 0xffff;
+ auto& state = m_dsp_core.DSPState();
+ const u8 dreg = (opc >> 8) & 0x1;
+ const u16 accm = state.r.ac[dreg].m ^ 0xffff;
ZeroWriteBackLogPreserveAcc(dreg);
- g_dsp.r.ac[dreg].m = accm;
- Update_SR_Register16((s16)accm, false, false, isOverS32(dsp_get_long_acc(dreg)));
+ state.r.ac[dreg].m = accm;
+ UpdateSR16(static_cast<s16>(accm), false, false, isOverS32(GetLongAcc(dreg)));
}
// XORI $acD.m, #I
@@ -321,13 +327,14 @@ void notc(const UDSPInstruction opc)
// immediate value I.
//
// flags out: --xx xx00
-void xori(const UDSPInstruction opc)
+void Interpreter::xori(const UDSPInstruction opc)
{
- u8 reg = (opc >> 8) & 0x1;
- u16 imm = dsp_fetch_code();
- g_dsp.r.ac[reg].m ^= imm;
+ auto& state = m_dsp_core.DSPState();
+ const u8 reg = (opc >> 8) & 0x1;
+ const u16 imm = state.FetchInstruction();
+ state.r.ac[reg].m ^= imm;
- Update_SR_Register16((s16)g_dsp.r.ac[reg].m, false, false, isOverS32(dsp_get_long_acc(reg)));
+ UpdateSR16(static_cast<s16>(state.r.ac[reg].m), false, false, isOverS32(GetLongAcc(reg)));
}
// ANDI $acD.m, #I
@@ -336,13 +343,15 @@ void xori(const UDSPInstruction opc)
// Logic AND of accumulator mid part $acD.m with immediate value I.
//
// flags out: --xx xx00
-void andi(const UDSPInstruction opc)
+void Interpreter::andi(const UDSPInstruction opc)
{
- u8 reg = (opc >> 8) & 0x1;
- u16 imm = dsp_fetch_code();
- g_dsp.r.ac[reg].m &= imm;
+ auto& state = m_dsp_core.DSPState();
+ const u8 reg = (opc >> 8) & 0x1;
+ const u16 imm = state.FetchInstruction();
- Update_SR_Register16((s16)g_dsp.r.ac[reg].m, false, false, isOverS32(dsp_get_long_acc(reg)));
+ state.r.ac[reg].m &= imm;
+
+ UpdateSR16(static_cast<s16>(state.r.ac[reg].m), false, false, isOverS32(GetLongAcc(reg)));
}
// ORI $acD.m, #I
@@ -351,13 +360,15 @@ void andi(const UDSPInstruction opc)
// Logic OR of accumulator mid part $acD.m with immediate value I.
//
// flags out: --xx xx00
-void ori(const UDSPInstruction opc)
+void Interpreter::ori(const UDSPInstruction opc)
{
- u8 reg = (opc >> 8) & 0x1;
- u16 imm = dsp_fetch_code();
- g_dsp.r.ac[reg].m |= imm;
+ auto& state = m_dsp_core.DSPState();
+ const u8 reg = (opc >> 8) & 0x1;
+ const u16 imm = state.FetchInstruction();
+
+ state.r.ac[reg].m |= imm;
- Update_SR_Register16((s16)g_dsp.r.ac[reg].m, false, false, isOverS32(dsp_get_long_acc(reg)));
+ UpdateSR16(static_cast<s16>(state.r.ac[reg].m), false, false, isOverS32(GetLongAcc(reg)));
}
//----
@@ -367,23 +378,24 @@ void ori(const UDSPInstruction opc)
// Adds register $axS.L to accumulator $acD.M register.
//
// flags out: x-xx xxxx
-void addr(const UDSPInstruction opc)
+void Interpreter::addr(const UDSPInstruction opc)
{
- u8 dreg = (opc >> 8) & 0x1;
- u8 sreg = ((opc >> 9) & 0x3) + DSP_REG_AXL0;
+ auto& state = m_dsp_core.DSPState();
+ const u8 dreg = (opc >> 8) & 0x1;
+ const u8 sreg = ((opc >> 9) & 0x3) + DSP_REG_AXL0;
- s64 acc = dsp_get_long_acc(dreg);
+ const s64 acc = GetLongAcc(dreg);
s64 ax = 0;
switch (sreg)
{
case DSP_REG_AXL0:
case DSP_REG_AXL1:
- ax = (s16)g_dsp.r.ax[sreg - DSP_REG_AXL0].l;
+ ax = static_cast<s16>(state.r.ax[sreg - DSP_REG_AXL0].l);
break;
case DSP_REG_AXH0:
case DSP_REG_AXH1:
- ax = (s16)g_dsp.r.ax[sreg - DSP_REG_AXH0].h;
+ ax = static_cast<s16>(state.r.ax[sreg - DSP_REG_AXH0].h);
break;
default:
ax = 0;
@@ -395,9 +407,9 @@ void addr(const UDSPInstruction opc)
ZeroWriteBackLog();
- dsp_set_long_acc(dreg, res);
- res = dsp_get_long_acc(dreg);
- Update_SR_Register64(res, isCarry(acc, res), isOverflow(acc, ax, res));
+ SetLongAcc(dreg, res);
+ res = GetLongAcc(dreg);
+ UpdateSR64(res, isCarry(acc, res), isOverflow(acc, ax, res));
}
// ADDAX $acD, $axS
@@ -405,20 +417,20 @@ void addr(const UDSPInstruction opc)
// Adds secondary accumulator $axS to accumulator register $acD.
//
// flags out: x-xx xxxx
-void addax(const UDSPInstruction opc)
+void Interpreter::addax(const UDSPInstruction opc)
{
- u8 dreg = (opc >> 8) & 0x1;
- u8 sreg = (opc >> 9) & 0x1;
+ const u8 dreg = (opc >> 8) & 0x1;
+ const u8 sreg = (opc >> 9) & 0x1;
- s64 acc = dsp_get_long_acc(dreg);
- s64 ax = dsp_get_long_acx(sreg);
+ const s64 acc = GetLongAcc(dreg);
+ const s64 ax = GetLongACX(sreg);
s64 res = acc + ax;
ZeroWriteBackLog();
- dsp_set_long_acc(dreg, res);
- res = dsp_get_long_acc(dreg);
- Update_SR_Register64(res, isCarry(acc, res), isOverflow(acc, ax, res));
+ SetLongAcc(dreg, res);
+ res = GetLongAcc(dreg);
+ UpdateSR64(res, isCarry(acc, res), isOverflow(acc, ax, res));
}
// ADD $acD, $ac(1-D)
@@ -426,19 +438,19 @@ void addax(const UDSPInstruction opc)
// Adds accumulator $ac(1-D) to accumulator register $acD.
//
// flags out: x-xx xxxx
-void add(const UDSPInstruction opc)
+void Interpreter::add(const UDSPInstruction opc)
{
- u8 dreg = (opc >> 8) & 0x1;
+ const u8 dreg = (opc >> 8) & 0x1;
- s64 acc0 = dsp_get_long_acc(dreg);
- s64 acc1 = dsp_get_long_acc(1 - dreg);
+ const s64 acc0 = GetLongAcc(dreg);
+ const s64 acc1 = GetLongAcc(1 - dreg);
s64 res = acc0 + acc1;
ZeroWriteBackLog();
- dsp_set_long_acc(dreg, res);
- res = dsp_get_long_acc(dreg);
- Update_SR_Register64(res, isCarry(acc0, res), isOverflow(acc0, acc1, res));
+ SetLongAcc(dreg, res);
+ res = GetLongAcc(dreg);
+ UpdateSR64(res, isCarry(acc0, res), isOverflow(acc0, acc1, res));
}
// ADDP $acD
@@ -446,19 +458,19 @@ void add(const UDSPInstruction opc)
// Adds product register to accumulator register.
//
// flags out: x-xx xxxx
-void addp(const UDSPInstruction opc)
+void Interpreter::addp(const UDSPInstruction opc)
{
- u8 dreg = (opc >> 8) & 0x1;
+ const u8 dreg = (opc >> 8) & 0x1;
- s64 acc = dsp_get_long_acc(dreg);
- s64 prod = dsp_get_long_prod();
+ const s64 acc = GetLongAcc(dreg);
+ const s64 prod = GetLongProduct();
s64 res = acc + prod;
ZeroWriteBackLog();
- dsp_set_long_acc(dreg, res);
- res = dsp_get_long_acc(dreg);
- Update_SR_Register64(res, isCarry(acc, res), isOverflow(acc, prod, res));
+ SetLongAcc(dreg, res);
+ res = GetLongAcc(dreg);
+ UpdateSR64(res, isCarry(acc, res), isOverflow(acc, prod, res));
}
// ADDAXL $acD, $axS.l
@@ -467,21 +479,22 @@ void addp(const UDSPInstruction opc)
// should be unsigned values!!
//
// flags out: x-xx xxxx
-void addaxl(const UDSPInstruction opc)
+void Interpreter::addaxl(const UDSPInstruction opc)
{
- u8 sreg = (opc >> 9) & 0x1;
- u8 dreg = (opc >> 8) & 0x1;
+ const u8 sreg = (opc >> 9) & 0x1;
+ const u8 dreg = (opc >> 8) & 0x1;
- u64 acc = dsp_get_long_acc(dreg);
- u16 acx = (u16)dsp_get_ax_l(sreg);
+ const u64 acc = GetLongAcc(dreg);
+ const u16 acx = static_cast<u16>(GetAXLow(sreg));
u64 res = acc + acx;
ZeroWriteBackLog();
- dsp_set_long_acc(dreg, (s64)res);
- res = dsp_get_long_acc(dreg);
- Update_SR_Register64((s64)res, isCarry(acc, res), isOverflow((s64)acc, (s64)acx, (s64)res));
+ SetLongAcc(dreg, static_cast<s64>(res));
+ res = GetLongAcc(dreg);
+ UpdateSR64(static_cast<s64>(res), isCarry(acc, res),
+ isOverflow(static_cast<s64>(acc), static_cast<s64>(acx), static_cast<s64>(res)));
}
// ADDI $amR, #I
@@ -490,18 +503,19 @@ void addaxl(const UDSPInstruction opc)
// Adds immediate (16-bit sign extended) to mid accumulator $acD.hm.
//
// flags out: x-xx xxxx
-void addi(const UDSPInstruction opc)
+void Interpreter::addi(const UDSPInstruction opc)
{
- u8 areg = (opc >> 8) & 0x1;
+ auto& state = m_dsp_core.DSPState();
+ const u8 areg = (opc >> 8) & 0x1;
- s64 acc = dsp_get_long_acc(areg);
- s64 imm = (s16)dsp_fetch_code();
+ const s64 acc = GetLongAcc(areg);
+ s64 imm = static_cast<s16>(state.FetchInstruction());
imm <<= 16;
s64 res = acc + imm;
- dsp_set_long_acc(areg, res);
- res = dsp_get_long_acc(areg);
- Update_SR_Register64(res, isCarry(acc, res), isOverflow(acc, imm, res));
+ SetLongAcc(areg, res);
+ res = GetLongAcc(areg);
+ UpdateSR64(res, isCarry(acc, res), isOverflow(acc, imm, res));
}
// ADDIS $acD, #I
@@ -509,18 +523,18 @@ void addi(const UDSPInstruction opc)
// Adds short immediate (8-bit sign extended) to mid accumulator $acD.hm.
//
// flags out: x-xx xxxx
-void addis(const UDSPInstruction opc)
+void Interpreter::addis(const UDSPInstruction opc)
{
- u8 dreg = (opc >> 8) & 0x1;
+ const u8 dreg = (opc >> 8) & 0x1;
- s64 acc = dsp_get_long_acc(dreg);
- s64 imm = (s8)(u8)opc;
+ const s64 acc = GetLongAcc(dreg);
+ s64 imm = static_cast<s8>(static_cast<u8>(opc));
imm <<= 16;
s64 res = acc + imm;
- dsp_set_long_acc(dreg, res);
- res = dsp_get_long_acc(dreg);
- Update_SR_Register64(res, isCarry(acc, res), isOverflow(acc, imm, res));
+ SetLongAcc(dreg, res);
+ res = GetLongAcc(dreg);
+ UpdateSR64(res, isCarry(acc, res), isOverflow(acc, imm, res));
}
// INCM $acsD
@@ -528,19 +542,19 @@ void addis(const UDSPInstruction opc)
// Increment 24-bit mid-accumulator $acsD.
//
// flags out: x-xx xxxx
-void incm(const UDSPInstruction opc)
+void Interpreter::incm(const UDSPInstruction opc)
{
- u8 dreg = (opc >> 8) & 0x1;
+ const u8 dreg = (opc >> 8) & 0x1;
- s64 sub = 0x10000;
- s64 acc = dsp_get_long_acc(dreg);
+ const s64 sub = 0x10000;
+ const s64 acc = GetLongAcc(dreg);
s64 res = acc + sub;
ZeroWriteBackLog();
- dsp_set_long_acc(dreg, res);
- res = dsp_get_long_acc(dreg);
- Update_SR_Register64(res, isCarry(acc, res), isOverflow(acc, sub, res));
+ SetLongAcc(dreg, res);
+ res = GetLongAcc(dreg);
+ UpdateSR64(res, isCarry(acc, res), isOverflow(acc, sub, res));
}
// INC $acD
@@ -548,18 +562,18 @@ void incm(const UDSPInstruction opc)
// Increment accumulator $acD.
//
// flags out: x-xx xxxx
-void inc(const UDSPInstruction opc)
+void Interpreter::inc(const UDSPInstruction opc)
{
- u8 dreg = (opc >> 8) & 0x1;
+ const u8 dreg = (opc >> 8) & 0x1;
- s64 acc = dsp_get_long_acc(dreg);
+ const s64 acc = GetLongAcc(dreg);
s64 res = acc + 1;
ZeroWriteBackLog();
- dsp_set_long_acc(dreg, res);
- res = dsp_get_long_acc(dreg);
- Update_SR_Register64(res, isCarry(acc, res), isOverflow(acc, 1, res));
+ SetLongAcc(dreg, res);
+ res = GetLongAcc(dreg);
+ UpdateSR64(res, isCarry(acc, res), isOverflow(acc, 1, res));
}
//----
@@ -569,23 +583,24 @@ void inc(const UDSPInstruction opc)
// Subtracts register $axS.L from accumulator $acD.M register.
//
// flags out: x-xx xxxx
-void subr(const UDSPInstruction opc)
+void Interpreter::subr(const UDSPInstruction opc)
{
- u8 dreg = (opc >> 8) & 0x1;
- u8 sreg = ((opc >> 9) & 0x3) + DSP_REG_AXL0;
+ auto& state = m_dsp_core.DSPState();
+ const u8 dreg = (opc >> 8) & 0x1;
+ const u8 sreg = ((opc >> 9) & 0x3) + DSP_REG_AXL0;
- s64 acc = dsp_get_long_acc(dreg);
+ const s64 acc = GetLongAcc(dreg);
s64 ax = 0;
switch (sreg)
{
case DSP_REG_AXL0:
case DSP_REG_AXL1:
- ax = (s16)g_dsp.r.ax[sreg - DSP_REG_AXL0].l;
+ ax = static_cast<s16>(state.r.ax[sreg - DSP_REG_AXL0].l);
break;
case DSP_REG_AXH0:
case DSP_REG_AXH1:
- ax = (s16)g_dsp.r.ax[sreg - DSP_REG_AXH0].h;
+ ax = static_cast<s16>(state.r.ax[sreg - DSP_REG_AXH0].h);
break;
default:
ax = 0;
@@ -597,9 +612,9 @@ void subr(const UDSPInstruction opc)
ZeroWriteBackLog();
- dsp_set_long_acc(dreg, res);
- res = dsp_get_long_acc(dreg);
- Update_SR_Register64(res, isCarry2(acc, res), isOverflow(acc, -ax, res));
+ SetLongAcc(dreg, res);
+ res = GetLongAcc(dreg);
+ UpdateSR64(res, isCarry2(acc, res), isOverflow(acc, -ax, res));
}
// SUBAX $acD, $axS
@@ -607,20 +622,20 @@ void subr(const UDSPInstruction opc)
// Subtracts secondary accumulator $axS from accumulator register $acD.
//
// flags out: x-xx xxxx
-void subax(const UDSPInstruction opc)
+void Interpreter::subax(const UDSPInstruction opc)
{
- u8 dreg = (opc >> 8) & 0x1;
- u8 sreg = (opc >> 9) & 0x1;
+ const u8 dreg = (opc >> 8) & 0x1;
+ const u8 sreg = (opc >> 9) & 0x1;
- s64 acc = dsp_get_long_acc(dreg);
- s64 acx = dsp_get_long_acx(sreg);
+ const s64 acc = GetLongAcc(dreg);
+ const s64 acx = GetLongACX(sreg);
s64 res = acc - acx;
ZeroWriteBackLog();
- dsp_set_long_acc(dreg, res);
- res = dsp_get_long_acc(dreg);
- Update_SR_Register64(res, isCarry2(acc, res), isOverflow(acc, -acx, res));
+ SetLongAcc(dreg, res);
+ res = GetLongAcc(dreg);
+ UpdateSR64(res, isCarry2(acc, res), isOverflow(acc, -acx, res));
}
// SUB $acD, $ac(1-D)
@@ -628,19 +643,19 @@ void subax(const UDSPInstruction opc)
// Subtracts accumulator $ac(1-D) from accumulator register $acD.
//
// flags out: x-xx xxxx
-void sub(const UDSPInstruction opc)
+void Interpreter::sub(const UDSPInstruction opc)
{
- u8 dreg = (opc >> 8) & 0x1;
+ const u8 dreg = (opc >> 8) & 0x1;
- s64 acc1 = dsp_get_long_acc(dreg);
- s64 acc2 = dsp_get_long_acc(1 - dreg);
+ const s64 acc1 = GetLongAcc(dreg);
+ const s64 acc2 = GetLongAcc(1 - dreg);
s64 res = acc1 - acc2;
ZeroWriteBackLog();
- dsp_set_long_acc(dreg, res);
- res = dsp_get_long_acc(dreg);
- Update_SR_Register64(res, isCarry2(acc1, res), isOverflow(acc1, -acc2, res));
+ SetLongAcc(dreg, res);
+ res = GetLongAcc(dreg);
+ UpdateSR64(res, isCarry2(acc1, res), isOverflow(acc1, -acc2, res));
}
// SUBP $acD
@@ -648,19 +663,19 @@ void sub(const UDSPInstruction opc)
// Subtracts product register from accumulator register.
//
// flags out: x-xx xxxx
-void subp(const UDSPInstruction opc)
+void Interpreter::subp(const UDSPInstruction opc)
{
- u8 dreg = (opc >> 8) & 0x1;
+ const u8 dreg = (opc >> 8) & 0x1;
- s64 acc = dsp_get_long_acc(dreg);
- s64 prod = dsp_get_long_prod();
+ const s64 acc = GetLongAcc(dreg);
+ const s64 prod = GetLongProduct();
s64 res = acc - prod;
ZeroWriteBackLog();
- dsp_set_long_acc(dreg, res);
- res = dsp_get_long_acc(dreg);
- Update_SR_Register64(res, isCarry2(acc, res), isOverflow(acc, -prod, res));
+ SetLongAcc(dreg, res);
+ res = GetLongAcc(dreg);
+ UpdateSR64(res, isCarry2(acc, res), isOverflow(acc, -prod, res));
}
// DECM $acsD
@@ -668,19 +683,19 @@ void subp(const UDSPInstruction opc)
// Decrement 24-bit mid-accumulator $acsD.
//
// flags out: x-xx xxxx
-void decm(const UDSPInstruction opc)
+void Interpreter::decm(const UDSPInstruction opc)
{
- u8 dreg = (opc >> 8) & 0x01;
+ const u8 dreg = (opc >> 8) & 0x01;
- s64 sub = 0x10000;
- s64 acc = dsp_get_long_acc(dreg);
+ const s64 sub = 0x10000;
+ const s64 acc = GetLongAcc(dreg);
s64 res = acc - sub;
ZeroWriteBackLog();
- dsp_set_long_acc(dreg, res);
- res = dsp_get_long_acc(dreg);
- Update_SR_Register64(res, isCarry2(acc, res), isOverflow(acc, -sub, res));
+ SetLongAcc(dreg, res);
+ res = GetLongAcc(dreg);
+ UpdateSR64(res, isCarry2(acc, res), isOverflow(acc, -sub, res));
}
// DEC $acD
@@ -688,18 +703,18 @@ void decm(const UDSPInstruction opc)
// Decrement accumulator $acD.
//
// flags out: x-xx xxxx
-void dec(const UDSPInstruction opc)
+void Interpreter::dec(const UDSPInstruction opc)
{
- u8 dreg = (opc >> 8) & 0x01;
+ const u8 dreg = (opc >> 8) & 0x01;
- s64 acc = dsp_get_long_acc(dreg);
+ const s64 acc = GetLongAcc(dreg);
s64 res = acc - 1;
ZeroWriteBackLog();
- dsp_set_long_acc(dreg, res);
- res = dsp_get_long_acc(dreg);
- Update_SR_Register64(res, isCarry2(acc, res), isOverflow(acc, -1, res));
+ SetLongAcc(dreg, res);
+ res = GetLongAcc(dreg);
+ UpdateSR64(res, isCarry2(acc, res), isOverflow(acc, -1, res));
}
//----
@@ -709,17 +724,17 @@ void dec(const UDSPInstruction opc)
// Negate accumulator $acD.
//
// flags out: --xx xx00
-void neg(const UDSPInstruction opc)
+void Interpreter::neg(const UDSPInstruction opc)
{
- u8 dreg = (opc >> 8) & 0x1;
+ const u8 dreg = (opc >> 8) & 0x1;
- s64 acc = dsp_get_long_acc(dreg);
+ s64 acc = GetLongAcc(dreg);
acc = 0 - acc;
ZeroWriteBackLog();
- dsp_set_long_acc(dreg, acc);
- Update_SR_Register64(dsp_get_long_acc(dreg));
+ SetLongAcc(dreg, acc);
+ UpdateSR64(GetLongAcc(dreg));
}
// ABS $acD
@@ -727,19 +742,19 @@ void neg(const UDSPInstruction opc)
// absolute value of $acD
//
// flags out: --xx xx00
-void abs(const UDSPInstruction opc)
+void Interpreter::abs(const UDSPInstruction opc)
{
- u8 dreg = (opc >> 11) & 0x1;
+ const u8 dreg = (opc >> 11) & 0x1;
- s64 acc = dsp_get_long_acc(dreg);
+ s64 acc = GetLongAcc(dreg);
if (acc < 0)
acc = 0 - acc;
ZeroWriteBackLog();
- dsp_set_long_acc(dreg, acc);
- Update_SR_Register64(dsp_get_long_acc(dreg));
+ SetLongAcc(dreg, acc);
+ UpdateSR64(GetLongAcc(dreg));
}
//----
@@ -749,21 +764,22 @@ void abs(const UDSPInstruction opc)
// Sets $acD.l to 0.
//
// flags out: --xx xx00
-void movr(const UDSPInstruction opc)
+void Interpreter::movr(const UDSPInstruction opc)
{
- u8 areg = (opc >> 8) & 0x1;
- u8 sreg = ((opc >> 9) & 0x3) + DSP_REG_AXL0;
+ auto& state = m_dsp_core.DSPState();
+ const u8 areg = (opc >> 8) & 0x1;
+ const u8 sreg = ((opc >> 9) & 0x3) + DSP_REG_AXL0;
s64 ax = 0;
switch (sreg)
{
case DSP_REG_AXL0:
case DSP_REG_AXL1:
- ax = (s16)g_dsp.r.ax[sreg - DSP_REG_AXL0].l;
+ ax = static_cast<s16>(state.r.ax[sreg - DSP_REG_AXL0].l);
break;
case DSP_REG_AXH0:
case DSP_REG_AXH1:
- ax = (s16)g_dsp.r.ax[sreg - DSP_REG_AXH0].h;
+ ax = static_cast<s16>(state.r.ax[sreg - DSP_REG_AXH0].h);
break;
default:
ax = 0;
@@ -773,8 +789,8 @@ void movr(const UDSPInstruction opc)
ZeroWriteBackLog();
- dsp_set_long_acc(areg, ax);
- Update_SR_Register64(ax);
+ SetLongAcc(areg, ax);
+ UpdateSR64(ax);
}
// MOVAX $acD, $axS
@@ -782,17 +798,17 @@ void movr(const UDSPInstruction opc)
// Moves secondary accumulator $axS to accumulator $axD.
//
// flags out: --xx xx00
-void movax(const UDSPInstruction opc)
+void Interpreter::movax(const UDSPInstruction opc)
{
- u8 dreg = (opc >> 8) & 0x1;
- u8 sreg = (opc >> 9) & 0x1;
+ const u8 dreg = (opc >> 8) & 0x1;
+ const u8 sreg = (opc >> 9) & 0x1;
- s64 acx = dsp_get_long_acx(sreg);
+ const s64 acx = GetLongACX(sreg);
ZeroWriteBackLog();
- dsp_set_long_acc(dreg, acx);
- Update_SR_Register64(acx);
+ SetLongAcc(dreg, acx);
+ UpdateSR64(acx);
}
// MOV $acD, $ac(1-D)
@@ -800,15 +816,15 @@ void movax(const UDSPInstruction opc)
// Moves accumulator $ax(1-D) to accumulator $axD.
//
// flags out: --x0 xx00
-void mov(const UDSPInstruction opc)
+void Interpreter::mov(const UDSPInstruction opc)
{
- u8 dreg = (opc >> 8) & 0x1;
- u64 acc = dsp_get_long_acc(1 - dreg);
+ const u8 dreg = (opc >> 8) & 0x1;
+ const u64 acc = GetLongAcc(1 - dreg);
ZeroWriteBackLog();
- dsp_set_long_acc(dreg, acc);
- Update_SR_Register64(acc);
+ SetLongAcc(dreg, acc);
+ UpdateSR64(acc);
}
//----
@@ -818,17 +834,17 @@ void mov(const UDSPInstruction opc)
// Logically shifts left accumulator $acR by 16.
//
// flags out: --xx xx00
-void lsl16(const UDSPInstruction opc)
+void Interpreter::lsl16(const UDSPInstruction opc)
{
- u8 areg = (opc >> 8) & 0x1;
+ const u8 areg = (opc >> 8) & 0x1;
- s64 acc = dsp_get_long_acc(areg);
+ s64 acc = GetLongAcc(areg);
acc <<= 16;
ZeroWriteBackLog();
- dsp_set_long_acc(areg, acc);
- Update_SR_Register64(dsp_get_long_acc(areg));
+ SetLongAcc(areg, acc);
+ UpdateSR64(GetLongAcc(areg));
}
// LSR16 $acR
@@ -836,19 +852,19 @@ void lsl16(const UDSPInstruction opc)
// Logically shifts right accumulator $acR by 16.
//
// flags out: --xx xx00
-void lsr16(const UDSPInstruction opc)
+void Interpreter::lsr16(const UDSPInstruction opc)
{
- u8 areg = (opc >> 8) & 0x1;
+ const u8 areg = (opc >> 8) & 0x1;
- u64 acc = dsp_get_long_acc(areg);
- acc &=
- 0x000000FFFFFFFFFFULL; // Lop off the extraneous sign extension our 64-bit fake accum causes
+ u64 acc = GetLongAcc(areg);
+ // Lop off the extraneous sign extension our 64-bit fake accum causes
+ acc &= 0x000000FFFFFFFFFFULL;
acc >>= 16;
ZeroWriteBackLog();
- dsp_set_long_acc(areg, (s64)acc);
- Update_SR_Register64(dsp_get_long_acc(areg));
+ SetLongAcc(areg, static_cast<s64>(acc));
+ UpdateSR64(GetLongAcc(areg));
}
// ASR16 $acR
@@ -856,17 +872,17 @@ void lsr16(const UDSPInstruction opc)
// Arithmetically shifts right accumulator $acR by 16.
//
// flags out: --xx xx00
-void asr16(const UDSPInstruction opc)
+void Interpreter::asr16(const UDSPInstruction opc)
{
- u8 areg = (opc >> 11) & 0x1;
+ const u8 areg = (opc >> 11) & 0x1;
- s64 acc = dsp_get_long_acc(areg);
+ s64 acc = GetLongAcc(areg);
acc >>= 16;
ZeroWriteBackLog();
- dsp_set_long_acc(areg, acc);
- Update_SR_Register64(dsp_get_long_acc(areg));
+ SetLongAcc(areg, acc);
+ UpdateSR64(GetLongAcc(areg));
}
// LSL $acR, #I
@@ -874,16 +890,16 @@ void asr16(const UDSPInstruction opc)
// Logically shifts left accumulator $acR by number specified by value I.
//
// flags out: --xx xx00
-void lsl(const UDSPInstruction opc)
+void Interpreter::lsl(const UDSPInstruction opc)
{
- u8 rreg = (opc >> 8) & 0x01;
- u16 shift = opc & 0x3f;
- u64 acc = dsp_get_long_acc(rreg);
+ const u8 rreg = (opc >> 8) & 0x01;
+ const u16 shift = opc & 0x3f;
+ u64 acc = GetLongAcc(rreg);
acc <<= shift;
- dsp_set_long_acc(rreg, acc);
- Update_SR_Register64(dsp_get_long_acc(rreg));
+ SetLongAcc(rreg, acc);
+ UpdateSR64(GetLongAcc(rreg));
}
// LSR $acR, #I
@@ -892,13 +908,13 @@ void lsl(const UDSPInstruction opc)
// calculated by negating sign extended bits 0-6.
//
// flags out: --xx xx00
-void lsr(const UDSPInstruction opc)
+void Interpreter::lsr(const UDSPInstruction opc)
{
- u8 rreg = (opc >> 8) & 0x01;
+ const u8 rreg = (opc >> 8) & 0x01;
u16 shift;
- u64 acc = dsp_get_long_acc(rreg);
- acc &=
- 0x000000FFFFFFFFFFULL; // Lop off the extraneous sign extension our 64-bit fake accum causes
+ u64 acc = GetLongAcc(rreg);
+ // Lop off the extraneous sign extension our 64-bit fake accum causes
+ acc &= 0x000000FFFFFFFFFFULL;
if ((opc & 0x3f) == 0)
shift = 0;
@@ -907,8 +923,8 @@ void lsr(const UDSPInstruction opc)
acc >>= shift;
- dsp_set_long_acc(rreg, (s64)acc);
- Update_SR_Register64(dsp_get_long_acc(rreg));
+ SetLongAcc(rreg, static_cast<s64>(acc));
+ UpdateSR64(GetLongAcc(rreg));
}
// ASL $acR, #I
@@ -916,16 +932,16 @@ void lsr(const UDSPInstruction opc)
// Logically shifts left accumulator $acR by number specified by value I.
//
// flags out: --xx xx00
-void asl(const UDSPInstruction opc)
+void Interpreter::asl(const UDSPInstruction opc)
{
- u8 rreg = (opc >> 8) & 0x01;
- u16 shift = opc & 0x3f;
- u64 acc = dsp_get_long_acc(rreg);
+ const u8 rreg = (opc >> 8) & 0x01;
+ const u16 shift = opc & 0x3f;
+ u64 acc = GetLongAcc(rreg);
acc <<= shift;
- dsp_set_long_acc(rreg, acc);
- Update_SR_Register64(dsp_get_long_acc(rreg));
+ SetLongAcc(rreg, acc);
+ UpdateSR64(GetLongAcc(rreg));
}
// ASR $acR, #I
@@ -934,9 +950,9 @@ void asl(const UDSPInstruction opc)
// value calculated by negating sign extended bits 0-6.
//
// flags out: --xx xx00
-void asr(const UDSPInstruction opc)
+void Interpreter::asr(const UDSPInstruction opc)
{
- u8 dreg = (opc >> 8) & 0x01;
+ const u8 dreg = (opc >> 8) & 0x01;
u16 shift;
if ((opc & 0x3f) == 0)
@@ -945,11 +961,11 @@ void asr(const UDSPInstruction opc)
shift = 0x40 - (opc & 0x3f);
// arithmetic shift
- s64 acc = dsp_get_long_acc(dreg);
+ s64 acc = GetLongAcc(dreg);
acc >>= shift;
- dsp_set_long_acc(dreg, acc);
- Update_SR_Register64(dsp_get_long_acc(dreg));
+ SetLongAcc(dreg, acc);
+ UpdateSR64(GetLongAcc(dreg));
}
// LSRN (fixed parameters)
@@ -958,16 +974,16 @@ void asr(const UDSPInstruction opc)
// (if value negative, becomes left shift).
//
// flags out: --xx xx00
-void lsrn(const UDSPInstruction opc)
+void Interpreter::lsrn(const UDSPInstruction opc)
{
s16 shift;
- u16 accm = (u16)dsp_get_acc_m(1);
- u64 acc = dsp_get_long_acc(0);
+ const u16 accm = static_cast<u16>(GetAccMid(1));
+ u64 acc = GetLongAcc(0);
acc &= 0x000000FFFFFFFFFFULL;
if ((accm & 0x3f) == 0)
shift = 0;
- else if (accm & 0x40)
+ else if ((accm & 0x40) != 0)
shift = -0x40 + (accm & 0x3f);
else
shift = accm & 0x3f;
@@ -981,8 +997,8 @@ void lsrn(const UDSPInstruction opc)
acc <<= -shift;
}
- dsp_set_long_acc(0, (s64)acc);
- Update_SR_Register64(dsp_get_long_acc(0));
+ SetLongAcc(0, static_cast<s64>(acc));
+ UpdateSR64(GetLongAcc(0));
}
// ASRN (fixed parameters)
@@ -991,15 +1007,15 @@ void lsrn(const UDSPInstruction opc)
// (if value negative, becomes left shift).
//
// flags out: --xx xx00
-void asrn(const UDSPInstruction opc)
+void Interpreter::asrn(const UDSPInstruction opc)
{
s16 shift;
- u16 accm = (u16)dsp_get_acc_m(1);
- s64 acc = dsp_get_long_acc(0);
+ const u16 accm = static_cast<u16>(GetAccMid(1));
+ s64 acc = GetLongAcc(0);
if ((accm & 0x3f) == 0)
shift = 0;
- else if (accm & 0x40)
+ else if ((accm & 0x40) != 0)
shift = -0x40 + (accm & 0x3f);
else
shift = accm & 0x3f;
@@ -1013,8 +1029,8 @@ void asrn(const UDSPInstruction opc)
acc <<= -shift;
}
- dsp_set_long_acc(0, acc);
- Update_SR_Register64(dsp_get_long_acc(0));
+ SetLongAcc(0, acc);
+ UpdateSR64(GetLongAcc(0));
}
// LSRNRX $acD, $axS.h
@@ -1023,19 +1039,20 @@ void asrn(const UDSPInstruction opc)
// x = extension (7 bits!!)
//
// flags out: --xx xx00
-void lsrnrx(const UDSPInstruction opc)
+void Interpreter::lsrnrx(const UDSPInstruction opc)
{
- u8 dreg = (opc >> 8) & 0x1;
- u8 sreg = (opc >> 9) & 0x1;
+ auto& state = m_dsp_core.DSPState();
+ const u8 dreg = (opc >> 8) & 0x1;
+ const u8 sreg = (opc >> 9) & 0x1;
s16 shift;
- u16 axh = g_dsp.r.ax[sreg].h;
- u64 acc = dsp_get_long_acc(dreg);
+ const u16 axh = state.r.ax[sreg].h;
+ u64 acc = GetLongAcc(dreg);
acc &= 0x000000FFFFFFFFFFULL;
if ((axh & 0x3f) == 0)
shift = 0;
- else if (axh & 0x40)
+ else if ((axh & 0x40) != 0)
shift = -0x40 + (axh & 0x3f);
else
shift = axh & 0x3f;
@@ -1051,8 +1068,8 @@ void lsrnrx(const UDSPInstruction opc)
ZeroWriteBackLog();
- dsp_set_long_acc(dreg, (s64)acc);
- Update_SR_Register64(dsp_get_long_acc(dreg));
+ SetLongAcc(dreg, static_cast<s64>(acc));
+ UpdateSR64(GetLongAcc(dreg));
}
// ASRNRX $acD, $axS.h
@@ -1061,18 +1078,19 @@ void lsrnrx(const UDSPInstruction opc)
// x = extension (7 bits!!)
//
// flags out: --xx xx00
-void asrnrx(const UDSPInstruction opc)
+void Interpreter::asrnrx(const UDSPInstruction opc)
{
- u8 dreg = (opc >> 8) & 0x1;
- u8 sreg = (opc >> 9) & 0x1;
+ auto& state = m_dsp_core.DSPState();
+ const u8 dreg = (opc >> 8) & 0x1;
+ const u8 sreg = (opc >> 9) & 0x1;
s16 shift;
- u16 axh = g_dsp.r.ax[sreg].h;
- s64 acc = dsp_get_long_acc(dreg);
+ const u16 axh = state.r.ax[sreg].h;
+ s64 acc = GetLongAcc(dreg);
if ((axh & 0x3f) == 0)
shift = 0;
- else if (axh & 0x40)
+ else if ((axh & 0x40) != 0)
shift = -0x40 + (axh & 0x3f);
else
shift = axh & 0x3f;
@@ -1088,8 +1106,8 @@ void asrnrx(const UDSPInstruction opc)
ZeroWriteBackLog();
- dsp_set_long_acc(dreg, acc);
- Update_SR_Register64(dsp_get_long_acc(dreg));
+ SetLongAcc(dreg, acc);
+ UpdateSR64(GetLongAcc(dreg));
}
// LSRNR $acD
@@ -1098,18 +1116,18 @@ void asrnrx(const UDSPInstruction opc)
// x = extension (7 bits!!)
//
// flags out: --xx xx00
-void lsrnr(const UDSPInstruction opc)
+void Interpreter::lsrnr(const UDSPInstruction opc)
{
- u8 dreg = (opc >> 8) & 0x1;
+ const u8 dreg = (opc >> 8) & 0x1;
s16 shift;
- u16 accm = (u16)dsp_get_acc_m(1 - dreg);
- u64 acc = dsp_get_long_acc(dreg);
+ const u16 accm = static_cast<u16>(GetAccMid(1 - dreg));
+ u64 acc = GetLongAcc(dreg);
acc &= 0x000000FFFFFFFFFFULL;
if ((accm & 0x3f) == 0)
shift = 0;
- else if (accm & 0x40)
+ else if ((accm & 0x40) != 0)
shift = -0x40 + (accm & 0x3f);
else
shift = accm & 0x3f;
@@ -1121,8 +1139,8 @@ void lsrnr(const UDSPInstruction opc)
ZeroWriteBackLog();
- dsp_set_long_acc(dreg, (s64)acc);
- Update_SR_Register64(dsp_get_long_acc(dreg));
+ SetLongAcc(dreg, static_cast<s64>(acc));
+ UpdateSR64(GetLongAcc(dreg));
}
// ASRNR $acD
@@ -1131,17 +1149,17 @@ void lsrnr(const UDSPInstruction opc)
// x = extension (7 bits!!)
//
// flags out: --xx xx00
-void asrnr(const UDSPInstruction opc)
+void Interpreter::asrnr(const UDSPInstruction opc)
{
- u8 dreg = (opc >> 8) & 0x1;
+ const u8 dreg = (opc >> 8) & 0x1;
s16 shift;
- u16 accm = (u16)dsp_get_acc_m(1 - dreg);
- s64 acc = dsp_get_long_acc(dreg);
+ const u16 accm = static_cast<u16>(GetAccMid(1 - dreg));
+ s64 acc = GetLongAcc(dreg);
if ((accm & 0x3f) == 0)
shift = 0;
- else if (accm & 0x40)
+ else if ((accm & 0x40) != 0)
shift = -0x40 + (accm & 0x3f);
else
shift = accm & 0x3f;
@@ -1153,7 +1171,7 @@ void asrnr(const UDSPInstruction opc)
ZeroWriteBackLog();
- dsp_set_long_acc(dreg, acc);
- Update_SR_Register64(dsp_get_long_acc(dreg));
+ SetLongAcc(dreg, acc);
+ UpdateSR64(GetLongAcc(dreg));
}
} // namespace DSP::Interpreter
diff --git a/Source/Core/Core/DSP/Interpreter/DSPIntBranch.cpp b/Source/Core/Core/DSP/Interpreter/DSPIntBranch.cpp
index ef487758a3..9e263a73cf 100644
--- a/Source/Core/Core/DSP/Interpreter/DSPIntBranch.cpp
+++ b/Source/Core/Core/DSP/Interpreter/DSPIntBranch.cpp
@@ -5,10 +5,6 @@
// Additional copyrights go to Duddie and Tratax (c) 2004
#include "Core/DSP/DSPCore.h"
-#include "Core/DSP/DSPMemoryMap.h"
-#include "Core/DSP/DSPStacks.h"
-#include "Core/DSP/Interpreter/DSPIntCCUtil.h"
-#include "Core/DSP/Interpreter/DSPIntUtil.h"
#include "Core/DSP/Interpreter/DSPInterpreter.h"
namespace DSP::Interpreter
@@ -20,14 +16,16 @@ namespace DSP::Interpreter
// Call function if condition cc has been met. Push program counter of
// instruction following "call" to $st0. Set program counter to address
// represented by value that follows this "call" instruction.
-void call(const UDSPInstruction opc)
+void Interpreter::call(const UDSPInstruction opc)
{
+ auto& state = m_dsp_core.DSPState();
+
// must be outside the if.
- u16 dest = dsp_fetch_code();
+ const u16 dest = state.FetchInstruction();
if (CheckCondition(opc & 0xf))
{
- dsp_reg_store_stack(StackRegister::Call, g_dsp.pc);
- g_dsp.pc = dest;
+ state.StoreStack(StackRegister::Call, state.pc);
+ state.pc = dest;
}
}
@@ -37,28 +35,29 @@ void call(const UDSPInstruction opc)
// Call function if condition cc has been met. Push program counter of
// instruction following "call" to call stack $st0. Set program counter to
// register $R.
-void callr(const UDSPInstruction opc)
+void Interpreter::callr(const UDSPInstruction opc)
{
- if (CheckCondition(opc & 0xf))
- {
- u8 reg = (opc >> 5) & 0x7;
- u16 addr = dsp_op_read_reg(reg);
- dsp_reg_store_stack(StackRegister::Call, g_dsp.pc);
- g_dsp.pc = addr;
- }
+ if (!CheckCondition(opc & 0xf))
+ return;
+
+ auto& state = m_dsp_core.DSPState();
+ const u8 reg = (opc >> 5) & 0x7;
+ const u16 addr = OpReadRegister(reg);
+ state.StoreStack(StackRegister::Call, state.pc);
+ state.pc = addr;
}
// Generic if implementation
// IFcc
// 0000 0010 0111 cccc
// Execute following opcode if the condition has been met.
-void ifcc(const UDSPInstruction opc)
+void Interpreter::ifcc(const UDSPInstruction opc)
{
- if (!CheckCondition(opc & 0xf))
- {
- // skip the next opcode - we have to lookup its size.
- dsp_skip_inst();
- }
+ if (CheckCondition(opc & 0xf))
+ return;
+
+ // skip the next opcode - we have to lookup its size.
+ m_dsp_core.DSPState().SkipInstruction();
}
// Generic jmp implementation
@@ -67,12 +66,13 @@ void ifcc(const UDSPInstruction opc)
// aaaa aaaa aaaa aaaa
// Jump to addressA if condition cc has been met. Set program counter to
// address represented by value that follows this "jmp" instruction.
-void jcc(const UDSPInstruction opc)
+void Interpreter::jcc(const UDSPInstruction opc)
{
- u16 dest = dsp_fetch_code();
+ auto& state = m_dsp_core.DSPState();
+ const u16 dest = state.FetchInstruction();
if (CheckCondition(opc & 0xf))
{
- g_dsp.pc = dest;
+ state.pc = dest;
}
}
@@ -80,13 +80,14 @@ void jcc(const UDSPInstruction opc)
// JMPcc $R
// 0001 0111 rrr0 cccc
// Jump to address; set program counter to a value from register $R.
-void jmprcc(const UDSPInstruction opc)
+void Interpreter::jmprcc(const UDSPInstruction opc)
{
- if (CheckCondition(opc & 0xf))
- {
- u8 reg = (opc >> 5) & 0x7;
- g_dsp.pc = dsp_op_read_reg(reg);
- }
+ if (!CheckCondition(opc & 0xf))
+ return;
+
+ auto& state = m_dsp_core.DSPState();
+ const u8 reg = (opc >> 5) & 0x7;
+ state.pc = OpReadRegister(reg);
}
// Generic ret implementation
@@ -94,12 +95,13 @@ void jmprcc(const UDSPInstruction opc)
// 0000 0010 1101 cccc
// Return from subroutine if condition cc has been met. Pops stored PC
// from call stack $st0 and sets $pc to this location.
-void ret(const UDSPInstruction opc)
+void Interpreter::ret(const UDSPInstruction opc)
{
- if (CheckCondition(opc & 0xf))
- {
- g_dsp.pc = dsp_reg_load_stack(StackRegister::Call);
- }
+ if (!CheckCondition(opc & 0xf))
+ return;
+
+ auto& state = m_dsp_core.DSPState();
+ state.pc = state.PopStack(StackRegister::Call);
}
// RTI
@@ -107,19 +109,21 @@ void ret(const UDSPInstruction opc)
// Return from exception. Pops stored status register $sr from data stack
// $st1 and program counter PC from call stack $st0 and sets $pc to this
// location.
-void rti(const UDSPInstruction opc)
+void Interpreter::rti(const UDSPInstruction)
{
- g_dsp.r.sr = dsp_reg_load_stack(StackRegister::Data);
- g_dsp.pc = dsp_reg_load_stack(StackRegister::Call);
+ auto& state = m_dsp_core.DSPState();
+ state.r.sr = state.PopStack(StackRegister::Data);
+ state.pc = state.PopStack(StackRegister::Call);
}
// HALT
// 0000 0000 0020 0001
// Stops execution of DSP code. Sets bit DSP_CR_HALT in register DREG_CR.
-void halt(const UDSPInstruction opc)
+void Interpreter::halt(const UDSPInstruction)
{
- g_dsp.cr |= 0x4;
- g_dsp.pc--;
+ auto& state = m_dsp_core.DSPState();
+ state.cr |= 0x4;
+ state.pc--;
}
// LOOP handling: Loop stack is used to control execution of repeated blocks of
@@ -128,29 +132,31 @@ void halt(const UDSPInstruction opc)
// then PC is modified with value from call stack $st0. Otherwise values from
// call stack $st0 and both loop stacks $st2 and $st3 are popped and execution
// continues at next opcode.
-void HandleLoop()
+void Interpreter::HandleLoop()
{
+ auto& state = m_dsp_core.DSPState();
+
// Handle looping hardware.
- const u16 rCallAddress = g_dsp.r.st[0];
- const u16 rLoopAddress = g_dsp.r.st[2];
- u16& rLoopCounter = g_dsp.r.st[3];
+ const u16 rCallAddress = state.r.st[0];
+ const u16 rLoopAddress = state.r.st[2];
+ u16& rLoopCounter = state.r.st[3];
if (rLoopAddress > 0 && rLoopCounter > 0)
{
// FIXME: why -1? because we just read past it.
- if (g_dsp.pc - 1 == rLoopAddress)
+ if (state.pc - 1 == rLoopAddress)
{
rLoopCounter--;
if (rLoopCounter > 0)
{
- g_dsp.pc = rCallAddress;
+ state.pc = rCallAddress;
}
else
{
// end of loop
- dsp_reg_load_stack(StackRegister::Call);
- dsp_reg_load_stack(StackRegister::LoopAddress);
- dsp_reg_load_stack(StackRegister::LoopCounter);
+ state.PopStack(StackRegister::Call);
+ state.PopStack(StackRegister::LoopAddress);
+ state.PopStack(StackRegister::LoopCounter);
}
}
}
@@ -164,21 +170,22 @@ void HandleLoop()
// then looped instruction will not get executed.
// Actually, this instruction simply prepares the loop stacks for the above.
// The looping hardware takes care of the rest.
-void loop(const UDSPInstruction opc)
+void Interpreter::loop(const UDSPInstruction opc)
{
- u16 reg = opc & 0x1f;
- u16 cnt = dsp_op_read_reg(reg);
- u16 loop_pc = g_dsp.pc;
+ auto& state = m_dsp_core.DSPState();
+ const u16 reg = opc & 0x1f;
+ const u16 cnt = OpReadRegister(reg);
+ const u16 loop_pc = state.pc;
- if (cnt)
+ if (cnt != 0)
{
- dsp_reg_store_stack(StackRegister::Call, g_dsp.pc);
- dsp_reg_store_stack(StackRegister::LoopAddress, loop_pc);
- dsp_reg_store_stack(StackRegister::LoopCounter, cnt);
+ state.StoreStack(StackRegister::Call, state.pc);
+ state.StoreStack(StackRegister::LoopAddress, loop_pc);
+ state.StoreStack(StackRegister::LoopCounter, cnt);
}
else
{
- dsp_skip_inst();
+ state.SkipInstruction();
}
}
@@ -190,20 +197,21 @@ void loop(const UDSPInstruction opc)
// instruction will not get executed.
// Actually, this instruction simply prepares the loop stacks for the above.
// The looping hardware takes care of the rest.
-void loopi(const UDSPInstruction opc)
+void Interpreter::loopi(const UDSPInstruction opc)
{
- u16 cnt = opc & 0xff;
- u16 loop_pc = g_dsp.pc;
+ auto& state = m_dsp_core.DSPState();
+ const u16 cnt = opc & 0xff;
+ const u16 loop_pc = state.pc;
- if (cnt)
+ if (cnt != 0)
{
- dsp_reg_store_stack(StackRegister::Call, g_dsp.pc);
- dsp_reg_store_stack(StackRegister::LoopAddress, loop_pc);
- dsp_reg_store_stack(StackRegister::LoopCounter, cnt);
+ state.StoreStack(StackRegister::Call, state.pc);
+ state.StoreStack(StackRegister::LoopAddress, loop_pc);
+ state.StoreStack(StackRegister::LoopCounter, cnt);
}
else
{
- dsp_skip_inst();
+ state.SkipInstruction();
}
}
@@ -216,22 +224,23 @@ void loopi(const UDSPInstruction opc)
// included in loop. Counter is pushed on loop stack $st3, end of block address
// is pushed on loop stack $st2 and repeat address is pushed on call stack $st0.
// Up to 4 nested loops are allowed.
-void bloop(const UDSPInstruction opc)
+void Interpreter::bloop(const UDSPInstruction opc)
{
- u16 reg = opc & 0x1f;
- u16 cnt = dsp_op_read_reg(reg);
- u16 loop_pc = dsp_fetch_code();
+ auto& state = m_dsp_core.DSPState();
+ const u16 reg = opc & 0x1f;
+ const u16 cnt = OpReadRegister(reg);
+ const u16 loop_pc = state.FetchInstruction();
- if (cnt)
+ if (cnt != 0)
{
- dsp_reg_store_stack(StackRegister::Call, g_dsp.pc);
- dsp_reg_store_stack(StackRegister::LoopAddress, loop_pc);
- dsp_reg_store_stack(StackRegister::LoopCounter, cnt);
+ state.StoreStack(StackRegister::Call, state.pc);
+ state.StoreStack(StackRegister::LoopAddress, loop_pc);
+ state.StoreStack(StackRegister::LoopCounter, cnt);
}
else
{
- g_dsp.pc = loop_pc;
- dsp_skip_inst();
+ state.pc = loop_pc;
+ state.SkipInstruction();
}
}
@@ -244,21 +253,22 @@ void bloop(const UDSPInstruction opc)
// loop. Counter is pushed on loop stack $st3, end of block address is pushed
// on loop stack $st2 and repeat address is pushed on call stack $st0. Up to 4
// nested loops are allowed.
-void bloopi(const UDSPInstruction opc)
+void Interpreter::bloopi(const UDSPInstruction opc)
{
- u16 cnt = opc & 0xff;
- u16 loop_pc = dsp_fetch_code();
+ auto& state = m_dsp_core.DSPState();
+ const u16 cnt = opc & 0xff;
+ const u16 loop_pc = state.FetchInstruction();
- if (cnt)
+ if (cnt != 0)
{
- dsp_reg_store_stack(StackRegister::Call, g_dsp.pc);
- dsp_reg_store_stack(StackRegister::LoopAddress, loop_pc);
- dsp_reg_store_stack(StackRegister::LoopCounter, cnt);
+ state.StoreStack(StackRegister::Call, state.pc);
+ state.StoreStack(StackRegister::LoopAddress, loop_pc);
+ state.StoreStack(StackRegister::LoopCounter, cnt);
}
else
{
- g_dsp.pc = loop_pc;
- dsp_skip_inst();
+ state.pc = loop_pc;
+ state.SkipInstruction();
}
}
} // namespace DSP::Interpreter
diff --git a/Source/Core/Core/DSP/Interpreter/DSPIntCCUtil.cpp b/Source/Core/Core/DSP/Interpreter/DSPIntCCUtil.cpp
deleted file mode 100644
index 0fbd71c516..0000000000
--- a/Source/Core/Core/DSP/Interpreter/DSPIntCCUtil.cpp
+++ /dev/null
@@ -1,183 +0,0 @@
-// Copyright 2009 Dolphin Emulator Project
-// Licensed under GPLv2+
-// Refer to the license.txt file included.
-//
-// Additional copyrights go to Duddie and Tratax (c) 2004
-
-// HELPER FUNCTIONS
-
-#include "Core/DSP/Interpreter/DSPIntCCUtil.h"
-#include "Core/DSP/DSPCore.h"
-
-namespace DSP::Interpreter
-{
-void Update_SR_Register64(s64 _Value, bool carry, bool overflow)
-{
- g_dsp.r.sr &= ~SR_CMP_MASK;
-
- // 0x01
- if (carry)
- {
- g_dsp.r.sr |= SR_CARRY;
- }
-
- // 0x02 and 0x80
- if (overflow)
- {
- g_dsp.r.sr |= SR_OVERFLOW;
- g_dsp.r.sr |= SR_OVERFLOW_STICKY;
- }
-
- // 0x04
- if (_Value == 0)
- {
- g_dsp.r.sr |= SR_ARITH_ZERO;
- }
-
- // 0x08
- if (_Value < 0)
- {
- g_dsp.r.sr |= SR_SIGN;
- }
-
- // 0x10
- if (_Value != (s32)_Value)
- {
- g_dsp.r.sr |= SR_OVER_S32;
- }
-
- // 0x20 - Checks if top bits of m are equal
- if (((_Value & 0xc0000000) == 0) || ((_Value & 0xc0000000) == 0xc0000000))
- {
- g_dsp.r.sr |= SR_TOP2BITS;
- }
-}
-
-void Update_SR_Register16(s16 _Value, bool carry, bool overflow, bool overS32)
-{
- g_dsp.r.sr &= ~SR_CMP_MASK;
-
- // 0x01
- if (carry)
- {
- g_dsp.r.sr |= SR_CARRY;
- }
-
- // 0x02 and 0x80
- if (overflow)
- {
- g_dsp.r.sr |= SR_OVERFLOW;
- g_dsp.r.sr |= SR_OVERFLOW_STICKY;
- }
-
- // 0x04
- if (_Value == 0)
- {
- g_dsp.r.sr |= SR_ARITH_ZERO;
- }
-
- // 0x08
- if (_Value < 0)
- {
- g_dsp.r.sr |= SR_SIGN;
- }
-
- // 0x10
- if (overS32)
- {
- g_dsp.r.sr |= SR_OVER_S32;
- }
-
- // 0x20 - Checks if top bits of m are equal
- if ((((u16)_Value >> 14) == 0) || (((u16)_Value >> 14) == 3))
- {
- g_dsp.r.sr |= SR_TOP2BITS;
- }
-}
-
-void Update_SR_LZ(bool value)
-{
- if (value == true)
- g_dsp.r.sr |= SR_LOGIC_ZERO;
- else
- g_dsp.r.sr &= ~SR_LOGIC_ZERO;
-}
-
-static bool IsCarry()
-{
- return (g_dsp.r.sr & SR_CARRY) != 0;
-}
-
-static bool IsOverflow()
-{
- return (g_dsp.r.sr & SR_OVERFLOW) != 0;
-}
-
-static bool IsOverS32()
-{
- return (g_dsp.r.sr & SR_OVER_S32) != 0;
-}
-
-static bool IsLess()
-{
- return (g_dsp.r.sr & SR_OVERFLOW) != (g_dsp.r.sr & SR_SIGN);
-}
-
-static bool IsZero()
-{
- return (g_dsp.r.sr & SR_ARITH_ZERO) != 0;
-}
-
-static bool IsLogicZero()
-{
- return (g_dsp.r.sr & SR_LOGIC_ZERO) != 0;
-}
-
-static bool IsConditionA()
-{
- return (((g_dsp.r.sr & SR_OVER_S32) || (g_dsp.r.sr & SR_TOP2BITS)) &&
- !(g_dsp.r.sr & SR_ARITH_ZERO)) != 0;
-}
-
-// see DSPCore.h for flags
-bool CheckCondition(u8 _Condition)
-{
- switch (_Condition & 0xf)
- {
- case 0xf: // Always true.
- return true;
- case 0x0: // GE - Greater Equal
- return !IsLess();
- case 0x1: // L - Less
- return IsLess();
- case 0x2: // G - Greater
- return !IsLess() && !IsZero();
- case 0x3: // LE - Less Equal
- return IsLess() || IsZero();
- case 0x4: // NZ - Not Zero
- return !IsZero();
- case 0x5: // Z - Zero
- return IsZero();
- case 0x6: // NC - Not carry
- return !IsCarry();
- case 0x7: // C - Carry
- return IsCarry();
- case 0x8: // ? - Not over s32
- return !IsOverS32();
- case 0x9: // ? - Over s32
- return IsOverS32();
- case 0xa: // ?
- return IsConditionA();
- case 0xb: // ?
- return !IsConditionA();
- case 0xc: // LNZ - Logic Not Zero
- return !IsLogicZero();
- case 0xd: // LZ - Logic Zero
- return IsLogicZero();
- case 0xe: // 0 - Overflow
- return IsOverflow();
- default:
- return true;
- }
-}
-} // namespace DSP::Interpreter
diff --git a/Source/Core/Core/DSP/Interpreter/DSPIntCCUtil.h b/Source/Core/Core/DSP/Interpreter/DSPIntCCUtil.h
index 12b8beda78..d6f1ff3362 100644
--- a/Source/Core/Core/DSP/Interpreter/DSPIntCCUtil.h
+++ b/Source/Core/Core/DSP/Interpreter/DSPIntCCUtil.h
@@ -6,36 +6,29 @@
#pragma once
-// Anything to do with SR and conditions goes here.
-
#include "Common/CommonTypes.h"
+// Anything to do with SR and conditions goes here.
+
namespace DSP::Interpreter
{
-bool CheckCondition(u8 _Condition);
-
-void Update_SR_Register16(s16 _Value, bool carry = false, bool overflow = false,
- bool overS32 = false);
-void Update_SR_Register64(s64 _Value, bool carry = false, bool overflow = false);
-void Update_SR_LZ(bool value);
-
-inline bool isCarry(u64 val, u64 result)
+constexpr bool isCarry(u64 val, u64 result)
{
- return (val > result);
+ return val > result;
}
-inline bool isCarry2(u64 val, u64 result)
+constexpr bool isCarry2(u64 val, u64 result)
{
- return (val >= result);
+ return val >= result;
}
-inline bool isOverflow(s64 val1, s64 val2, s64 res)
+constexpr bool isOverflow(s64 val1, s64 val2, s64 res)
{
return ((val1 ^ res) & (val2 ^ res)) < 0;
}
-inline bool isOverS32(s64 acc)
+constexpr bool isOverS32(s64 acc)
{
- return (acc != (s32)acc) ? true : false;
+ return acc != static_cast<s32>(acc);
}
} // namespace DSP::Interpreter
diff --git a/Source/Core/Core/DSP/Interpreter/DSPIntExtOps.cpp b/Source/Core/Core/DSP/Interpreter/DSPIntExtOps.cpp
index e9b2e8c963..60169b7085 100644
--- a/Source/Core/Core/DSP/Interpreter/DSPIntExtOps.cpp
+++ b/Source/Core/Core/DSP/Interpreter/DSPIntExtOps.cpp
@@ -2,15 +2,7 @@
// Licensed under GPLv2+
// Refer to the license.txt file included.
-#include "Core/DSP/Interpreter/DSPIntExtOps.h"
-
-#include "Core/DSP/DSPMemoryMap.h"
-#include "Core/DSP/DSPTables.h"
-#include "Core/DSP/Interpreter/DSPIntUtil.h"
-
-// not needed for game ucodes (it slows down interpreter/dspjit32 + easier to compare int VS
-// dspjit64 without it)
-//#define PRECISE_BACKLOG
+#include "Core/DSP/Interpreter/DSPInterpreter.h"
// Extended opcodes do not exist on their own. These opcodes can only be
// attached to opcodes that allow extending (8 (or 7) lower bits of opcode not used by
@@ -22,15 +14,7 @@
// registers will wrap in odd ways, dictated by the corresponding wrapping
// register, WR0-3.
-namespace DSP
-{
-static void WriteToBackLog(int i, int idx, u16 value)
-{
- writeBackLog[i] = value;
- writeBackLogIdx[i] = idx;
-}
-
-namespace Interpreter::Ext
+namespace DSP::Interpreter
{
static bool IsSameMemArea(u16 a, u16 b)
{
@@ -41,46 +25,48 @@ static bool IsSameMemArea(u16 a, u16 b)
// DR $arR
// xxxx xxxx 0000 01rr
// Decrement addressing register $arR.
-void dr(const UDSPInstruction opc)
+void Interpreter::dr(const UDSPInstruction opc)
{
- WriteToBackLog(0, opc & 0x3, dsp_decrement_addr_reg(opc & 0x3));
+ WriteToBackLog(0, opc & 0x3, DecrementAddressRegister(opc & 0x3));
}
// IR $arR
// xxxx xxxx 0000 10rr
// Increment addressing register $arR.
-void ir(const UDSPInstruction opc)
+void Interpreter::ir(const UDSPInstruction opc)
{
- WriteToBackLog(0, opc & 0x3, dsp_increment_addr_reg(opc & 0x3));
+ WriteToBackLog(0, opc & 0x3, IncrementAddressRegister(opc & 0x3));
}
// NR $arR
// xxxx xxxx 0000 11rr
// Add corresponding indexing register $ixR to addressing register $arR.
-void nr(const UDSPInstruction opc)
+void Interpreter::nr(const UDSPInstruction opc)
{
- u8 reg = opc & 0x3;
+ const u8 reg = opc & 0x3;
+ const auto& state = m_dsp_core.DSPState();
- WriteToBackLog(0, reg, dsp_increase_addr_reg(reg, (s16)g_dsp.r.ix[reg]));
+ WriteToBackLog(0, reg, IncreaseAddressRegister(reg, static_cast<s16>(state.r.ix[reg])));
}
// MV $axD.D, $acS.S
// xxxx xxxx 0001 ddss
// Move value of $acS.S to the $axD.D.
-void mv(const UDSPInstruction opc)
+void Interpreter::mv(const UDSPInstruction opc)
{
- u8 sreg = (opc & 0x3) + DSP_REG_ACL0;
- u8 dreg = ((opc >> 2) & 0x3);
+ const u8 sreg = (opc & 0x3) + DSP_REG_ACL0;
+ const u8 dreg = ((opc >> 2) & 0x3);
+ auto& state = m_dsp_core.DSPState();
switch (sreg)
{
case DSP_REG_ACL0:
case DSP_REG_ACL1:
- WriteToBackLog(0, dreg + DSP_REG_AXL0, g_dsp.r.ac[sreg - DSP_REG_ACL0].l);
+ WriteToBackLog(0, dreg + DSP_REG_AXL0, state.r.ac[sreg - DSP_REG_ACL0].l);
break;
case DSP_REG_ACM0:
case DSP_REG_ACM1:
- WriteToBackLog(0, dreg + DSP_REG_AXL0, dsp_op_read_reg_and_saturate(sreg - DSP_REG_ACM0));
+ WriteToBackLog(0, dreg + DSP_REG_AXL0, OpReadRegisterAndSaturate(sreg - DSP_REG_ACM0));
break;
}
}
@@ -89,69 +75,72 @@ void mv(const UDSPInstruction opc)
// xxxx xxxx 001s s0dd
// Store value of $acS.S in the memory pointed by register $arD.
// Post increment register $arD.
-void s(const UDSPInstruction opc)
+void Interpreter::s(const UDSPInstruction opc)
{
- u8 dreg = opc & 0x3;
- u8 sreg = ((opc >> 3) & 0x3) + DSP_REG_ACL0;
+ const u8 dreg = opc & 0x3;
+ const u8 sreg = ((opc >> 3) & 0x3) + DSP_REG_ACL0;
+ auto& state = m_dsp_core.DSPState();
switch (sreg)
{
case DSP_REG_ACL0:
case DSP_REG_ACL1:
- dsp_dmem_write(g_dsp.r.ar[dreg], g_dsp.r.ac[sreg - DSP_REG_ACL0].l);
+ state.WriteDMEM(state.r.ar[dreg], state.r.ac[sreg - DSP_REG_ACL0].l);
break;
case DSP_REG_ACM0:
case DSP_REG_ACM1:
- dsp_dmem_write(g_dsp.r.ar[dreg], dsp_op_read_reg_and_saturate(sreg - DSP_REG_ACM0));
+ state.WriteDMEM(state.r.ar[dreg], OpReadRegisterAndSaturate(sreg - DSP_REG_ACM0));
break;
}
- WriteToBackLog(0, dreg, dsp_increment_addr_reg(dreg));
+ WriteToBackLog(0, dreg, IncrementAddressRegister(dreg));
}
// SN @$arD, $acS.S
// xxxx xxxx 001s s1dd
// Store value of register $acS.S in the memory pointed by register $arD.
// Add indexing register $ixD to register $arD.
-void sn(const UDSPInstruction opc)
+void Interpreter::sn(const UDSPInstruction opc)
{
- u8 dreg = opc & 0x3;
- u8 sreg = ((opc >> 3) & 0x3) + DSP_REG_ACL0;
+ const u8 dreg = opc & 0x3;
+ const u8 sreg = ((opc >> 3) & 0x3) + DSP_REG_ACL0;
+ auto& state = m_dsp_core.DSPState();
switch (sreg)
{
case DSP_REG_ACL0:
case DSP_REG_ACL1:
- dsp_dmem_write(g_dsp.r.ar[dreg], g_dsp.r.ac[sreg - DSP_REG_ACL0].l);
+ state.WriteDMEM(state.r.ar[dreg], state.r.ac[sreg - DSP_REG_ACL0].l);
break;
case DSP_REG_ACM0:
case DSP_REG_ACM1:
- dsp_dmem_write(g_dsp.r.ar[dreg], dsp_op_read_reg_and_saturate(sreg - DSP_REG_ACM0));
+ state.WriteDMEM(state.r.ar[dreg], OpReadRegisterAndSaturate(sreg - DSP_REG_ACM0));
break;
}
- WriteToBackLog(0, dreg, dsp_increase_addr_reg(dreg, (s16)g_dsp.r.ix[dreg]));
+ WriteToBackLog(0, dreg, IncreaseAddressRegister(dreg, static_cast<s16>(state.r.ix[dreg])));
}
// L $axD.D, @$arS
// xxxx xxxx 01dd d0ss
// Load $axD.D/$acD.D with value from memory pointed by register $arS.
// Post increment register $arS.
-void l(const UDSPInstruction opc)
+void Interpreter::l(const UDSPInstruction opc)
{
- u8 sreg = opc & 0x3;
- u8 dreg = ((opc >> 3) & 0x7) + DSP_REG_AXL0;
+ const u8 sreg = opc & 0x3;
+ const u8 dreg = ((opc >> 3) & 0x7) + DSP_REG_AXL0;
+ auto& state = m_dsp_core.DSPState();
- if ((dreg >= DSP_REG_ACM0) && (g_dsp.r.sr & SR_40_MODE_BIT))
+ if (dreg >= DSP_REG_ACM0 && IsSRFlagSet(SR_40_MODE_BIT))
{
- u16 val = dsp_dmem_read(g_dsp.r.ar[sreg]);
- WriteToBackLog(0, dreg - DSP_REG_ACM0 + DSP_REG_ACH0, (val & 0x8000) ? 0xFFFF : 0x0000);
+ const u16 val = state.ReadDMEM(state.r.ar[sreg]);
+ WriteToBackLog(0, dreg - DSP_REG_ACM0 + DSP_REG_ACH0, (val & 0x8000) != 0 ? 0xFFFF : 0x0000);
WriteToBackLog(1, dreg, val);
WriteToBackLog(2, dreg - DSP_REG_ACM0 + DSP_REG_ACL0, 0);
- WriteToBackLog(3, sreg, dsp_increment_addr_reg(sreg));
+ WriteToBackLog(3, sreg, IncrementAddressRegister(sreg));
}
else
{
- WriteToBackLog(0, dreg, dsp_dmem_read(g_dsp.r.ar[sreg]));
- WriteToBackLog(1, sreg, dsp_increment_addr_reg(sreg));
+ WriteToBackLog(0, dreg, state.ReadDMEM(state.r.ar[sreg]));
+ WriteToBackLog(1, sreg, IncrementAddressRegister(sreg));
}
}
@@ -159,23 +148,24 @@ void l(const UDSPInstruction opc)
// xxxx xxxx 01dd d0ss
// Load $axD.D/$acD.D with value from memory pointed by register $arS.
// Add indexing register $ixS to register $arS.
-void ln(const UDSPInstruction opc)
+void Interpreter::ln(const UDSPInstruction opc)
{
- u8 sreg = opc & 0x3;
- u8 dreg = ((opc >> 3) & 0x7) + DSP_REG_AXL0;
+ const u8 sreg = opc & 0x3;
+ const u8 dreg = ((opc >> 3) & 0x7) + DSP_REG_AXL0;
+ auto& state = m_dsp_core.DSPState();
- if ((dreg >= DSP_REG_ACM0) && (g_dsp.r.sr & SR_40_MODE_BIT))
+ if (dreg >= DSP_REG_ACM0 && IsSRFlagSet(SR_40_MODE_BIT))
{
- u16 val = dsp_dmem_read(g_dsp.r.ar[sreg]);
- WriteToBackLog(0, dreg - DSP_REG_ACM0 + DSP_REG_ACH0, (val & 0x8000) ? 0xFFFF : 0x0000);
+ const u16 val = state.ReadDMEM(state.r.ar[sreg]);
+ WriteToBackLog(0, dreg - DSP_REG_ACM0 + DSP_REG_ACH0, (val & 0x8000) != 0 ? 0xFFFF : 0x0000);
WriteToBackLog(1, dreg, val);
WriteToBackLog(2, dreg - DSP_REG_ACM0 + DSP_REG_ACL0, 0);
- WriteToBackLog(3, sreg, dsp_increase_addr_reg(sreg, (s16)g_dsp.r.ix[sreg]));
+ WriteToBackLog(3, sreg, IncreaseAddressRegister(sreg, static_cast<s16>(state.r.ix[sreg])));
}
else
{
- WriteToBackLog(0, dreg, dsp_dmem_read(g_dsp.r.ar[sreg]));
- WriteToBackLog(1, sreg, dsp_increase_addr_reg(sreg, (s16)g_dsp.r.ix[sreg]));
+ WriteToBackLog(0, dreg, state.ReadDMEM(state.r.ar[sreg]));
+ WriteToBackLog(1, sreg, IncreaseAddressRegister(sreg, static_cast<s16>(state.r.ix[sreg])));
}
}
@@ -184,16 +174,17 @@ void ln(const UDSPInstruction opc)
// Load register $axD.D with value from memory pointed by register
// $ar0. Store value from register $acS.m to memory location pointed by
// register $ar3. Increment both $ar0 and $ar3.
-void ls(const UDSPInstruction opc)
+void Interpreter::ls(const UDSPInstruction opc)
{
- u8 sreg = opc & 0x1;
- u8 dreg = ((opc >> 4) & 0x3) + DSP_REG_AXL0;
+ const u8 sreg = opc & 0x1;
+ const u8 dreg = ((opc >> 4) & 0x3) + DSP_REG_AXL0;
+ auto& state = m_dsp_core.DSPState();
- dsp_dmem_write(g_dsp.r.ar[3], dsp_op_read_reg_and_saturate(sreg));
+ state.WriteDMEM(state.r.ar[3], OpReadRegisterAndSaturate(sreg));
- WriteToBackLog(0, dreg, dsp_dmem_read(g_dsp.r.ar[0]));
- WriteToBackLog(1, DSP_REG_AR3, dsp_increment_addr_reg(DSP_REG_AR3));
- WriteToBackLog(2, DSP_REG_AR0, dsp_increment_addr_reg(DSP_REG_AR0));
+ WriteToBackLog(0, dreg, state.ReadDMEM(state.r.ar[0]));
+ WriteToBackLog(1, DSP_REG_AR3, IncrementAddressRegister(DSP_REG_AR3));
+ WriteToBackLog(2, DSP_REG_AR0, IncrementAddressRegister(DSP_REG_AR0));
}
// LSN $axD.D, $acS.m
@@ -202,16 +193,18 @@ void ls(const UDSPInstruction opc)
// $ar0. Store value from register $acS.m to memory location pointed by
// register $ar3. Add corresponding indexing register $ix0 to addressing
// register $ar0 and increment $ar3.
-void lsn(const UDSPInstruction opc)
+void Interpreter::lsn(const UDSPInstruction opc)
{
- u8 sreg = opc & 0x1;
- u8 dreg = ((opc >> 4) & 0x3) + DSP_REG_AXL0;
+ const u8 sreg = opc & 0x1;
+ const u8 dreg = ((opc >> 4) & 0x3) + DSP_REG_AXL0;
+ auto& state = m_dsp_core.DSPState();
- dsp_dmem_write(g_dsp.r.ar[3], dsp_op_read_reg_and_saturate(sreg));
+ state.WriteDMEM(state.r.ar[3], OpReadRegisterAndSaturate(sreg));
- WriteToBackLog(0, dreg, dsp_dmem_read(g_dsp.r.ar[0]));
- WriteToBackLog(1, DSP_REG_AR3, dsp_increment_addr_reg(DSP_REG_AR3));
- WriteToBackLog(2, DSP_REG_AR0, dsp_increase_addr_reg(DSP_REG_AR0, (s16)g_dsp.r.ix[0]));
+ WriteToBackLog(0, dreg, state.ReadDMEM(state.r.ar[0]));
+ WriteToBackLog(1, DSP_REG_AR3, IncrementAddressRegister(DSP_REG_AR3));
+ WriteToBackLog(2, DSP_REG_AR0,
+ IncreaseAddressRegister(DSP_REG_AR0, static_cast<s16>(state.r.ix[0])));
}
// LSM $axD.D, $acS.m
@@ -220,16 +213,18 @@ void lsn(const UDSPInstruction opc)
// $ar0. Store value from register $acS.m to memory location pointed by
// register $ar3. Add corresponding indexing register $ix3 to addressing
// register $ar3 and increment $ar0.
-void lsm(const UDSPInstruction opc)
+void Interpreter::lsm(const UDSPInstruction opc)
{
- u8 sreg = opc & 0x1;
- u8 dreg = ((opc >> 4) & 0x3) + DSP_REG_AXL0;
+ const u8 sreg = opc & 0x1;
+ const u8 dreg = ((opc >> 4) & 0x3) + DSP_REG_AXL0;
+ auto& state = m_dsp_core.DSPState();
- dsp_dmem_write(g_dsp.r.ar[3], dsp_op_read_reg_and_saturate(sreg));
+ state.WriteDMEM(state.r.ar[3], OpReadRegisterAndSaturate(sreg));
- WriteToBackLog(0, dreg, dsp_dmem_read(g_dsp.r.ar[0]));
- WriteToBackLog(1, DSP_REG_AR3, dsp_increase_addr_reg(DSP_REG_AR3, (s16)g_dsp.r.ix[3]));
- WriteToBackLog(2, DSP_REG_AR0, dsp_increment_addr_reg(DSP_REG_AR0));
+ WriteToBackLog(0, dreg, state.ReadDMEM(state.r.ar[0]));
+ WriteToBackLog(1, DSP_REG_AR3,
+ IncreaseAddressRegister(DSP_REG_AR3, static_cast<s16>(state.r.ix[3])));
+ WriteToBackLog(2, DSP_REG_AR0, IncrementAddressRegister(DSP_REG_AR0));
}
// LSMN $axD.D, $acS.m
@@ -239,16 +234,19 @@ void lsm(const UDSPInstruction opc)
// register $ar3. Add corresponding indexing register $ix0 to addressing
// register $ar0 and add corresponding indexing register $ix3 to addressing
// register $ar3.
-void lsnm(const UDSPInstruction opc)
+void Interpreter::lsnm(const UDSPInstruction opc)
{
- u8 sreg = opc & 0x1;
- u8 dreg = ((opc >> 4) & 0x3) + DSP_REG_AXL0;
+ const u8 sreg = opc & 0x1;
+ const u8 dreg = ((opc >> 4) & 0x3) + DSP_REG_AXL0;
+ auto& state = m_dsp_core.DSPState();
- dsp_dmem_write(g_dsp.r.ar[3], dsp_op_read_reg_and_saturate(sreg));
+ state.WriteDMEM(state.r.ar[3], OpReadRegisterAndSaturate(sreg));
- WriteToBackLog(0, dreg, dsp_dmem_read(g_dsp.r.ar[0]));
- WriteToBackLog(1, DSP_REG_AR3, dsp_increase_addr_reg(DSP_REG_AR3, (s16)g_dsp.r.ix[3]));
- WriteToBackLog(2, DSP_REG_AR0, dsp_increase_addr_reg(DSP_REG_AR0, (s16)g_dsp.r.ix[0]));
+ WriteToBackLog(0, dreg, state.ReadDMEM(state.r.ar[0]));
+ WriteToBackLog(1, DSP_REG_AR3,
+ IncreaseAddressRegister(DSP_REG_AR3, static_cast<s16>(state.r.ix[3])));
+ WriteToBackLog(2, DSP_REG_AR0,
+ IncreaseAddressRegister(DSP_REG_AR0, static_cast<s16>(state.r.ix[0])));
}
// SL $acS.m, $axD.D
@@ -256,16 +254,17 @@ void lsnm(const UDSPInstruction opc)
// Store value from register $acS.m to memory location pointed by register
// $ar0. Load register $axD.D with value from memory pointed by register
// $ar3. Increment both $ar0 and $ar3.
-void sl(const UDSPInstruction opc)
+void Interpreter::sl(const UDSPInstruction opc)
{
- u8 sreg = opc & 0x1;
- u8 dreg = ((opc >> 4) & 0x3) + DSP_REG_AXL0;
+ const u8 sreg = opc & 0x1;
+ const u8 dreg = ((opc >> 4) & 0x3) + DSP_REG_AXL0;
+ auto& state = m_dsp_core.DSPState();
- dsp_dmem_write(g_dsp.r.ar[0], dsp_op_read_reg_and_saturate(sreg));
+ state.WriteDMEM(state.r.ar[0], OpReadRegisterAndSaturate(sreg));
- WriteToBackLog(0, dreg, dsp_dmem_read(g_dsp.r.ar[3]));
- WriteToBackLog(1, DSP_REG_AR3, dsp_increment_addr_reg(DSP_REG_AR3));
- WriteToBackLog(2, DSP_REG_AR0, dsp_increment_addr_reg(DSP_REG_AR0));
+ WriteToBackLog(0, dreg, state.ReadDMEM(state.r.ar[3]));
+ WriteToBackLog(1, DSP_REG_AR3, IncrementAddressRegister(DSP_REG_AR3));
+ WriteToBackLog(2, DSP_REG_AR0, IncrementAddressRegister(DSP_REG_AR0));
}
// SLN $acS.m, $axD.D
@@ -274,16 +273,18 @@ void sl(const UDSPInstruction opc)
// $ar0. Load register $axD.D with value from memory pointed by register
// $ar3. Add corresponding indexing register $ix0 to addressing register $ar0
// and increment $ar3.
-void sln(const UDSPInstruction opc)
+void Interpreter::sln(const UDSPInstruction opc)
{
- u8 sreg = opc & 0x1;
- u8 dreg = ((opc >> 4) & 0x3) + DSP_REG_AXL0;
+ const u8 sreg = opc & 0x1;
+ const u8 dreg = ((opc >> 4) & 0x3) + DSP_REG_AXL0;
+ auto& state = m_dsp_core.DSPState();
- dsp_dmem_write(g_dsp.r.ar[0], dsp_op_read_reg_and_saturate(sreg));
+ state.WriteDMEM(state.r.ar[0], OpReadRegisterAndSaturate(sreg));
- WriteToBackLog(0, dreg, dsp_dmem_read(g_dsp.r.ar[3]));
- WriteToBackLog(1, DSP_REG_AR3, dsp_increment_addr_reg(DSP_REG_AR3));
- WriteToBackLog(2, DSP_REG_AR0, dsp_increase_addr_reg(DSP_REG_AR0, (s16)g_dsp.r.ix[0]));
+ WriteToBackLog(0, dreg, state.ReadDMEM(state.r.ar[3]));
+ WriteToBackLog(1, DSP_REG_AR3, IncrementAddressRegister(DSP_REG_AR3));
+ WriteToBackLog(2, DSP_REG_AR0,
+ IncreaseAddressRegister(DSP_REG_AR0, static_cast<s16>(state.r.ix[0])));
}
// SLM $acS.m, $axD.D
@@ -292,16 +293,18 @@ void sln(const UDSPInstruction opc)
// $ar0. Load register $axD.D with value from memory pointed by register
// $ar3. Add corresponding indexing register $ix3 to addressing register $ar3
// and increment $ar0.
-void slm(const UDSPInstruction opc)
+void Interpreter::slm(const UDSPInstruction opc)
{
- u8 sreg = opc & 0x1;
- u8 dreg = ((opc >> 4) & 0x3) + DSP_REG_AXL0;
+ const u8 sreg = opc & 0x1;
+ const u8 dreg = ((opc >> 4) & 0x3) + DSP_REG_AXL0;
+ auto& state = m_dsp_core.DSPState();
- dsp_dmem_write(g_dsp.r.ar[0], dsp_op_read_reg_and_saturate(sreg));
+ state.WriteDMEM(state.r.ar[0], OpReadRegisterAndSaturate(sreg));
- WriteToBackLog(0, dreg, dsp_dmem_read(g_dsp.r.ar[3]));
- WriteToBackLog(1, DSP_REG_AR3, dsp_increase_addr_reg(DSP_REG_AR3, (s16)g_dsp.r.ix[3]));
- WriteToBackLog(2, DSP_REG_AR0, dsp_increment_addr_reg(DSP_REG_AR0));
+ WriteToBackLog(0, dreg, state.ReadDMEM(state.r.ar[3]));
+ WriteToBackLog(1, DSP_REG_AR3,
+ IncreaseAddressRegister(DSP_REG_AR3, static_cast<s16>(state.r.ix[3])));
+ WriteToBackLog(2, DSP_REG_AR0, IncrementAddressRegister(DSP_REG_AR0));
}
// SLMN $acS.m, $axD.D
@@ -310,16 +313,19 @@ void slm(const UDSPInstruction opc)
// $ar0. Load register $axD.D with value from memory pointed by register
// $ar3. Add corresponding indexing register $ix0 to addressing register $ar0
// and add corresponding indexing register $ix3 to addressing register $ar3.
-void slnm(const UDSPInstruction opc)
+void Interpreter::slnm(const UDSPInstruction opc)
{
- u8 sreg = opc & 0x1;
- u8 dreg = ((opc >> 4) & 0x3) + DSP_REG_AXL0;
+ const u8 sreg = opc & 0x1;
+ const u8 dreg = ((opc >> 4) & 0x3) + DSP_REG_AXL0;
+ auto& state = m_dsp_core.DSPState();
- dsp_dmem_write(g_dsp.r.ar[0], dsp_op_read_reg_and_saturate(sreg));
+ state.WriteDMEM(state.r.ar[0], OpReadRegisterAndSaturate(sreg));
- WriteToBackLog(0, dreg, dsp_dmem_read(g_dsp.r.ar[3]));
- WriteToBackLog(1, DSP_REG_AR3, dsp_increase_addr_reg(DSP_REG_AR3, (s16)g_dsp.r.ix[3]));
- WriteToBackLog(2, DSP_REG_AR0, dsp_increase_addr_reg(DSP_REG_AR0, (s16)g_dsp.r.ix[0]));
+ WriteToBackLog(0, dreg, state.ReadDMEM(state.r.ar[3]));
+ WriteToBackLog(1, DSP_REG_AR3,
+ IncreaseAddressRegister(DSP_REG_AR3, static_cast<s16>(state.r.ix[3])));
+ WriteToBackLog(2, DSP_REG_AR0,
+ IncreaseAddressRegister(DSP_REG_AR0, static_cast<s16>(state.r.ix[0])));
}
// LD $ax0.d, $ax1.r, @$arS
@@ -334,228 +340,173 @@ void slnm(const UDSPInstruction opc)
// implemented yet)
// If AR3 points into an invalid memory page, then AX0.L gets the same value as AX0.H. (not
// implemented yet)
-void ld(const UDSPInstruction opc)
+void Interpreter::ld(const UDSPInstruction opc)
{
- u8 dreg = (opc >> 5) & 0x1;
- u8 rreg = (opc >> 4) & 0x1;
- u8 sreg = opc & 0x3;
+ const u8 dreg = (opc >> 5) & 0x1;
+ const u8 rreg = (opc >> 4) & 0x1;
+ const u8 sreg = opc & 0x3;
+ auto& state = m_dsp_core.DSPState();
- WriteToBackLog(0, (dreg << 1) + DSP_REG_AXL0, dsp_dmem_read(g_dsp.r.ar[sreg]));
+ WriteToBackLog(0, (dreg << 1) + DSP_REG_AXL0, state.ReadDMEM(state.r.ar[sreg]));
- if (IsSameMemArea(g_dsp.r.ar[sreg], g_dsp.r.ar[3]))
- WriteToBackLog(1, (rreg << 1) + DSP_REG_AXL1, dsp_dmem_read(g_dsp.r.ar[sreg]));
+ if (IsSameMemArea(state.r.ar[sreg], state.r.ar[3]))
+ WriteToBackLog(1, (rreg << 1) + DSP_REG_AXL1, state.ReadDMEM(state.r.ar[sreg]));
else
- WriteToBackLog(1, (rreg << 1) + DSP_REG_AXL1, dsp_dmem_read(g_dsp.r.ar[3]));
+ WriteToBackLog(1, (rreg << 1) + DSP_REG_AXL1, state.ReadDMEM(state.r.ar[3]));
- WriteToBackLog(2, sreg, dsp_increment_addr_reg(sreg));
+ WriteToBackLog(2, sreg, IncrementAddressRegister(sreg));
- WriteToBackLog(3, DSP_REG_AR3, dsp_increment_addr_reg(DSP_REG_AR3));
+ WriteToBackLog(3, DSP_REG_AR3, IncrementAddressRegister(DSP_REG_AR3));
}
// LDAX $axR, @$arS
// xxxx xxxx 11sr 0011
-void ldax(const UDSPInstruction opc)
+void Interpreter::ldax(const UDSPInstruction opc)
{
- u8 sreg = (opc >> 5) & 0x1;
- u8 rreg = (opc >> 4) & 0x1;
+ const u8 sreg = (opc >> 5) & 0x1;
+ const u8 rreg = (opc >> 4) & 0x1;
+ auto& state = m_dsp_core.DSPState();
- WriteToBackLog(0, rreg + DSP_REG_AXH0, dsp_dmem_read(g_dsp.r.ar[sreg]));
+ WriteToBackLog(0, rreg + DSP_REG_AXH0, state.ReadDMEM(state.r.ar[sreg]));
- if (IsSameMemArea(g_dsp.r.ar[sreg], g_dsp.r.ar[3]))
- WriteToBackLog(1, rreg + DSP_REG_AXL0, dsp_dmem_read(g_dsp.r.ar[sreg]));
+ if (IsSameMemArea(state.r.ar[sreg], state.r.ar[3]))
+ WriteToBackLog(1, rreg + DSP_REG_AXL0, state.ReadDMEM(state.r.ar[sreg]));
else
- WriteToBackLog(1, rreg + DSP_REG_AXL0, dsp_dmem_read(g_dsp.r.ar[3]));
+ WriteToBackLog(1, rreg + DSP_REG_AXL0, state.ReadDMEM(state.r.ar[3]));
- WriteToBackLog(2, sreg, dsp_increment_addr_reg(sreg));
+ WriteToBackLog(2, sreg, IncrementAddressRegister(sreg));
- WriteToBackLog(3, DSP_REG_AR3, dsp_increment_addr_reg(DSP_REG_AR3));
+ WriteToBackLog(3, DSP_REG_AR3, IncrementAddressRegister(DSP_REG_AR3));
}
// LDN $ax0.d, $ax1.r, @$arS
// xxxx xxxx 11dr 01ss
-void ldn(const UDSPInstruction opc)
+void Interpreter::ldn(const UDSPInstruction opc)
{
- u8 dreg = (opc >> 5) & 0x1;
- u8 rreg = (opc >> 4) & 0x1;
- u8 sreg = opc & 0x3;
+ const u8 dreg = (opc >> 5) & 0x1;
+ const u8 rreg = (opc >> 4) & 0x1;
+ const u8 sreg = opc & 0x3;
+ auto& state = m_dsp_core.DSPState();
- WriteToBackLog(0, (dreg << 1) + DSP_REG_AXL0, dsp_dmem_read(g_dsp.r.ar[sreg]));
+ WriteToBackLog(0, (dreg << 1) + DSP_REG_AXL0, state.ReadDMEM(state.r.ar[sreg]));
- if (IsSameMemArea(g_dsp.r.ar[sreg], g_dsp.r.ar[3]))
- WriteToBackLog(1, (rreg << 1) + DSP_REG_AXL1, dsp_dmem_read(g_dsp.r.ar[sreg]));
+ if (IsSameMemArea(state.r.ar[sreg], state.r.ar[3]))
+ WriteToBackLog(1, (rreg << 1) + DSP_REG_AXL1, state.ReadDMEM(state.r.ar[sreg]));
else
- WriteToBackLog(1, (rreg << 1) + DSP_REG_AXL1, dsp_dmem_read(g_dsp.r.ar[3]));
+ WriteToBackLog(1, (rreg << 1) + DSP_REG_AXL1, state.ReadDMEM(state.r.ar[3]));
- WriteToBackLog(2, sreg, dsp_increase_addr_reg(sreg, (s16)g_dsp.r.ix[sreg]));
+ WriteToBackLog(2, sreg, IncreaseAddressRegister(sreg, static_cast<s16>(state.r.ix[sreg])));
- WriteToBackLog(3, DSP_REG_AR3, dsp_increment_addr_reg(DSP_REG_AR3));
+ WriteToBackLog(3, DSP_REG_AR3, IncrementAddressRegister(DSP_REG_AR3));
}
// LDAXN $axR, @$arS
// xxxx xxxx 11sr 0111
-void ldaxn(const UDSPInstruction opc)
+void Interpreter::ldaxn(const UDSPInstruction opc)
{
- u8 sreg = (opc >> 5) & 0x1;
- u8 rreg = (opc >> 4) & 0x1;
+ const u8 sreg = (opc >> 5) & 0x1;
+ const u8 rreg = (opc >> 4) & 0x1;
+ auto& state = m_dsp_core.DSPState();
- WriteToBackLog(0, rreg + DSP_REG_AXH0, dsp_dmem_read(g_dsp.r.ar[sreg]));
+ WriteToBackLog(0, rreg + DSP_REG_AXH0, state.ReadDMEM(state.r.ar[sreg]));
- if (IsSameMemArea(g_dsp.r.ar[sreg], g_dsp.r.ar[3]))
- WriteToBackLog(1, rreg + DSP_REG_AXL0, dsp_dmem_read(g_dsp.r.ar[sreg]));
+ if (IsSameMemArea(state.r.ar[sreg], state.r.ar[3]))
+ WriteToBackLog(1, rreg + DSP_REG_AXL0, state.ReadDMEM(state.r.ar[sreg]));
else
- WriteToBackLog(1, rreg + DSP_REG_AXL0, dsp_dmem_read(g_dsp.r.ar[3]));
+ WriteToBackLog(1, rreg + DSP_REG_AXL0, state.ReadDMEM(state.r.ar[3]));
- WriteToBackLog(2, sreg, dsp_increase_addr_reg(sreg, (s16)g_dsp.r.ix[sreg]));
+ WriteToBackLog(2, sreg, IncreaseAddressRegister(sreg, static_cast<s16>(state.r.ix[sreg])));
- WriteToBackLog(3, DSP_REG_AR3, dsp_increment_addr_reg(DSP_REG_AR3));
+ WriteToBackLog(3, DSP_REG_AR3, IncrementAddressRegister(DSP_REG_AR3));
}
// LDM $ax0.d, $ax1.r, @$arS
// xxxx xxxx 11dr 10ss
-void ldm(const UDSPInstruction opc)
+void Interpreter::ldm(const UDSPInstruction opc)
{
- u8 dreg = (opc >> 5) & 0x1;
- u8 rreg = (opc >> 4) & 0x1;
- u8 sreg = opc & 0x3;
+ const u8 dreg = (opc >> 5) & 0x1;
+ const u8 rreg = (opc >> 4) & 0x1;
+ const u8 sreg = opc & 0x3;
+ auto& state = m_dsp_core.DSPState();
- WriteToBackLog(0, (dreg << 1) + DSP_REG_AXL0, dsp_dmem_read(g_dsp.r.ar[sreg]));
+ WriteToBackLog(0, (dreg << 1) + DSP_REG_AXL0, state.ReadDMEM(state.r.ar[sreg]));
- if (IsSameMemArea(g_dsp.r.ar[sreg], g_dsp.r.ar[3]))
- WriteToBackLog(1, (rreg << 1) + DSP_REG_AXL1, dsp_dmem_read(g_dsp.r.ar[sreg]));
+ if (IsSameMemArea(state.r.ar[sreg], state.r.ar[3]))
+ WriteToBackLog(1, (rreg << 1) + DSP_REG_AXL1, state.ReadDMEM(state.r.ar[sreg]));
else
- WriteToBackLog(1, (rreg << 1) + DSP_REG_AXL1, dsp_dmem_read(g_dsp.r.ar[3]));
+ WriteToBackLog(1, (rreg << 1) + DSP_REG_AXL1, state.ReadDMEM(state.r.ar[3]));
- WriteToBackLog(2, sreg, dsp_increment_addr_reg(sreg));
+ WriteToBackLog(2, sreg, IncrementAddressRegister(sreg));
- WriteToBackLog(3, DSP_REG_AR3, dsp_increase_addr_reg(DSP_REG_AR3, (s16)g_dsp.r.ix[3]));
+ WriteToBackLog(3, DSP_REG_AR3,
+ IncreaseAddressRegister(DSP_REG_AR3, static_cast<s16>(state.r.ix[3])));
}
// LDAXM $axR, @$arS
// xxxx xxxx 11sr 1011
-void ldaxm(const UDSPInstruction opc)
+void Interpreter::ldaxm(const UDSPInstruction opc)
{
- u8 sreg = (opc >> 5) & 0x1;
- u8 rreg = (opc >> 4) & 0x1;
+ const u8 sreg = (opc >> 5) & 0x1;
+ const u8 rreg = (opc >> 4) & 0x1;
+ auto& state = m_dsp_core.DSPState();
- WriteToBackLog(0, rreg + DSP_REG_AXH0, dsp_dmem_read(g_dsp.r.ar[sreg]));
+ WriteToBackLog(0, rreg + DSP_REG_AXH0, state.ReadDMEM(state.r.ar[sreg]));
- if (IsSameMemArea(g_dsp.r.ar[sreg], g_dsp.r.ar[3]))
- WriteToBackLog(1, rreg + DSP_REG_AXL0, dsp_dmem_read(g_dsp.r.ar[sreg]));
+ if (IsSameMemArea(state.r.ar[sreg], state.r.ar[3]))
+ WriteToBackLog(1, rreg + DSP_REG_AXL0, state.ReadDMEM(state.r.ar[sreg]));
else
- WriteToBackLog(1, rreg + DSP_REG_AXL0, dsp_dmem_read(g_dsp.r.ar[3]));
+ WriteToBackLog(1, rreg + DSP_REG_AXL0, state.ReadDMEM(state.r.ar[3]));
- WriteToBackLog(2, sreg, dsp_increment_addr_reg(sreg));
+ WriteToBackLog(2, sreg, IncrementAddressRegister(sreg));
- WriteToBackLog(3, DSP_REG_AR3, dsp_increase_addr_reg(DSP_REG_AR3, (s16)g_dsp.r.ix[3]));
+ WriteToBackLog(3, DSP_REG_AR3,
+ IncreaseAddressRegister(DSP_REG_AR3, static_cast<s16>(state.r.ix[3])));
}
// LDNM $ax0.d, $ax1.r, @$arS
// xxxx xxxx 11dr 11ss
-void ldnm(const UDSPInstruction opc)
+void Interpreter::ldnm(const UDSPInstruction opc)
{
- u8 dreg = (opc >> 5) & 0x1;
- u8 rreg = (opc >> 4) & 0x1;
- u8 sreg = opc & 0x3;
+ const u8 dreg = (opc >> 5) & 0x1;
+ const u8 rreg = (opc >> 4) & 0x1;
+ const u8 sreg = opc & 0x3;
+ auto& state = m_dsp_core.DSPState();
- WriteToBackLog(0, (dreg << 1) + DSP_REG_AXL0, dsp_dmem_read(g_dsp.r.ar[sreg]));
+ WriteToBackLog(0, (dreg << 1) + DSP_REG_AXL0, state.ReadDMEM(state.r.ar[sreg]));
- if (IsSameMemArea(g_dsp.r.ar[sreg], g_dsp.r.ar[3]))
- WriteToBackLog(1, (rreg << 1) + DSP_REG_AXL1, dsp_dmem_read(g_dsp.r.ar[sreg]));
+ if (IsSameMemArea(state.r.ar[sreg], state.r.ar[3]))
+ WriteToBackLog(1, (rreg << 1) + DSP_REG_AXL1, state.ReadDMEM(state.r.ar[sreg]));
else
- WriteToBackLog(1, (rreg << 1) + DSP_REG_AXL1, dsp_dmem_read(g_dsp.r.ar[3]));
+ WriteToBackLog(1, (rreg << 1) + DSP_REG_AXL1, state.ReadDMEM(state.r.ar[3]));
- WriteToBackLog(2, sreg, dsp_increase_addr_reg(sreg, (s16)g_dsp.r.ix[sreg]));
+ WriteToBackLog(2, sreg, IncreaseAddressRegister(sreg, static_cast<s16>(state.r.ix[sreg])));
- WriteToBackLog(3, DSP_REG_AR3, dsp_increase_addr_reg(DSP_REG_AR3, (s16)g_dsp.r.ix[3]));
+ WriteToBackLog(3, DSP_REG_AR3,
+ IncreaseAddressRegister(DSP_REG_AR3, static_cast<s16>(state.r.ix[3])));
}
// LDAXNM $axR, @$arS
// xxxx xxxx 11dr 1111
-void ldaxnm(const UDSPInstruction opc)
+void Interpreter::ldaxnm(const UDSPInstruction opc)
{
- u8 sreg = (opc >> 5) & 0x1;
- u8 rreg = (opc >> 4) & 0x1;
+ const u8 sreg = (opc >> 5) & 0x1;
+ const u8 rreg = (opc >> 4) & 0x1;
+ auto& state = m_dsp_core.DSPState();
- WriteToBackLog(0, rreg + DSP_REG_AXH0, dsp_dmem_read(g_dsp.r.ar[sreg]));
+ WriteToBackLog(0, rreg + DSP_REG_AXH0, state.ReadDMEM(state.r.ar[sreg]));
- if (IsSameMemArea(g_dsp.r.ar[sreg], g_dsp.r.ar[3]))
- WriteToBackLog(1, rreg + DSP_REG_AXL0, dsp_dmem_read(g_dsp.r.ar[sreg]));
+ if (IsSameMemArea(state.r.ar[sreg], state.r.ar[3]))
+ WriteToBackLog(1, rreg + DSP_REG_AXL0, state.ReadDMEM(state.r.ar[sreg]));
else
- WriteToBackLog(1, rreg + DSP_REG_AXL0, dsp_dmem_read(g_dsp.r.ar[3]));
-
- WriteToBackLog(2, sreg, dsp_increase_addr_reg(sreg, (s16)g_dsp.r.ix[sreg]));
-
- WriteToBackLog(3, DSP_REG_AR3, dsp_increase_addr_reg(DSP_REG_AR3, (s16)g_dsp.r.ix[3]));
-}
-
-void nop(const UDSPInstruction opc)
-{
-}
-} // namespace Interpreter::Ext
+ WriteToBackLog(1, rreg + DSP_REG_AXL0, state.ReadDMEM(state.r.ar[3]));
-// The ext ops are calculated in parallel with the actual op. That means that
-// both the main op and the ext op see the same register state as input. The
-// output is simple as long as the main and ext ops don't change the same
-// register. If they do the output is the bitwise or of the result of both the
-// main and ext ops.
+ WriteToBackLog(2, sreg, IncreaseAddressRegister(sreg, static_cast<s16>(state.r.ix[sreg])));
-// The ext op are writing their output into the backlog which is
-// being applied to the real registers after the main op was executed
-void ApplyWriteBackLog()
-{
- // always make sure to have an extra entry at the end w/ -1 to avoid
- // infinitive loops
- for (int i = 0; writeBackLogIdx[i] != -1; i++)
- {
- u16 value = writeBackLog[i];
-#ifdef PRECISE_BACKLOG
- value |= Interpreter::dsp_op_read_reg(writeBackLogIdx[i]);
-#endif
- Interpreter::dsp_op_write_reg(writeBackLogIdx[i], value);
-
- // Clear back log
- writeBackLogIdx[i] = -1;
- }
+ WriteToBackLog(3, DSP_REG_AR3,
+ IncreaseAddressRegister(DSP_REG_AR3, static_cast<s16>(state.r.ix[3])));
}
-// This function is being called in the main op after all input regs were read
-// and before it writes into any regs. This way we can always use bitwise or to
-// apply the ext command output, because if the main op didn't change the value
-// then 0 | ext output = ext output and if it did then bitwise or is still the
-// right thing to do
-// Only needed for cases when mainop and extended are modifying the same ACC
-// Games are not doing that + in motorola (similar DSP) dox this is forbidden to do.
-void ZeroWriteBackLog()
+void Interpreter::nop_ext(const UDSPInstruction)
{
-#ifdef PRECISE_BACKLOG
- // always make sure to have an extra entry at the end w/ -1 to avoid
- // infinitive loops
- for (int i = 0; writeBackLogIdx[i] != -1; i++)
- {
- Interpreter::dsp_op_write_reg(writeBackLogIdx[i], 0);
- }
-#endif
-}
-
-void ZeroWriteBackLogPreserveAcc(u8 acc)
-{
-#ifdef PRECISE_BACKLOG
- for (int i = 0; writeBackLogIdx[i] != -1; i++)
- {
- // acc0
- if ((acc == 0) &&
- ((writeBackLogIdx[i] == DSP_REG_ACL0) || (writeBackLogIdx[i] == DSP_REG_ACM0) ||
- (writeBackLogIdx[i] == DSP_REG_ACH0)))
- continue;
-
- // acc1
- if ((acc == 1) &&
- ((writeBackLogIdx[i] == DSP_REG_ACL1) || (writeBackLogIdx[i] == DSP_REG_ACM1) ||
- (writeBackLogIdx[i] == DSP_REG_ACH1)))
- continue;
-
- Interpreter::dsp_op_write_reg(writeBackLogIdx[i], 0);
- }
-#endif
}
-} // namespace DSP
+} // namespace DSP::Interpreter
diff --git a/Source/Core/Core/DSP/Interpreter/DSPIntExtOps.h b/Source/Core/Core/DSP/Interpreter/DSPIntExtOps.h
deleted file mode 100644
index ec1e23ac9e..0000000000
--- a/Source/Core/Core/DSP/Interpreter/DSPIntExtOps.h
+++ /dev/null
@@ -1,41 +0,0 @@
-// Copyright 2008 Dolphin Emulator Project
-// Copyright 2005 Duddie
-// Licensed under GPLv2+
-// Refer to the license.txt file included.
-
-#pragma once
-
-#include "Core/DSP/DSPCommon.h"
-
-// Extended opcode support.
-// Many opcode have the lower 0xFF (some only 0x7f) free - there, an opcode extension
-// can be stored.
-
-namespace DSP::Interpreter::Ext
-{
-void l(UDSPInstruction opc);
-void ln(UDSPInstruction opc);
-void ls(UDSPInstruction opc);
-void lsn(UDSPInstruction opc);
-void lsm(UDSPInstruction opc);
-void lsnm(UDSPInstruction opc);
-void sl(UDSPInstruction opc);
-void sln(UDSPInstruction opc);
-void slm(UDSPInstruction opc);
-void slnm(UDSPInstruction opc);
-void s(UDSPInstruction opc);
-void sn(UDSPInstruction opc);
-void ld(UDSPInstruction opc);
-void ldax(UDSPInstruction opc);
-void ldn(UDSPInstruction opc);
-void ldaxn(UDSPInstruction opc);
-void ldm(UDSPInstruction opc);
-void ldaxm(UDSPInstruction opc);
-void ldnm(UDSPInstruction opc);
-void ldaxnm(UDSPInstruction opc);
-void mv(UDSPInstruction opc);
-void dr(UDSPInstruction opc);
-void ir(UDSPInstruction opc);
-void nr(UDSPInstruction opc);
-void nop(UDSPInstruction opc);
-} // namespace DSP::Interpreter::Ext
diff --git a/Source/Core/Core/DSP/Interpreter/DSPIntLoadStore.cpp b/Source/Core/Core/DSP/Interpreter/DSPIntLoadStore.cpp
index a3488da8ae..a5cb0bbad3 100644
--- a/Source/Core/Core/DSP/Interpreter/DSPIntLoadStore.cpp
+++ b/Source/Core/Core/DSP/Interpreter/DSPIntLoadStore.cpp
@@ -4,8 +4,7 @@
//
// Additional copyrights go to Duddie and Tratax (c) 2004
-#include "Core/DSP/DSPMemoryMap.h"
-#include "Core/DSP/Interpreter/DSPIntUtil.h"
+#include "Common/CommonTypes.h"
#include "Core/DSP/Interpreter/DSPInterpreter.h"
namespace DSP::Interpreter
@@ -16,15 +15,16 @@ namespace DSP::Interpreter
// CR[0-7] | M. That is, the upper 8 bits of the address are the
// bottom 8 bits from CR, and the lower 8 bits are from the 8-bit immediate.
// Note: pc+=2 in duddie's doc seems wrong
-void srs(const UDSPInstruction opc)
+void Interpreter::srs(const UDSPInstruction opc)
{
- u8 reg = ((opc >> 8) & 0x7) + 0x18;
- u16 addr = (g_dsp.r.cr << 8) | (opc & 0xFF);
+ auto& state = m_dsp_core.DSPState();
+ const auto reg = static_cast<u8>(((opc >> 8) & 0x7) + 0x18);
+ const auto addr = static_cast<u16>((state.r.cr << 8) | (opc & 0xFF));
if (reg >= DSP_REG_ACM0)
- dsp_dmem_write(addr, dsp_op_read_reg_and_saturate(reg - DSP_REG_ACM0));
+ state.WriteDMEM(addr, OpReadRegisterAndSaturate(reg - DSP_REG_ACM0));
else
- dsp_dmem_write(addr, dsp_op_read_reg(reg));
+ state.WriteDMEM(addr, OpReadRegister(reg));
}
// LRS $(0x18+D), @M
@@ -32,40 +32,45 @@ void srs(const UDSPInstruction opc)
// Move value from data memory pointed by address CR[0-7] | M to register
// $(0x18+D). That is, the upper 8 bits of the address are the bottom 8 bits
// from CR, and the lower 8 bits are from the 8-bit immediate.
-void lrs(const UDSPInstruction opc)
+void Interpreter::lrs(const UDSPInstruction opc)
{
- u8 reg = ((opc >> 8) & 0x7) + 0x18;
- u16 addr = (g_dsp.r.cr << 8) | (opc & 0xFF);
- dsp_op_write_reg(reg, dsp_dmem_read(addr));
- dsp_conditional_extend_accum(reg);
+ auto& state = m_dsp_core.DSPState();
+ const auto reg = static_cast<u8>(((opc >> 8) & 0x7) + 0x18);
+ const auto addr = static_cast<u16>((state.r.cr << 8) | (opc & 0xFF));
+
+ OpWriteRegister(reg, state.ReadDMEM(addr));
+ ConditionalExtendAccum(reg);
}
// LR $D, @M
// 0000 0000 110d dddd
// mmmm mmmm mmmm mmmm
// Move value from data memory pointed by address M to register $D.
-void lr(const UDSPInstruction opc)
+void Interpreter::lr(const UDSPInstruction opc)
{
- u8 reg = opc & 0x1F;
- u16 addr = dsp_fetch_code();
- u16 val = dsp_dmem_read(addr);
- dsp_op_write_reg(reg, val);
- dsp_conditional_extend_accum(reg);
+ auto& state = m_dsp_core.DSPState();
+ const u8 reg = opc & 0x1F;
+ const u16 addr = state.FetchInstruction();
+ const u16 val = state.ReadDMEM(addr);
+
+ OpWriteRegister(reg, val);
+ ConditionalExtendAccum(reg);
}
// SR @M, $S
// 0000 0000 111s ssss
// mmmm mmmm mmmm mmmm
// Store value from register $S to a memory pointed by address M.
-void sr(const UDSPInstruction opc)
+void Interpreter::sr(const UDSPInstruction opc)
{
- u8 reg = opc & 0x1F;
- u16 addr = dsp_fetch_code();
+ auto& state = m_dsp_core.DSPState();
+ const u8 reg = opc & 0x1F;
+ const u16 addr = state.FetchInstruction();
if (reg >= DSP_REG_ACM0)
- dsp_dmem_write(addr, dsp_op_read_reg_and_saturate(reg - DSP_REG_ACM0));
+ state.WriteDMEM(addr, OpReadRegisterAndSaturate(reg - DSP_REG_ACM0));
else
- dsp_dmem_write(addr, dsp_op_read_reg(reg));
+ state.WriteDMEM(addr, OpReadRegister(reg));
}
// SI @M, #I
@@ -73,176 +78,189 @@ void sr(const UDSPInstruction opc)
// iiii iiii iiii iiii
// Store 16-bit immediate value I to a memory location pointed by address
// M (M is 8-bit value sign extended).
-void si(const UDSPInstruction opc)
+void Interpreter::si(const UDSPInstruction opc)
{
- u16 addr = (s8)opc;
- u16 imm = dsp_fetch_code();
- dsp_dmem_write(addr, imm);
+ auto& state = m_dsp_core.DSPState();
+ const u16 addr = static_cast<u16>(static_cast<s8>(opc));
+ const u16 imm = state.FetchInstruction();
+
+ state.WriteDMEM(addr, imm);
}
// LRR $D, @$S
// 0001 1000 0ssd dddd
// Move value from data memory pointed by addressing register $S to register $D.
-void lrr(const UDSPInstruction opc)
+void Interpreter::lrr(const UDSPInstruction opc)
{
- u8 sreg = (opc >> 5) & 0x3;
- u8 dreg = opc & 0x1f;
+ const u8 sreg = (opc >> 5) & 0x3;
+ const u8 dreg = opc & 0x1f;
+ auto& state = m_dsp_core.DSPState();
- u16 val = dsp_dmem_read(dsp_op_read_reg(sreg));
- dsp_op_write_reg(dreg, val);
- dsp_conditional_extend_accum(dreg);
+ const u16 val = state.ReadDMEM(OpReadRegister(sreg));
+ OpWriteRegister(dreg, val);
+ ConditionalExtendAccum(dreg);
}
// LRRD $D, @$S
// 0001 1000 1ssd dddd
// Move value from data memory pointed by addressing register $S to register $D.
// Decrement register $S.
-void lrrd(const UDSPInstruction opc)
+void Interpreter::lrrd(const UDSPInstruction opc)
{
- u8 sreg = (opc >> 5) & 0x3;
- u8 dreg = opc & 0x1f;
-
- u16 val = dsp_dmem_read(dsp_op_read_reg(sreg));
- dsp_op_write_reg(dreg, val);
- dsp_conditional_extend_accum(dreg);
- g_dsp.r.ar[sreg] = dsp_decrement_addr_reg(sreg);
+ const u8 sreg = (opc >> 5) & 0x3;
+ const u8 dreg = opc & 0x1f;
+ auto& state = m_dsp_core.DSPState();
+
+ const u16 val = state.ReadDMEM(OpReadRegister(sreg));
+ OpWriteRegister(dreg, val);
+ ConditionalExtendAccum(dreg);
+ state.r.ar[sreg] = DecrementAddressRegister(sreg);
}
// LRRI $D, @$S
// 0001 1001 0ssd dddd
// Move value from data memory pointed by addressing register $S to register $D.
// Increment register $S.
-void lrri(const UDSPInstruction opc)
+void Interpreter::lrri(const UDSPInstruction opc)
{
- u8 sreg = (opc >> 5) & 0x3;
- u8 dreg = opc & 0x1f;
-
- u16 val = dsp_dmem_read(dsp_op_read_reg(sreg));
- dsp_op_write_reg(dreg, val);
- dsp_conditional_extend_accum(dreg);
- g_dsp.r.ar[sreg] = dsp_increment_addr_reg(sreg);
+ const u8 sreg = (opc >> 5) & 0x3;
+ const u8 dreg = opc & 0x1f;
+ auto& state = m_dsp_core.DSPState();
+
+ const u16 val = state.ReadDMEM(OpReadRegister(sreg));
+ OpWriteRegister(dreg, val);
+ ConditionalExtendAccum(dreg);
+ state.r.ar[sreg] = IncrementAddressRegister(sreg);
}
// LRRN $D, @$S
// 0001 1001 1ssd dddd
// Move value from data memory pointed by addressing register $S to register $D.
// Add indexing register $(0x4+S) to register $S.
-void lrrn(const UDSPInstruction opc)
+void Interpreter::lrrn(const UDSPInstruction opc)
{
- u8 sreg = (opc >> 5) & 0x3;
- u8 dreg = opc & 0x1f;
-
- u16 val = dsp_dmem_read(dsp_op_read_reg(sreg));
- dsp_op_write_reg(dreg, val);
- dsp_conditional_extend_accum(dreg);
- g_dsp.r.ar[sreg] = dsp_increase_addr_reg(sreg, (s16)g_dsp.r.ix[sreg]);
+ const u8 sreg = (opc >> 5) & 0x3;
+ const u8 dreg = opc & 0x1f;
+ auto& state = m_dsp_core.DSPState();
+
+ const u16 val = state.ReadDMEM(OpReadRegister(sreg));
+ OpWriteRegister(dreg, val);
+ ConditionalExtendAccum(dreg);
+ state.r.ar[sreg] = IncreaseAddressRegister(sreg, static_cast<s16>(state.r.ix[sreg]));
}
// SRR @$D, $S
// 0001 1010 0dds ssss
// Store value from source register $S to a memory location pointed by
// addressing register $D.
-void srr(const UDSPInstruction opc)
+void Interpreter::srr(const UDSPInstruction opc)
{
- u8 dreg = (opc >> 5) & 0x3;
- u8 sreg = opc & 0x1f;
+ const u8 dreg = (opc >> 5) & 0x3;
+ const u8 sreg = opc & 0x1f;
+ auto& state = m_dsp_core.DSPState();
if (sreg >= DSP_REG_ACM0)
- dsp_dmem_write(g_dsp.r.ar[dreg], dsp_op_read_reg_and_saturate(sreg - DSP_REG_ACM0));
+ state.WriteDMEM(state.r.ar[dreg], OpReadRegisterAndSaturate(sreg - DSP_REG_ACM0));
else
- dsp_dmem_write(g_dsp.r.ar[dreg], dsp_op_read_reg(sreg));
+ state.WriteDMEM(state.r.ar[dreg], OpReadRegister(sreg));
}
// SRRD @$D, $S
// 0001 1010 1dds ssss
// Store value from source register $S to a memory location pointed by
// addressing register $D. Decrement register $D.
-void srrd(const UDSPInstruction opc)
+void Interpreter::srrd(const UDSPInstruction opc)
{
- u8 dreg = (opc >> 5) & 0x3;
- u8 sreg = opc & 0x1f;
+ const u8 dreg = (opc >> 5) & 0x3;
+ const u8 sreg = opc & 0x1f;
+ auto& state = m_dsp_core.DSPState();
if (sreg >= DSP_REG_ACM0)
- dsp_dmem_write(g_dsp.r.ar[dreg], dsp_op_read_reg_and_saturate(sreg - DSP_REG_ACM0));
+ state.WriteDMEM(state.r.ar[dreg], OpReadRegisterAndSaturate(sreg - DSP_REG_ACM0));
else
- dsp_dmem_write(g_dsp.r.ar[dreg], dsp_op_read_reg(sreg));
+ state.WriteDMEM(state.r.ar[dreg], OpReadRegister(sreg));
- g_dsp.r.ar[dreg] = dsp_decrement_addr_reg(dreg);
+ state.r.ar[dreg] = DecrementAddressRegister(dreg);
}
// SRRI @$D, $S
// 0001 1011 0dds ssss
// Store value from source register $S to a memory location pointed by
// addressing register $D. Increment register $D.
-void srri(const UDSPInstruction opc)
+void Interpreter::srri(const UDSPInstruction opc)
{
- u8 dreg = (opc >> 5) & 0x3;
- u8 sreg = opc & 0x1f;
+ const u8 dreg = (opc >> 5) & 0x3;
+ const u8 sreg = opc & 0x1f;
+ auto& state = m_dsp_core.DSPState();
if (sreg >= DSP_REG_ACM0)
- dsp_dmem_write(g_dsp.r.ar[dreg], dsp_op_read_reg_and_saturate(sreg - DSP_REG_ACM0));
+ state.WriteDMEM(state.r.ar[dreg], OpReadRegisterAndSaturate(sreg - DSP_REG_ACM0));
else
- dsp_dmem_write(g_dsp.r.ar[dreg], dsp_op_read_reg(sreg));
+ state.WriteDMEM(state.r.ar[dreg], OpReadRegister(sreg));
- g_dsp.r.ar[dreg] = dsp_increment_addr_reg(dreg);
+ state.r.ar[dreg] = IncrementAddressRegister(dreg);
}
// SRRN @$D, $S
// 0001 1011 1dds ssss
// Store value from source register $S to a memory location pointed by
// addressing register $D. Add DSP_REG_IX0 register to register $D.
-void srrn(const UDSPInstruction opc)
+void Interpreter::srrn(const UDSPInstruction opc)
{
- u8 dreg = (opc >> 5) & 0x3;
- u8 sreg = opc & 0x1f;
+ const u8 dreg = (opc >> 5) & 0x3;
+ const u8 sreg = opc & 0x1f;
+ auto& state = m_dsp_core.DSPState();
if (sreg >= DSP_REG_ACM0)
- dsp_dmem_write(g_dsp.r.ar[dreg], dsp_op_read_reg_and_saturate(sreg - DSP_REG_ACM0));
+ state.WriteDMEM(state.r.ar[dreg], OpReadRegisterAndSaturate(sreg - DSP_REG_ACM0));
else
- dsp_dmem_write(g_dsp.r.ar[dreg], dsp_op_read_reg(sreg));
+ state.WriteDMEM(state.r.ar[dreg], OpReadRegister(sreg));
- g_dsp.r.ar[dreg] = dsp_increase_addr_reg(dreg, (s16)g_dsp.r.ix[dreg]);
+ state.r.ar[dreg] = IncreaseAddressRegister(dreg, static_cast<s16>(state.r.ix[dreg]));
}
// ILRR $acD.m, @$arS
// 0000 001d 0001 00ss
// Move value from instruction memory pointed by addressing register
// $arS to mid accumulator register $acD.m.
-void ilrr(const UDSPInstruction opc)
+void Interpreter::ilrr(const UDSPInstruction opc)
{
- u16 reg = opc & 0x3;
- u16 dreg = DSP_REG_ACM0 + ((opc >> 8) & 1);
+ const u16 reg = opc & 0x3;
+ const u16 dreg = DSP_REG_ACM0 + ((opc >> 8) & 1);
+ auto& state = m_dsp_core.DSPState();
- g_dsp.r.ac[dreg - DSP_REG_ACM0].m = dsp_imem_read(g_dsp.r.ar[reg]);
- dsp_conditional_extend_accum(dreg);
+ state.r.ac[dreg - DSP_REG_ACM0].m = state.ReadIMEM(state.r.ar[reg]);
+ ConditionalExtendAccum(dreg);
}
// ILRRD $acD.m, @$arS
// 0000 001d 0001 01ss
// Move value from instruction memory pointed by addressing register
// $arS to mid accumulator register $acD.m. Decrement addressing register $arS.
-void ilrrd(const UDSPInstruction opc)
+void Interpreter::ilrrd(const UDSPInstruction opc)
{
- u16 reg = opc & 0x3;
- u16 dreg = DSP_REG_ACM0 + ((opc >> 8) & 1);
+ const u16 reg = opc & 0x3;
+ const u16 dreg = DSP_REG_ACM0 + ((opc >> 8) & 1);
+ auto& state = m_dsp_core.DSPState();
- g_dsp.r.ac[dreg - DSP_REG_ACM0].m = dsp_imem_read(g_dsp.r.ar[reg]);
- dsp_conditional_extend_accum(dreg);
- g_dsp.r.ar[reg] = dsp_decrement_addr_reg(reg);
+ state.r.ac[dreg - DSP_REG_ACM0].m = state.ReadIMEM(state.r.ar[reg]);
+ ConditionalExtendAccum(dreg);
+ state.r.ar[reg] = DecrementAddressRegister(reg);
}
// ILRRI $acD.m, @$S
// 0000 001d 0001 10ss
// Move value from instruction memory pointed by addressing register
// $arS to mid accumulator register $acD.m. Increment addressing register $arS.
-void ilrri(const UDSPInstruction opc)
+void Interpreter::ilrri(const UDSPInstruction opc)
{
- u16 reg = opc & 0x3;
- u16 dreg = DSP_REG_ACM0 + ((opc >> 8) & 1);
+ const u16 reg = opc & 0x3;
+ const u16 dreg = DSP_REG_ACM0 + ((opc >> 8) & 1);
+ auto& state = m_dsp_core.DSPState();
- g_dsp.r.ac[dreg - DSP_REG_ACM0].m = dsp_imem_read(g_dsp.r.ar[reg]);
- dsp_conditional_extend_accum(dreg);
- g_dsp.r.ar[reg] = dsp_increment_addr_reg(reg);
+ state.r.ac[dreg - DSP_REG_ACM0].m = state.ReadIMEM(state.r.ar[reg]);
+ ConditionalExtendAccum(dreg);
+ state.r.ar[reg] = IncrementAddressRegister(reg);
}
// ILRRN $acD.m, @$arS
@@ -250,13 +268,14 @@ void ilrri(const UDSPInstruction opc)
// Move value from instruction memory pointed by addressing register
// $arS to mid accumulator register $acD.m. Add corresponding indexing
// register $ixS to addressing register $arS.
-void ilrrn(const UDSPInstruction opc)
+void Interpreter::ilrrn(const UDSPInstruction opc)
{
- u16 reg = opc & 0x3;
- u16 dreg = DSP_REG_ACM0 + ((opc >> 8) & 1);
+ const u16 reg = opc & 0x3;
+ const u16 dreg = DSP_REG_ACM0 + ((opc >> 8) & 1);
+ auto& state = m_dsp_core.DSPState();
- g_dsp.r.ac[dreg - DSP_REG_ACM0].m = dsp_imem_read(g_dsp.r.ar[reg]);
- dsp_conditional_extend_accum(dreg);
- g_dsp.r.ar[reg] = dsp_increase_addr_reg(reg, (s16)g_dsp.r.ix[reg]);
+ state.r.ac[dreg - DSP_REG_ACM0].m = state.ReadIMEM(state.r.ar[reg]);
+ ConditionalExtendAccum(dreg);
+ state.r.ar[reg] = IncreaseAddressRegister(reg, static_cast<s16>(state.r.ix[reg]));
}
} // namespace DSP::Interpreter
diff --git a/Source/Core/Core/DSP/Interpreter/DSPIntMisc.cpp b/Source/Core/Core/DSP/Interpreter/DSPIntMisc.cpp
index 2285aec37f..1d566c6a02 100644
--- a/Source/Core/Core/DSP/Interpreter/DSPIntMisc.cpp
+++ b/Source/Core/Core/DSP/Interpreter/DSPIntMisc.cpp
@@ -5,7 +5,6 @@
// Additional copyrights go to Duddie and Tratax (c) 2004
#include "Core/DSP/DSPCore.h"
-#include "Core/DSP/DSPMemoryMap.h"
#include "Core/DSP/DSPTables.h"
#include "Core/DSP/Interpreter/DSPIntUtil.h"
#include "Core/DSP/Interpreter/DSPInterpreter.h"
@@ -15,17 +14,17 @@ namespace DSP::Interpreter
// MRR $D, $S
// 0001 11dd ddds ssss
// Move value from register $S to register $D.
-void mrr(const UDSPInstruction opc)
+void Interpreter::mrr(const UDSPInstruction opc)
{
- u8 sreg = opc & 0x1f;
- u8 dreg = (opc >> 5) & 0x1f;
+ const u8 sreg = opc & 0x1f;
+ const u8 dreg = (opc >> 5) & 0x1f;
if (sreg >= DSP_REG_ACM0)
- dsp_op_write_reg(dreg, dsp_op_read_reg_and_saturate(sreg - DSP_REG_ACM0));
+ OpWriteRegister(dreg, OpReadRegisterAndSaturate(sreg - DSP_REG_ACM0));
else
- dsp_op_write_reg(dreg, dsp_op_read_reg(sreg));
+ OpWriteRegister(dreg, OpReadRegister(sreg));
- dsp_conditional_extend_accum(dreg);
+ ConditionalExtendAccum(dreg);
}
// LRI $D, #I
@@ -37,23 +36,26 @@ void mrr(const UDSPInstruction opc)
// register, has a different behaviour in S40 mode if loaded to AC0.M: The
// value gets sign extended to the whole accumulator! This does not happen in
// S16 mode.
-void lri(const UDSPInstruction opc)
+void Interpreter::lri(const UDSPInstruction opc)
{
- u8 reg = opc & 0x1F;
- u16 imm = dsp_fetch_code();
- dsp_op_write_reg(reg, imm);
- dsp_conditional_extend_accum(reg);
+ auto& state = m_dsp_core.DSPState();
+ const u8 reg = opc & 0x1F;
+ const u16 imm = state.FetchInstruction();
+
+ OpWriteRegister(reg, imm);
+ ConditionalExtendAccum(reg);
}
// LRIS $(0x18+D), #I
// 0000 1ddd iiii iiii
// Load immediate value I (8-bit sign extended) to accumulator register.
-void lris(const UDSPInstruction opc)
+void Interpreter::lris(const UDSPInstruction opc)
{
- u8 reg = ((opc >> 8) & 0x7) + DSP_REG_AXL0;
- u16 imm = (s8)opc;
- dsp_op_write_reg(reg, imm);
- dsp_conditional_extend_accum(reg);
+ const u8 reg = ((opc >> 8) & 0x7) + DSP_REG_AXL0;
+ const u16 imm = static_cast<u16>(static_cast<s8>(opc));
+
+ OpWriteRegister(reg, imm);
+ ConditionalExtendAccum(reg);
}
//----
@@ -63,7 +65,7 @@ void lris(const UDSPInstruction opc)
// No operation, but can be extended with extended opcode.
// This opcode is supposed to do nothing - it's used if you want to use
// an opcode extension but not do anything. At least according to duddie.
-void nx(const UDSPInstruction opc)
+void Interpreter::nx(const UDSPInstruction)
{
ZeroWriteBackLog();
}
@@ -73,38 +75,48 @@ void nx(const UDSPInstruction opc)
// DAR $arD
// 0000 0000 0000 01dd
// Decrement address register $arD.
-void dar(const UDSPInstruction opc)
+void Interpreter::dar(const UDSPInstruction opc)
{
- g_dsp.r.ar[opc & 0x3] = dsp_decrement_addr_reg(opc & 0x3);
+ auto& state = m_dsp_core.DSPState();
+ const u16 index = opc & 3;
+
+ state.r.ar[index] = DecrementAddressRegister(index);
}
// IAR $arD
// 0000 0000 0000 10dd
// Increment address register $arD.
-void iar(const UDSPInstruction opc)
+void Interpreter::iar(const UDSPInstruction opc)
{
- g_dsp.r.ar[opc & 0x3] = dsp_increment_addr_reg(opc & 0x3);
+ auto& state = m_dsp_core.DSPState();
+ const u16 index = opc & 3;
+
+ state.r.ar[index] = IncrementAddressRegister(index);
}
// SUBARN $arD
// 0000 0000 0000 11dd
// Subtract indexing register $ixD from an addressing register $arD.
// used only in IPL-NTSC ucode
-void subarn(const UDSPInstruction opc)
+void Interpreter::subarn(const UDSPInstruction opc)
{
- u8 dreg = opc & 0x3;
- g_dsp.r.ar[dreg] = dsp_decrease_addr_reg(dreg, (s16)g_dsp.r.ix[dreg]);
+ auto& state = m_dsp_core.DSPState();
+ const u8 dreg = opc & 0x3;
+
+ state.r.ar[dreg] = DecreaseAddressRegister(dreg, static_cast<s16>(state.r.ix[dreg]));
}
// ADDARN $arD, $ixS
// 0000 0000 0001 ssdd
// Adds indexing register $ixS to an addressing register $arD.
// It is critical for the Zelda ucode that this one wraps correctly.
-void addarn(const UDSPInstruction opc)
+void Interpreter::addarn(const UDSPInstruction opc)
{
- u8 dreg = opc & 0x3;
- u8 sreg = (opc >> 2) & 0x3;
- g_dsp.r.ar[dreg] = dsp_increase_addr_reg(dreg, (s16)g_dsp.r.ix[sreg]);
+ auto& state = m_dsp_core.DSPState();
+ const u8 dreg = opc & 0x3;
+ const u8 sreg = (opc >> 2) & 0x3;
+
+ state.r.ar[dreg] = IncreaseAddressRegister(dreg, static_cast<s16>(state.r.ix[sreg]));
}
//----
@@ -113,45 +125,51 @@ void addarn(const UDSPInstruction opc)
// 0001 0010 aaaa aiii
// bit of status register $sr. Bit number is calculated by adding 6 to
// immediate value I.
-void sbclr(const UDSPInstruction opc)
+void Interpreter::sbclr(const UDSPInstruction opc)
{
- u8 bit = (opc & 0x7) + 6;
- g_dsp.r.sr &= ~(1 << bit);
+ auto& state = m_dsp_core.DSPState();
+ const u8 bit = (opc & 0x7) + 6;
+
+ state.r.sr &= ~(1U << bit);
}
// SBSET #I
// 0001 0011 aaaa aiii
// Set bit of status register $sr. Bit number is calculated by adding 6 to
// immediate value I.
-void sbset(const UDSPInstruction opc)
+void Interpreter::sbset(const UDSPInstruction opc)
{
- u8 bit = (opc & 0x7) + 6;
- g_dsp.r.sr |= (1 << bit);
+ auto& state = m_dsp_core.DSPState();
+ const u8 bit = (opc & 0x7) + 6;
+
+ state.r.sr |= (1U << bit);
}
// This is a bunch of flag setters, flipping bits in SR.
-void srbith(const UDSPInstruction opc)
+void Interpreter::srbith(const UDSPInstruction opc)
{
+ auto& state = m_dsp_core.DSPState();
+
ZeroWriteBackLog();
switch ((opc >> 8) & 0x7)
{
case 2: // M2
- g_dsp.r.sr &= ~SR_MUL_MODIFY;
+ state.r.sr &= ~SR_MUL_MODIFY;
break;
case 3: // M0
- g_dsp.r.sr |= SR_MUL_MODIFY;
+ state.r.sr |= SR_MUL_MODIFY;
break;
case 4: // CLR15
- g_dsp.r.sr &= ~SR_MUL_UNSIGNED;
+ state.r.sr &= ~SR_MUL_UNSIGNED;
break;
case 5: // SET15
- g_dsp.r.sr |= SR_MUL_UNSIGNED;
+ state.r.sr |= SR_MUL_UNSIGNED;
break;
case 6: // SET16 (CLR40)
- g_dsp.r.sr &= ~SR_40_MODE_BIT;
+ state.r.sr &= ~SR_40_MODE_BIT;
break;
case 7: // SET40
- g_dsp.r.sr |= SR_40_MODE_BIT;
+ state.r.sr |= SR_40_MODE_BIT;
break;
default:
break;
diff --git a/Source/Core/Core/DSP/Interpreter/DSPIntMultiplier.cpp b/Source/Core/Core/DSP/Interpreter/DSPIntMultiplier.cpp
index e30b5fefa0..fe225dc758 100644
--- a/Source/Core/Core/DSP/Interpreter/DSPIntMultiplier.cpp
+++ b/Source/Core/Core/DSP/Interpreter/DSPIntMultiplier.cpp
@@ -13,62 +13,6 @@
namespace DSP::Interpreter
{
-namespace
-{
-// Only MULX family instructions have unsigned/mixed support.
-s64 dsp_get_multiply_prod(u16 a, u16 b, u8 sign)
-{
- s64 prod;
-
- if ((sign == 1) && (g_dsp.r.sr & SR_MUL_UNSIGNED)) // unsigned
- prod = (u32)(a * b);
- else if ((sign == 2) && (g_dsp.r.sr & SR_MUL_UNSIGNED)) // mixed
- prod = a * (s16)b;
- else
- prod = (s16)a * (s16)b; // signed
-
- // Conditionally multiply by 2.
- if ((g_dsp.r.sr & SR_MUL_MODIFY) == 0)
- prod <<= 1;
-
- return prod;
-}
-
-s64 dsp_multiply(u16 a, u16 b, u8 sign = 0)
-{
- s64 prod = dsp_get_multiply_prod(a, b, sign);
- return prod;
-}
-
-s64 dsp_multiply_add(u16 a, u16 b, u8 sign = 0)
-{
- s64 prod = dsp_get_long_prod() + dsp_get_multiply_prod(a, b, sign);
- return prod;
-}
-
-s64 dsp_multiply_sub(u16 a, u16 b, u8 sign = 0)
-{
- s64 prod = dsp_get_long_prod() - dsp_get_multiply_prod(a, b, sign);
- return prod;
-}
-
-s64 dsp_multiply_mulx(u8 axh0, u8 axh1, u16 val1, u16 val2)
-{
- s64 result;
-
- if ((axh0 == 0) && (axh1 == 0))
- result = dsp_multiply(val1, val2, 1); // unsigned support ON if both ax?.l regs are used
- else if ((axh0 == 0) && (axh1 == 1))
- result = dsp_multiply(val1, val2, 2); // mixed support ON (u16)axl.0 * (s16)axh.1
- else if ((axh0 == 1) && (axh1 == 0))
- result = dsp_multiply(val2, val1, 2); // mixed support ON (u16)axl.1 * (s16)axh.0
- else
- result = dsp_multiply(val1, val2, 0); // unsigned support OFF if both ax?.h regs are used
-
- return result;
-}
-} // Anonymous namespace
-
// CLRP
// 1000 0100 xxxx xxxx
// Clears product register $prod.
@@ -78,14 +22,15 @@ s64 dsp_multiply_mulx(u8 axh0, u8 axh1, u16 val1, u16 val2)
//
// It's not ok, to just zero all of them, correct values should be set because of
// direct use of prod regs by AX/AXWII (look @that part of ucode).
-void clrp(const UDSPInstruction opc)
+void Interpreter::clrp(const UDSPInstruction)
{
ZeroWriteBackLog();
- g_dsp.r.prod.l = 0x0000;
- g_dsp.r.prod.m = 0xfff0;
- g_dsp.r.prod.h = 0x00ff;
- g_dsp.r.prod.m2 = 0x0010;
+ auto& state = m_dsp_core.DSPState();
+ state.r.prod.l = 0x0000;
+ state.r.prod.m = 0xfff0;
+ state.r.prod.h = 0x00ff;
+ state.r.prod.m2 = 0x0010;
}
// TSTPROD
@@ -93,10 +38,10 @@ void clrp(const UDSPInstruction opc)
// Test prod regs value.
//
// flags out: --xx xx0x
-void tstprod(const UDSPInstruction opc)
+void Interpreter::tstprod(const UDSPInstruction)
{
- s64 prod = dsp_get_long_prod();
- Update_SR_Register64(prod);
+ const s64 prod = GetLongProduct();
+ UpdateSR64(prod);
ZeroWriteBackLog();
}
@@ -107,16 +52,15 @@ void tstprod(const UDSPInstruction opc)
// Moves multiply product from $prod register to accumulator $acD register.
//
// flags out: --xx xx0x
-void movp(const UDSPInstruction opc)
+void Interpreter::movp(const UDSPInstruction opc)
{
- u8 dreg = (opc >> 8) & 0x1;
-
- s64 acc = dsp_get_long_prod();
+ const u8 dreg = (opc >> 8) & 0x1;
+ const s64 acc = GetLongProduct();
ZeroWriteBackLog();
- dsp_set_long_acc(dreg, acc);
- Update_SR_Register64(acc);
+ SetLongAcc(dreg, acc);
+ UpdateSR64(acc);
}
// MOVNP $acD
@@ -125,16 +69,15 @@ void movp(const UDSPInstruction opc)
// $acD register.
//
// flags out: --xx xx0x
-void movnp(const UDSPInstruction opc)
+void Interpreter::movnp(const UDSPInstruction opc)
{
- u8 dreg = (opc >> 8) & 0x1;
-
- s64 acc = -dsp_get_long_prod();
+ const u8 dreg = (opc >> 8) & 0x1;
+ const s64 acc = -GetLongProduct();
ZeroWriteBackLog();
- dsp_set_long_acc(dreg, acc);
- Update_SR_Register64(acc);
+ SetLongAcc(dreg, acc);
+ UpdateSR64(acc);
}
// MOVPZ $acD
@@ -143,16 +86,15 @@ void movnp(const UDSPInstruction opc)
// register and sets (rounds) $acD.l to 0
//
// flags out: --xx xx0x
-void movpz(const UDSPInstruction opc)
+void Interpreter::movpz(const UDSPInstruction opc)
{
- u8 dreg = (opc >> 8) & 0x01;
-
- s64 acc = dsp_get_long_prod_round_prodl();
+ const u8 dreg = (opc >> 8) & 0x01;
+ const s64 acc = GetLongProductRounded();
ZeroWriteBackLog();
- dsp_set_long_acc(dreg, acc);
- Update_SR_Register64(acc);
+ SetLongAcc(dreg, acc);
+ UpdateSR64(acc);
}
// ADDPAXZ $acD, $axS
@@ -162,21 +104,21 @@ void movpz(const UDSPInstruction opc)
//
// TODO: ugly code and still small error here (+/- 1 in .m - randomly)
// flags out: --xx xx0x
-void addpaxz(const UDSPInstruction opc)
+void Interpreter::addpaxz(const UDSPInstruction opc)
{
- u8 dreg = (opc >> 8) & 0x1;
- u8 sreg = (opc >> 9) & 0x1;
+ const u8 dreg = (opc >> 8) & 0x1;
+ const u8 sreg = (opc >> 9) & 0x1;
- s64 oldprod = dsp_get_long_prod();
- s64 prod = dsp_get_long_prod_round_prodl();
- s64 ax = dsp_get_long_acx(sreg);
+ const s64 oldprod = GetLongProduct();
+ const s64 prod = GetLongProductRounded();
+ const s64 ax = GetLongACX(sreg);
s64 res = prod + (ax & ~0xffff);
ZeroWriteBackLog();
- dsp_set_long_acc(dreg, res);
- res = dsp_get_long_acc(dreg);
- Update_SR_Register64(res, isCarry(oldprod, res), false);
+ SetLongAcc(dreg, res);
+ res = GetLongAcc(dreg);
+ UpdateSR64(res, isCarry(oldprod, res), false);
}
//----
@@ -184,13 +126,14 @@ void addpaxz(const UDSPInstruction opc)
// MULAXH
// 1000 0011 xxxx xxxx
// Multiply $ax0.h by $ax0.h
-void mulaxh(const UDSPInstruction opc)
+void Interpreter::mulaxh(const UDSPInstruction)
{
- s64 prod = dsp_multiply(dsp_get_ax_h(0), dsp_get_ax_h(0));
+ const s16 value = GetAXHigh(0);
+ const s64 prod = Multiply(value, value);
ZeroWriteBackLog();
- dsp_set_long_prod(prod);
+ SetLongProduct(prod);
}
//----
@@ -199,17 +142,16 @@ void mulaxh(const UDSPInstruction opc)
// 1001 s000 xxxx xxxx
// Multiply low part $axS.l of secondary accumulator $axS by high part
// $axS.h of secondary accumulator $axS (treat them both as signed).
-void mul(const UDSPInstruction opc)
+void Interpreter::mul(const UDSPInstruction opc)
{
- u8 sreg = (opc >> 11) & 0x1;
-
- u16 axl = dsp_get_ax_l(sreg);
- u16 axh = dsp_get_ax_h(sreg);
- s64 prod = dsp_multiply(axh, axl);
+ const u8 sreg = (opc >> 11) & 0x1;
+ const u16 axl = GetAXLow(sreg);
+ const u16 axh = GetAXHigh(sreg);
+ const s64 prod = Multiply(axh, axl);
ZeroWriteBackLog();
- dsp_set_long_prod(prod);
+ SetLongProduct(prod);
}
// MULAC $axS.l, $axS.h, $acR
@@ -219,21 +161,21 @@ void mul(const UDSPInstruction opc)
// accumulator $axS (treat them both as signed).
//
// flags out: --xx xx0x
-void mulac(const UDSPInstruction opc)
+void Interpreter::mulac(const UDSPInstruction opc)
{
- u8 rreg = (opc >> 8) & 0x1;
- u8 sreg = (opc >> 11) & 0x1;
+ const u8 rreg = (opc >> 8) & 0x1;
+ const u8 sreg = (opc >> 11) & 0x1;
- s64 acc = dsp_get_long_acc(rreg) + dsp_get_long_prod();
- u16 axl = dsp_get_ax_l(sreg);
- u16 axh = dsp_get_ax_h(sreg);
- s64 prod = dsp_multiply(axl, axh);
+ const s64 acc = GetLongAcc(rreg) + GetLongProduct();
+ const u16 axl = GetAXLow(sreg);
+ const u16 axh = GetAXHigh(sreg);
+ const s64 prod = Multiply(axl, axh);
ZeroWriteBackLog();
- dsp_set_long_prod(prod);
- dsp_set_long_acc(rreg, acc);
- Update_SR_Register64(dsp_get_long_acc(rreg));
+ SetLongProduct(prod);
+ SetLongAcc(rreg, acc);
+ UpdateSR64(GetLongAcc(rreg));
}
// MULMV $axS.l, $axS.h, $acR
@@ -243,21 +185,21 @@ void mulac(const UDSPInstruction opc)
// accumulator $axS (treat them both as signed).
//
// flags out: --xx xx0x
-void mulmv(const UDSPInstruction opc)
+void Interpreter::mulmv(const UDSPInstruction opc)
{
- u8 rreg = (opc >> 8) & 0x1;
- u8 sreg = ((opc >> 11) & 0x1);
+ const u8 rreg = (opc >> 8) & 0x1;
+ const u8 sreg = ((opc >> 11) & 0x1);
- s64 acc = dsp_get_long_prod();
- u16 axl = dsp_get_ax_l(sreg);
- u16 axh = dsp_get_ax_h(sreg);
- s64 prod = dsp_multiply(axl, axh);
+ const s64 acc = GetLongProduct();
+ const u16 axl = GetAXLow(sreg);
+ const u16 axh = GetAXHigh(sreg);
+ const s64 prod = Multiply(axl, axh);
ZeroWriteBackLog();
- dsp_set_long_prod(prod);
- dsp_set_long_acc(rreg, acc);
- Update_SR_Register64(dsp_get_long_acc(rreg));
+ SetLongProduct(prod);
+ SetLongAcc(rreg, acc);
+ UpdateSR64(GetLongAcc(rreg));
}
// MULMVZ $axS.l, $axS.h, $acR
@@ -268,21 +210,21 @@ void mulmv(const UDSPInstruction opc)
// them both as signed).
//
// flags out: --xx xx0x
-void mulmvz(const UDSPInstruction opc)
+void Interpreter::mulmvz(const UDSPInstruction opc)
{
- u8 rreg = (opc >> 8) & 0x1;
- u8 sreg = (opc >> 11) & 0x1;
+ const u8 rreg = (opc >> 8) & 0x1;
+ const u8 sreg = (opc >> 11) & 0x1;
- s64 acc = dsp_get_long_prod_round_prodl();
- u16 axl = dsp_get_ax_l(sreg);
- u16 axh = dsp_get_ax_h(sreg);
- s64 prod = dsp_multiply(axl, axh);
+ const s64 acc = GetLongProductRounded();
+ const u16 axl = GetAXLow(sreg);
+ const u16 axh = GetAXHigh(sreg);
+ const s64 prod = Multiply(axl, axh);
ZeroWriteBackLog();
- dsp_set_long_prod(prod);
- dsp_set_long_acc(rreg, acc);
- Update_SR_Register64(dsp_get_long_acc(rreg));
+ SetLongProduct(prod);
+ SetLongAcc(rreg, acc);
+ UpdateSR64(GetLongAcc(rreg));
}
//----
@@ -291,18 +233,18 @@ void mulmvz(const UDSPInstruction opc)
// 101s t000 xxxx xxxx
// Multiply one part $ax0 by one part $ax1.
// Part is selected by S and T bits. Zero selects low part, one selects high part.
-void mulx(const UDSPInstruction opc)
+void Interpreter::mulx(const UDSPInstruction opc)
{
- u8 treg = ((opc >> 11) & 0x1);
- u8 sreg = ((opc >> 12) & 0x1);
+ const u8 treg = ((opc >> 11) & 0x1);
+ const u8 sreg = ((opc >> 12) & 0x1);
- u16 val1 = (sreg == 0) ? dsp_get_ax_l(0) : dsp_get_ax_h(0);
- u16 val2 = (treg == 0) ? dsp_get_ax_l(1) : dsp_get_ax_h(1);
- s64 prod = dsp_multiply_mulx(sreg, treg, val1, val2);
+ const u16 val1 = (sreg == 0) ? GetAXLow(0) : GetAXHigh(0);
+ const u16 val2 = (treg == 0) ? GetAXLow(1) : GetAXHigh(1);
+ const s64 prod = MultiplyMulX(sreg, treg, val1, val2);
ZeroWriteBackLog();
- dsp_set_long_prod(prod);
+ SetLongProduct(prod);
}
// MULXAC $ax0.S, $ax1.T, $acR
@@ -312,22 +254,22 @@ void mulx(const UDSPInstruction opc)
// T bits. Zero selects low part, one selects high part.
//
// flags out: --xx xx0x
-void mulxac(const UDSPInstruction opc)
+void Interpreter::mulxac(const UDSPInstruction opc)
{
- u8 rreg = (opc >> 8) & 0x1;
- u8 treg = (opc >> 11) & 0x1;
- u8 sreg = (opc >> 12) & 0x1;
+ const u8 rreg = (opc >> 8) & 0x1;
+ const u8 treg = (opc >> 11) & 0x1;
+ const u8 sreg = (opc >> 12) & 0x1;
- s64 acc = dsp_get_long_acc(rreg) + dsp_get_long_prod();
- u16 val1 = (sreg == 0) ? dsp_get_ax_l(0) : dsp_get_ax_h(0);
- u16 val2 = (treg == 0) ? dsp_get_ax_l(1) : dsp_get_ax_h(1);
- s64 prod = dsp_multiply_mulx(sreg, treg, val1, val2);
+ const s64 acc = GetLongAcc(rreg) + GetLongProduct();
+ const u16 val1 = (sreg == 0) ? GetAXLow(0) : GetAXHigh(0);
+ const u16 val2 = (treg == 0) ? GetAXLow(1) : GetAXHigh(1);
+ const s64 prod = MultiplyMulX(sreg, treg, val1, val2);
ZeroWriteBackLog();
- dsp_set_long_prod(prod);
- dsp_set_long_acc(rreg, acc);
- Update_SR_Register64(dsp_get_long_acc(rreg));
+ SetLongProduct(prod);
+ SetLongAcc(rreg, acc);
+ UpdateSR64(GetLongAcc(rreg));
}
// MULXMV $ax0.S, $ax1.T, $acR
@@ -337,22 +279,22 @@ void mulxac(const UDSPInstruction opc)
// T bits. Zero selects low part, one selects high part.
//
// flags out: --xx xx0x
-void mulxmv(const UDSPInstruction opc)
+void Interpreter::mulxmv(const UDSPInstruction opc)
{
- u8 rreg = ((opc >> 8) & 0x1);
- u8 treg = (opc >> 11) & 0x1;
- u8 sreg = (opc >> 12) & 0x1;
+ const u8 rreg = ((opc >> 8) & 0x1);
+ const u8 treg = (opc >> 11) & 0x1;
+ const u8 sreg = (opc >> 12) & 0x1;
- s64 acc = dsp_get_long_prod();
- u16 val1 = (sreg == 0) ? dsp_get_ax_l(0) : dsp_get_ax_h(0);
- u16 val2 = (treg == 0) ? dsp_get_ax_l(1) : dsp_get_ax_h(1);
- s64 prod = dsp_multiply_mulx(sreg, treg, val1, val2);
+ const s64 acc = GetLongProduct();
+ const u16 val1 = (sreg == 0) ? GetAXLow(0) : GetAXHigh(0);
+ const u16 val2 = (treg == 0) ? GetAXLow(1) : GetAXHigh(1);
+ const s64 prod = MultiplyMulX(sreg, treg, val1, val2);
ZeroWriteBackLog();
- dsp_set_long_prod(prod);
- dsp_set_long_acc(rreg, acc);
- Update_SR_Register64(dsp_get_long_acc(rreg));
+ SetLongProduct(prod);
+ SetLongAcc(rreg, acc);
+ UpdateSR64(GetLongAcc(rreg));
}
// MULXMVZ $ax0.S, $ax1.T, $acR
@@ -363,22 +305,22 @@ void mulxmv(const UDSPInstruction opc)
// one selects high part.
//
// flags out: --xx xx0x
-void mulxmvz(const UDSPInstruction opc)
+void Interpreter::mulxmvz(const UDSPInstruction opc)
{
- u8 rreg = (opc >> 8) & 0x1;
- u8 treg = (opc >> 11) & 0x1;
- u8 sreg = (opc >> 12) & 0x1;
+ const u8 rreg = (opc >> 8) & 0x1;
+ const u8 treg = (opc >> 11) & 0x1;
+ const u8 sreg = (opc >> 12) & 0x1;
- s64 acc = dsp_get_long_prod_round_prodl();
- u16 val1 = (sreg == 0) ? dsp_get_ax_l(0) : dsp_get_ax_h(0);
- u16 val2 = (treg == 0) ? dsp_get_ax_l(1) : dsp_get_ax_h(1);
- s64 prod = dsp_multiply_mulx(sreg, treg, val1, val2);
+ const s64 acc = GetLongProductRounded();
+ const u16 val1 = (sreg == 0) ? GetAXLow(0) : GetAXHigh(0);
+ const u16 val2 = (treg == 0) ? GetAXLow(1) : GetAXHigh(1);
+ const s64 prod = MultiplyMulX(sreg, treg, val1, val2);
ZeroWriteBackLog();
- dsp_set_long_prod(prod);
- dsp_set_long_acc(rreg, acc);
- Update_SR_Register64(dsp_get_long_acc(rreg));
+ SetLongProduct(prod);
+ SetLongAcc(rreg, acc);
+ UpdateSR64(GetLongAcc(rreg));
}
//----
@@ -387,18 +329,18 @@ void mulxmvz(const UDSPInstruction opc)
// 110s t000 xxxx xxxx
// Multiply mid part of accumulator register $acS.m by high part $axS.h of
// secondary accumulator $axS (treat them both as signed).
-void mulc(const UDSPInstruction opc)
+void Interpreter::mulc(const UDSPInstruction opc)
{
- u8 treg = (opc >> 11) & 0x1;
- u8 sreg = (opc >> 12) & 0x1;
+ const u8 treg = (opc >> 11) & 0x1;
+ const u8 sreg = (opc >> 12) & 0x1;
- u16 accm = dsp_get_acc_m(sreg);
- u16 axh = dsp_get_ax_h(treg);
- s64 prod = dsp_multiply(accm, axh);
+ const u16 accm = GetAccMid(sreg);
+ const u16 axh = GetAXHigh(treg);
+ const s64 prod = Multiply(accm, axh);
ZeroWriteBackLog();
- dsp_set_long_prod(prod);
+ SetLongProduct(prod);
}
// MULCAC $acS.m, $axT.h, $acR
@@ -408,22 +350,22 @@ void mulc(const UDSPInstruction opc)
// register before multiplication to accumulator $acR.
//
// flags out: --xx xx0x
-void mulcac(const UDSPInstruction opc)
+void Interpreter::mulcac(const UDSPInstruction opc)
{
- u8 rreg = (opc >> 8) & 0x1;
- u8 treg = (opc >> 11) & 0x1;
- u8 sreg = (opc >> 12) & 0x1;
+ const u8 rreg = (opc >> 8) & 0x1;
+ const u8 treg = (opc >> 11) & 0x1;
+ const u8 sreg = (opc >> 12) & 0x1;
- s64 acc = dsp_get_long_acc(rreg) + dsp_get_long_prod();
- u16 accm = dsp_get_acc_m(sreg);
- u16 axh = dsp_get_ax_h(treg);
- s64 prod = dsp_multiply(accm, axh);
+ const s64 acc = GetLongAcc(rreg) + GetLongProduct();
+ const u16 accm = GetAccMid(sreg);
+ const u16 axh = GetAXHigh(treg);
+ const s64 prod = Multiply(accm, axh);
ZeroWriteBackLog();
- dsp_set_long_prod(prod);
- dsp_set_long_acc(rreg, acc);
- Update_SR_Register64(dsp_get_long_acc(rreg));
+ SetLongProduct(prod);
+ SetLongAcc(rreg, acc);
+ UpdateSR64(GetLongAcc(rreg));
}
// MULCMV $acS.m, $axT.h, $acR
@@ -434,22 +376,22 @@ void mulcac(const UDSPInstruction opc)
// possible mistake in duddie's doc axT.h rather than axS.h
//
// flags out: --xx xx0x
-void mulcmv(const UDSPInstruction opc)
+void Interpreter::mulcmv(const UDSPInstruction opc)
{
- u8 rreg = (opc >> 8) & 0x1;
- u8 treg = (opc >> 11) & 0x1;
- u8 sreg = (opc >> 12) & 0x1;
+ const u8 rreg = (opc >> 8) & 0x1;
+ const u8 treg = (opc >> 11) & 0x1;
+ const u8 sreg = (opc >> 12) & 0x1;
- s64 acc = dsp_get_long_prod();
- u16 accm = dsp_get_acc_m(sreg);
- u16 axh = dsp_get_ax_h(treg);
- s64 prod = dsp_multiply(accm, axh);
+ const s64 acc = GetLongProduct();
+ const u16 accm = GetAccMid(sreg);
+ const u16 axh = GetAXHigh(treg);
+ const s64 prod = Multiply(accm, axh);
ZeroWriteBackLog();
- dsp_set_long_prod(prod);
- dsp_set_long_acc(rreg, acc);
- Update_SR_Register64(dsp_get_long_acc(rreg));
+ SetLongProduct(prod);
+ SetLongAcc(rreg, acc);
+ UpdateSR64(GetLongAcc(rreg));
}
// MULCMVZ $acS.m, $axT.h, $acR
@@ -461,22 +403,22 @@ void mulcmv(const UDSPInstruction opc)
// accumulator $acR.l to zero.
//
// flags out: --xx xx0x
-void mulcmvz(const UDSPInstruction opc)
+void Interpreter::mulcmvz(const UDSPInstruction opc)
{
- u8 rreg = (opc >> 8) & 0x1;
- u8 treg = (opc >> 11) & 0x1;
- u8 sreg = (opc >> 12) & 0x1;
+ const u8 rreg = (opc >> 8) & 0x1;
+ const u8 treg = (opc >> 11) & 0x1;
+ const u8 sreg = (opc >> 12) & 0x1;
- s64 acc = dsp_get_long_prod_round_prodl();
- u16 accm = dsp_get_acc_m(sreg);
- u16 axh = dsp_get_ax_h(treg);
- s64 prod = dsp_multiply(accm, axh);
+ const s64 acc = GetLongProductRounded();
+ const u16 accm = GetAccMid(sreg);
+ const u16 axh = GetAXHigh(treg);
+ const s64 prod = Multiply(accm, axh);
ZeroWriteBackLog();
- dsp_set_long_prod(prod);
- dsp_set_long_acc(rreg, acc);
- Update_SR_Register64(dsp_get_long_acc(rreg));
+ SetLongProduct(prod);
+ SetLongAcc(rreg, acc);
+ UpdateSR64(GetLongAcc(rreg));
}
//----
@@ -486,18 +428,18 @@ void mulcmvz(const UDSPInstruction opc)
// Multiply one part of secondary accumulator $ax0 (selected by S) by
// one part of secondary accumulator $ax1 (selected by T) (treat them both as
// signed) and add result to product register.
-void maddx(const UDSPInstruction opc)
+void Interpreter::maddx(const UDSPInstruction opc)
{
- u8 treg = (opc >> 8) & 0x1;
- u8 sreg = (opc >> 9) & 0x1;
+ const u8 treg = (opc >> 8) & 0x1;
+ const u8 sreg = (opc >> 9) & 0x1;
- u16 val1 = (sreg == 0) ? dsp_get_ax_l(0) : dsp_get_ax_h(0);
- u16 val2 = (treg == 0) ? dsp_get_ax_l(1) : dsp_get_ax_h(1);
- s64 prod = dsp_multiply_add(val1, val2);
+ const u16 val1 = (sreg == 0) ? GetAXLow(0) : GetAXHigh(0);
+ const u16 val2 = (treg == 0) ? GetAXLow(1) : GetAXHigh(1);
+ const s64 prod = MultiplyAdd(val1, val2);
ZeroWriteBackLog();
- dsp_set_long_prod(prod);
+ SetLongProduct(prod);
}
// MSUBX $(0x18+S*2), $(0x19+T*2)
@@ -505,18 +447,18 @@ void maddx(const UDSPInstruction opc)
// Multiply one part of secondary accumulator $ax0 (selected by S) by
// one part of secondary accumulator $ax1 (selected by T) (treat them both as
// signed) and subtract result from product register.
-void msubx(const UDSPInstruction opc)
+void Interpreter::msubx(const UDSPInstruction opc)
{
- u8 treg = (opc >> 8) & 0x1;
- u8 sreg = (opc >> 9) & 0x1;
+ const u8 treg = (opc >> 8) & 0x1;
+ const u8 sreg = (opc >> 9) & 0x1;
- u16 val1 = (sreg == 0) ? dsp_get_ax_l(0) : dsp_get_ax_h(0);
- u16 val2 = (treg == 0) ? dsp_get_ax_l(1) : dsp_get_ax_h(1);
- s64 prod = dsp_multiply_sub(val1, val2);
+ const u16 val1 = (sreg == 0) ? GetAXLow(0) : GetAXHigh(0);
+ const u16 val2 = (treg == 0) ? GetAXLow(1) : GetAXHigh(1);
+ const s64 prod = MultiplySub(val1, val2);
ZeroWriteBackLog();
- dsp_set_long_prod(prod);
+ SetLongProduct(prod);
}
// MADDC $acS.m, $axT.h
@@ -524,18 +466,18 @@ void msubx(const UDSPInstruction opc)
// Multiply middle part of accumulator $acS.m by high part of secondary
// accumulator $axT.h (treat them both as signed) and add result to product
// register.
-void maddc(const UDSPInstruction opc)
+void Interpreter::maddc(const UDSPInstruction opc)
{
- u8 treg = (opc >> 8) & 0x1;
- u8 sreg = (opc >> 9) & 0x1;
+ const u8 treg = (opc >> 8) & 0x1;
+ const u8 sreg = (opc >> 9) & 0x1;
- u16 accm = dsp_get_acc_m(sreg);
- u16 axh = dsp_get_ax_h(treg);
- s64 prod = dsp_multiply_add(accm, axh);
+ const u16 accm = GetAccMid(sreg);
+ const u16 axh = GetAXHigh(treg);
+ const s64 prod = MultiplyAdd(accm, axh);
ZeroWriteBackLog();
- dsp_set_long_prod(prod);
+ SetLongProduct(prod);
}
// MSUBC $acS.m, $axT.h
@@ -543,18 +485,18 @@ void maddc(const UDSPInstruction opc)
// Multiply middle part of accumulator $acS.m by high part of secondary
// accumulator $axT.h (treat them both as signed) and subtract result from
// product register.
-void msubc(const UDSPInstruction opc)
+void Interpreter::msubc(const UDSPInstruction opc)
{
- u8 treg = (opc >> 8) & 0x1;
- u8 sreg = (opc >> 9) & 0x1;
+ const u8 treg = (opc >> 8) & 0x1;
+ const u8 sreg = (opc >> 9) & 0x1;
- u16 accm = dsp_get_acc_m(sreg);
- u16 axh = dsp_get_ax_h(treg);
- s64 prod = dsp_multiply_sub(accm, axh);
+ const u16 accm = GetAccMid(sreg);
+ const u16 axh = GetAXHigh(treg);
+ const s64 prod = MultiplySub(accm, axh);
ZeroWriteBackLog();
- dsp_set_long_prod(prod);
+ SetLongProduct(prod);
}
// MADD $axS.l, $axS.h
@@ -562,17 +504,16 @@ void msubc(const UDSPInstruction opc)
// Multiply low part $axS.l of secondary accumulator $axS by high part
// $axS.h of secondary accumulator $axS (treat them both as signed) and add
// result to product register.
-void madd(const UDSPInstruction opc)
+void Interpreter::madd(const UDSPInstruction opc)
{
- u8 sreg = (opc >> 8) & 0x1;
-
- u16 axl = dsp_get_ax_l(sreg);
- u16 axh = dsp_get_ax_h(sreg);
- s64 prod = dsp_multiply_add(axl, axh);
+ const u8 sreg = (opc >> 8) & 0x1;
+ const u16 axl = GetAXLow(sreg);
+ const u16 axh = GetAXHigh(sreg);
+ const s64 prod = MultiplyAdd(axl, axh);
ZeroWriteBackLog();
- dsp_set_long_prod(prod);
+ SetLongProduct(prod);
}
// MSUB $axS.l, $axS.h
@@ -580,16 +521,15 @@ void madd(const UDSPInstruction opc)
// Multiply low part $axS.l of secondary accumulator $axS by high part
// $axS.h of secondary accumulator $axS (treat them both as signed) and
// subtract result from product register.
-void msub(const UDSPInstruction opc)
+void Interpreter::msub(const UDSPInstruction opc)
{
- u8 sreg = (opc >> 8) & 0x1;
-
- u16 axl = dsp_get_ax_l(sreg);
- u16 axh = dsp_get_ax_h(sreg);
- s64 prod = dsp_multiply_sub(axl, axh);
+ const u8 sreg = (opc >> 8) & 0x1;
+ const u16 axl = GetAXLow(sreg);
+ const u16 axh = GetAXHigh(sreg);
+ const s64 prod = MultiplySub(axl, axh);
ZeroWriteBackLog();
- dsp_set_long_prod(prod);
+ SetLongProduct(prod);
}
} // namespace DSP::Interpreter
diff --git a/Source/Core/Core/DSP/Interpreter/DSPIntTables.cpp b/Source/Core/Core/DSP/Interpreter/DSPIntTables.cpp
index 32035f9172..1b4e9bb779 100644
--- a/Source/Core/Core/DSP/Interpreter/DSPIntTables.cpp
+++ b/Source/Core/Core/DSP/Interpreter/DSPIntTables.cpp
@@ -8,7 +8,6 @@
#include "Common/CommonTypes.h"
#include "Core/DSP/DSPTables.h"
-#include "Core/DSP/Interpreter/DSPIntExtOps.h"
#include "Core/DSP/Interpreter/DSPInterpreter.h"
namespace DSP::Interpreter
@@ -23,216 +22,216 @@ struct InterpreterOpInfo
// clang-format off
constexpr std::array<InterpreterOpInfo, 124> s_opcodes
{{
- {0x0000, 0xfffc, nop},
+ {0x0000, 0xfffc, &Interpreter::nop},
- {0x0004, 0xfffc, dar},
- {0x0008, 0xfffc, iar},
- {0x000c, 0xfffc, subarn},
- {0x0010, 0xfff0, addarn},
+ {0x0004, 0xfffc, &Interpreter::dar},
+ {0x0008, 0xfffc, &Interpreter::iar},
+ {0x000c, 0xfffc, &Interpreter::subarn},
+ {0x0010, 0xfff0, &Interpreter::addarn},
- {0x0021, 0xffff, halt},
+ {0x0021, 0xffff, &Interpreter::halt},
- {0x02d0, 0xfff0, ret},
+ {0x02d0, 0xfff0, &Interpreter::ret},
- {0x02ff, 0xffff, rti},
+ {0x02ff, 0xffff, &Interpreter::rti},
- {0x02b0, 0xfff0, call},
+ {0x02b0, 0xfff0, &Interpreter::call},
- {0x0270, 0xfff0, ifcc},
+ {0x0270, 0xfff0, &Interpreter::ifcc},
- {0x0290, 0xfff0, jcc},
+ {0x0290, 0xfff0, &Interpreter::jcc},
- {0x1700, 0xff10, jmprcc},
+ {0x1700, 0xff10, &Interpreter::jmprcc},
- {0x1710, 0xff10, callr},
+ {0x1710, 0xff10, &Interpreter::callr},
- {0x1200, 0xff00, sbclr},
- {0x1300, 0xff00, sbset},
+ {0x1200, 0xff00, &Interpreter::sbclr},
+ {0x1300, 0xff00, &Interpreter::sbset},
- {0x1400, 0xfec0, lsl},
- {0x1440, 0xfec0, lsr},
- {0x1480, 0xfec0, asl},
- {0x14c0, 0xfec0, asr},
+ {0x1400, 0xfec0, &Interpreter::lsl},
+ {0x1440, 0xfec0, &Interpreter::lsr},
+ {0x1480, 0xfec0, &Interpreter::asl},
+ {0x14c0, 0xfec0, &Interpreter::asr},
// these two were discovered by ector
- {0x02ca, 0xffff, lsrn},
- {0x02cb, 0xffff, asrn},
+ {0x02ca, 0xffff, &Interpreter::lsrn},
+ {0x02cb, 0xffff, &Interpreter::asrn},
- {0x0080, 0xffe0, lri},
- {0x00c0, 0xffe0, lr},
- {0x00e0, 0xffe0, sr},
+ {0x0080, 0xffe0, &Interpreter::lri},
+ {0x00c0, 0xffe0, &Interpreter::lr},
+ {0x00e0, 0xffe0, &Interpreter::sr},
- {0x1c00, 0xfc00, mrr},
+ {0x1c00, 0xfc00, &Interpreter::mrr},
- {0x1600, 0xff00, si},
+ {0x1600, 0xff00, &Interpreter::si},
- {0x0400, 0xfe00, addis},
- {0x0600, 0xfe00, cmpis},
- {0x0800, 0xf800, lris},
+ {0x0400, 0xfe00, &Interpreter::addis},
+ {0x0600, 0xfe00, &Interpreter::cmpis},
+ {0x0800, 0xf800, &Interpreter::lris},
- {0x0200, 0xfeff, addi},
- {0x0220, 0xfeff, xori},
- {0x0240, 0xfeff, andi},
- {0x0260, 0xfeff, ori},
- {0x0280, 0xfeff, cmpi},
+ {0x0200, 0xfeff, &Interpreter::addi},
+ {0x0220, 0xfeff, &Interpreter::xori},
+ {0x0240, 0xfeff, &Interpreter::andi},
+ {0x0260, 0xfeff, &Interpreter::ori},
+ {0x0280, 0xfeff, &Interpreter::cmpi},
- {0x02a0, 0xfeff, andf},
- {0x02c0, 0xfeff, andcf},
+ {0x02a0, 0xfeff, &Interpreter::andf},
+ {0x02c0, 0xfeff, &Interpreter::andcf},
- {0x0210, 0xfefc, ilrr},
- {0x0214, 0xfefc, ilrrd},
- {0x0218, 0xfefc, ilrri},
- {0x021c, 0xfefc, ilrrn},
+ {0x0210, 0xfefc, &Interpreter::ilrr},
+ {0x0214, 0xfefc, &Interpreter::ilrrd},
+ {0x0218, 0xfefc, &Interpreter::ilrri},
+ {0x021c, 0xfefc, &Interpreter::ilrrn},
// LOOPS
- {0x0040, 0xffe0, loop},
- {0x0060, 0xffe0, bloop},
- {0x1000, 0xff00, loopi},
- {0x1100, 0xff00, bloopi},
+ {0x0040, 0xffe0, &Interpreter::loop},
+ {0x0060, 0xffe0, &Interpreter::bloop},
+ {0x1000, 0xff00, &Interpreter::loopi},
+ {0x1100, 0xff00, &Interpreter::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},
+ {0x1800, 0xff80, &Interpreter::lrr},
+ {0x1880, 0xff80, &Interpreter::lrrd},
+ {0x1900, 0xff80, &Interpreter::lrri},
+ {0x1980, 0xff80, &Interpreter::lrrn},
- {0x1a00, 0xff80, srr},
- {0x1a80, 0xff80, srrd},
- {0x1b00, 0xff80, srri},
- {0x1b80, 0xff80, srrn},
+ {0x1a00, 0xff80, &Interpreter::srr},
+ {0x1a80, 0xff80, &Interpreter::srrd},
+ {0x1b00, 0xff80, &Interpreter::srri},
+ {0x1b80, 0xff80, &Interpreter::srrn},
// 2
- {0x2000, 0xf800, lrs},
- {0x2800, 0xf800, srs},
+ {0x2000, 0xf800, &Interpreter::lrs},
+ {0x2800, 0xf800, &Interpreter::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},
+ {0x3000, 0xfc80, &Interpreter::xorr},
+ {0x3400, 0xfc80, &Interpreter::andr},
+ {0x3800, 0xfc80, &Interpreter::orr},
+ {0x3c00, 0xfe80, &Interpreter::andc},
+ {0x3e00, 0xfe80, &Interpreter::orc},
+ {0x3080, 0xfe80, &Interpreter::xorc},
+ {0x3280, 0xfe80, &Interpreter::notc},
+ {0x3480, 0xfc80, &Interpreter::lsrnrx},
+ {0x3880, 0xfc80, &Interpreter::asrnrx},
+ {0x3c80, 0xfe80, &Interpreter::lsrnr},
+ {0x3e80, 0xfe80, &Interpreter::asrnr},
// 4
- {0x4000, 0xf800, addr},
- {0x4800, 0xfc00, addax},
- {0x4c00, 0xfe00, add},
- {0x4e00, 0xfe00, addp},
+ {0x4000, 0xf800, &Interpreter::addr},
+ {0x4800, 0xfc00, &Interpreter::addax},
+ {0x4c00, 0xfe00, &Interpreter::add},
+ {0x4e00, 0xfe00, &Interpreter::addp},
// 5
- {0x5000, 0xf800, subr},
- {0x5800, 0xfc00, subax},
- {0x5c00, 0xfe00, sub},
- {0x5e00, 0xfe00, subp},
+ {0x5000, 0xf800, &Interpreter::subr},
+ {0x5800, 0xfc00, &Interpreter::subax},
+ {0x5c00, 0xfe00, &Interpreter::sub},
+ {0x5e00, 0xfe00, &Interpreter::subp},
// 6
- {0x6000, 0xf800, movr},
- {0x6800, 0xfc00, movax},
- {0x6c00, 0xfe00, mov},
- {0x6e00, 0xfe00, movp},
+ {0x6000, 0xf800, &Interpreter::movr},
+ {0x6800, 0xfc00, &Interpreter::movax},
+ {0x6c00, 0xfe00, &Interpreter::mov},
+ {0x6e00, 0xfe00, &Interpreter::movp},
// 7
- {0x7000, 0xfc00, addaxl},
- {0x7400, 0xfe00, incm},
- {0x7600, 0xfe00, inc},
- {0x7800, 0xfe00, decm},
- {0x7a00, 0xfe00, dec},
- {0x7c00, 0xfe00, neg},
- {0x7e00, 0xfe00, movnp},
+ {0x7000, 0xfc00, &Interpreter::addaxl},
+ {0x7400, 0xfe00, &Interpreter::incm},
+ {0x7600, 0xfe00, &Interpreter::inc},
+ {0x7800, 0xfe00, &Interpreter::decm},
+ {0x7a00, 0xfe00, &Interpreter::dec},
+ {0x7c00, 0xfe00, &Interpreter::neg},
+ {0x7e00, 0xfe00, &Interpreter::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},
+ {0x8000, 0xf700, &Interpreter::nx},
+ {0x8100, 0xf700, &Interpreter::clr},
+ {0x8200, 0xff00, &Interpreter::cmp},
+ {0x8300, 0xff00, &Interpreter::mulaxh},
+ {0x8400, 0xff00, &Interpreter::clrp},
+ {0x8500, 0xff00, &Interpreter::tstprod},
+ {0x8600, 0xfe00, &Interpreter::tstaxh},
+ {0x8a00, 0xff00, &Interpreter::srbith},
+ {0x8b00, 0xff00, &Interpreter::srbith},
+ {0x8c00, 0xff00, &Interpreter::srbith},
+ {0x8d00, 0xff00, &Interpreter::srbith},
+ {0x8e00, 0xff00, &Interpreter::srbith},
+ {0x8f00, 0xff00, &Interpreter::srbith},
// 9
- {0x9000, 0xf700, mul},
- {0x9100, 0xf700, asr16},
- {0x9200, 0xf600, mulmvz},
- {0x9400, 0xf600, mulac},
- {0x9600, 0xf600, mulmv},
+ {0x9000, 0xf700, &Interpreter::mul},
+ {0x9100, 0xf700, &Interpreter::asr16},
+ {0x9200, 0xf600, &Interpreter::mulmvz},
+ {0x9400, 0xf600, &Interpreter::mulac},
+ {0x9600, 0xf600, &Interpreter::mulmv},
// A-B
- {0xa000, 0xe700, mulx},
- {0xa100, 0xf700, abs},
- {0xa200, 0xe600, mulxmvz},
- {0xa400, 0xe600, mulxac},
- {0xa600, 0xe600, mulxmv},
- {0xb100, 0xf700, tst},
+ {0xa000, 0xe700, &Interpreter::mulx},
+ {0xa100, 0xf700, &Interpreter::abs},
+ {0xa200, 0xe600, &Interpreter::mulxmvz},
+ {0xa400, 0xe600, &Interpreter::mulxac},
+ {0xa600, 0xe600, &Interpreter::mulxmv},
+ {0xb100, 0xf700, &Interpreter::tst},
// C-D
- {0xc000, 0xe700, mulc},
- {0xc100, 0xe700, cmpar},
- {0xc200, 0xe600, mulcmvz},
- {0xc400, 0xe600, mulcac},
- {0xc600, 0xe600, mulcmv},
+ {0xc000, 0xe700, &Interpreter::mulc},
+ {0xc100, 0xe700, &Interpreter::cmpar},
+ {0xc200, 0xe600, &Interpreter::mulcmvz},
+ {0xc400, 0xe600, &Interpreter::mulcac},
+ {0xc600, 0xe600, &Interpreter::mulcmv},
// E
- {0xe000, 0xfc00, maddx},
- {0xe400, 0xfc00, msubx},
- {0xe800, 0xfc00, maddc},
- {0xec00, 0xfc00, msubc},
+ {0xe000, 0xfc00, &Interpreter::maddx},
+ {0xe400, 0xfc00, &Interpreter::msubx},
+ {0xe800, 0xfc00, &Interpreter::maddc},
+ {0xec00, 0xfc00, &Interpreter::msubc},
// F
- {0xf000, 0xfe00, lsl16},
- {0xf200, 0xfe00, madd},
- {0xf400, 0xfe00, lsr16},
- {0xf600, 0xfe00, msub},
- {0xf800, 0xfc00, addpaxz},
- {0xfc00, 0xfe00, clrl},
- {0xfe00, 0xfe00, movpz},
+ {0xf000, 0xfe00, &Interpreter::lsl16},
+ {0xf200, 0xfe00, &Interpreter::madd},
+ {0xf400, 0xfe00, &Interpreter::lsr16},
+ {0xf600, 0xfe00, &Interpreter::msub},
+ {0xf800, 0xfc00, &Interpreter::addpaxz},
+ {0xfc00, 0xfe00, &Interpreter::clrl},
+ {0xfe00, 0xfe00, &Interpreter::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},
+ {0x0000, 0x00fc, &Interpreter::nop_ext},
+
+ {0x0004, 0x00fc, &Interpreter::dr},
+ {0x0008, 0x00fc, &Interpreter::ir},
+ {0x000c, 0x00fc, &Interpreter::nr},
+ {0x0010, 0x00f0, &Interpreter::mv},
+
+ {0x0020, 0x00e4, &Interpreter::s},
+ {0x0024, 0x00e4, &Interpreter::sn},
+
+ {0x0040, 0x00c4, &Interpreter::l},
+ {0x0044, 0x00c4, &Interpreter::ln},
+
+ {0x0080, 0x00ce, &Interpreter::ls},
+ {0x0082, 0x00ce, &Interpreter::sl},
+ {0x0084, 0x00ce, &Interpreter::lsn},
+ {0x0086, 0x00ce, &Interpreter::sln},
+ {0x0088, 0x00ce, &Interpreter::lsm},
+ {0x008a, 0x00ce, &Interpreter::slm},
+ {0x008c, 0x00ce, &Interpreter::lsnm},
+ {0x008e, 0x00ce, &Interpreter::slnm},
+
+ {0x00c3, 0x00cf, &Interpreter::ldax},
+ {0x00c7, 0x00cf, &Interpreter::ldaxn},
+ {0x00cb, 0x00cf, &Interpreter::ldaxm},
+ {0x00cf, 0x00cf, &Interpreter::ldaxnm},
+
+ {0x00c0, 0x00cc, &Interpreter::ld},
+ {0x00c4, 0x00cc, &Interpreter::ldn},
+ {0x00c8, 0x00cc, &Interpreter::ldm},
+ {0x00cc, 0x00cc, &Interpreter::ldnm},
}};
// clang-format on
@@ -266,7 +265,7 @@ void InitInstructionTables()
// ext op table
for (size_t i = 0; i < s_ext_op_table.size(); i++)
{
- s_ext_op_table[i] = nop;
+ s_ext_op_table[i] = &Interpreter::nop;
const auto iter = FindByOpcode(static_cast<UDSPInstruction>(i), s_opcodes_ext);
if (iter == s_opcodes_ext.cend())
@@ -278,7 +277,7 @@ void InitInstructionTables()
// op table
for (size_t i = 0; i < s_op_table.size(); i++)
{
- s_op_table[i] = nop;
+ s_op_table[i] = &Interpreter::nop;
const auto iter = FindByOpcode(static_cast<UDSPInstruction>(i), s_opcodes);
if (iter == s_opcodes.cend())
diff --git a/Source/Core/Core/DSP/Interpreter/DSPIntTables.h b/Source/Core/Core/DSP/Interpreter/DSPIntTables.h
index 7a665687f1..17e6dd5b2c 100644
--- a/Source/Core/Core/DSP/Interpreter/DSPIntTables.h
+++ b/Source/Core/Core/DSP/Interpreter/DSPIntTables.h
@@ -8,7 +8,9 @@
namespace DSP::Interpreter
{
-using InterpreterFunction = void (*)(UDSPInstruction);
+class Interpreter;
+
+using InterpreterFunction = void (Interpreter::*)(UDSPInstruction);
InterpreterFunction GetOp(UDSPInstruction inst);
InterpreterFunction GetExtOp(UDSPInstruction inst);
diff --git a/Source/Core/Core/DSP/Interpreter/DSPIntUtil.h b/Source/Core/Core/DSP/Interpreter/DSPIntUtil.h
index 8903e830d0..973911481d 100644
--- a/Source/Core/Core/DSP/Interpreter/DSPIntUtil.h
+++ b/Source/Core/Core/DSP/Interpreter/DSPIntUtil.h
@@ -5,376 +5,27 @@
#pragma once
-#include "Common/Assert.h"
#include "Common/CommonTypes.h"
-#include "Core/DSP/DSPCore.h"
-#include "Core/DSP/DSPStacks.h"
-
namespace DSP::Interpreter
{
// ---------------------------------------------------------------------------------------
-// --- SR
-// ---------------------------------------------------------------------------------------
-
-static inline void dsp_SR_set_flag(int flag)
-{
- g_dsp.r.sr |= flag;
-}
-
-static inline bool dsp_SR_is_flag_set(int flag)
-{
- return (g_dsp.r.sr & flag) != 0;
-}
-
-// ---------------------------------------------------------------------------------------
-// --- AR increments, decrements
-// ---------------------------------------------------------------------------------------
-
-static inline u16 dsp_increase_addr_reg(u16 reg, s16 _ix)
-{
- u32 ar = g_dsp.r.ar[reg];
- u32 wr = g_dsp.r.wr[reg];
- s32 ix = _ix;
-
- u32 mx = (wr | 1) << 1;
- u32 nar = ar + ix;
- u32 dar = (nar ^ ar ^ ix) & mx;
-
- if (ix >= 0)
- {
- if (dar > wr) // overflow
- nar -= wr + 1;
- }
- else
- {
- if ((((nar + wr + 1) ^ nar) & dar) <= wr) // underflow or below min for mask
- nar += wr + 1;
- }
- return nar;
-}
-
-static inline u16 dsp_decrease_addr_reg(u16 reg, s16 _ix)
-{
- u32 ar = g_dsp.r.ar[reg];
- u32 wr = g_dsp.r.wr[reg];
- s32 ix = _ix;
-
- u32 mx = (wr | 1) << 1;
- u32 nar = ar - ix;
- u32 dar = (nar ^ ar ^ ~ix) & mx;
-
- if ((u32)ix > 0xFFFF8000) //(ix < 0 && ix != -0x8000)
- {
- if (dar > wr) // overflow
- nar -= wr + 1;
- }
- else
- {
- if ((((nar + wr + 1) ^ nar) & dar) <= wr) // underflow or below min for mask
- nar += wr + 1;
- }
- return nar;
-}
-
-static inline u16 dsp_increment_addr_reg(u16 reg)
-{
- u32 ar = g_dsp.r.ar[reg];
- u32 wr = g_dsp.r.wr[reg];
-
- u32 nar = ar + 1;
-
- if ((nar ^ ar) > ((wr | 1) << 1))
- nar -= wr + 1;
- return nar;
-}
-
-static inline u16 dsp_decrement_addr_reg(u16 reg)
-{
- u32 ar = g_dsp.r.ar[reg];
- u32 wr = g_dsp.r.wr[reg];
-
- u32 nar = ar + wr;
-
- if (((nar ^ ar) & ((wr | 1) << 1)) > wr)
- nar -= wr + 1;
- return nar;
-}
-
-// ---------------------------------------------------------------------------------------
-// --- reg
-// ---------------------------------------------------------------------------------------
-
-static inline u16 dsp_op_read_reg(int _reg)
-{
- int reg = _reg & 0x1f;
-
- switch (reg)
- {
- case DSP_REG_ST0:
- case DSP_REG_ST1:
- case DSP_REG_ST2:
- case DSP_REG_ST3:
- return dsp_reg_load_stack(static_cast<StackRegister>(reg - DSP_REG_ST0));
- case DSP_REG_AR0:
- case DSP_REG_AR1:
- case DSP_REG_AR2:
- case DSP_REG_AR3:
- return g_dsp.r.ar[reg - DSP_REG_AR0];
- case DSP_REG_IX0:
- case DSP_REG_IX1:
- case DSP_REG_IX2:
- case DSP_REG_IX3:
- return g_dsp.r.ix[reg - DSP_REG_IX0];
- case DSP_REG_WR0:
- case DSP_REG_WR1:
- case DSP_REG_WR2:
- case DSP_REG_WR3:
- return g_dsp.r.wr[reg - DSP_REG_WR0];
- case DSP_REG_ACH0:
- case DSP_REG_ACH1:
- return g_dsp.r.ac[reg - DSP_REG_ACH0].h;
- case DSP_REG_CR:
- return g_dsp.r.cr;
- case DSP_REG_SR:
- return g_dsp.r.sr;
- case DSP_REG_PRODL:
- return g_dsp.r.prod.l;
- case DSP_REG_PRODM:
- return g_dsp.r.prod.m;
- case DSP_REG_PRODH:
- return g_dsp.r.prod.h;
- case DSP_REG_PRODM2:
- return g_dsp.r.prod.m2;
- case DSP_REG_AXL0:
- case DSP_REG_AXL1:
- return g_dsp.r.ax[reg - DSP_REG_AXL0].l;
- case DSP_REG_AXH0:
- case DSP_REG_AXH1:
- return g_dsp.r.ax[reg - DSP_REG_AXH0].h;
- case DSP_REG_ACL0:
- case DSP_REG_ACL1:
- return g_dsp.r.ac[reg - DSP_REG_ACL0].l;
- case DSP_REG_ACM0:
- case DSP_REG_ACM1:
- return g_dsp.r.ac[reg - DSP_REG_ACM0].m;
- default:
- ASSERT_MSG(DSP_INT, 0, "cannot happen");
- return 0;
- }
-}
-
-static inline void dsp_op_write_reg(int _reg, u16 val)
-{
- int reg = _reg & 0x1f;
-
- switch (reg)
- {
- // 8-bit sign extended registers. Should look at prod.h too...
- case DSP_REG_ACH0:
- case DSP_REG_ACH1:
- // sign extend from the bottom 8 bits.
- g_dsp.r.ac[reg - DSP_REG_ACH0].h = (u16)(s16)(s8)(u8)val;
- break;
-
- // Stack registers.
- case DSP_REG_ST0:
- case DSP_REG_ST1:
- case DSP_REG_ST2:
- case DSP_REG_ST3:
- dsp_reg_store_stack(static_cast<StackRegister>(reg - DSP_REG_ST0), val);
- break;
- case DSP_REG_AR0:
- case DSP_REG_AR1:
- case DSP_REG_AR2:
- case DSP_REG_AR3:
- g_dsp.r.ar[reg - DSP_REG_AR0] = val;
- break;
- case DSP_REG_IX0:
- case DSP_REG_IX1:
- case DSP_REG_IX2:
- case DSP_REG_IX3:
- g_dsp.r.ix[reg - DSP_REG_IX0] = val;
- break;
- case DSP_REG_WR0:
- case DSP_REG_WR1:
- case DSP_REG_WR2:
- case DSP_REG_WR3:
- g_dsp.r.wr[reg - DSP_REG_WR0] = val;
- break;
- case DSP_REG_CR:
- g_dsp.r.cr = val;
- break;
- case DSP_REG_SR:
- g_dsp.r.sr = val;
- break;
- case DSP_REG_PRODL:
- g_dsp.r.prod.l = val;
- break;
- case DSP_REG_PRODM:
- g_dsp.r.prod.m = val;
- break;
- case DSP_REG_PRODH:
- g_dsp.r.prod.h = val;
- break;
- case DSP_REG_PRODM2:
- g_dsp.r.prod.m2 = val;
- break;
- case DSP_REG_AXL0:
- case DSP_REG_AXL1:
- g_dsp.r.ax[reg - DSP_REG_AXL0].l = val;
- break;
- case DSP_REG_AXH0:
- case DSP_REG_AXH1:
- g_dsp.r.ax[reg - DSP_REG_AXH0].h = val;
- break;
- case DSP_REG_ACL0:
- case DSP_REG_ACL1:
- g_dsp.r.ac[reg - DSP_REG_ACL0].l = val;
- break;
- case DSP_REG_ACM0:
- case DSP_REG_ACM1:
- g_dsp.r.ac[reg - DSP_REG_ACM0].m = val;
- break;
- }
-}
-
-static inline void dsp_conditional_extend_accum(int reg)
-{
- switch (reg)
- {
- case DSP_REG_ACM0:
- case DSP_REG_ACM1:
- if (g_dsp.r.sr & SR_40_MODE_BIT)
- {
- // Sign extend into whole accum.
- u16 val = g_dsp.r.ac[reg - DSP_REG_ACM0].m;
- g_dsp.r.ac[reg - DSP_REG_ACM0].h = (val & 0x8000) ? 0xFFFF : 0x0000;
- g_dsp.r.ac[reg - DSP_REG_ACM0].l = 0;
- }
- }
-}
-
-// ---------------------------------------------------------------------------------------
-// --- prod (40-bit)
-// ---------------------------------------------------------------------------------------
-
-static inline s64 dsp_get_long_prod()
-{
- s64 val = (s8)(u8)g_dsp.r.prod.h;
- val <<= 32;
- s64 low_prod = g_dsp.r.prod.m;
- low_prod += g_dsp.r.prod.m2;
- low_prod <<= 16;
- low_prod |= g_dsp.r.prod.l;
- val += low_prod;
- return val;
-}
-
-static inline s64 dsp_get_long_prod_round_prodl()
-{
- s64 prod = dsp_get_long_prod();
-
- if (prod & 0x10000)
- prod = (prod + 0x8000) & ~0xffff;
- else
- prod = (prod + 0x7fff) & ~0xffff;
-
- return prod;
-}
-
-// For accurate emulation, this is wrong - but the real prod registers behave
-// in completely bizarre ways. Not needed to emulate them correctly for game ucodes.
-inline void dsp_set_long_prod(s64 val)
-{
- g_dsp.r.prod.val = val & 0x000000FFFFFFFFFFULL;
-}
-
-// ---------------------------------------------------------------------------------------
// --- ACC - main accumulators (40-bit)
// ---------------------------------------------------------------------------------------
-inline s64 dsp_get_long_acc(int reg)
-{
- return ((s64)(g_dsp.r.ac[reg].val << 24) >> 24);
-}
-
-inline void dsp_set_long_acc(int _reg, s64 val)
-{
- g_dsp.r.ac[_reg].val = (u64)val;
-}
-
-inline s64 dsp_convert_long_acc(s64 val) // s64 -> s40
+// s64 -> s40
+inline s64 dsp_convert_long_acc(s64 val)
{
return ((val << 24) >> 24);
}
inline s64 dsp_round_long_acc(s64 val)
{
- if (val & 0x10000)
+ if ((val & 0x10000) != 0)
val = (val + 0x8000) & ~0xffff;
else
val = (val + 0x7fff) & ~0xffff;
return val;
}
-
-inline s16 dsp_get_acc_l(int _reg)
-{
- return (s16)g_dsp.r.ac[_reg].l;
-}
-
-inline s16 dsp_get_acc_m(int _reg)
-{
- return (s16)g_dsp.r.ac[_reg].m;
-}
-
-inline s16 dsp_get_acc_h(int _reg)
-{
- return (s16)g_dsp.r.ac[_reg].h;
-}
-
-inline u16 dsp_op_read_reg_and_saturate(u8 _reg)
-{
- if (g_dsp.r.sr & SR_40_MODE_BIT)
- {
- s64 acc = dsp_get_long_acc(_reg);
-
- if (acc != (s32)acc)
- {
- if (acc > 0)
- return 0x7fff;
- else
- return 0x8000;
- }
- else
- {
- return g_dsp.r.ac[_reg].m;
- }
- }
- else
- {
- return g_dsp.r.ac[_reg].m;
- }
-}
-
-// ---------------------------------------------------------------------------------------
-// --- AX - extra accumulators (32-bit)
-// ---------------------------------------------------------------------------------------
-
-inline s32 dsp_get_long_acx(int _reg)
-{
- return (s32)(((u32)g_dsp.r.ax[_reg].h << 16) | g_dsp.r.ax[_reg].l);
-}
-
-inline s16 dsp_get_ax_l(int _reg)
-{
- return (s16)g_dsp.r.ax[_reg].l;
-}
-
-inline s16 dsp_get_ax_h(int _reg)
-{
- return (s16)g_dsp.r.ax[_reg].h;
-}
-
} // namespace DSP::Interpreter
diff --git a/Source/Core/Core/DSP/Interpreter/DSPInterpreter.cpp b/Source/Core/Core/DSP/Interpreter/DSPInterpreter.cpp
index c17b20a0c2..70ea39b8f2 100644
--- a/Source/Core/Core/DSP/Interpreter/DSPInterpreter.cpp
+++ b/Source/Core/Core/DSP/Interpreter/DSPInterpreter.cpp
@@ -5,115 +5,68 @@
#include "Core/DSP/Interpreter/DSPInterpreter.h"
+#include "Common/Assert.h"
#include "Common/CommonTypes.h"
#include "Common/Logging/Log.h"
#include "Core/DSP/DSPAnalyzer.h"
#include "Core/DSP/DSPCore.h"
-#include "Core/DSP/DSPMemoryMap.h"
#include "Core/DSP/DSPTables.h"
#include "Core/DSP/Interpreter/DSPIntTables.h"
namespace DSP::Interpreter
{
-namespace
+Interpreter::Interpreter(DSPCore& dsp) : m_dsp_core{dsp}
{
-void ExecuteInstruction(const UDSPInstruction inst)
+ InitInstructionTables();
+}
+
+Interpreter::~Interpreter() = default;
+
+void Interpreter::ExecuteInstruction(const UDSPInstruction inst)
{
const DSPOPCTemplate* opcode_template = GetOpTemplate(inst);
if (opcode_template->extended)
{
- GetExtOp(inst)(inst);
+ (this->*GetExtOp(inst))(inst);
}
- GetOp(inst)(inst);
+ (this->*GetOp(inst))(inst);
if (opcode_template->extended)
{
ApplyWriteBackLog();
}
}
-} // Anonymous namespace
-// NOTE: These have nothing to do with g_dsp.r.cr !
-void WriteCR(u16 val)
+void Interpreter::Step()
{
- // reset
- if (val & 1)
- {
- INFO_LOG_FMT(DSPLLE, "DSP_CONTROL RESET");
- DSPCore_Reset();
- val &= ~1;
- }
- // init
- else if (val == 4)
- {
- // HAX!
- // OSInitAudioSystem ucode should send this mail - not DSP core itself
- INFO_LOG_FMT(DSPLLE, "DSP_CONTROL INIT");
- g_init_hax = true;
- val |= 0x800;
- }
+ m_dsp_core.CheckExceptions();
+ m_dsp_core.DSPState().step_counter++;
- // update cr
- g_dsp.cr = val;
-}
+ const u16 opc = m_dsp_core.DSPState().FetchInstruction();
+ ExecuteInstruction(UDSPInstruction{opc});
-u16 ReadCR()
-{
- if (g_dsp.pc & 0x8000)
- {
- g_dsp.cr |= 0x800;
- }
- else
- {
- g_dsp.cr &= ~0x800;
- }
-
- return g_dsp.cr;
-}
-
-void Step()
-{
- DSPCore_CheckExceptions();
-
- g_dsp.step_counter++;
-
-#if PROFILE
- g_dsp.err_pc = g_dsp.pc;
-
- ProfilerAddDelta(g_dsp.err_pc, 1);
- if (g_dsp.step_counter == 1)
- {
- ProfilerInit();
- }
-
- if ((g_dsp.step_counter & 0xFFFFF) == 0)
- {
- ProfilerDump(g_dsp.step_counter);
- }
-#endif
-
- u16 opc = dsp_fetch_code();
- ExecuteInstruction(UDSPInstruction(opc));
-
- if (Analyzer::GetCodeFlags(static_cast<u16>(g_dsp.pc - 1u)) & Analyzer::CODE_LOOP_END)
+ const auto pc = m_dsp_core.DSPState().pc;
+ if ((Analyzer::GetCodeFlags(static_cast<u16>(pc - 1)) & Analyzer::CODE_LOOP_END) != 0)
HandleLoop();
}
// Used by thread mode.
-int RunCyclesThread(int cycles)
+int Interpreter::RunCyclesThread(int cycles)
{
+ auto& state = m_dsp_core.DSPState();
+
while (true)
{
- if (g_dsp.cr & CR_HALT)
+ if ((state.cr & CR_HALT) != 0)
return 0;
- if (g_dsp.external_interrupt_waiting)
+ if (state.external_interrupt_waiting)
{
- DSPCore_CheckExternalInterrupt();
- DSPCore_SetExternalInterrupt(false);
+ m_dsp_core.CheckExternalInterrupt();
+ m_dsp_core.SetExternalInterrupt(false);
}
Step();
@@ -124,16 +77,19 @@ int RunCyclesThread(int cycles)
}
// This one has basic idle skipping, and checks breakpoints.
-int RunCyclesDebug(int cycles)
+int Interpreter::RunCyclesDebug(int cycles)
{
+ auto& state = m_dsp_core.DSPState();
+
// First, let's run a few cycles with no idle skipping so that things can progress a bit.
for (int i = 0; i < 8; i++)
{
- if (g_dsp.cr & CR_HALT)
+ if ((state.cr & CR_HALT) != 0)
return 0;
- if (g_dsp_breakpoints.IsAddressBreakPoint(g_dsp.pc))
+
+ if (m_dsp_core.BreakPoints().IsAddressBreakPoint(state.pc))
{
- DSPCore_SetState(State::Stepping);
+ m_dsp_core.SetState(State::Stepping);
return cycles;
}
Step();
@@ -148,16 +104,19 @@ int RunCyclesDebug(int cycles)
// idle loops.
for (int i = 0; i < 8; i++)
{
- if (g_dsp.cr & CR_HALT)
+ if ((state.cr & CR_HALT) != 0)
return 0;
- if (g_dsp_breakpoints.IsAddressBreakPoint(g_dsp.pc))
+
+ if (m_dsp_core.BreakPoints().IsAddressBreakPoint(state.pc))
{
- DSPCore_SetState(State::Stepping);
+ m_dsp_core.SetState(State::Stepping);
return cycles;
}
+
// Idle skipping.
- if (Analyzer::GetCodeFlags(g_dsp.pc) & Analyzer::CODE_IDLE_SKIP)
+ if ((Analyzer::GetCodeFlags(state.pc) & Analyzer::CODE_IDLE_SKIP) != 0)
return 0;
+
Step();
cycles--;
if (cycles < 0)
@@ -167,9 +126,9 @@ int RunCyclesDebug(int cycles)
// Now, lets run some more without idle skipping.
for (int i = 0; i < 200; i++)
{
- if (g_dsp_breakpoints.IsAddressBreakPoint(g_dsp.pc))
+ if (m_dsp_core.BreakPoints().IsAddressBreakPoint(state.pc))
{
- DSPCore_SetState(State::Stepping);
+ m_dsp_core.SetState(State::Stepping);
return cycles;
}
Step();
@@ -183,16 +142,20 @@ int RunCyclesDebug(int cycles)
}
// Used by non-thread mode. Meant to be efficient.
-int RunCycles(int cycles)
+int Interpreter::RunCycles(int cycles)
{
+ auto& state = m_dsp_core.DSPState();
+
// First, let's run a few cycles with no idle skipping so that things can
// progress a bit.
for (int i = 0; i < 8; i++)
{
- if (g_dsp.cr & CR_HALT)
+ if ((state.cr & CR_HALT) != 0)
return 0;
+
Step();
cycles--;
+
if (cycles < 0)
return 0;
}
@@ -203,13 +166,16 @@ int RunCycles(int cycles)
// idle loops.
for (int i = 0; i < 8; i++)
{
- if (g_dsp.cr & CR_HALT)
+ if ((state.cr & CR_HALT) != 0)
return 0;
+
// Idle skipping.
- if (Analyzer::GetCodeFlags(g_dsp.pc) & Analyzer::CODE_IDLE_SKIP)
+ if ((Analyzer::GetCodeFlags(state.pc) & Analyzer::CODE_IDLE_SKIP) != 0)
return 0;
+
Step();
cycles--;
+
if (cycles < 0)
return 0;
}
@@ -227,7 +193,656 @@ int RunCycles(int cycles)
}
}
-void nop(const UDSPInstruction opc)
+// NOTE: These have nothing to do with SDSP::r::cr!
+void Interpreter::WriteCR(u16 val)
+{
+ // reset
+ if ((val & 1) != 0)
+ {
+ INFO_LOG_FMT(DSPLLE, "DSP_CONTROL RESET");
+ m_dsp_core.Reset();
+ val &= ~1;
+ }
+ // init
+ else if (val == 4)
+ {
+ // HAX!
+ // OSInitAudioSystem ucode should send this mail - not DSP core itself
+ INFO_LOG_FMT(DSPLLE, "DSP_CONTROL INIT");
+ m_dsp_core.SetInitHax(true);
+ val |= 0x800;
+ }
+
+ // update cr
+ m_dsp_core.DSPState().cr = val;
+}
+
+u16 Interpreter::ReadCR()
+{
+ auto& state = m_dsp_core.DSPState();
+
+ if ((state.pc & 0x8000) != 0)
+ {
+ state.cr |= 0x800;
+ }
+ else
+ {
+ state.cr &= ~0x800;
+ }
+
+ return state.cr;
+}
+
+void Interpreter::SetSRFlag(u16 flag)
+{
+ m_dsp_core.DSPState().SetSRFlag(flag);
+}
+
+bool Interpreter::IsSRFlagSet(u16 flag) const
+{
+ return m_dsp_core.DSPState().IsSRFlagSet(flag);
+}
+
+bool Interpreter::CheckCondition(u8 condition) const
+{
+ const auto IsCarry = [this] { return IsSRFlagSet(SR_CARRY); };
+ const auto IsOverflow = [this] { return IsSRFlagSet(SR_OVERFLOW); };
+ const auto IsOverS32 = [this] { return IsSRFlagSet(SR_OVER_S32); };
+ const auto IsLess = [this] {
+ const auto& state = m_dsp_core.DSPState();
+ return (state.r.sr & SR_OVERFLOW) != (state.r.sr & SR_SIGN);
+ };
+ const auto IsZero = [this] { return IsSRFlagSet(SR_ARITH_ZERO); };
+ const auto IsLogicZero = [this] { return IsSRFlagSet(SR_LOGIC_ZERO); };
+ const auto IsConditionA = [this] {
+ return (IsSRFlagSet(SR_OVER_S32) || IsSRFlagSet(SR_TOP2BITS)) && !IsSRFlagSet(SR_ARITH_ZERO);
+ };
+
+ switch (condition & 0xf)
+ {
+ case 0xf: // Always true.
+ return true;
+ case 0x0: // GE - Greater Equal
+ return !IsLess();
+ case 0x1: // L - Less
+ return IsLess();
+ case 0x2: // G - Greater
+ return !IsLess() && !IsZero();
+ case 0x3: // LE - Less Equal
+ return IsLess() || IsZero();
+ case 0x4: // NZ - Not Zero
+ return !IsZero();
+ case 0x5: // Z - Zero
+ return IsZero();
+ case 0x6: // NC - Not carry
+ return !IsCarry();
+ case 0x7: // C - Carry
+ return IsCarry();
+ case 0x8: // ? - Not over s32
+ return !IsOverS32();
+ case 0x9: // ? - Over s32
+ return IsOverS32();
+ case 0xa: // ?
+ return IsConditionA();
+ case 0xb: // ?
+ return !IsConditionA();
+ case 0xc: // LNZ - Logic Not Zero
+ return !IsLogicZero();
+ case 0xd: // LZ - Logic Zero
+ return IsLogicZero();
+ case 0xe: // 0 - Overflow
+ return IsOverflow();
+ default:
+ return true;
+ }
+}
+
+u16 Interpreter::IncrementAddressRegister(u16 reg) const
+{
+ auto& state = m_dsp_core.DSPState();
+ const u32 ar = state.r.ar[reg];
+ const u32 wr = state.r.wr[reg];
+ u32 nar = ar + 1;
+
+ if ((nar ^ ar) > ((wr | 1) << 1))
+ nar -= wr + 1;
+
+ return static_cast<u16>(nar);
+}
+
+u16 Interpreter::DecrementAddressRegister(u16 reg) const
+{
+ const auto& state = m_dsp_core.DSPState();
+ const u32 ar = state.r.ar[reg];
+ const u32 wr = state.r.wr[reg];
+ u32 nar = ar + wr;
+
+ if (((nar ^ ar) & ((wr | 1) << 1)) > wr)
+ nar -= wr + 1;
+
+ return static_cast<u16>(nar);
+}
+
+u16 Interpreter::IncreaseAddressRegister(u16 reg, s16 ix_) const
+{
+ const auto& state = m_dsp_core.DSPState();
+ const u32 ar = state.r.ar[reg];
+ const u32 wr = state.r.wr[reg];
+ const s32 ix = ix_;
+
+ const u32 mx = (wr | 1) << 1;
+ u32 nar = ar + ix;
+ const u32 dar = (nar ^ ar ^ ix) & mx;
+
+ if (ix >= 0)
+ {
+ if (dar > wr) // Overflow
+ nar -= wr + 1;
+ }
+ else
+ {
+ // Underflow or below min for mask
+ if ((((nar + wr + 1) ^ nar) & dar) <= wr)
+ nar += wr + 1;
+ }
+
+ return static_cast<u16>(nar);
+}
+
+u16 Interpreter::DecreaseAddressRegister(u16 reg, s16 ix_) const
+{
+ const auto& state = m_dsp_core.DSPState();
+ const u32 ar = state.r.ar[reg];
+ const u32 wr = state.r.wr[reg];
+ const s32 ix = ix_;
+
+ const u32 mx = (wr | 1) << 1;
+ u32 nar = ar - ix;
+ const u32 dar = (nar ^ ar ^ ~ix) & mx;
+
+ // (ix < 0 && ix != -0x8000)
+ if (static_cast<u32>(ix) > 0xFFFF8000)
+ {
+ if (dar > wr) // overflow
+ nar -= wr + 1;
+ }
+ else
+ {
+ // Underflow or below min for mask
+ if ((((nar + wr + 1) ^ nar) & dar) <= wr)
+ nar += wr + 1;
+ }
+
+ return static_cast<u16>(nar);
+}
+
+s32 Interpreter::GetLongACX(s32 reg) const
+{
+ const auto& state = m_dsp_core.DSPState();
+ return static_cast<s32>((static_cast<u32>(state.r.ax[reg].h) << 16) | state.r.ax[reg].l);
+}
+
+s16 Interpreter::GetAXLow(s32 reg) const
+{
+ return static_cast<s16>(m_dsp_core.DSPState().r.ax[reg].l);
+}
+
+s16 Interpreter::GetAXHigh(s32 reg) const
+{
+ return static_cast<s16>(m_dsp_core.DSPState().r.ax[reg].h);
+}
+
+s64 Interpreter::GetLongAcc(s32 reg) const
+{
+ const auto& state = m_dsp_core.DSPState();
+ return static_cast<s64>(state.r.ac[reg].val << 24) >> 24;
+}
+
+void Interpreter::SetLongAcc(s32 reg, s64 value)
+{
+ auto& state = m_dsp_core.DSPState();
+ state.r.ac[reg].val = static_cast<u64>(value);
+}
+
+s16 Interpreter::GetAccLow(s32 reg) const
+{
+ return static_cast<s16>(m_dsp_core.DSPState().r.ac[reg].l);
+}
+
+s16 Interpreter::GetAccMid(s32 reg) const
+{
+ return static_cast<s16>(m_dsp_core.DSPState().r.ac[reg].m);
+}
+
+s16 Interpreter::GetAccHigh(s32 reg) const
+{
+ return static_cast<s16>(m_dsp_core.DSPState().r.ac[reg].h);
+}
+
+s64 Interpreter::GetLongProduct() const
+{
+ const auto& state = m_dsp_core.DSPState();
+
+ s64 val = static_cast<s8>(static_cast<u8>(state.r.prod.h));
+ val <<= 32;
+
+ s64 low_prod = state.r.prod.m;
+ low_prod += state.r.prod.m2;
+ low_prod <<= 16;
+ low_prod |= state.r.prod.l;
+
+ val += low_prod;
+
+ return val;
+}
+
+s64 Interpreter::GetLongProductRounded() const
+{
+ const s64 prod = GetLongProduct();
+
+ if ((prod & 0x10000) != 0)
+ return (prod + 0x8000) & ~0xffff;
+ else
+ return (prod + 0x7fff) & ~0xffff;
+}
+
+void Interpreter::SetLongProduct(s64 value)
+{
+ // For accurate emulation, this is wrong - but the real prod registers behave
+ // in completely bizarre ways. Not needed to emulate them correctly for game ucodes.
+ m_dsp_core.DSPState().r.prod.val = static_cast<u64>(value & 0x000000FFFFFFFFFFULL);
+}
+
+s64 Interpreter::GetMultiplyProduct(u16 a, u16 b, u8 sign) const
+{
+ s64 prod;
+
+ // Unsigned
+ if (sign == 1 && IsSRFlagSet(SR_MUL_UNSIGNED))
+ prod = static_cast<u32>(a * b);
+ else if (sign == 2 && IsSRFlagSet(SR_MUL_UNSIGNED)) // mixed
+ prod = a * static_cast<s16>(b);
+ else // Signed
+ prod = static_cast<s16>(a) * static_cast<s16>(b);
+
+ // Conditionally multiply by 2.
+ if (!IsSRFlagSet(SR_MUL_MODIFY))
+ prod <<= 1;
+
+ return prod;
+}
+
+s64 Interpreter::Multiply(u16 a, u16 b, u8 sign) const
+{
+ return GetMultiplyProduct(a, b, sign);
+}
+
+s64 Interpreter::MultiplyAdd(u16 a, u16 b, u8 sign) const
+{
+ return GetLongProduct() + GetMultiplyProduct(a, b, sign);
+}
+
+s64 Interpreter::MultiplySub(u16 a, u16 b, u8 sign) const
+{
+ return GetLongProduct() - GetMultiplyProduct(a, b, sign);
+}
+
+s64 Interpreter::MultiplyMulX(u8 axh0, u8 axh1, u16 val1, u16 val2) const
+{
+ s64 result;
+
+ if (axh0 == 0 && axh1 == 0)
+ result = Multiply(val1, val2, 1); // Unsigned support ON if both ax?.l regs are used
+ else if (axh0 == 0 && axh1 == 1)
+ result = Multiply(val1, val2, 2); // Mixed support ON (u16)axl.0 * (s16)axh.1
+ else if (axh0 == 1 && axh1 == 0)
+ result = Multiply(val2, val1, 2); // Mixed support ON (u16)axl.1 * (s16)axh.0
+ else
+ result = Multiply(val1, val2, 0); // Unsigned support OFF if both ax?.h regs are used
+
+ return result;
+}
+
+void Interpreter::UpdateSR16(s16 value, bool carry, bool overflow, bool over_s32)
+{
+ auto& state = m_dsp_core.DSPState();
+
+ state.r.sr &= ~SR_CMP_MASK;
+
+ // 0x01
+ if (carry)
+ {
+ state.r.sr |= SR_CARRY;
+ }
+
+ // 0x02 and 0x80
+ if (overflow)
+ {
+ state.r.sr |= SR_OVERFLOW;
+ state.r.sr |= SR_OVERFLOW_STICKY;
+ }
+
+ // 0x04
+ if (value == 0)
+ {
+ state.r.sr |= SR_ARITH_ZERO;
+ }
+
+ // 0x08
+ if (value < 0)
+ {
+ state.r.sr |= SR_SIGN;
+ }
+
+ // 0x10
+ if (over_s32)
+ {
+ state.r.sr |= SR_OVER_S32;
+ }
+
+ // 0x20 - Checks if top bits of m are equal
+ if (((static_cast<u16>(value) >> 14) == 0) || ((static_cast<u16>(value) >> 14) == 3))
+ {
+ state.r.sr |= SR_TOP2BITS;
+ }
+}
+
+void Interpreter::UpdateSR64(s64 value, bool carry, bool overflow)
+{
+ auto& state = m_dsp_core.DSPState();
+
+ state.r.sr &= ~SR_CMP_MASK;
+
+ // 0x01
+ if (carry)
+ {
+ state.r.sr |= SR_CARRY;
+ }
+
+ // 0x02 and 0x80
+ if (overflow)
+ {
+ state.r.sr |= SR_OVERFLOW;
+ state.r.sr |= SR_OVERFLOW_STICKY;
+ }
+
+ // 0x04
+ if (value == 0)
+ {
+ state.r.sr |= SR_ARITH_ZERO;
+ }
+
+ // 0x08
+ if (value < 0)
+ {
+ state.r.sr |= SR_SIGN;
+ }
+
+ // 0x10
+ if (value != static_cast<s32>(value))
+ {
+ state.r.sr |= SR_OVER_S32;
+ }
+
+ // 0x20 - Checks if top bits of m are equal
+ if (((value & 0xc0000000) == 0) || ((value & 0xc0000000) == 0xc0000000))
+ {
+ state.r.sr |= SR_TOP2BITS;
+ }
+}
+
+void Interpreter::UpdateSRLogicZero(bool value)
+{
+ auto& state = m_dsp_core.DSPState();
+
+ if (value)
+ state.r.sr |= SR_LOGIC_ZERO;
+ else
+ state.r.sr &= ~SR_LOGIC_ZERO;
+}
+
+u16 Interpreter::OpReadRegister(int reg_)
+{
+ const int reg = reg_ & 0x1f;
+ auto& state = m_dsp_core.DSPState();
+
+ switch (reg)
+ {
+ case DSP_REG_ST0:
+ case DSP_REG_ST1:
+ case DSP_REG_ST2:
+ case DSP_REG_ST3:
+ return state.PopStack(static_cast<StackRegister>(reg - DSP_REG_ST0));
+ case DSP_REG_AR0:
+ case DSP_REG_AR1:
+ case DSP_REG_AR2:
+ case DSP_REG_AR3:
+ return state.r.ar[reg - DSP_REG_AR0];
+ case DSP_REG_IX0:
+ case DSP_REG_IX1:
+ case DSP_REG_IX2:
+ case DSP_REG_IX3:
+ return state.r.ix[reg - DSP_REG_IX0];
+ case DSP_REG_WR0:
+ case DSP_REG_WR1:
+ case DSP_REG_WR2:
+ case DSP_REG_WR3:
+ return state.r.wr[reg - DSP_REG_WR0];
+ case DSP_REG_ACH0:
+ case DSP_REG_ACH1:
+ return state.r.ac[reg - DSP_REG_ACH0].h;
+ case DSP_REG_CR:
+ return state.r.cr;
+ case DSP_REG_SR:
+ return state.r.sr;
+ case DSP_REG_PRODL:
+ return state.r.prod.l;
+ case DSP_REG_PRODM:
+ return state.r.prod.m;
+ case DSP_REG_PRODH:
+ return state.r.prod.h;
+ case DSP_REG_PRODM2:
+ return state.r.prod.m2;
+ case DSP_REG_AXL0:
+ case DSP_REG_AXL1:
+ return state.r.ax[reg - DSP_REG_AXL0].l;
+ case DSP_REG_AXH0:
+ case DSP_REG_AXH1:
+ return state.r.ax[reg - DSP_REG_AXH0].h;
+ case DSP_REG_ACL0:
+ case DSP_REG_ACL1:
+ return state.r.ac[reg - DSP_REG_ACL0].l;
+ case DSP_REG_ACM0:
+ case DSP_REG_ACM1:
+ return state.r.ac[reg - DSP_REG_ACM0].m;
+ default:
+ ASSERT_MSG(DSP_INT, 0, "cannot happen");
+ return 0;
+ }
+}
+
+u16 Interpreter::OpReadRegisterAndSaturate(int reg) const
+{
+ if (IsSRFlagSet(SR_40_MODE_BIT))
+ {
+ const s64 acc = GetLongAcc(reg);
+
+ if (acc != static_cast<s32>(acc))
+ {
+ if (acc > 0)
+ return 0x7fff;
+ else
+ return 0x8000;
+ }
+
+ return m_dsp_core.DSPState().r.ac[reg].m;
+ }
+
+ return m_dsp_core.DSPState().r.ac[reg].m;
+}
+
+void Interpreter::OpWriteRegister(int reg_, u16 val)
+{
+ const int reg = reg_ & 0x1f;
+ auto& state = m_dsp_core.DSPState();
+
+ switch (reg)
+ {
+ // 8-bit sign extended registers. Should look at prod.h too...
+ case DSP_REG_ACH0:
+ case DSP_REG_ACH1:
+ // sign extend from the bottom 8 bits.
+ state.r.ac[reg - DSP_REG_ACH0].h = (u16)(s16)(s8)(u8)val;
+ break;
+
+ // Stack registers.
+ case DSP_REG_ST0:
+ case DSP_REG_ST1:
+ case DSP_REG_ST2:
+ case DSP_REG_ST3:
+ state.StoreStack(static_cast<StackRegister>(reg - DSP_REG_ST0), val);
+ break;
+ case DSP_REG_AR0:
+ case DSP_REG_AR1:
+ case DSP_REG_AR2:
+ case DSP_REG_AR3:
+ state.r.ar[reg - DSP_REG_AR0] = val;
+ break;
+ case DSP_REG_IX0:
+ case DSP_REG_IX1:
+ case DSP_REG_IX2:
+ case DSP_REG_IX3:
+ state.r.ix[reg - DSP_REG_IX0] = val;
+ break;
+ case DSP_REG_WR0:
+ case DSP_REG_WR1:
+ case DSP_REG_WR2:
+ case DSP_REG_WR3:
+ state.r.wr[reg - DSP_REG_WR0] = val;
+ break;
+ case DSP_REG_CR:
+ state.r.cr = val;
+ break;
+ case DSP_REG_SR:
+ state.r.sr = val;
+ break;
+ case DSP_REG_PRODL:
+ state.r.prod.l = val;
+ break;
+ case DSP_REG_PRODM:
+ state.r.prod.m = val;
+ break;
+ case DSP_REG_PRODH:
+ state.r.prod.h = val;
+ break;
+ case DSP_REG_PRODM2:
+ state.r.prod.m2 = val;
+ break;
+ case DSP_REG_AXL0:
+ case DSP_REG_AXL1:
+ state.r.ax[reg - DSP_REG_AXL0].l = val;
+ break;
+ case DSP_REG_AXH0:
+ case DSP_REG_AXH1:
+ state.r.ax[reg - DSP_REG_AXH0].h = val;
+ break;
+ case DSP_REG_ACL0:
+ case DSP_REG_ACL1:
+ state.r.ac[reg - DSP_REG_ACL0].l = val;
+ break;
+ case DSP_REG_ACM0:
+ case DSP_REG_ACM1:
+ state.r.ac[reg - DSP_REG_ACM0].m = val;
+ break;
+ }
+}
+
+void Interpreter::ConditionalExtendAccum(int reg)
+{
+ if (reg != DSP_REG_ACM0 && reg != DSP_REG_ACM1)
+ return;
+
+ if (!IsSRFlagSet(SR_40_MODE_BIT))
+ return;
+
+ // Sign extend into whole accum.
+ auto& state = m_dsp_core.DSPState();
+ const u16 val = state.r.ac[reg - DSP_REG_ACM0].m;
+ state.r.ac[reg - DSP_REG_ACM0].h = (val & 0x8000) != 0 ? 0xFFFF : 0x0000;
+ state.r.ac[reg - DSP_REG_ACM0].l = 0;
+}
+
+// The ext op are writing their output into the backlog which is
+// being applied to the real registers after the main op was executed
+void Interpreter::ApplyWriteBackLog()
+{
+ // Always make sure to have an extra entry at the end w/ -1 to avoid
+ // infinitive loops
+ for (int i = 0; m_write_back_log_idx[i] != -1; i++)
+ {
+ u16 value = m_write_back_log[i];
+#ifdef PRECISE_BACKLOG
+ value |= OpReadRegister(m_write_back_log_idx[i]);
+#endif
+ OpWriteRegister(m_write_back_log_idx[i], value);
+
+ // Clear back log
+ m_write_back_log_idx[i] = -1;
+ }
+}
+
+void Interpreter::WriteToBackLog(int i, int idx, u16 value)
+{
+ m_write_back_log[i] = value;
+ m_write_back_log_idx[i] = idx;
+}
+
+// This function is being called in the main op after all input regs were read
+// and before it writes into any regs. This way we can always use bitwise or to
+// apply the ext command output, because if the main op didn't change the value
+// then 0 | ext output = ext output and if it did then bitwise or is still the
+// right thing to do
+// Only needed for cases when mainop and extended are modifying the same ACC
+// Games are not doing that + in motorola (similar DSP) dox this is forbidden to do.
+void Interpreter::ZeroWriteBackLog()
+{
+#ifdef PRECISE_BACKLOG
+ // always make sure to have an extra entry at the end w/ -1 to avoid
+ // infinitive loops
+ for (int i = 0; m_write_back_log_idx[i] != -1; i++)
+ {
+ OpWriteRegister(m_write_back_log_idx[i], 0);
+ }
+#endif
+}
+
+void Interpreter::ZeroWriteBackLogPreserveAcc([[maybe_unused]] u8 acc)
+{
+#ifdef PRECISE_BACKLOG
+ for (int i = 0; m_write_back_log_idx[i] != -1; i++)
+ {
+ // acc0
+ if (acc == 0 &&
+ ((m_write_back_log_idx[i] == DSP_REG_ACL0) || (m_write_back_log_idx[i] == DSP_REG_ACM0) ||
+ (m_write_back_log_idx[i] == DSP_REG_ACH0)))
+ {
+ continue;
+ }
+
+ // acc1
+ if (acc == 1 &&
+ ((m_write_back_log_idx[i] == DSP_REG_ACL1) || (m_write_back_log_idx[i] == DSP_REG_ACM1) ||
+ (m_write_back_log_idx[i] == DSP_REG_ACH1)))
+ {
+ continue;
+ }
+
+ OpWriteRegister(m_write_back_log_idx[i], 0);
+ }
+#endif
+}
+
+void Interpreter::nop(const UDSPInstruction opc)
{
// The real nop is 0. Anything else is bad.
if (opc == 0)
diff --git a/Source/Core/Core/DSP/Interpreter/DSPInterpreter.h b/Source/Core/Core/DSP/Interpreter/DSPInterpreter.h
index 7d94804604..a02c009e0a 100644
--- a/Source/Core/Core/DSP/Interpreter/DSPInterpreter.h
+++ b/Source/Core/Core/DSP/Interpreter/DSPInterpreter.h
@@ -4,144 +4,248 @@
#pragma once
+#include <array>
+#include <cstddef>
+
#include "Core/DSP/DSPCommon.h"
+#include "Core/DSP/DSPCore.h"
namespace DSP::Interpreter
{
-void Step();
-
-// See: DspIntBranch.cpp
-void HandleLoop();
-
-// If these simply return the same number of cycles as was passed into them,
-// chances are that the DSP is halted.
-// The difference between them is that the debug one obeys breakpoints.
-int RunCyclesThread(int cycles);
-int RunCycles(int cycles);
-int RunCyclesDebug(int cycles);
-
-void WriteCR(u16 val);
-u16 ReadCR();
-
-// All the opcode functions.
-void abs(UDSPInstruction opc);
-void add(UDSPInstruction opc);
-void addarn(UDSPInstruction opc);
-void addax(UDSPInstruction opc);
-void addaxl(UDSPInstruction opc);
-void addi(UDSPInstruction opc);
-void addis(UDSPInstruction opc);
-void addp(UDSPInstruction opc);
-void addpaxz(UDSPInstruction opc);
-void addr(UDSPInstruction opc);
-void andc(UDSPInstruction opc);
-void andcf(UDSPInstruction opc);
-void andf(UDSPInstruction opc);
-void andi(UDSPInstruction opc);
-void andr(UDSPInstruction opc);
-void asl(UDSPInstruction opc);
-void asr(UDSPInstruction opc);
-void asr16(UDSPInstruction opc);
-void asrn(UDSPInstruction opc);
-void asrnr(UDSPInstruction opc);
-void asrnrx(UDSPInstruction opc);
-void bloop(UDSPInstruction opc);
-void bloopi(UDSPInstruction opc);
-void call(UDSPInstruction opc);
-void callr(UDSPInstruction opc);
-void clr(UDSPInstruction opc);
-void clrl(UDSPInstruction opc);
-void clrp(UDSPInstruction opc);
-void cmp(UDSPInstruction opc);
-void cmpar(UDSPInstruction opc);
-void cmpi(UDSPInstruction opc);
-void cmpis(UDSPInstruction opc);
-void dar(UDSPInstruction opc);
-void dec(UDSPInstruction opc);
-void decm(UDSPInstruction opc);
-void halt(UDSPInstruction opc);
-void iar(UDSPInstruction opc);
-void ifcc(UDSPInstruction opc);
-void ilrr(UDSPInstruction opc);
-void ilrrd(UDSPInstruction opc);
-void ilrri(UDSPInstruction opc);
-void ilrrn(UDSPInstruction opc);
-void inc(UDSPInstruction opc);
-void incm(UDSPInstruction opc);
-void jcc(UDSPInstruction opc);
-void jmprcc(UDSPInstruction opc);
-void loop(UDSPInstruction opc);
-void loopi(UDSPInstruction opc);
-void lr(UDSPInstruction opc);
-void lri(UDSPInstruction opc);
-void lris(UDSPInstruction opc);
-void lrr(UDSPInstruction opc);
-void lrrd(UDSPInstruction opc);
-void lrri(UDSPInstruction opc);
-void lrrn(UDSPInstruction opc);
-void lrs(UDSPInstruction opc);
-void lsl(UDSPInstruction opc);
-void lsl16(UDSPInstruction opc);
-void lsr(UDSPInstruction opc);
-void lsr16(UDSPInstruction opc);
-void lsrn(UDSPInstruction opc);
-void lsrnr(UDSPInstruction opc);
-void lsrnrx(UDSPInstruction opc);
-void madd(UDSPInstruction opc);
-void maddc(UDSPInstruction opc);
-void maddx(UDSPInstruction opc);
-void mov(UDSPInstruction opc);
-void movax(UDSPInstruction opc);
-void movnp(UDSPInstruction opc);
-void movp(UDSPInstruction opc);
-void movpz(UDSPInstruction opc);
-void movr(UDSPInstruction opc);
-void mrr(UDSPInstruction opc);
-void msub(UDSPInstruction opc);
-void msubc(UDSPInstruction opc);
-void msubx(UDSPInstruction opc);
-void mul(UDSPInstruction opc);
-void mulac(UDSPInstruction opc);
-void mulaxh(UDSPInstruction opc);
-void mulc(UDSPInstruction opc);
-void mulcac(UDSPInstruction opc);
-void mulcmv(UDSPInstruction opc);
-void mulcmvz(UDSPInstruction opc);
-void mulmv(UDSPInstruction opc);
-void mulmvz(UDSPInstruction opc);
-void mulx(UDSPInstruction opc);
-void mulxac(UDSPInstruction opc);
-void mulxmv(UDSPInstruction opc);
-void mulxmvz(UDSPInstruction opc);
-void neg(UDSPInstruction opc);
-void nop(UDSPInstruction opc);
-void notc(UDSPInstruction opc);
-void nx(UDSPInstruction opc);
-void orc(UDSPInstruction opc);
-void ori(UDSPInstruction opc);
-void orr(UDSPInstruction opc);
-void ret(UDSPInstruction opc);
-void rti(UDSPInstruction opc);
-void sbclr(UDSPInstruction opc);
-void sbset(UDSPInstruction opc);
-void si(UDSPInstruction opc);
-void sr(UDSPInstruction opc);
-void srbith(UDSPInstruction opc);
-void srr(UDSPInstruction opc);
-void srrd(UDSPInstruction opc);
-void srri(UDSPInstruction opc);
-void srrn(UDSPInstruction opc);
-void srs(UDSPInstruction opc);
-void sub(UDSPInstruction opc);
-void subarn(UDSPInstruction opc);
-void subax(UDSPInstruction opc);
-void subp(UDSPInstruction opc);
-void subr(UDSPInstruction opc);
-void tst(UDSPInstruction opc);
-void tstaxh(UDSPInstruction opc);
-void tstprod(UDSPInstruction opc);
-void xorc(UDSPInstruction opc);
-void xori(UDSPInstruction opc);
-void xorr(UDSPInstruction opc);
+class Interpreter
+{
+public:
+ explicit Interpreter(DSPCore& dsp);
+ ~Interpreter();
+
+ Interpreter(const Interpreter&) = delete;
+ Interpreter& operator=(const Interpreter&) = delete;
+
+ Interpreter(Interpreter&&) = delete;
+ Interpreter& operator=(Interpreter&&) = delete;
+
+ void Step();
+
+ // If these simply return the same number of cycles as was passed into them,
+ // chances are that the DSP is halted.
+ // The difference between them is that the debug one obeys breakpoints.
+ int RunCyclesThread(int cycles);
+ int RunCycles(int cycles);
+ int RunCyclesDebug(int cycles);
+
+ void WriteCR(u16 val);
+ u16 ReadCR();
+
+ void SetSRFlag(u16 flag);
+ bool IsSRFlagSet(u16 flag) const;
+
+ void ApplyWriteBackLog();
+
+ // All the opcode functions.
+ void abs(UDSPInstruction opc);
+ void add(UDSPInstruction opc);
+ void addarn(UDSPInstruction opc);
+ void addax(UDSPInstruction opc);
+ void addaxl(UDSPInstruction opc);
+ void addi(UDSPInstruction opc);
+ void addis(UDSPInstruction opc);
+ void addp(UDSPInstruction opc);
+ void addpaxz(UDSPInstruction opc);
+ void addr(UDSPInstruction opc);
+ void andc(UDSPInstruction opc);
+ void andcf(UDSPInstruction opc);
+ void andf(UDSPInstruction opc);
+ void andi(UDSPInstruction opc);
+ void andr(UDSPInstruction opc);
+ void asl(UDSPInstruction opc);
+ void asr(UDSPInstruction opc);
+ void asr16(UDSPInstruction opc);
+ void asrn(UDSPInstruction opc);
+ void asrnr(UDSPInstruction opc);
+ void asrnrx(UDSPInstruction opc);
+ void bloop(UDSPInstruction opc);
+ void bloopi(UDSPInstruction opc);
+ void call(UDSPInstruction opc);
+ void callr(UDSPInstruction opc);
+ void clr(UDSPInstruction opc);
+ void clrl(UDSPInstruction opc);
+ void clrp(UDSPInstruction opc);
+ void cmp(UDSPInstruction opc);
+ void cmpar(UDSPInstruction opc);
+ void cmpi(UDSPInstruction opc);
+ void cmpis(UDSPInstruction opc);
+ void dar(UDSPInstruction opc);
+ void dec(UDSPInstruction opc);
+ void decm(UDSPInstruction opc);
+ void halt(UDSPInstruction opc);
+ void iar(UDSPInstruction opc);
+ void ifcc(UDSPInstruction opc);
+ void ilrr(UDSPInstruction opc);
+ void ilrrd(UDSPInstruction opc);
+ void ilrri(UDSPInstruction opc);
+ void ilrrn(UDSPInstruction opc);
+ void inc(UDSPInstruction opc);
+ void incm(UDSPInstruction opc);
+ void jcc(UDSPInstruction opc);
+ void jmprcc(UDSPInstruction opc);
+ void loop(UDSPInstruction opc);
+ void loopi(UDSPInstruction opc);
+ void lr(UDSPInstruction opc);
+ void lri(UDSPInstruction opc);
+ void lris(UDSPInstruction opc);
+ void lrr(UDSPInstruction opc);
+ void lrrd(UDSPInstruction opc);
+ void lrri(UDSPInstruction opc);
+ void lrrn(UDSPInstruction opc);
+ void lrs(UDSPInstruction opc);
+ void lsl(UDSPInstruction opc);
+ void lsl16(UDSPInstruction opc);
+ void lsr(UDSPInstruction opc);
+ void lsr16(UDSPInstruction opc);
+ void lsrn(UDSPInstruction opc);
+ void lsrnr(UDSPInstruction opc);
+ void lsrnrx(UDSPInstruction opc);
+ void madd(UDSPInstruction opc);
+ void maddc(UDSPInstruction opc);
+ void maddx(UDSPInstruction opc);
+ void mov(UDSPInstruction opc);
+ void movax(UDSPInstruction opc);
+ void movnp(UDSPInstruction opc);
+ void movp(UDSPInstruction opc);
+ void movpz(UDSPInstruction opc);
+ void movr(UDSPInstruction opc);
+ void mrr(UDSPInstruction opc);
+ void msub(UDSPInstruction opc);
+ void msubc(UDSPInstruction opc);
+ void msubx(UDSPInstruction opc);
+ void mul(UDSPInstruction opc);
+ void mulac(UDSPInstruction opc);
+ void mulaxh(UDSPInstruction opc);
+ void mulc(UDSPInstruction opc);
+ void mulcac(UDSPInstruction opc);
+ void mulcmv(UDSPInstruction opc);
+ void mulcmvz(UDSPInstruction opc);
+ void mulmv(UDSPInstruction opc);
+ void mulmvz(UDSPInstruction opc);
+ void mulx(UDSPInstruction opc);
+ void mulxac(UDSPInstruction opc);
+ void mulxmv(UDSPInstruction opc);
+ void mulxmvz(UDSPInstruction opc);
+ void neg(UDSPInstruction opc);
+ void nop(UDSPInstruction opc);
+ void notc(UDSPInstruction opc);
+ void nx(UDSPInstruction opc);
+ void orc(UDSPInstruction opc);
+ void ori(UDSPInstruction opc);
+ void orr(UDSPInstruction opc);
+ void ret(UDSPInstruction opc);
+ void rti(UDSPInstruction opc);
+ void sbclr(UDSPInstruction opc);
+ void sbset(UDSPInstruction opc);
+ void si(UDSPInstruction opc);
+ void sr(UDSPInstruction opc);
+ void srbith(UDSPInstruction opc);
+ void srr(UDSPInstruction opc);
+ void srrd(UDSPInstruction opc);
+ void srri(UDSPInstruction opc);
+ void srrn(UDSPInstruction opc);
+ void srs(UDSPInstruction opc);
+ void sub(UDSPInstruction opc);
+ void subarn(UDSPInstruction opc);
+ void subax(UDSPInstruction opc);
+ void subp(UDSPInstruction opc);
+ void subr(UDSPInstruction opc);
+ void tst(UDSPInstruction opc);
+ void tstaxh(UDSPInstruction opc);
+ void tstprod(UDSPInstruction opc);
+ void xorc(UDSPInstruction opc);
+ void xori(UDSPInstruction opc);
+ void xorr(UDSPInstruction opc);
+
+ // Extended ops
+ void l(UDSPInstruction opc);
+ void ln(UDSPInstruction opc);
+ void ls(UDSPInstruction opc);
+ void lsn(UDSPInstruction opc);
+ void lsm(UDSPInstruction opc);
+ void lsnm(UDSPInstruction opc);
+ void sl(UDSPInstruction opc);
+ void sln(UDSPInstruction opc);
+ void slm(UDSPInstruction opc);
+ void slnm(UDSPInstruction opc);
+ void s(UDSPInstruction opc);
+ void sn(UDSPInstruction opc);
+ void ld(UDSPInstruction opc);
+ void ldax(UDSPInstruction opc);
+ void ldn(UDSPInstruction opc);
+ void ldaxn(UDSPInstruction opc);
+ void ldm(UDSPInstruction opc);
+ void ldaxm(UDSPInstruction opc);
+ void ldnm(UDSPInstruction opc);
+ void ldaxnm(UDSPInstruction opc);
+ void mv(UDSPInstruction opc);
+ void dr(UDSPInstruction opc);
+ void ir(UDSPInstruction opc);
+ void nr(UDSPInstruction opc);
+ void nop_ext(UDSPInstruction opc);
+
+private:
+ void ExecuteInstruction(UDSPInstruction inst);
+
+ bool CheckCondition(u8 condition) const;
+
+ // See: DspIntBranch.cpp
+ void HandleLoop();
+
+ u16 IncrementAddressRegister(u16 reg) const;
+ u16 DecrementAddressRegister(u16 reg) const;
+
+ u16 IncreaseAddressRegister(u16 reg, s16 ix_) const;
+ u16 DecreaseAddressRegister(u16 reg, s16 ix_) const;
+
+ s32 GetLongACX(s32 reg) const;
+ s16 GetAXLow(s32 reg) const;
+ s16 GetAXHigh(s32 reg) const;
+
+ s64 GetLongAcc(s32 reg) const;
+ void SetLongAcc(s32 reg, s64 value);
+ s16 GetAccLow(s32 reg) const;
+ s16 GetAccMid(s32 reg) const;
+ s16 GetAccHigh(s32 reg) const;
+
+ s64 GetLongProduct() const;
+ s64 GetLongProductRounded() const;
+ void SetLongProduct(s64 value);
+
+ s64 GetMultiplyProduct(u16 a, u16 b, u8 sign = 0) const;
+ s64 Multiply(u16 a, u16 b, u8 sign = 0) const;
+ s64 MultiplyAdd(u16 a, u16 b, u8 sign = 0) const;
+ s64 MultiplySub(u16 a, u16 b, u8 sign = 0) const;
+ s64 MultiplyMulX(u8 axh0, u8 axh1, u16 val1, u16 val2) const;
+
+ void UpdateSR16(s16 value, bool carry = false, bool overflow = false, bool over_s32 = false);
+ void UpdateSR64(s64 value, bool carry = false, bool overflow = false);
+ void UpdateSRLogicZero(bool value);
+
+ u16 OpReadRegister(int reg_);
+ u16 OpReadRegisterAndSaturate(int reg) const;
+ void OpWriteRegister(int reg_, u16 val);
+
+ void ConditionalExtendAccum(int reg);
+
+ // The ext ops are calculated in parallel with the actual op. That means that
+ // both the main op and the ext op see the same register state as input. The
+ // output is simple as long as the main and ext ops don't change the same
+ // register. If they do the output is the bitwise OR of the result of both the
+ // main and ext ops.
+ void WriteToBackLog(int i, int idx, u16 value);
+ void ZeroWriteBackLog();
+ void ZeroWriteBackLogPreserveAcc(u8 acc);
+
+ DSPCore& m_dsp_core;
+ static constexpr size_t WRITEBACK_LOG_SIZE = 5;
+ std::array<u16, WRITEBACK_LOG_SIZE> m_write_back_log{};
+ std::array<int, WRITEBACK_LOG_SIZE> m_write_back_log_idx{-1, -1, -1, -1, -1};
+};
} // namespace DSP::Interpreter
diff --git a/Source/Core/Core/DSP/Jit/DSPEmitterBase.cpp b/Source/Core/Core/DSP/Jit/DSPEmitterBase.cpp
index be6208bdbe..29d416a2e0 100644
--- a/Source/Core/Core/DSP/Jit/DSPEmitterBase.cpp
+++ b/Source/Core/Core/DSP/Jit/DSPEmitterBase.cpp
@@ -12,10 +12,10 @@ namespace DSP::JIT
{
DSPEmitter::~DSPEmitter() = default;
-std::unique_ptr<DSPEmitter> CreateDSPEmitter()
+std::unique_ptr<DSPEmitter> CreateDSPEmitter([[maybe_unused]] DSPCore& dsp)
{
#if defined(_M_X86) || defined(_M_X86_64)
- return std::make_unique<x64::DSPEmitter>();
+ return std::make_unique<x64::DSPEmitter>(dsp);
#else
return std::make_unique<DSPEmitterNull>();
#endif
diff --git a/Source/Core/Core/DSP/Jit/DSPEmitterBase.h b/Source/Core/Core/DSP/Jit/DSPEmitterBase.h
index 7120e1de68..cc48ca4452 100644
--- a/Source/Core/Core/DSP/Jit/DSPEmitterBase.h
+++ b/Source/Core/Core/DSP/Jit/DSPEmitterBase.h
@@ -10,6 +10,11 @@
class PointerWrap;
+namespace DSP
+{
+class DSPCore;
+}
+
namespace DSP::JIT
{
class DSPEmitter
@@ -31,5 +36,5 @@ public:
void DoState(PointerWrap&) override {}
};
-std::unique_ptr<DSPEmitter> CreateDSPEmitter();
+std::unique_ptr<DSPEmitter> CreateDSPEmitter(DSPCore& dsp);
} // namespace DSP::JIT
diff --git a/Source/Core/Core/DSP/Jit/x64/DSPEmitter.cpp b/Source/Core/Core/DSP/Jit/x64/DSPEmitter.cpp
index 727b48267c..25f26d0f34 100644
--- a/Source/Core/Core/DSP/Jit/x64/DSPEmitter.cpp
+++ b/Source/Core/Core/DSP/Jit/x64/DSPEmitter.cpp
@@ -17,9 +17,9 @@
#include "Core/DSP/DSPAnalyzer.h"
#include "Core/DSP/DSPCore.h"
#include "Core/DSP/DSPHost.h"
-#include "Core/DSP/DSPMemoryMap.h"
#include "Core/DSP/DSPTables.h"
#include "Core/DSP/Interpreter/DSPIntTables.h"
+#include "Core/DSP/Interpreter/DSPInterpreter.h"
#include "Core/DSP/Jit/x64/DSPJitTables.h"
using namespace Gen;
@@ -30,9 +30,9 @@ constexpr size_t COMPILED_CODE_SIZE = 2097152;
constexpr size_t MAX_BLOCK_SIZE = 250;
constexpr u16 DSP_IDLE_SKIP_CYCLES = 0x1000;
-DSPEmitter::DSPEmitter()
+DSPEmitter::DSPEmitter(DSPCore& dsp)
: 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)
+ m_block_size(MAX_BLOCKS), m_block_links(MAX_BLOCKS), m_dsp_core{dsp}
{
x64::InitInstructionTables();
AllocCodeSpace(COMPILED_CODE_SIZE);
@@ -51,18 +51,18 @@ DSPEmitter::~DSPEmitter()
u16 DSPEmitter::RunCycles(u16 cycles)
{
- if (g_dsp.external_interrupt_waiting)
+ if (m_dsp_core.DSPState().external_interrupt_waiting)
{
- DSPCore_CheckExternalInterrupt();
- DSPCore_CheckExceptions();
- DSPCore_SetExternalInterrupt(false);
+ m_dsp_core.CheckExternalInterrupt();
+ m_dsp_core.CheckExceptions();
+ m_dsp_core.SetExternalInterrupt(false);
}
m_cycles_left = cycles;
auto exec_addr = (DSPCompiledCode)m_enter_dispatcher;
exec_addr();
- if (g_dsp.reset_dspjit_codespace)
+ if (m_dsp_core.DSPState().reset_dspjit_codespace)
ClearIRAMandDSPJITCodespaceReset();
return m_cycles_left;
@@ -82,7 +82,7 @@ void DSPEmitter::ClearIRAM()
m_block_size[i] = 0;
m_unresolved_jumps[i].clear();
}
- g_dsp.reset_dspjit_codespace = true;
+ m_dsp_core.DSPState().reset_dspjit_codespace = true;
}
void DSPEmitter::ClearIRAMandDSPJITCodespaceReset()
@@ -98,7 +98,12 @@ void DSPEmitter::ClearIRAMandDSPJITCodespaceReset()
m_block_size[i] = 0;
m_unresolved_jumps[i].clear();
}
- g_dsp.reset_dspjit_codespace = false;
+ m_dsp_core.DSPState().reset_dspjit_codespace = false;
+}
+
+static void CheckExceptionsThunk(DSPCore& dsp)
+{
+ dsp.CheckExceptions();
}
// Must go out of block if exception is detected
@@ -112,7 +117,7 @@ void DSPEmitter::checkExceptions(u32 retval)
DSPJitRegCache c(m_gpr);
m_gpr.SaveRegs();
- ABI_CallFunction(DSPCore_CheckExceptions);
+ ABI_CallFunctionP(CheckExceptionsThunk, &m_dsp_core);
MOV(32, R(EAX), Imm32(retval));
JMP(m_return_dispatcher, true);
m_gpr.LoadRegs(false);
@@ -128,6 +133,11 @@ bool DSPEmitter::FlagsNeeded() const
return !(flags & Analyzer::CODE_START_OF_INST) || (flags & Analyzer::CODE_UPDATE_SR);
}
+static void FallbackThunk(Interpreter::Interpreter& interpreter, UDSPInstruction inst)
+{
+ (interpreter.*Interpreter::GetOp(inst))(inst);
+}
+
void DSPEmitter::FallBackToInterpreter(UDSPInstruction inst)
{
const DSPOPCTemplate* const op_template = GetOpTemplate(inst);
@@ -146,10 +156,20 @@ void DSPEmitter::FallBackToInterpreter(UDSPInstruction inst)
m_gpr.PushRegs();
ASSERT_MSG(DSPLLE, interpreter_function != nullptr, "No function for %04x", inst);
- ABI_CallFunctionC16(interpreter_function, inst);
+ ABI_CallFunctionPC(FallbackThunk, &m_dsp_core.GetInterpreter(), inst);
m_gpr.PopRegs();
}
+static void FallbackExtThunk(Interpreter::Interpreter& interpreter, UDSPInstruction inst)
+{
+ (interpreter.*Interpreter::GetExtOp(inst))(inst);
+}
+
+static void ApplyWriteBackLogThunk(Interpreter::Interpreter& interpreter)
+{
+ interpreter.ApplyWriteBackLog();
+}
+
void DSPEmitter::EmitInstruction(UDSPInstruction inst)
{
const DSPOPCTemplate* const op_template = GetOpTemplate(inst);
@@ -168,10 +188,8 @@ void DSPEmitter::EmitInstruction(UDSPInstruction inst)
else
{
// Fall back to interpreter
- const auto interpreter_function = Interpreter::GetExtOp(inst);
-
m_gpr.PushRegs();
- ABI_CallFunctionC16(interpreter_function, inst);
+ ABI_CallFunctionPC(FallbackExtThunk, &m_dsp_core.GetInterpreter(), inst);
m_gpr.PopRegs();
INFO_LOG_FMT(DSPLLE, "Instruction not JITed(ext part): {:04x}", inst);
ext_is_jit = false;
@@ -198,7 +216,7 @@ void DSPEmitter::EmitInstruction(UDSPInstruction inst)
// need to call the online cleanup function because
// the writeBackLog gets populated at runtime
m_gpr.PushRegs();
- ABI_CallFunction(ApplyWriteBackLog);
+ ABI_CallFunctionP(ApplyWriteBackLogThunk, &m_dsp_core.GetInterpreter());
m_gpr.PopRegs();
}
else
@@ -229,7 +247,7 @@ void DSPEmitter::Compile(u16 start_addr)
if (Analyzer::GetCodeFlags(m_compile_pc) & Analyzer::CODE_CHECK_INT)
checkExceptions(m_block_size[start_addr]);
- UDSPInstruction inst = dsp_imem_read(m_compile_pc);
+ const UDSPInstruction inst = m_dsp_core.DSPState().ReadIMEM(m_compile_pc);
const DSPOPCTemplate* opcode = GetOpTemplate(inst);
EmitInstruction(inst);
@@ -377,7 +395,7 @@ void DSPEmitter::Compile(u16 start_addr)
void DSPEmitter::CompileCurrent(DSPEmitter& emitter)
{
- emitter.Compile(g_dsp.pc);
+ emitter.Compile(emitter.m_dsp_core.DSPState().pc);
bool retry = true;
@@ -414,7 +432,7 @@ void DSPEmitter::CompileDispatcher()
BitSet32 registers_used = ABI_ALL_CALLEE_SAVED & BitSet32(0xffff);
ABI_PushRegistersAndAdjustStack(registers_used, 8);
- MOV(64, R(R15), ImmPtr(&g_dsp));
+ MOV(64, R(R15), ImmPtr(&m_dsp_core.DSPState()));
const u8* dispatcherLoop = GetCodePtr();
diff --git a/Source/Core/Core/DSP/Jit/x64/DSPEmitter.h b/Source/Core/Core/DSP/Jit/x64/DSPEmitter.h
index 4c65c9ad4e..3429cf6b51 100644
--- a/Source/Core/Core/DSP/Jit/x64/DSPEmitter.h
+++ b/Source/Core/Core/DSP/Jit/x64/DSPEmitter.h
@@ -28,7 +28,7 @@ namespace JIT::x64
class DSPEmitter final : public JIT::DSPEmitter, public Gen::X64CodeBlock
{
public:
- DSPEmitter();
+ explicit DSPEmitter(DSPCore& dsp);
~DSPEmitter() override;
u16 RunCycles(u16 cycles) override;
@@ -197,6 +197,9 @@ private:
// within the class itself to allow access to member variables.
static void CompileCurrent(DSPEmitter& emitter);
+ static u16 ReadIFXRegisterHelper(DSPEmitter& emitter, u16 address);
+ static void WriteIFXRegisterHelper(DSPEmitter& emitter, u16 address, u16 value);
+
void EmitInstruction(UDSPInstruction inst);
void ClearIRAMandDSPJITCodespaceReset();
@@ -321,6 +324,8 @@ private:
const u8* m_enter_dispatcher;
const u8* m_return_dispatcher;
const u8* m_stub_entry_point;
+
+ DSPCore& m_dsp_core;
};
} // namespace JIT::x64
diff --git a/Source/Core/Core/DSP/Jit/x64/DSPJitArithmetic.cpp b/Source/Core/Core/DSP/Jit/x64/DSPJitArithmetic.cpp
index 7d421b50a7..7efa262609 100644
--- a/Source/Core/Core/DSP/Jit/x64/DSPJitArithmetic.cpp
+++ b/Source/Core/Core/DSP/Jit/x64/DSPJitArithmetic.cpp
@@ -7,7 +7,6 @@
#include "Common/CommonTypes.h"
#include "Core/DSP/DSPCore.h"
-#include "Core/DSP/DSPMemoryMap.h"
#include "Core/DSP/Jit/x64/DSPEmitter.h"
using namespace Gen;
@@ -65,9 +64,9 @@ void DSPEmitter::andcf(const UDSPInstruction opc)
{
if (FlagsNeeded())
{
- u8 reg = (opc >> 8) & 0x1;
+ const u8 reg = (opc >> 8) & 0x1;
// u16 imm = dsp_fetch_code();
- u16 imm = dsp_imem_read(m_compile_pc + 1);
+ const u16 imm = m_dsp_core.DSPState().ReadIMEM(m_compile_pc + 1);
// u16 val = dsp_get_acc_m(reg);
get_acc_m(reg);
// Update_SR_LZ(((val & imm) == imm) ? true : false);
@@ -100,9 +99,9 @@ void DSPEmitter::andf(const UDSPInstruction opc)
{
if (FlagsNeeded())
{
- u8 reg = (opc >> 8) & 0x1;
+ const u8 reg = (opc >> 8) & 0x1;
// u16 imm = dsp_fetch_code();
- u16 imm = dsp_imem_read(m_compile_pc + 1);
+ const u16 imm = m_dsp_core.DSPState().ReadIMEM(m_compile_pc + 1);
// u16 val = dsp_get_acc_m(reg);
get_acc_m(reg);
// Update_SR_LZ(((val & imm) == 0) ? true : false);
@@ -226,14 +225,14 @@ void DSPEmitter::cmpi(const UDSPInstruction opc)
{
if (FlagsNeeded())
{
- u8 reg = (opc >> 8) & 0x1;
- X64Reg tmp1 = m_gpr.GetFreeXReg();
+ const u8 reg = (opc >> 8) & 0x1;
+ const X64Reg tmp1 = m_gpr.GetFreeXReg();
// s64 val = dsp_get_long_acc(reg);
get_long_acc(reg, tmp1);
MOV(64, R(RAX), R(tmp1));
// s64 imm = (s64)(s16)dsp_fetch_code() << 16; // Immediate is considered to be at M level in
// the 40-bit accumulator.
- u16 imm = dsp_imem_read(m_compile_pc + 1);
+ const u16 imm = m_dsp_core.DSPState().ReadIMEM(m_compile_pc + 1);
MOV(64, R(RDX), Imm64((s64)(s16)imm << 16));
// s64 res = dsp_convert_long_acc(val - imm);
SUB(64, R(RAX), R(RDX));
@@ -451,9 +450,9 @@ void DSPEmitter::notc(const UDSPInstruction opc)
// flags out: --xx xx00
void DSPEmitter::xori(const UDSPInstruction opc)
{
- u8 reg = (opc >> 8) & 0x1;
+ const u8 reg = (opc >> 8) & 0x1;
// u16 imm = dsp_fetch_code();
- u16 imm = dsp_imem_read(m_compile_pc + 1);
+ const u16 imm = m_dsp_core.DSPState().ReadIMEM(m_compile_pc + 1);
// g_dsp.r.acm[reg] ^= imm;
get_acc_m(reg, RAX);
XOR(16, R(RAX), Imm16(imm));
@@ -474,9 +473,9 @@ void DSPEmitter::xori(const UDSPInstruction opc)
// flags out: --xx xx00
void DSPEmitter::andi(const UDSPInstruction opc)
{
- u8 reg = (opc >> 8) & 0x1;
+ const u8 reg = (opc >> 8) & 0x1;
// u16 imm = dsp_fetch_code();
- u16 imm = dsp_imem_read(m_compile_pc + 1);
+ const u16 imm = m_dsp_core.DSPState().ReadIMEM(m_compile_pc + 1);
// g_dsp.r.acm[reg] &= imm;
get_acc_m(reg, RAX);
AND(16, R(RAX), Imm16(imm));
@@ -497,9 +496,9 @@ void DSPEmitter::andi(const UDSPInstruction opc)
// flags out: --xx xx00
void DSPEmitter::ori(const UDSPInstruction opc)
{
- u8 reg = (opc >> 8) & 0x1;
+ const u8 reg = (opc >> 8) & 0x1;
// u16 imm = dsp_fetch_code();
- u16 imm = dsp_imem_read(m_compile_pc + 1);
+ const u16 imm = m_dsp_core.DSPState().ReadIMEM(m_compile_pc + 1);
// g_dsp.r.acm[reg] |= imm;
get_acc_m(reg, RAX);
OR(16, R(RAX), Imm16(imm));
@@ -699,7 +698,7 @@ void DSPEmitter::addi(const UDSPInstruction opc)
get_long_acc(areg, tmp1);
MOV(64, R(RAX), R(tmp1));
// s64 imm = (s16)dsp_fetch_code();
- s16 imm = dsp_imem_read(m_compile_pc + 1);
+ const s16 imm = m_dsp_core.DSPState().ReadIMEM(m_compile_pc + 1);
// imm <<= 16;
MOV(64, R(RDX), Imm32(imm << 16));
// s64 res = acc + imm;
diff --git a/Source/Core/Core/DSP/Jit/x64/DSPJitBranch.cpp b/Source/Core/Core/DSP/Jit/x64/DSPJitBranch.cpp
index 339d81b4e3..664ce367c6 100644
--- a/Source/Core/Core/DSP/Jit/x64/DSPJitBranch.cpp
+++ b/Source/Core/Core/DSP/Jit/x64/DSPJitBranch.cpp
@@ -6,7 +6,6 @@
#include "Core/DSP/DSPAnalyzer.h"
#include "Core/DSP/DSPCore.h"
-#include "Core/DSP/DSPMemoryMap.h"
#include "Core/DSP/DSPTables.h"
#include "Core/DSP/Jit/x64/DSPEmitter.h"
@@ -126,7 +125,7 @@ void DSPEmitter::WriteBlockLink(u16 dest)
void DSPEmitter::r_jcc(const UDSPInstruction opc)
{
- u16 dest = dsp_imem_read(m_compile_pc + 1);
+ const u16 dest = m_dsp_core.DSPState().ReadIMEM(m_compile_pc + 1);
const DSPOPCTemplate* opcode = GetOpTemplate(opc);
// If the block is unconditional, attempt to link block
@@ -172,7 +171,7 @@ void DSPEmitter::r_call(const UDSPInstruction opc)
{
MOV(16, R(DX), Imm16(m_compile_pc + 2));
dsp_reg_store_stack(StackRegister::Call);
- u16 dest = dsp_imem_read(m_compile_pc + 1);
+ const u16 dest = m_dsp_core.DSPState().ReadIMEM(m_compile_pc + 1);
const DSPOPCTemplate* opcode = GetOpTemplate(opc);
// If the block is unconditional, attempt to link block
@@ -228,8 +227,9 @@ void DSPEmitter::r_ifcc(const UDSPInstruction opc)
// NOTE: Cannot use FallBackToInterpreter(opc) here because of the need to write branch exit
void DSPEmitter::ifcc(const UDSPInstruction opc)
{
+ const auto& state = m_dsp_core.DSPState();
const u16 address = m_compile_pc + 1;
- const DSPOPCTemplate* const op_template = GetOpTemplate(dsp_imem_read(address));
+ const DSPOPCTemplate* const op_template = GetOpTemplate(state.ReadIMEM(address));
MOV(16, M_SDSP_pc(), Imm16(address + op_template->size));
ReJitConditional(opc, &DSPEmitter::r_ifcc);
@@ -347,7 +347,8 @@ void DSPEmitter::loop(const UDSPInstruction opc)
SetJumpTarget(cnt);
// dsp_skip_inst();
- MOV(16, M_SDSP_pc(), Imm16(loop_pc + GetOpTemplate(dsp_imem_read(loop_pc))->size));
+ const auto& state = m_dsp_core.DSPState();
+ MOV(16, M_SDSP_pc(), Imm16(loop_pc + GetOpTemplate(state.ReadIMEM(loop_pc))->size));
WriteBranchExit();
m_gpr.FlushRegs(c, false);
SetJumpTarget(exit);
@@ -380,7 +381,8 @@ void DSPEmitter::loopi(const UDSPInstruction opc)
else
{
// dsp_skip_inst();
- MOV(16, M_SDSP_pc(), Imm16(loop_pc + GetOpTemplate(dsp_imem_read(loop_pc))->size));
+ const auto& state = m_dsp_core.DSPState();
+ MOV(16, M_SDSP_pc(), Imm16(loop_pc + GetOpTemplate(state.ReadIMEM(loop_pc))->size));
WriteBranchExit();
}
}
@@ -396,11 +398,11 @@ void DSPEmitter::loopi(const UDSPInstruction opc)
// Up to 4 nested loops are allowed.
void DSPEmitter::bloop(const UDSPInstruction opc)
{
- u16 reg = opc & 0x1f;
+ const u16 reg = opc & 0x1f;
// u16 cnt = g_dsp.r[reg];
// todo: check if we can use normal variant here
dsp_op_read_reg_dont_saturate(reg, RDX, RegisterExtension::Zero);
- u16 loop_pc = dsp_imem_read(m_compile_pc + 1);
+ const u16 loop_pc = m_dsp_core.DSPState().ReadIMEM(m_compile_pc + 1);
TEST(16, R(EDX), R(EDX));
DSPJitRegCache c(m_gpr);
@@ -417,7 +419,8 @@ void DSPEmitter::bloop(const UDSPInstruction opc)
SetJumpTarget(cnt);
// g_dsp.pc = loop_pc;
// dsp_skip_inst();
- MOV(16, M_SDSP_pc(), Imm16(loop_pc + GetOpTemplate(dsp_imem_read(loop_pc))->size));
+ const auto& state = m_dsp_core.DSPState();
+ MOV(16, M_SDSP_pc(), Imm16(loop_pc + GetOpTemplate(state.ReadIMEM(loop_pc))->size));
WriteBranchExit();
m_gpr.FlushRegs(c, false);
SetJumpTarget(exit);
@@ -434,11 +437,12 @@ void DSPEmitter::bloop(const UDSPInstruction opc)
// nested loops are allowed.
void DSPEmitter::bloopi(const UDSPInstruction opc)
{
- u16 cnt = opc & 0xff;
+ const auto& state = m_dsp_core.DSPState();
+ const u16 cnt = opc & 0xff;
// u16 loop_pc = dsp_fetch_code();
- u16 loop_pc = dsp_imem_read(m_compile_pc + 1);
+ const u16 loop_pc = state.ReadIMEM(m_compile_pc + 1);
- if (cnt)
+ if (cnt != 0)
{
MOV(16, R(RDX), Imm16(m_compile_pc + 2));
dsp_reg_store_stack(StackRegister::Call);
@@ -453,7 +457,7 @@ void DSPEmitter::bloopi(const UDSPInstruction opc)
{
// g_dsp.pc = loop_pc;
// dsp_skip_inst();
- MOV(16, M_SDSP_pc(), Imm16(loop_pc + GetOpTemplate(dsp_imem_read(loop_pc))->size));
+ MOV(16, M_SDSP_pc(), Imm16(loop_pc + GetOpTemplate(state.ReadIMEM(loop_pc))->size));
WriteBranchExit();
}
}
diff --git a/Source/Core/Core/DSP/Jit/x64/DSPJitLoadStore.cpp b/Source/Core/Core/DSP/Jit/x64/DSPJitLoadStore.cpp
index bf46a9a6cf..05b93f4e67 100644
--- a/Source/Core/Core/DSP/Jit/x64/DSPJitLoadStore.cpp
+++ b/Source/Core/Core/DSP/Jit/x64/DSPJitLoadStore.cpp
@@ -7,7 +7,6 @@
#include "Common/CommonTypes.h"
#include "Core/DSP/DSPCore.h"
-#include "Core/DSP/DSPMemoryMap.h"
#include "Core/DSP/Jit/x64/DSPEmitter.h"
using namespace Gen;
@@ -65,8 +64,8 @@ void DSPEmitter::lrs(const UDSPInstruction opc)
// Move value from data memory pointed by address M to register $D.
void DSPEmitter::lr(const UDSPInstruction opc)
{
- int reg = opc & 0x1F;
- u16 address = dsp_imem_read(m_compile_pc + 1);
+ const int reg = opc & 0x1F;
+ const u16 address = m_dsp_core.DSPState().ReadIMEM(m_compile_pc + 1);
dmem_read_imm(address);
dsp_op_write_reg(reg, EAX);
dsp_conditional_extend_accum(reg);
@@ -78,10 +77,10 @@ void DSPEmitter::lr(const UDSPInstruction opc)
// Store value from register $S to a memory pointed by address M.
void DSPEmitter::sr(const UDSPInstruction opc)
{
- u8 reg = opc & 0x1F;
- u16 address = dsp_imem_read(m_compile_pc + 1);
+ const u8 reg = opc & 0x1F;
+ const u16 address = m_dsp_core.DSPState().ReadIMEM(m_compile_pc + 1);
- X64Reg tmp1 = m_gpr.GetFreeXReg();
+ const X64Reg tmp1 = m_gpr.GetFreeXReg();
dsp_op_read_reg(reg, tmp1);
dmem_write_imm(address, tmp1);
@@ -96,10 +95,10 @@ void DSPEmitter::sr(const UDSPInstruction opc)
// M (M is 8-bit value sign extended).
void DSPEmitter::si(const UDSPInstruction opc)
{
- u16 address = (s8)opc;
- u16 imm = dsp_imem_read(m_compile_pc + 1);
+ const u16 address = static_cast<s8>(opc);
+ const u16 imm = m_dsp_core.DSPState().ReadIMEM(m_compile_pc + 1);
- X64Reg tmp1 = m_gpr.GetFreeXReg();
+ const X64Reg tmp1 = m_gpr.GetFreeXReg();
MOV(32, R(tmp1), Imm32((u32)imm));
dmem_write_imm(address, tmp1);
diff --git a/Source/Core/Core/DSP/Jit/x64/DSPJitMisc.cpp b/Source/Core/Core/DSP/Jit/x64/DSPJitMisc.cpp
index 0adfb091a1..49fafe2021 100644
--- a/Source/Core/Core/DSP/Jit/x64/DSPJitMisc.cpp
+++ b/Source/Core/Core/DSP/Jit/x64/DSPJitMisc.cpp
@@ -5,7 +5,6 @@
#include "Common/CommonTypes.h"
#include "Core/DSP/DSPCore.h"
-#include "Core/DSP/DSPMemoryMap.h"
#include "Core/DSP/Jit/x64/DSPEmitter.h"
using namespace Gen;
@@ -36,8 +35,8 @@ void DSPEmitter::mrr(const UDSPInstruction opc)
// S16 mode.
void DSPEmitter::lri(const UDSPInstruction opc)
{
- u8 reg = opc & 0x1F;
- u16 imm = dsp_imem_read(m_compile_pc + 1);
+ const u8 reg = opc & 0x1F;
+ const u16 imm = m_dsp_core.DSPState().ReadIMEM(m_compile_pc + 1);
dsp_op_write_reg_imm(reg, imm);
dsp_conditional_extend_accum_imm(reg, imm);
}
diff --git a/Source/Core/Core/DSP/Jit/x64/DSPJitRegCache.cpp b/Source/Core/Core/DSP/Jit/x64/DSPJitRegCache.cpp
index e00cec1dab..aface8ab9b 100644
--- a/Source/Core/Core/DSP/Jit/x64/DSPJitRegCache.cpp
+++ b/Source/Core/Core/DSP/Jit/x64/DSPJitRegCache.cpp
@@ -11,7 +11,6 @@
#include "Common/Logging/Log.h"
#include "Core/DSP/DSPCore.h"
-#include "Core/DSP/DSPMemoryMap.h"
#include "Core/DSP/Jit/x64/DSPEmitter.h"
using namespace Gen;
diff --git a/Source/Core/Core/DSP/Jit/x64/DSPJitUtil.cpp b/Source/Core/Core/DSP/Jit/x64/DSPJitUtil.cpp
index 206b8a0bf9..1aff54bd12 100644
--- a/Source/Core/Core/DSP/Jit/x64/DSPJitUtil.cpp
+++ b/Source/Core/Core/DSP/Jit/x64/DSPJitUtil.cpp
@@ -6,13 +6,22 @@
#include "Common/Logging/Log.h"
#include "Core/DSP/DSPCore.h"
-#include "Core/DSP/DSPHWInterface.h"
#include "Core/DSP/Jit/x64/DSPEmitter.h"
using namespace Gen;
namespace DSP::JIT::x64
{
+u16 DSPEmitter::ReadIFXRegisterHelper(DSPEmitter& emitter, u16 address)
+{
+ return emitter.m_dsp_core.DSPState().ReadIFX(address);
+}
+
+void DSPEmitter::WriteIFXRegisterHelper(DSPEmitter& emitter, u16 address, u16 value)
+{
+ emitter.m_dsp_core.DSPState().WriteIFX(address, value);
+}
+
// clobbers:
// EAX = (s8)g_dsp.reg_stack_ptrs[reg_index]
// expects:
@@ -32,7 +41,7 @@ void DSPEmitter::dsp_reg_stack_push(StackRegister stack_reg)
// g_dsp.reg_stack[reg_index][g_dsp.reg_stack_ptrs[reg_index]] = g_dsp.r[DSP_REG_ST0 + reg_index];
MOV(16, R(tmp1), M_SDSP_r_st(reg_index));
MOVZX(64, 8, RAX, R(AL));
- MOV(64, R(tmp2), ImmPtr(g_dsp.reg_stacks[reg_index]));
+ MOV(64, R(tmp2), ImmPtr(m_dsp_core.DSPState().reg_stacks[reg_index]));
MOV(16, MComplex(tmp2, EAX, SCALE_2, 0), R(tmp1));
m_gpr.PutXReg(tmp1);
m_gpr.PutXReg(tmp2);
@@ -50,7 +59,7 @@ void DSPEmitter::dsp_reg_stack_pop(StackRegister stack_reg)
X64Reg tmp1 = m_gpr.GetFreeXReg();
X64Reg tmp2 = m_gpr.GetFreeXReg();
MOVZX(64, 8, RAX, R(AL));
- MOV(64, R(tmp2), ImmPtr(g_dsp.reg_stacks[reg_index]));
+ MOV(64, R(tmp2), ImmPtr(m_dsp_core.DSPState().reg_stacks[reg_index]));
MOV(16, R(tmp1), MComplex(tmp2, EAX, SCALE_2, 0));
MOV(16, M_SDSP_r_st(reg_index), R(tmp1));
m_gpr.PutXReg(tmp1);
@@ -520,7 +529,7 @@ void DSPEmitter::dmem_write(X64Reg value)
// g_dsp.dram[addr & DSP_DRAM_MASK] = val;
AND(16, R(EAX), Imm16(DSP_DRAM_MASK));
- MOV(64, R(ECX), ImmPtr(g_dsp.dram));
+ MOV(64, R(ECX), ImmPtr(m_dsp_core.DSPState().dram));
MOV(16, MComplex(ECX, EAX, SCALE_2, 0), R(value));
FixupBranch end = J(true);
@@ -530,7 +539,7 @@ void DSPEmitter::dmem_write(X64Reg value)
X64Reg abisafereg = m_gpr.MakeABICallSafe(value);
MOVZX(32, 16, abisafereg, R(abisafereg));
m_gpr.PushRegs();
- ABI_CallFunctionRR(gdsp_ifx_write, EAX, abisafereg);
+ ABI_CallFunctionPRR(WriteIFXRegisterHelper, this, EAX, abisafereg);
m_gpr.PopRegs();
m_gpr.FlushRegs(c);
SetJumpTarget(end);
@@ -541,7 +550,7 @@ void DSPEmitter::dmem_write_imm(u16 address, X64Reg value)
switch (address >> 12)
{
case 0x0: // 0xxx DRAM
- MOV(64, R(RDX), ImmPtr(g_dsp.dram));
+ MOV(64, R(RDX), ImmPtr(m_dsp_core.DSPState().dram));
MOV(16, MDisp(RDX, (address & DSP_DRAM_MASK) * 2), R(value));
break;
@@ -550,12 +559,13 @@ void DSPEmitter::dmem_write_imm(u16 address, X64Reg value)
MOV(16, R(EAX), Imm16(address));
X64Reg abisafereg = m_gpr.MakeABICallSafe(value);
m_gpr.PushRegs();
- ABI_CallFunctionRR(gdsp_ifx_write, EAX, abisafereg);
+ ABI_CallFunctionPRR(WriteIFXRegisterHelper, this, EAX, abisafereg);
m_gpr.PopRegs();
break;
}
default: // Unmapped/non-existing memory
- ERROR_LOG_FMT(DSPLLE, "{:04x} DSP ERROR: Write to UNKNOWN ({:04x}) memory", g_dsp.pc, address);
+ ERROR_LOG_FMT(DSPLLE, "{:04x} DSP ERROR: Write to UNKNOWN ({:04x}) memory",
+ m_dsp_core.DSPState().pc, address);
break;
}
}
@@ -570,7 +580,7 @@ void DSPEmitter::imem_read(X64Reg address)
FixupBranch irom = J_CC(CC_A);
// return g_dsp.iram[addr & DSP_IRAM_MASK];
AND(16, R(address), Imm16(DSP_IRAM_MASK));
- MOV(64, R(ECX), ImmPtr(g_dsp.iram));
+ MOV(64, R(ECX), ImmPtr(m_dsp_core.DSPState().iram));
MOV(16, R(EAX), MComplex(ECX, address, SCALE_2, 0));
FixupBranch end = J();
@@ -578,7 +588,7 @@ void DSPEmitter::imem_read(X64Reg address)
// else if (addr == 0x8)
// return g_dsp.irom[addr & DSP_IROM_MASK];
AND(16, R(address), Imm16(DSP_IROM_MASK));
- MOV(64, R(ECX), ImmPtr(g_dsp.irom));
+ MOV(64, R(ECX), ImmPtr(m_dsp_core.DSPState().irom));
MOV(16, R(EAX), MComplex(ECX, address, SCALE_2, 0));
SetJumpTarget(end);
@@ -594,7 +604,7 @@ void DSPEmitter::dmem_read(X64Reg address)
FixupBranch dram = J_CC(CC_A);
// return g_dsp.dram[addr & DSP_DRAM_MASK];
AND(32, R(address), Imm32(DSP_DRAM_MASK));
- MOV(64, R(ECX), ImmPtr(g_dsp.dram));
+ MOV(64, R(ECX), ImmPtr(m_dsp_core.DSPState().dram));
MOV(16, R(EAX), MComplex(ECX, address, SCALE_2, 0));
FixupBranch end = J(true);
@@ -604,7 +614,7 @@ void DSPEmitter::dmem_read(X64Reg address)
FixupBranch ifx = J_CC(CC_A);
// return g_dsp.coef[addr & DSP_COEF_MASK];
AND(32, R(address), Imm32(DSP_COEF_MASK));
- MOV(64, R(ECX), ImmPtr(g_dsp.coef));
+ MOV(64, R(ECX), ImmPtr(m_dsp_core.DSPState().coef));
MOV(16, R(EAX), MComplex(ECX, address, SCALE_2, 0));
FixupBranch end2 = J(true);
@@ -614,7 +624,7 @@ void DSPEmitter::dmem_read(X64Reg address)
DSPJitRegCache c(m_gpr);
X64Reg abisafereg = m_gpr.MakeABICallSafe(address);
m_gpr.PushRegs();
- ABI_CallFunctionR(gdsp_ifx_read, abisafereg);
+ ABI_CallFunctionPR(ReadIFXRegisterHelper, this, abisafereg);
m_gpr.PopRegs();
m_gpr.FlushRegs(c);
SetJumpTarget(end);
@@ -626,24 +636,25 @@ void DSPEmitter::dmem_read_imm(u16 address)
switch (address >> 12)
{
case 0x0: // 0xxx DRAM
- MOV(64, R(RDX), ImmPtr(g_dsp.dram));
+ MOV(64, R(RDX), ImmPtr(m_dsp_core.DSPState().dram));
MOV(16, R(EAX), MDisp(RDX, (address & DSP_DRAM_MASK) * 2));
break;
case 0x1: // 1xxx COEF
- MOV(64, R(RDX), ImmPtr(g_dsp.coef));
+ MOV(64, R(RDX), ImmPtr(m_dsp_core.DSPState().coef));
MOV(16, R(EAX), MDisp(RDX, (address & DSP_COEF_MASK) * 2));
break;
case 0xf: // Fxxx HW regs
{
m_gpr.PushRegs();
- ABI_CallFunctionC16(gdsp_ifx_read, address);
+ ABI_CallFunctionPC(ReadIFXRegisterHelper, this, address);
m_gpr.PopRegs();
break;
}
default: // Unmapped/non-existing memory
- ERROR_LOG_FMT(DSPLLE, "{:04x} DSP ERROR: Read from UNKNOWN ({:04x}) memory", g_dsp.pc, address);
+ ERROR_LOG_FMT(DSPLLE, "{:04x} DSP ERROR: Read from UNKNOWN ({:04x}) memory",
+ m_dsp_core.DSPState().pc, address);
}
}
diff --git a/Source/Core/Core/HW/DSPLLE/DSPDebugInterface.cpp b/Source/Core/Core/HW/DSPLLE/DSPDebugInterface.cpp
deleted file mode 100644
index c4f14febbd..0000000000
--- a/Source/Core/Core/HW/DSPLLE/DSPDebugInterface.cpp
+++ /dev/null
@@ -1,323 +0,0 @@
-// Copyright 2009 Dolphin Emulator Project
-// Licensed under GPLv2+
-// Refer to the license.txt file included.
-
-#include "Core/HW/DSPLLE/DSPDebugInterface.h"
-
-#include <array>
-#include <cstddef>
-#include <string>
-
-#include <fmt/format.h>
-
-#include "Common/MsgHandler.h"
-#include "Core/DSP/DSPCore.h"
-#include "Core/DSP/DSPMemoryMap.h"
-#include "Core/HW/DSPLLE/DSPSymbols.h"
-
-namespace DSP::LLE
-{
-void DSPPatches::Patch(std::size_t index)
-{
- PanicAlertFmt("Patch functionality not supported in DSP module.");
-}
-
-DSPDebugInterface::DSPDebugInterface() = default;
-DSPDebugInterface::~DSPDebugInterface() = default;
-
-std::size_t DSPDebugInterface::SetWatch(u32 address, std::string name)
-{
- return m_watches.SetWatch(address, std::move(name));
-}
-
-const Common::Debug::Watch& DSPDebugInterface::GetWatch(std::size_t index) const
-{
- return m_watches.GetWatch(index);
-}
-
-const std::vector<Common::Debug::Watch>& DSPDebugInterface::GetWatches() const
-{
- return m_watches.GetWatches();
-}
-
-void DSPDebugInterface::UnsetWatch(u32 address)
-{
- m_watches.UnsetWatch(address);
-}
-
-void DSPDebugInterface::UpdateWatch(std::size_t index, u32 address, std::string name)
-{
- return m_watches.UpdateWatch(index, address, std::move(name));
-}
-
-void DSPDebugInterface::UpdateWatchAddress(std::size_t index, u32 address)
-{
- return m_watches.UpdateWatchAddress(index, address);
-}
-
-void DSPDebugInterface::UpdateWatchName(std::size_t index, std::string name)
-{
- return m_watches.UpdateWatchName(index, std::move(name));
-}
-
-void DSPDebugInterface::EnableWatch(std::size_t index)
-{
- m_watches.EnableWatch(index);
-}
-
-void DSPDebugInterface::DisableWatch(std::size_t index)
-{
- m_watches.DisableWatch(index);
-}
-
-bool DSPDebugInterface::HasEnabledWatch(u32 address) const
-{
- return m_watches.HasEnabledWatch(address);
-}
-
-void DSPDebugInterface::RemoveWatch(std::size_t index)
-{
- return m_watches.RemoveWatch(index);
-}
-
-void DSPDebugInterface::LoadWatchesFromStrings(const std::vector<std::string>& watches)
-{
- m_watches.LoadFromStrings(watches);
-}
-
-std::vector<std::string> DSPDebugInterface::SaveWatchesToStrings() const
-{
- return m_watches.SaveToStrings();
-}
-
-void DSPDebugInterface::ClearWatches()
-{
- m_watches.Clear();
-}
-
-void DSPDebugInterface::SetPatch(u32 address, u32 value)
-{
- m_patches.SetPatch(address, value);
-}
-
-void DSPDebugInterface::SetPatch(u32 address, std::vector<u8> value)
-{
- m_patches.SetPatch(address, std::move(value));
-}
-
-const std::vector<Common::Debug::MemoryPatch>& DSPDebugInterface::GetPatches() const
-{
- return m_patches.GetPatches();
-}
-
-void DSPDebugInterface::UnsetPatch(u32 address)
-{
- m_patches.UnsetPatch(address);
-}
-
-void DSPDebugInterface::EnablePatch(std::size_t index)
-{
- m_patches.EnablePatch(index);
-}
-
-void DSPDebugInterface::DisablePatch(std::size_t index)
-{
- m_patches.DisablePatch(index);
-}
-
-void DSPDebugInterface::RemovePatch(std::size_t index)
-{
- m_patches.RemovePatch(index);
-}
-
-bool DSPDebugInterface::HasEnabledPatch(u32 address) const
-{
- return m_patches.HasEnabledPatch(address);
-}
-
-void DSPDebugInterface::ClearPatches()
-{
- m_patches.ClearPatches();
-}
-
-Common::Debug::Threads DSPDebugInterface::GetThreads() const
-{
- return {};
-}
-
-std::string DSPDebugInterface::Disassemble(u32 address) const
-{
- // we'll treat addresses as line numbers.
- return Symbols::GetLineText(address);
-}
-
-std::string DSPDebugInterface::GetRawMemoryString(int memory, u32 address) const
-{
- if (DSPCore_GetState() == State::Stopped)
- return "";
-
- switch (memory)
- {
- case 0: // IMEM
- switch (address >> 12)
- {
- case 0:
- case 0x8:
- return fmt::format("{:04x}", dsp_imem_read(address));
- default:
- return "--IMEM--";
- }
-
- case 1: // DMEM
- switch (address >> 12)
- {
- case 0:
- case 1:
- return fmt::format("{:04x} (DMEM)", dsp_dmem_read(address));
- case 0xf:
- return fmt::format("{:04x} (MMIO)", g_dsp.ifx_regs[address & 0xFF]);
- default:
- return "--DMEM--";
- }
- }
-
- return "";
-}
-
-u32 DSPDebugInterface::ReadMemory(u32 address) const
-{
- return 0;
-}
-
-u32 DSPDebugInterface::ReadInstruction(u32 address) const
-{
- return 0;
-}
-
-bool DSPDebugInterface::IsAlive() const
-{
- return true;
-}
-
-bool DSPDebugInterface::IsBreakpoint(u32 address) const
-{
- int real_addr = Symbols::Line2Addr(address);
- if (real_addr >= 0)
- return g_dsp_breakpoints.IsAddressBreakPoint(real_addr);
-
- return false;
-}
-
-void DSPDebugInterface::SetBreakpoint(u32 address)
-{
- int real_addr = Symbols::Line2Addr(address);
-
- if (real_addr >= 0)
- {
- g_dsp_breakpoints.Add(real_addr);
- }
-}
-
-void DSPDebugInterface::ClearBreakpoint(u32 address)
-{
- int real_addr = Symbols::Line2Addr(address);
-
- if (real_addr >= 0)
- {
- g_dsp_breakpoints.Remove(real_addr);
- }
-}
-
-void DSPDebugInterface::ClearAllBreakpoints()
-{
- g_dsp_breakpoints.Clear();
-}
-
-void DSPDebugInterface::ToggleBreakpoint(u32 address)
-{
- int real_addr = Symbols::Line2Addr(address);
- if (real_addr >= 0)
- {
- if (g_dsp_breakpoints.IsAddressBreakPoint(real_addr))
- g_dsp_breakpoints.Remove(real_addr);
- else
- g_dsp_breakpoints.Add(real_addr);
- }
-}
-
-bool DSPDebugInterface::IsMemCheck(u32 address, size_t size) const
-{
- return false;
-}
-
-void DSPDebugInterface::ClearAllMemChecks()
-{
- PanicAlertFmt("MemCheck functionality not supported in DSP module.");
-}
-
-void DSPDebugInterface::ToggleMemCheck(u32 address, bool read, bool write, bool log)
-{
- PanicAlertFmt("MemCheck functionality not supported in DSP module.");
-}
-
-// =======================================================
-// Separate the blocks with colors.
-// -------------
-u32 DSPDebugInterface::GetColor(u32 address) const
-{
- // Scan backwards so we don't miss it. Hm, actually, let's not - it looks pretty good.
- int addr = -1;
- for (int i = 0; i < 1; i++)
- {
- addr = Symbols::Line2Addr(address - i);
- if (addr >= 0)
- break;
- }
- if (addr == -1)
- return 0xFFFFFF;
-
- Common::Symbol* symbol = Symbols::g_dsp_symbol_db.GetSymbolFromAddr(addr);
- if (!symbol)
- return 0xFFFFFF;
- if (symbol->type != Common::Symbol::Type::Function)
- return 0xEEEEFF;
-
- static constexpr std::array<u32, 6> colors{
- 0xd0FFFF, // light cyan
- 0xFFd0d0, // light red
- 0xd8d8FF, // light blue
- 0xFFd0FF, // light purple
- 0xd0FFd0, // light green
- 0xFFFFd0, // light yellow
- };
- return colors[symbol->index % colors.size()];
-}
-// =============
-
-std::string DSPDebugInterface::GetDescription(u32 address) const
-{
- return ""; // g_symbolDB.GetDescription(address);
-}
-
-u32 DSPDebugInterface::GetPC() const
-{
- return Symbols::Addr2Line(DSP::g_dsp.pc);
-}
-
-void DSPDebugInterface::SetPC(u32 address)
-{
- int new_pc = Symbols::Line2Addr(address);
- if (new_pc > 0)
- g_dsp.pc = new_pc;
-}
-
-void DSPDebugInterface::RunToBreakpoint()
-{
-}
-
-void DSPDebugInterface::Clear()
-{
- ClearPatches();
- ClearWatches();
-}
-} // namespace DSP::LLE
diff --git a/Source/Core/Core/HW/DSPLLE/DSPDebugInterface.h b/Source/Core/Core/HW/DSPLLE/DSPDebugInterface.h
deleted file mode 100644
index 1fa80012e4..0000000000
--- a/Source/Core/Core/HW/DSPLLE/DSPDebugInterface.h
+++ /dev/null
@@ -1,85 +0,0 @@
-// Copyright 2008 Dolphin Emulator Project
-// Licensed under GPLv2+
-// Refer to the license.txt file included.
-
-#pragma once
-
-#include <cstddef>
-#include <string>
-
-#include "Common/CommonTypes.h"
-#include "Common/Debug/MemoryPatches.h"
-#include "Common/Debug/Watches.h"
-#include "Common/DebugInterface.h"
-
-namespace DSP::LLE
-{
-class DSPPatches : public Common::Debug::MemoryPatches
-{
-private:
- void Patch(std::size_t index) override;
-};
-
-class DSPDebugInterface final : public Common::DebugInterface
-{
-public:
- DSPDebugInterface();
- ~DSPDebugInterface() override;
-
- // Watches
- std::size_t SetWatch(u32 address, std::string name = "") override;
- const Common::Debug::Watch& GetWatch(std::size_t index) const override;
- const std::vector<Common::Debug::Watch>& GetWatches() const override;
- void UnsetWatch(u32 address) override;
- void UpdateWatch(std::size_t index, u32 address, std::string name) override;
- void UpdateWatchAddress(std::size_t index, u32 address) override;
- void UpdateWatchName(std::size_t index, std::string name) override;
- void EnableWatch(std::size_t index) override;
- void DisableWatch(std::size_t index) override;
- bool HasEnabledWatch(u32 address) const override;
- void RemoveWatch(std::size_t index) override;
- void LoadWatchesFromStrings(const std::vector<std::string>& watches) override;
- std::vector<std::string> SaveWatchesToStrings() const override;
- void ClearWatches() override;
-
- // Memory Patches
- void SetPatch(u32 address, u32 value) override;
- void SetPatch(u32 address, std::vector<u8> value) override;
- const std::vector<Common::Debug::MemoryPatch>& GetPatches() const override;
- void UnsetPatch(u32 address) override;
- void EnablePatch(std::size_t index) override;
- void DisablePatch(std::size_t index) override;
- void RemovePatch(std::size_t index) override;
- bool HasEnabledPatch(u32 address) const override;
- void ClearPatches() override;
-
- // Threads
- Common::Debug::Threads GetThreads() const override;
-
- std::string Disassemble(u32 address) const override;
- std::string GetRawMemoryString(int memory, u32 address) const override;
- bool IsAlive() const override;
- bool IsBreakpoint(u32 address) const override;
- void SetBreakpoint(u32 address) override;
- void ClearBreakpoint(u32 address) override;
- void ClearAllBreakpoints() override;
- void ToggleBreakpoint(u32 address) override;
- void ClearAllMemChecks() override;
- bool IsMemCheck(u32 address, size_t size) const override;
- void ToggleMemCheck(u32 address, bool read = true, bool write = true, bool log = true) override;
- u32 ReadMemory(u32 address) const override;
- u32 ReadInstruction(u32 address) const override;
- u32 GetPC() const override;
- void SetPC(u32 address) override;
- void Step() override {}
- void RunToBreakpoint() override;
- u32 GetColor(u32 address) const override;
- std::string GetDescription(u32 address) const override;
-
- void Clear() override;
-
-private:
- Common::Debug::Watches m_watches;
- DSPPatches m_patches;
-};
-} // namespace DSP::LLE
diff --git a/Source/Core/Core/HW/DSPLLE/DSPHost.cpp b/Source/Core/Core/HW/DSPLLE/DSPHost.cpp
index bbd2b7ac20..f42510b874 100644
--- a/Source/Core/Core/HW/DSPLLE/DSPHost.cpp
+++ b/Source/Core/Core/HW/DSPLLE/DSPHost.cpp
@@ -68,31 +68,33 @@ void InterruptRequest()
DSP::GenerateDSPInterruptFromDSPEmu(DSP::INT_DSP);
}
-void CodeLoaded(u32 addr, size_t size)
+void CodeLoaded(DSPCore& dsp, u32 addr, size_t size)
{
- CodeLoaded(Memory::GetPointer(addr), size);
+ CodeLoaded(dsp, Memory::GetPointer(addr), size);
}
-void CodeLoaded(const u8* ptr, size_t size)
+void CodeLoaded(DSPCore& dsp, const u8* ptr, size_t size)
{
- g_dsp.iram_crc = Common::HashEctor(ptr, size);
+ auto& state = dsp.DSPState();
+ const u32 iram_crc = Common::HashEctor(ptr, size);
+ state.iram_crc = iram_crc;
+
if (SConfig::GetInstance().m_DumpUCode)
{
- DSP::DumpDSPCode(ptr, size, g_dsp.iram_crc);
+ DSP::DumpDSPCode(ptr, size, iram_crc);
}
- NOTICE_LOG_FMT(DSPLLE, "g_dsp.iram_crc: {:08x}", g_dsp.iram_crc);
+ NOTICE_LOG_FMT(DSPLLE, "g_dsp.iram_crc: {:08x}", iram_crc);
Symbols::Clear();
- Symbols::AutoDisassembly(0x0, 0x1000);
- Symbols::AutoDisassembly(0x8000, 0x9000);
+ Symbols::AutoDisassembly(state, 0x0, 0x1000);
+ Symbols::AutoDisassembly(state, 0x8000, 0x9000);
UpdateDebugger();
- if (g_dsp_jit)
- g_dsp_jit->ClearIRAM();
+ dsp.ClearIRAM();
- Analyzer::Analyze();
+ Analyzer::Analyze(state);
}
void UpdateDebugger()
diff --git a/Source/Core/Core/HW/DSPLLE/DSPLLE.cpp b/Source/Core/Core/HW/DSPLLE/DSPLLE.cpp
index 3cedfdb787..03a9cefc43 100644
--- a/Source/Core/Core/HW/DSPLLE/DSPLLE.cpp
+++ b/Source/Core/Core/HW/DSPLLE/DSPLLE.cpp
@@ -21,7 +21,6 @@
#include "Core/DSP/DSPAccelerator.h"
#include "Core/DSP/DSPCaptureLogger.h"
#include "Core/DSP/DSPCore.h"
-#include "Core/DSP/DSPHWInterface.h"
#include "Core/DSP/DSPHost.h"
#include "Core/DSP/DSPTables.h"
#include "Core/DSP/Interpreter/DSPInterpreter.h"
@@ -32,15 +31,11 @@
namespace DSP::LLE
{
-static Common::Event s_dsp_event;
-static Common::Event s_ppc_event;
-static bool s_request_disable_thread;
-
DSPLLE::DSPLLE() = default;
DSPLLE::~DSPLLE()
{
- DSPCore_Shutdown();
+ m_dsp_core.Shutdown();
DSP_StopSoundStream();
}
@@ -55,39 +50,8 @@ void DSPLLE::DoState(PointerWrap& p)
p.SetMode(PointerWrap::MODE_VERIFY);
return;
}
- p.Do(g_dsp.r);
- p.Do(g_dsp.pc);
-#if PROFILE
- p.Do(g_dsp.err_pc);
-#endif
- p.Do(g_dsp.cr);
- p.Do(g_dsp.reg_stack_ptrs);
- p.Do(g_dsp.exceptions);
- p.Do(g_dsp.external_interrupt_waiting);
-
- for (auto& stack : g_dsp.reg_stacks)
- {
- p.Do(stack);
- }
-
- p.Do(g_dsp.step_counter);
- p.DoArray(g_dsp.ifx_regs);
- g_dsp.accelerator->DoState(p);
- p.Do(g_dsp.mbox[0]);
- p.Do(g_dsp.mbox[1]);
- Common::UnWriteProtectMemory(g_dsp.iram, DSP_IRAM_BYTE_SIZE, false);
- p.DoArray(g_dsp.iram, DSP_IRAM_SIZE);
- Common::WriteProtectMemory(g_dsp.iram, DSP_IRAM_BYTE_SIZE, false);
- // TODO: This uses the wrong endianness (producing bad disassembly)
- // and a bogus byte count (producing bad hashes)
- if (p.GetMode() == PointerWrap::MODE_READ)
- Host::CodeLoaded(reinterpret_cast<const u8*>(g_dsp.iram), DSP_IRAM_BYTE_SIZE);
- p.DoArray(g_dsp.dram, DSP_DRAM_SIZE);
- p.Do(g_init_hax);
+ m_dsp_core.DoState(p);
p.Do(m_cycle_count);
-
- if (g_dsp_jit)
- g_dsp_jit->DoState(p);
}
// Regular thread
@@ -103,21 +67,21 @@ void DSPLLE::DSPThread(DSPLLE* dsp_lle)
std::unique_lock dsp_thread_lock(dsp_lle->m_dsp_thread_mutex, std::try_to_lock);
if (dsp_thread_lock)
{
- if (g_dsp_jit)
+ if (dsp_lle->m_dsp_core.IsJITCreated())
{
- DSPCore_RunCycles(cycles);
+ dsp_lle->m_dsp_core.RunCycles(cycles);
}
else
{
- DSP::Interpreter::RunCyclesThread(cycles);
+ dsp_lle->m_dsp_core.GetInterpreter().RunCyclesThread(cycles);
}
dsp_lle->m_cycle_count.store(0);
continue;
}
}
- s_ppc_event.Set();
- s_dsp_event.Wait();
+ dsp_lle->m_ppc_event.Set();
+ dsp_lle->m_dsp_event.Wait();
}
}
@@ -173,22 +137,22 @@ static bool FillDSPInitOptions(DSPInitOptions* opts)
bool DSPLLE::Initialize(bool wii, bool dsp_thread)
{
- s_request_disable_thread = false;
+ m_request_disable_thread = false;
DSPInitOptions opts;
if (!FillDSPInitOptions(&opts))
return false;
- if (!DSPCore_Init(opts))
+ if (!m_dsp_core.Initialize(opts))
return false;
// needs to be after DSPCore_Init for the dspjit ptr
- if (Core::WantsDeterminism() || !g_dsp_jit)
+ if (Core::WantsDeterminism() || !m_dsp_core.IsJITCreated())
dsp_thread = false;
m_wii = wii;
m_is_dsp_on_thread = dsp_thread;
- DSPCore_Reset();
+ m_dsp_core.Reset();
InitInstructionTable();
@@ -204,77 +168,70 @@ bool DSPLLE::Initialize(bool wii, bool dsp_thread)
void DSPLLE::DSP_StopSoundStream()
{
- if (m_is_dsp_on_thread)
- {
- m_is_running.Clear();
- s_ppc_event.Set();
- s_dsp_event.Set();
- m_dsp_thread.join();
- }
+ if (!m_is_dsp_on_thread)
+ return;
+
+ m_is_running.Clear();
+ m_ppc_event.Set();
+ m_dsp_event.Set();
+ m_dsp_thread.join();
}
void DSPLLE::Shutdown()
{
- DSPCore_Shutdown();
+ m_dsp_core.Shutdown();
}
u16 DSPLLE::DSP_WriteControlRegister(u16 value)
{
- DSP::Interpreter::WriteCR(value);
+ m_dsp_core.GetInterpreter().WriteCR(value);
- if (value & 2)
+ if ((value & 2) != 0)
{
- if (!m_is_dsp_on_thread)
- {
- DSPCore_CheckExternalInterrupt();
- DSPCore_CheckExceptions();
- }
- else
+ if (m_is_dsp_on_thread)
{
// External interrupt pending: this is the zelda ucode.
// Disable the DSP thread because there is no performance gain.
- s_request_disable_thread = true;
+ m_request_disable_thread = true;
- DSPCore_SetExternalInterrupt(true);
+ m_dsp_core.SetExternalInterrupt(true);
+ }
+ else
+ {
+ m_dsp_core.CheckExternalInterrupt();
+ m_dsp_core.CheckExceptions();
}
}
- return DSP::Interpreter::ReadCR();
+ return DSP_ReadControlRegister();
}
u16 DSPLLE::DSP_ReadControlRegister()
{
- return DSP::Interpreter::ReadCR();
+ return m_dsp_core.GetInterpreter().ReadCR();
}
u16 DSPLLE::DSP_ReadMailBoxHigh(bool cpu_mailbox)
{
- return gdsp_mbox_read_h(cpu_mailbox ? MAILBOX_CPU : MAILBOX_DSP);
+ return m_dsp_core.ReadMailboxHigh(cpu_mailbox ? MAILBOX_CPU : MAILBOX_DSP);
}
u16 DSPLLE::DSP_ReadMailBoxLow(bool cpu_mailbox)
{
- return gdsp_mbox_read_l(cpu_mailbox ? MAILBOX_CPU : MAILBOX_DSP);
+ return m_dsp_core.ReadMailboxLow(cpu_mailbox ? MAILBOX_CPU : MAILBOX_DSP);
}
void DSPLLE::DSP_WriteMailBoxHigh(bool cpu_mailbox, u16 value)
{
if (cpu_mailbox)
{
- if (gdsp_mbox_peek(MAILBOX_CPU) & 0x80000000)
+ if ((m_dsp_core.PeekMailbox(MAILBOX_CPU) & 0x80000000) != 0)
{
// the DSP didn't read the previous value
WARN_LOG_FMT(DSPLLE, "Mailbox isn't empty ... strange");
}
-#if PROFILE
- if (value == 0xBABE)
- {
- ProfilerStart();
- }
-#endif
-
- gdsp_mbox_write_h(MAILBOX_CPU, value);
+ m_dsp_core.WriteMailboxHigh(MAILBOX_CPU, value);
}
else
{
@@ -286,7 +243,7 @@ void DSPLLE::DSP_WriteMailBoxLow(bool cpu_mailbox, u16 value)
{
if (cpu_mailbox)
{
- gdsp_mbox_write_l(MAILBOX_CPU, value);
+ m_dsp_core.WriteMailboxLow(MAILBOX_CPU, value);
}
else
{
@@ -296,18 +253,18 @@ void DSPLLE::DSP_WriteMailBoxLow(bool cpu_mailbox, u16 value)
void DSPLLE::DSP_Update(int cycles)
{
- int dsp_cycles = cycles / 6;
+ const int dsp_cycles = cycles / 6;
if (dsp_cycles <= 0)
return;
if (m_is_dsp_on_thread)
{
- if (s_request_disable_thread || Core::WantsDeterminism())
+ if (m_request_disable_thread || Core::WantsDeterminism())
{
DSP_StopSoundStream();
m_is_dsp_on_thread = false;
- s_request_disable_thread = false;
+ m_request_disable_thread = false;
SConfig::GetInstance().bDSPThread = false;
}
}
@@ -316,14 +273,14 @@ void DSPLLE::DSP_Update(int cycles)
if (!m_is_dsp_on_thread)
{
// ~1/6th as many cycles as the period PPC-side.
- DSPCore_RunCycles(dsp_cycles);
+ m_dsp_core.RunCycles(dsp_cycles);
}
else
{
// Wait for DSP thread to complete its cycle. Note: this logic should be thought through.
- s_ppc_event.Wait();
+ m_ppc_event.Wait();
m_cycle_count.fetch_add(dsp_cycles);
- s_dsp_event.Set();
+ m_dsp_event.Set();
}
}
@@ -345,8 +302,8 @@ void DSPLLE::PauseAndLock(bool do_lock, bool unpause_on_unlock)
if (m_is_dsp_on_thread)
{
// Signal the DSP thread so it can perform any outstanding work now (if any)
- s_ppc_event.Wait();
- s_dsp_event.Set();
+ m_ppc_event.Wait();
+ m_dsp_event.Set();
}
}
}
diff --git a/Source/Core/Core/HW/DSPLLE/DSPLLE.h b/Source/Core/Core/HW/DSPLLE/DSPLLE.h
index 2e05ee3f6a..ce5c44d245 100644
--- a/Source/Core/Core/HW/DSPLLE/DSPLLE.h
+++ b/Source/Core/Core/HW/DSPLLE/DSPLLE.h
@@ -10,6 +10,7 @@
#include "Common/CommonTypes.h"
#include "Common/Flag.h"
+#include "Core/DSP/DSPCore.h"
#include "Core/DSPEmulator.h"
class PointerWrap;
@@ -41,10 +42,15 @@ public:
private:
static void DSPThread(DSPLLE* dsp_lle);
+ DSPCore m_dsp_core;
std::thread m_dsp_thread;
std::mutex m_dsp_thread_mutex;
bool m_is_dsp_on_thread = false;
Common::Flag m_is_running;
std::atomic<u32> m_cycle_count{};
+
+ Common::Event m_dsp_event;
+ Common::Event m_ppc_event;
+ bool m_request_disable_thread = false;
};
} // namespace DSP::LLE
diff --git a/Source/Core/Core/HW/DSPLLE/DSPSymbols.cpp b/Source/Core/Core/HW/DSPLLE/DSPSymbols.cpp
index b438294be4..f00d23af47 100644
--- a/Source/Core/Core/HW/DSPLLE/DSPSymbols.cpp
+++ b/Source/Core/Core/HW/DSPLLE/DSPSymbols.cpp
@@ -69,7 +69,7 @@ Common::Symbol* DSPSymbolDB::GetSymbolFromAddr(u32 addr)
return nullptr;
}
-void AutoDisassembly(u16 start_addr, u16 end_addr)
+void AutoDisassembly(const SDSP& dsp, u16 start_addr, u16 end_addr)
{
AssemblerSettings settings;
settings.show_pc = true;
@@ -77,7 +77,7 @@ void AutoDisassembly(u16 start_addr, u16 end_addr)
DSPDisassembler disasm(settings);
u16 addr = start_addr;
- const u16* ptr = (start_addr >> 15) ? g_dsp.irom : g_dsp.iram;
+ const u16* ptr = (start_addr >> 15) != 0 ? dsp.irom : dsp.iram;
while (addr < end_addr)
{
line_to_addr[line_counter] = addr;
diff --git a/Source/Core/Core/HW/DSPLLE/DSPSymbols.h b/Source/Core/Core/HW/DSPLLE/DSPSymbols.h
index df08124e4b..5d7629ecf9 100644
--- a/Source/Core/Core/HW/DSPLLE/DSPSymbols.h
+++ b/Source/Core/Core/HW/DSPLLE/DSPSymbols.h
@@ -9,6 +9,11 @@
#include "Common/CommonTypes.h"
#include "Common/SymbolDB.h"
+namespace DSP
+{
+struct SDSP;
+}
+
namespace DSP::Symbols
{
class DSPSymbolDB : public Common::SymbolDB
@@ -21,7 +26,7 @@ public:
extern DSPSymbolDB g_dsp_symbol_db;
-void AutoDisassembly(u16 start_addr, u16 end_addr);
+void AutoDisassembly(const SDSP& dsp, u16 start_addr, u16 end_addr);
void Clear();
diff --git a/Source/Core/Core/State.cpp b/Source/Core/Core/State.cpp
index 84fce4f471..823b39c1ba 100644
--- a/Source/Core/Core/State.cpp
+++ b/Source/Core/Core/State.cpp
@@ -74,7 +74,7 @@ static Common::Event g_compressAndDumpStateSyncEvent;
static std::thread g_save_thread;
// Don't forget to increase this after doing changes on the savestate system
-constexpr u32 STATE_VERSION = 125; // Last changed in PR 8867
+constexpr u32 STATE_VERSION = 126; // Last changed in PR 9348
// Maps savestate versions to Dolphin versions.
// Versions after 42 don't need to be added to this list,