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 @@ -1096,6 +1096,13 @@ public: ABI_CallFunction(func); } + template + void ABI_CallFunctionP(FunctionPointer func, const void* param1) + { + MOV(64, R(ABI_PARAM1), Imm64(reinterpret_cast(param1))); + ABI_CallFunction(func); + } + template void ABI_CallFunctionPC(FunctionPointer func, const void* param1, u32 param2) { @@ -1122,6 +1129,15 @@ public: ABI_CallFunction(func); } + // Pass a pointer and register as a parameter. + template + 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(ptr))); + ABI_CallFunction(func); + } + // Pass two registers as parameters. template 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 + 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(ptr))); + ABI_CallFunction(func); + } + template 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 @@ - @@ -107,7 +106,6 @@ - @@ -420,13 +418,9 @@ - - - - @@ -466,7 +460,6 @@ - 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 @@ DSPCore\Interpreter - - DSPCore\Interpreter - DSPCore\Interpreter @@ -416,9 +413,6 @@ HW %28Flipper/Hollywood%29\DSP Interface + HLE\HLE - - HW %28Flipper/Hollywood%29\DSP Interface + HLE\LLE - HW %28Flipper/Hollywood%29\DSP Interface + HLE\LLE @@ -1070,9 +1064,6 @@ DSPCore\Interpreter - - DSPCore\Interpreter - DSPCore\Interpreter @@ -1199,9 +1190,6 @@ HW %28Flipper/Hollywood%29\DSP Interface + HLE\HLE - - HW %28Flipper/Hollywood%29\DSP Interface + HLE\LLE - HW %28Flipper/Hollywood%29\DSP Interface + HLE\LLE @@ -1388,15 +1376,6 @@ DSPCore - - DSPCore - - - DSPCore - - - DSPCore - DSPCore 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(addr + i))) + if (idle_skip_sigs[s][i] != dsp.ReadIMEM(static_cast(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..ccda5e77f7 100644 --- a/Source/Core/Core/DSP/DSPCore.cpp +++ b/Source/Core/Core/DSP/DSPCore.cpp @@ -10,6 +10,7 @@ #include #include +#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 g_dsp_jit; -std::unique_ptr 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 DSPCore& core) { struct DspRomHashes { @@ -64,8 +59,11 @@ static bool VerifyRoms() {0x128ea7a2, 0xa4a575f5}, }}; - const u32 hash_irom = Common::HashAdler32(reinterpret_cast(g_dsp.irom), DSP_IROM_BYTE_SIZE); - const u32 hash_drom = Common::HashAdler32(reinterpret_cast(g_dsp.coef), DSP_COEF_BYTE_SIZE); + const auto& state = core.DSPState(); + const u32 hash_irom = + Common::HashAdler32(reinterpret_cast(state.irom), DSP_IROM_BYTE_SIZE); + const u32 hash_drom = + Common::HashAdler32(reinterpret_cast(state.coef), DSP_COEF_BYTE_SIZE); int rom_idx = -1; for (size_t i = 0; i < known_roms.size(); ++i) @@ -104,151 +102,228 @@ 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(DSPCore& core) : m_core{core} {} + 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_core.SetException(ExceptionType::AcceleratorOverflow); } + +private: + DSPCore& m_core; }; -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(); +SDSP::~SDSP() = default; - g_dsp.irom = static_cast(Common::AllocateMemoryPages(DSP_IROM_BYTE_SIZE)); - g_dsp.iram = static_cast(Common::AllocateMemoryPages(DSP_IRAM_BYTE_SIZE)); - g_dsp.dram = static_cast(Common::AllocateMemoryPages(DSP_DRAM_BYTE_SIZE)); - g_dsp.coef = static_cast(Common::AllocateMemoryPages(DSP_COEF_BYTE_SIZE)); +DSPCore::DSPCore() + : m_dsp{*this}, m_dsp_interpreter{std::make_unique(*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); +DSPCore::~DSPCore() = default; + +bool DSPCore::Initialize(const DSPInitOptions& opts) +{ + m_dsp.step_counter = 0; + m_init_hax = false; + + m_dsp.accelerator = std::make_unique(*this); + + m_dsp.irom = static_cast(Common::AllocateMemoryPages(DSP_IROM_BYTE_SIZE)); + m_dsp.iram = static_cast(Common::AllocateMemoryPages(DSP_IRAM_BYTE_SIZE)); + m_dsp.dram = static_cast(Common::AllocateMemoryPages(DSP_DRAM_BYTE_SIZE)); + m_dsp.coef = static_cast(Common::AllocateMemoryPages(DSP_COEF_BYTE_SIZE)); + + std::memcpy(m_dsp.irom, opts.irom_contents.data(), DSP_IROM_BYTE_SIZE); + std::memcpy(m_dsp.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(&m_dsp.r, 0, sizeof(m_dsp.r)); - std::fill(std::begin(g_dsp.reg_stack_ptrs), std::end(g_dsp.reg_stack_ptrs), 0); + std::fill(std::begin(m_dsp.reg_stack_ptrs), std::end(m_dsp.reg_stack_ptrs), 0); - for (auto& stack : g_dsp.reg_stacks) + for (auto& stack : m_dsp.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(m_dsp.iram, m_dsp.iram + DSP_IRAM_SIZE, 0x0021); // Just zero out DRAM. - std::fill(g_dsp.dram, g_dsp.dram + DSP_DRAM_SIZE, 0); + std::fill(m_dsp.dram, m_dsp.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(m_dsp.r.wr), std::end(m_dsp.r.wr), 0xffff); - g_dsp.r.sr |= SR_INT_ENABLE; - g_dsp.r.sr |= SR_EXT_INT_ENABLE; + m_dsp.r.sr |= SR_INT_ENABLE; + m_dsp.r.sr |= SR_EXT_INT_ENABLE; - g_dsp.cr = 0x804; - gdsp_ifx_init(); + m_dsp.cr = 0x804; + m_dsp.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); + Common::WriteProtectMemory(m_dsp.iram, DSP_IRAM_BYTE_SIZE, false); // Initialize JIT, if necessary if (opts.core_type == DSPInitOptions::CoreType::JIT64) - g_dsp_jit = JIT::CreateDSPEmitter(); + m_dsp_jit = JIT::CreateDSPEmitter(*this); - g_dsp_cap.reset(opts.capture_logger); + m_dsp_cap.reset(opts.capture_logger); - core_state = State::Running; + m_core_state = State::Running; return true; } -void DSPCore_Shutdown() +void DSPCore::Shutdown() { - if (core_state == State::Stopped) + if (m_core_state == State::Stopped) return; - core_state = State::Stopped; + m_core_state = State::Stopped; - g_dsp_jit.reset(); + m_dsp_jit.reset(); - DSPCore_FreeMemoryPages(); + FreeMemoryPages(); - g_dsp_cap.reset(); + m_dsp_cap.reset(); } -void DSPCore_Reset() +// Delegate to JIT or interpreter as appropriate. +// Handle state changes and stepping. +int DSPCore::RunCycles(int cycles) { - g_dsp.pc = DSP_RESET_VECTOR; + if (m_dsp_jit) + { + return m_dsp_jit->RunCycles(static_cast(cycles)); + } - std::fill(std::begin(g_dsp.r.wr), std::end(g_dsp.r.wr), 0xffff); + 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; - Analyzer::Analyze(); + 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_SetException(ExceptionType exception) +void DSPCore::Step() { - g_dsp.exceptions |= 1 << static_cast>(exception); + if (m_core_state == State::Stepping) + m_step_event.Set(); } -// Notify that an external interrupt is pending (used by thread mode) -void DSPCore_SetExternalInterrupt(bool val) +void DSPCore::Reset() { - g_dsp.external_interrupt_waiting = val; + m_dsp.pc = DSP_RESET_VECTOR; + + std::fill(std::begin(m_dsp.r.wr), std::end(m_dsp.r.wr), 0xffff); + + Analyzer::Analyze(m_dsp); } -// Coming from the CPU -void DSPCore_CheckExternalInterrupt() +void DSPCore::ClearIRAM() { - if (!Interpreter::dsp_SR_is_flag_set(SR_EXT_INT_ENABLE)) + 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.exceptions |= 1 << static_cast>(exception); +} + +void DSPCore::SetExternalInterrupt(bool val) +{ + m_dsp.external_interrupt_waiting = val; +} + +void DSPCore::CheckExternalInterrupt() +{ + if (!m_dsp.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; + m_dsp.cr &= ~CR_EXTERNAL_INT; } -void DSPCore_CheckExceptions() +void DSPCore::CheckExceptions() { // Early out to skip the loop in the common case. - if (g_dsp.exceptions == 0) + if (m_dsp.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 ((m_dsp.exceptions & (1U << i)) != 0) { - if (Interpreter::dsp_SR_is_flag_set(SR_INT_ENABLE) || + if (m_dsp.IsSRFlagSet(SR_INT_ENABLE) || i == static_cast(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); + m_dsp.StoreStack(StackRegister::Call, m_dsp.pc); + m_dsp.StoreStack(StackRegister::Data, m_dsp.r.sr); - g_dsp.pc = i * 2; - g_dsp.exceptions &= ~(1 << i); + m_dsp.pc = static_cast(i * 2); + m_dsp.exceptions &= ~(1 << i); if (i == 7) - g_dsp.r.sr &= ~SR_EXT_INT_ENABLE; + m_dsp.r.sr &= ~SR_EXT_INT_ENABLE; else - g_dsp.r.sr &= ~SR_INT_ENABLE; + m_dsp.r.sr &= ~SR_INT_ENABLE; break; } else @@ -261,68 +336,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(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 DSPCore::ReadRegister(size_t reg) const { switch (reg) { @@ -330,56 +344,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 m_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]; + return m_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]; + return m_dsp.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 m_dsp.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 m_dsp.r.ac[reg - DSP_REG_ACH0].h; case DSP_REG_CR: - return g_dsp.r.cr; + return m_dsp.r.cr; case DSP_REG_SR: - return g_dsp.r.sr; + return m_dsp.r.sr; case DSP_REG_PRODL: - return g_dsp.r.prod.l; + return m_dsp.r.prod.l; case DSP_REG_PRODM: - return g_dsp.r.prod.m; + return m_dsp.r.prod.m; case DSP_REG_PRODH: - return g_dsp.r.prod.h; + return m_dsp.r.prod.h; case DSP_REG_PRODM2: - return g_dsp.r.prod.m2; + return m_dsp.r.prod.m2; case DSP_REG_AXL0: case DSP_REG_AXL1: - return g_dsp.r.ax[reg - DSP_REG_AXL0].l; + return m_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; + return m_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; + return m_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; + return m_dsp.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 DSPCore::WriteRegister(size_t reg, u16 val) { switch (reg) { @@ -387,64 +401,154 @@ 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; + m_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; + m_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; + m_dsp.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; + m_dsp.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; + m_dsp.r.ac[reg - DSP_REG_ACH0].h = val; break; case DSP_REG_CR: - g_dsp.r.cr = val; + m_dsp.r.cr = val; break; case DSP_REG_SR: - g_dsp.r.sr = val; + m_dsp.r.sr = val; break; case DSP_REG_PRODL: - g_dsp.r.prod.l = val; + m_dsp.r.prod.l = val; break; case DSP_REG_PRODM: - g_dsp.r.prod.m = val; + m_dsp.r.prod.m = val; break; case DSP_REG_PRODH: - g_dsp.r.prod.h = val; + m_dsp.r.prod.h = val; break; case DSP_REG_PRODM2: - g_dsp.r.prod.m2 = val; + m_dsp.r.prod.m2 = val; break; case DSP_REG_AXL0: case DSP_REG_AXL1: - g_dsp.r.ax[reg - DSP_REG_AXL0].l = val; + m_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; + m_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; + m_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; + m_dsp.r.ac[reg - DSP_REG_ACM0].m = val; break; } } + +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) +{ + p.Do(m_dsp.r); + p.Do(m_dsp.pc); + p.Do(m_dsp.cr); + p.Do(m_dsp.reg_stack_ptrs); + p.Do(m_dsp.exceptions); + p.Do(m_dsp.external_interrupt_waiting); + + for (auto& stack : m_dsp.reg_stacks) + { + p.Do(stack); + } + + p.Do(m_dsp.step_counter); + p.DoArray(m_dsp.ifx_regs); + m_dsp.accelerator->DoState(p); + p.Do(m_dsp.mbox[0]); + p.Do(m_dsp.mbox[1]); + Common::UnWriteProtectMemory(m_dsp.iram, DSP_IRAM_BYTE_SIZE, false); + p.DoArray(m_dsp.iram, DSP_IRAM_SIZE); + Common::WriteProtectMemory(m_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(*this, reinterpret_cast(m_dsp.iram), DSP_IRAM_BYTE_SIZE); + p.DoArray(m_dsp.dram, DSP_DRAM_SIZE); + p.Do(m_init_hax); + + if (m_dsp_jit) + m_dsp_jit->DoState(p); +} + +void DSPCore::FreeMemoryPages() +{ + Common::FreeMemoryPages(m_dsp.irom, DSP_IROM_BYTE_SIZE); + Common::FreeMemoryPages(m_dsp.iram, DSP_IRAM_BYTE_SIZE); + Common::FreeMemoryPages(m_dsp.dram, DSP_DRAM_BYTE_SIZE); + Common::FreeMemoryPages(m_dsp.coef, DSP_COEF_BYTE_SIZE); + m_dsp.irom = nullptr; + m_dsp.iram = nullptr; + m_dsp.dram = nullptr; + m_dsp.coef = nullptr; +} } // namespace DSP diff --git a/Source/Core/Core/DSP/DSPCore.h b/Source/Core/Core/DSP/DSPCore.h index a3f61d1e96..7852d233df 100644 --- a/Source/Core/Core/DSP/DSPCore.h +++ b/Source/Core/Core/DSP/DSPCore.h @@ -11,12 +11,21 @@ #include #include +#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]; @@ -263,22 +278,82 @@ struct DSP_Regs // 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 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; } + + // 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); + + 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,33 +361,38 @@ 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 mbox[2]; // Accelerator / DMA / other hardware registers. Not GPRs. - std::array ifx_regs; + std::array ifx_regs{}; std::unique_ptr 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; -extern SDSP g_dsp; -extern DSPBreakpoints g_dsp_breakpoints; -extern bool g_init_hax; -extern std::unique_ptr g_dsp_jit; -extern std::unique_ptr g_dsp_cap; +private: + 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; +}; struct DSPInitOptions { @@ -338,20 +418,6 @@ struct DSPInitOptions DSPInitOptions() : capture_logger(new DefaultDSPCaptureLogger()) {} }; -// 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); - -void DSPCore_Reset(); -void DSPCore_Shutdown(); // Frees all allocated memory. - -void DSPCore_CheckExternalInterrupt(); -void DSPCore_CheckExceptions(); -void DSPCore_SetExternalInterrupt(bool val); - -// sets a flag in the pending exception register. -void DSPCore_SetException(ExceptionType exception); - enum class State { Stopped, @@ -359,14 +425,117 @@ enum class State Stepping, }; -int DSPCore_RunCycles(int cycles); +class DSPCore +{ +public: + DSPCore(); + ~DSPCore(); -// These are meant to be called from the UI thread. -void DSPCore_SetState(State new_state); -State DSPCore_GetState(); + DSPCore(const DSPCore&) = delete; + DSPCore& operator=(const DSPCore&) = delete; -void DSPCore_Step(); + DSPCore(DSPCore&&) = delete; + DSPCore& operator=(DSPCore&&) = delete; -u16 DSPCore_ReadRegister(size_t reg); -void DSPCore_WriteRegister(size_t reg, u16 val); + // Initializes the DSP emulator using the provided options. Takes ownership of + // all the pointers contained in the options structure. + bool Initialize(const DSPInitOptions& opts); + + // Shuts down the DSP core and cleans up any necessary state. + void Shutdown(); + + // Delegates to JIT or interpreter as appropriate. + // Handle state changes and stepping. + int RunCycles(int cycles); + + // Steps the DSP by a single instruction. + void Step(); + + // Resets DSP state as if the reset exception vector has been taken. + void Reset(); + + // Clears the DSP instruction RAM. + void ClearIRAM(); + + // 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(); + + // 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); + + // Checks the value within a mailbox. + u32 PeekMailbox(Mailbox mailbox) const; + + // 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: + void FreeMemoryPages(); + + SDSP m_dsp; + DSPBreakpoints m_dsp_breakpoints; + State m_core_state = State::Stopped; + bool m_init_hax = false; + std::unique_ptr m_dsp_interpreter; + std::unique_ptr m_dsp_jit; + std::unique_ptr 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 #include #include @@ -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); + mbox[MAILBOX_CPU].store(0); + mbox[MAILBOX_DSP].store(0); } -u32 gdsp_mbox_peek(Mailbox mbx) +u32 SDSP::PeekMailbox(Mailbox mailbox) const { - return g_dsp.mbox[mbx].load(); + return mbox[mailbox].load(); } -void gdsp_mbox_write_h(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 << 16); + 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); -} - -void gdsp_mbox_write_l(Mailbox mbx, u16 val) -{ - const u32 old_value = g_dsp.mbox[mbx].load(std::memory_order_acquire); - const u32 new_value = (old_value & ~0xffff) | val; - - g_dsp.mbox[mbx].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, "{}(WM) B:{} M:{:#010x} (pc={:#06x})", type, mbx, gdsp_mbox_peek(mbx), - g_dsp.pc); -#endif -} - -u16 gdsp_mbox_read_h(Mailbox mbx) -{ - 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? -} - -u16 gdsp_mbox_read_l(Mailbox mbx) -{ - const u32 value = g_dsp.mbox[mbx].load(std::memory_order_acquire); - g_dsp.mbox[mbx].store(value & ~0x80000000, std::memory_order_release); - - if (g_init_hax && mbx == MAILBOX_DSP) - { - g_init_hax = false; - DSPCore_Reset(); + 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, "{}(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, "{}(RM) B:{} M:0x{:#010x} (pc={:#06x})", type, mailbox, + PeekMailbox(mailbox), pc); #endif - return (u16)value; + return static_cast(value); } -void gdsp_ifx_write(u32 addr, u16 val) +u16 SDSP::ReadMailboxHigh(Mailbox mailbox) { - g_dsp_cap->LogIFXWrite(addr, val); + if (m_dsp_core.GetInitHax() && mailbox == MAILBOX_DSP) + { + return 0x8054; + } - switch (addr & 0xff) + // TODO: mask away the top bit? + return static_cast(PeekMailbox(mailbox) >> 16); +} + +void SDSP::WriteMailboxLow(Mailbox mailbox, u16 value) +{ + const u32 old_value = mbox[mailbox].load(std::memory_order_acquire); + const u32 new_value = (old_value & ~0xffff) | value; + + mbox[mailbox].store(new_value | 0x80000000, std::memory_order_release); + +#if defined(_DEBUG) || defined(DEBUGFAST) + 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 +} + +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 SDSP::WriteIFX(u32 address, u16 value) +{ + m_dsp_core.LogIFXWrite(address, value); + + 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(g_dsp.accelerator->GetStartAddress())); + accelerator->SetStartAddress(value << 16 | static_cast(accelerator->GetStartAddress())); break; case DSP_ACSAL: - g_dsp.accelerator->SetStartAddress( - static_cast(g_dsp.accelerator->GetStartAddress() >> 16) << 16 | val); + accelerator->SetStartAddress(static_cast(accelerator->GetStartAddress() >> 16) << 16 | + value); break; case DSP_ACEAH: - g_dsp.accelerator->SetEndAddress(val << 16 | - static_cast(g_dsp.accelerator->GetEndAddress())); + accelerator->SetEndAddress(value << 16 | static_cast(accelerator->GetEndAddress())); break; case DSP_ACEAL: - g_dsp.accelerator->SetEndAddress( - static_cast(g_dsp.accelerator->GetEndAddress() >> 16) << 16 | val); + accelerator->SetEndAddress(static_cast(accelerator->GetEndAddress() >> 16) << 16 | value); break; case DSP_ACCAH: - g_dsp.accelerator->SetCurrentAddress(val << 16 | - static_cast(g_dsp.accelerator->GetCurrentAddress())); + accelerator->SetCurrentAddress(value << 16 | + static_cast(accelerator->GetCurrentAddress())); break; case DSP_ACCAL: - g_dsp.accelerator->SetCurrentAddress( - static_cast(g_dsp.accelerator->GetCurrentAddress() >> 16) << 16 | val); + accelerator->SetCurrentAddress(static_cast(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(g_dsp.accelerator->GetStartAddress() >> 16); + return static_cast(accelerator->GetStartAddress() >> 16); case DSP_ACSAL: - return static_cast(g_dsp.accelerator->GetStartAddress()); + return static_cast(accelerator->GetStartAddress()); case DSP_ACEAH: - return static_cast(g_dsp.accelerator->GetEndAddress() >> 16); + return static_cast(accelerator->GetEndAddress() >> 16); case DSP_ACEAL: - return static_cast(g_dsp.accelerator->GetEndAddress()); + return static_cast(accelerator->GetEndAddress()); case DSP_ACCAH: - return static_cast(g_dsp.accelerator->GetCurrentAddress() >> 16); + return static_cast(accelerator->GetCurrentAddress() >> 16); case DSP_ACCAL: - return static_cast(g_dsp.accelerator->GetCurrentAddress()); + return static_cast(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(&g_dsp.ifx_regs[DSP_COEF_A1_0])); + return accelerator->Read(reinterpret_cast(&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(g_dsp.iram) + dsp_addr; + return reinterpret_cast(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(g_dsp.dram) + dsp_addr; + return reinterpret_cast(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(g_dsp.dram) + dsp_addr; + return reinterpret_cast(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 #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(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(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 regnames = }}; // clang-format on -std::array writeBackLog; -std::array 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 writeBackLog; -extern std::array 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(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(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(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(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(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(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(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(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(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(); - 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(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(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(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(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(res)); + res = GetLongAcc(dreg); + UpdateSR64(static_cast(res), isCarry(acc, res), + isOverflow(static_cast(acc), static_cast(acx), static_cast(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(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(static_cast(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(state.r.ix[3]))); + WriteToBackLog(2, DSP_REG_AR0, + IncreaseAddressRegister(DSP_REG_AR0, static_cast(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(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(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(state.r.ix[3]))); + WriteToBackLog(2, DSP_REG_AR0, + IncreaseAddressRegister(DSP_REG_AR0, static_cast(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(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(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(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(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(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(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(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(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(state.r.ix[3]))); } -void nop(const UDSPInstruction opc) +void Interpreter::nop_ext(const UDSPInstruction) { } -} // namespace Interpreter::Ext - -// 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. - -// 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; - } -} - -// 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() -{ -#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(((opc >> 8) & 0x7) + 0x18); + const auto addr = static_cast((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(((opc >> 8) & 0x7) + 0x18); + const auto addr = static_cast((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(static_cast(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; + 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); - g_dsp.r.ar[sreg] = dsp_decrement_addr_reg(sreg); + 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; + 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); - g_dsp.r.ar[sreg] = dsp_increment_addr_reg(sreg); + 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; + 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); - g_dsp.r.ar[sreg] = dsp_increase_addr_reg(sreg, (s16)g_dsp.r.ix[sreg]); + const u16 val = state.ReadDMEM(OpReadRegister(sreg)); + OpWriteRegister(dreg, val); + ConditionalExtendAccum(dreg); + state.r.ar[sreg] = IncreaseAddressRegister(sreg, static_cast(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(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(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(static_cast(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(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(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 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 s_opcodes_ext {{ - {0x0000, 0x00fc, Ext::nop}, + {0x0000, 0x00fc, &Interpreter::nop_ext}, - {0x0004, 0x00fc, Ext::dr}, - {0x0008, 0x00fc, Ext::ir}, - {0x000c, 0x00fc, Ext::nr}, - {0x0010, 0x00f0, Ext::mv}, + {0x0004, 0x00fc, &Interpreter::dr}, + {0x0008, 0x00fc, &Interpreter::ir}, + {0x000c, 0x00fc, &Interpreter::nr}, + {0x0010, 0x00f0, &Interpreter::mv}, - {0x0020, 0x00e4, Ext::s}, - {0x0024, 0x00e4, Ext::sn}, + {0x0020, 0x00e4, &Interpreter::s}, + {0x0024, 0x00e4, &Interpreter::sn}, - {0x0040, 0x00c4, Ext::l}, - {0x0044, 0x00c4, Ext::ln}, + {0x0040, 0x00c4, &Interpreter::l}, + {0x0044, 0x00c4, &Interpreter::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}, + {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, Ext::ldax}, - {0x00c7, 0x00cf, Ext::ldaxn}, - {0x00cb, 0x00cf, Ext::ldaxm}, - {0x00cf, 0x00cf, Ext::ldaxnm}, + {0x00c3, 0x00cf, &Interpreter::ldax}, + {0x00c7, 0x00cf, &Interpreter::ldaxn}, + {0x00cb, 0x00cf, &Interpreter::ldaxm}, + {0x00cf, 0x00cf, &Interpreter::ldaxnm}, - {0x00c0, 0x00cc, Ext::ld}, - {0x00c4, 0x00cc, Ext::ldn}, - {0x00c8, 0x00cc, Ext::ldm}, - {0x00cc, 0x00cc, Ext::ldnm}, + {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(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(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(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(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(g_dsp.pc - 1u)) & Analyzer::CODE_LOOP_END) + const auto pc = m_dsp_core.DSPState().pc; + if ((Analyzer::GetCodeFlags(static_cast(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(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(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(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(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(nar); +} + +s32 Interpreter::GetLongACX(s32 reg) const +{ + const auto& state = m_dsp_core.DSPState(); + return static_cast((static_cast(state.r.ax[reg].h) << 16) | state.r.ax[reg].l); +} + +s16 Interpreter::GetAXLow(s32 reg) const +{ + return static_cast(m_dsp_core.DSPState().r.ax[reg].l); +} + +s16 Interpreter::GetAXHigh(s32 reg) const +{ + return static_cast(m_dsp_core.DSPState().r.ax[reg].h); +} + +s64 Interpreter::GetLongAcc(s32 reg) const +{ + const auto& state = m_dsp_core.DSPState(); + return static_cast(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(value); +} + +s16 Interpreter::GetAccLow(s32 reg) const +{ + return static_cast(m_dsp_core.DSPState().r.ac[reg].l); +} + +s16 Interpreter::GetAccMid(s32 reg) const +{ + return static_cast(m_dsp_core.DSPState().r.ac[reg].m); +} + +s16 Interpreter::GetAccHigh(s32 reg) const +{ + return static_cast(m_dsp_core.DSPState().r.ac[reg].h); +} + +s64 Interpreter::GetLongProduct() const +{ + const auto& state = m_dsp_core.DSPState(); + + s64 val = static_cast(static_cast(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(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(a * b); + else if (sign == 2 && IsSRFlagSet(SR_MUL_UNSIGNED)) // mixed + prod = a * static_cast(b); + else // Signed + prod = static_cast(a) * static_cast(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(value) >> 14) == 0) || ((static_cast(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(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(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(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(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 +#include + #include "Core/DSP/DSPCommon.h" +#include "Core/DSP/DSPCore.h" namespace DSP::Interpreter { -void Step(); +class Interpreter +{ +public: + explicit Interpreter(DSPCore& dsp); + ~Interpreter(); -// See: DspIntBranch.cpp -void HandleLoop(); + Interpreter(const Interpreter&) = delete; + Interpreter& operator=(const Interpreter&) = delete; -// 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); + Interpreter(Interpreter&&) = delete; + Interpreter& operator=(Interpreter&&) = delete; -void WriteCR(u16 val); -u16 ReadCR(); + void Step(); -// 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); + // 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 m_write_back_log{}; + std::array 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 CreateDSPEmitter() +std::unique_ptr CreateDSPEmitter([[maybe_unused]] DSPCore& dsp) { #if defined(_M_X86) || defined(_M_X86_64) - return std::make_unique(); + return std::make_unique(dsp); #else return std::make_unique(); #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 CreateDSPEmitter(); +std::unique_ptr 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(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 -#include -#include - -#include - -#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& 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& watches) -{ - m_watches.LoadFromStrings(watches); -} - -std::vector 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 value) -{ - m_patches.SetPatch(address, std::move(value)); -} - -const std::vector& 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 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 -#include - -#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& 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& watches) override; - std::vector SaveWatchesToStrings() const override; - void ClearWatches() override; - - // Memory Patches - void SetPatch(u32 address, u32 value) override; - void SetPatch(u32 address, std::vector value) override; - const std::vector& 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(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 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, diff --git a/Source/DSPTool/DSPTool.cpp b/Source/DSPTool/DSPTool.cpp index 852aec9227..9a57efbc50 100644 --- a/Source/DSPTool/DSPTool.cpp +++ b/Source/DSPTool/DSPTool.cpp @@ -39,10 +39,10 @@ bool DSP::Host::IsWiiHost() { return false; } -void DSP::Host::CodeLoaded(u32 addr, size_t size) +void DSP::Host::CodeLoaded(DSPCore& dsp, u32 addr, size_t size) { } -void DSP::Host::CodeLoaded(const u8* ptr, size_t size) +void DSP::Host::CodeLoaded(DSPCore& dsp, const u8* ptr, size_t size) { } void DSP::Host::InterruptRequest()