From dd386d12a94252364b5e0706ec719c390faf90b8 Mon Sep 17 00:00:00 2001 From: RSDuck Date: Mon, 5 Aug 2024 03:23:49 +0200 Subject: [PATCH] use templates to only execute GDB stub related code if enabled --- src/ARM.cpp | 402 +++++++++++++++++++++++----------------------------- src/ARM.h | 25 ++-- src/NDS.cpp | 38 ++--- src/NDS.h | 6 +- 4 files changed, 218 insertions(+), 253 deletions(-) diff --git a/src/ARM.cpp b/src/ARM.cpp index a88c73aa..3452d361 100644 --- a/src/ARM.cpp +++ b/src/ARM.cpp @@ -582,9 +582,11 @@ void ARM::CheckGdbIncoming() GdbCheckA(); } +template void ARMv5::Execute() { - GdbCheckB(); + if constexpr (mode == CPUExecuteMode::InterpreterGDB) + GdbCheckB(); if (Halted) { @@ -607,231 +609,123 @@ void ARMv5::Execute() while (NDS.ARM9Timestamp < NDS.ARM9Target) { - if (CPSR & 0x20) // THUMB + if constexpr (mode == CPUExecuteMode::JIT) { - GdbCheckC(); + u32 instrAddr = R[15] - ((CPSR&0x20)?2:4); - // prefetch - R[15] += 2; - CurInstr = NextInstr[0]; - NextInstr[0] = NextInstr[1]; - if (R[15] & 0x2) { NextInstr[1] >>= 16; CodeCycles = 0; } - else NextInstr[1] = CodeRead32(R[15], false); - - // actually execute - u32 icode = (CurInstr >> 6) & 0x3FF; - ARMInterpreter::THUMBInstrTable[icode](this); - } - else - { - GdbCheckC(); - - // prefetch - R[15] += 4; - CurInstr = NextInstr[0]; - NextInstr[0] = NextInstr[1]; - NextInstr[1] = CodeRead32(R[15], false); - - // actually execute - if (CheckCondition(CurInstr >> 28)) - { - u32 icode = ((CurInstr >> 4) & 0xF) | ((CurInstr >> 16) & 0xFF0); - ARMInterpreter::ARMInstrTable[icode](this); - } - else if ((CurInstr & 0xFE000000) == 0xFA000000) - { - ARMInterpreter::A_BLX_IMM(this); - } - else - AddCycles_C(); - } - - // TODO optimize this shit!!! - if (Halted) - { - if (Halted == 1 && NDS.ARM9Timestamp < NDS.ARM9Target) + if ((instrAddr < FastBlockLookupStart || instrAddr >= (FastBlockLookupStart + FastBlockLookupSize)) + && !NDS.JIT.SetupExecutableRegion(0, instrAddr, FastBlockLookup, FastBlockLookupStart, FastBlockLookupSize)) { NDS.ARM9Timestamp = NDS.ARM9Target; + Log(LogLevel::Error, "ARMv5 PC in non executable region %08X\n", R[15]); + return; } - break; - } - /*if (NDS::IF[0] & NDS::IE[0]) - { - if (NDS::IME[0] & 0x1) - TriggerIRQ(); - }*/ - if (IRQ) TriggerIRQ(); - NDS.ARM9Timestamp += Cycles; - Cycles = 0; - } + JitBlockEntry block = NDS.JIT.LookUpBlock(0, FastBlockLookup, + instrAddr - FastBlockLookupStart, instrAddr); + if (block) + ARM_Dispatch(this, block); + else + NDS.JIT.CompileBlock(this); - if (Halted == 2) - Halted = 0; -} - -#ifdef JIT_ENABLED -void ARMv5::ExecuteJIT() -{ - if (Halted) - { - if (Halted == 2) - { - Halted = 0; - } - else if (NDS.HaltInterrupted(0)) - { - Halted = 0; - if (NDS.IME[0] & 0x1) - TriggerIRQ(); - } - else - { - NDS.ARM9Timestamp = NDS.ARM9Target; - return; - } - } - - while (NDS.ARM9Timestamp < NDS.ARM9Target) - { - u32 instrAddr = R[15] - ((CPSR&0x20)?2:4); - - if ((instrAddr < FastBlockLookupStart || instrAddr >= (FastBlockLookupStart + FastBlockLookupSize)) - && !NDS.JIT.SetupExecutableRegion(0, instrAddr, FastBlockLookup, FastBlockLookupStart, FastBlockLookupSize)) - { - NDS.ARM9Timestamp = NDS.ARM9Target; - Log(LogLevel::Error, "ARMv5 PC in non executable region %08X\n", R[15]); - return; - } - - JitBlockEntry block = NDS.JIT.LookUpBlock(0, FastBlockLookup, - instrAddr - FastBlockLookupStart, instrAddr); - if (block) - ARM_Dispatch(this, block); - else - NDS.JIT.CompileBlock(this); - - if (StopExecution) - { - // this order is crucial otherwise idle loops waiting for an IRQ won't function - if (IRQ) - TriggerIRQ(); - - if (Halted || IdleLoop) + if (StopExecution) { - if ((Halted == 1 || IdleLoop) && NDS.ARM9Timestamp < NDS.ARM9Target) + // this order is crucial otherwise idle loops waiting for an IRQ won't function + if (IRQ) + TriggerIRQ(); + + if (Halted || IdleLoop) { - Cycles = 0; - NDS.ARM9Timestamp = NDS.ARM9Target; + if ((Halted == 1 || IdleLoop) && NDS.ARM9Timestamp < NDS.ARM9Target) + { + Cycles = 0; + NDS.ARM9Timestamp = NDS.ARM9Target; + } + IdleLoop = 0; + break; } - IdleLoop = 0; - break; } } - - NDS.ARM9Timestamp += Cycles; - Cycles = 0; - } - - if (Halted == 2) - Halted = 0; -} -#endif - -void ARMv4::Execute() -{ - GdbCheckB(); - - if (Halted) - { - if (Halted == 2) - { - Halted = 0; - } - else if (NDS.HaltInterrupted(1)) - { - Halted = 0; - if (NDS.IME[1] & 0x1) - TriggerIRQ(); - } else { - NDS.ARM7Timestamp = NDS.ARM7Target; - return; - } - } - - while (NDS.ARM7Timestamp < NDS.ARM7Target) - { - if (CPSR & 0x20) // THUMB - { - GdbCheckC(); - - // prefetch - R[15] += 2; - CurInstr = NextInstr[0]; - NextInstr[0] = NextInstr[1]; - NextInstr[1] = CodeRead16(R[15]); - - // actually execute - u32 icode = (CurInstr >> 6); - ARMInterpreter::THUMBInstrTable[icode](this); - } - else - { - GdbCheckC(); - - // prefetch - R[15] += 4; - CurInstr = NextInstr[0]; - NextInstr[0] = NextInstr[1]; - NextInstr[1] = CodeRead32(R[15]); - - // actually execute - if (CheckCondition(CurInstr >> 28)) + if (CPSR & 0x20) // THUMB { - u32 icode = ((CurInstr >> 4) & 0xF) | ((CurInstr >> 16) & 0xFF0); - ARMInterpreter::ARMInstrTable[icode](this); + if constexpr (mode == CPUExecuteMode::InterpreterGDB) + GdbCheckC(); + + // prefetch + R[15] += 2; + CurInstr = NextInstr[0]; + NextInstr[0] = NextInstr[1]; + if (R[15] & 0x2) { NextInstr[1] >>= 16; CodeCycles = 0; } + else NextInstr[1] = CodeRead32(R[15], false); + + // actually execute + u32 icode = (CurInstr >> 6) & 0x3FF; + ARMInterpreter::THUMBInstrTable[icode](this); } else - AddCycles_C(); - } - - // TODO optimize this shit!!! - if (Halted) - { - if (Halted == 1 && NDS.ARM7Timestamp < NDS.ARM7Target) { - NDS.ARM7Timestamp = NDS.ARM7Target; - } - break; - } - /*if (NDS::IF[1] & NDS::IE[1]) - { - if (NDS::IME[1] & 0x1) - TriggerIRQ(); - }*/ - if (IRQ) TriggerIRQ(); + if constexpr (mode == CPUExecuteMode::InterpreterGDB) + GdbCheckC(); - NDS.ARM7Timestamp += Cycles; + // prefetch + R[15] += 4; + CurInstr = NextInstr[0]; + NextInstr[0] = NextInstr[1]; + NextInstr[1] = CodeRead32(R[15], false); + + // actually execute + if (CheckCondition(CurInstr >> 28)) + { + u32 icode = ((CurInstr >> 4) & 0xF) | ((CurInstr >> 16) & 0xFF0); + ARMInterpreter::ARMInstrTable[icode](this); + } + else if ((CurInstr & 0xFE000000) == 0xFA000000) + { + ARMInterpreter::A_BLX_IMM(this); + } + else + AddCycles_C(); + } + + // TODO optimize this shit!!! + if (Halted) + { + if (Halted == 1 && NDS.ARM9Timestamp < NDS.ARM9Target) + { + NDS.ARM9Timestamp = NDS.ARM9Target; + } + break; + } + /*if (NDS::IF[0] & NDS::IE[0]) + { + if (NDS::IME[0] & 0x1) + TriggerIRQ(); + }*/ + if (IRQ) TriggerIRQ(); + + } + + NDS.ARM9Timestamp += Cycles; Cycles = 0; } if (Halted == 2) Halted = 0; - - if (Halted == 4) - { - assert(NDS.ConsoleType == 1); - auto& dsi = dynamic_cast(NDS); - dsi.SoftReset(); - Halted = 2; - } } - +template void ARMv5::Execute(); +template void ARMv5::Execute(); #ifdef JIT_ENABLED -void ARMv4::ExecuteJIT() +template void ARMv5::Execute(); +#endif + +template +void ARMv4::Execute() { + if constexpr (mode == CPUExecuteMode::InterpreterGDB) + GdbCheckB(); + if (Halted) { if (Halted == 2) @@ -853,38 +747,95 @@ void ARMv4::ExecuteJIT() while (NDS.ARM7Timestamp < NDS.ARM7Target) { - u32 instrAddr = R[15] - ((CPSR&0x20)?2:4); - - if ((instrAddr < FastBlockLookupStart || instrAddr >= (FastBlockLookupStart + FastBlockLookupSize)) - && !NDS.JIT.SetupExecutableRegion(1, instrAddr, FastBlockLookup, FastBlockLookupStart, FastBlockLookupSize)) + if constexpr (mode == CPUExecuteMode::JIT) { - NDS.ARM7Timestamp = NDS.ARM7Target; - Log(LogLevel::Error, "ARMv4 PC in non executable region %08X\n", R[15]); - return; - } + u32 instrAddr = R[15] - ((CPSR&0x20)?2:4); - JitBlockEntry block = NDS.JIT.LookUpBlock(1, FastBlockLookup, - instrAddr - FastBlockLookupStart, instrAddr); - if (block) - ARM_Dispatch(this, block); - else - NDS.JIT.CompileBlock(this); - - if (StopExecution) - { - if (IRQ) - TriggerIRQ(); - - if (Halted || IdleLoop) + if ((instrAddr < FastBlockLookupStart || instrAddr >= (FastBlockLookupStart + FastBlockLookupSize)) + && !NDS.JIT.SetupExecutableRegion(1, instrAddr, FastBlockLookup, FastBlockLookupStart, FastBlockLookupSize)) { - if ((Halted == 1 || IdleLoop) && NDS.ARM7Timestamp < NDS.ARM7Target) + NDS.ARM7Timestamp = NDS.ARM7Target; + Log(LogLevel::Error, "ARMv4 PC in non executable region %08X\n", R[15]); + return; + } + + JitBlockEntry block = NDS.JIT.LookUpBlock(1, FastBlockLookup, + instrAddr - FastBlockLookupStart, instrAddr); + if (block) + ARM_Dispatch(this, block); + else + NDS.JIT.CompileBlock(this); + + if (StopExecution) + { + if (IRQ) + TriggerIRQ(); + + if (Halted || IdleLoop) + { + if ((Halted == 1 || IdleLoop) && NDS.ARM7Timestamp < NDS.ARM7Target) + { + Cycles = 0; + NDS.ARM7Timestamp = NDS.ARM7Target; + } + IdleLoop = 0; + break; + } + } + } + else + { + if (CPSR & 0x20) // THUMB + { + if constexpr (mode == CPUExecuteMode::InterpreterGDB) + GdbCheckC(); + + // prefetch + R[15] += 2; + CurInstr = NextInstr[0]; + NextInstr[0] = NextInstr[1]; + NextInstr[1] = CodeRead16(R[15]); + + // actually execute + u32 icode = (CurInstr >> 6); + ARMInterpreter::THUMBInstrTable[icode](this); + } + else + { + if constexpr (mode == CPUExecuteMode::InterpreterGDB) + GdbCheckC(); + + // prefetch + R[15] += 4; + CurInstr = NextInstr[0]; + NextInstr[0] = NextInstr[1]; + NextInstr[1] = CodeRead32(R[15]); + + // actually execute + if (CheckCondition(CurInstr >> 28)) + { + u32 icode = ((CurInstr >> 4) & 0xF) | ((CurInstr >> 16) & 0xFF0); + ARMInterpreter::ARMInstrTable[icode](this); + } + else + AddCycles_C(); + } + + // TODO optimize this shit!!! + if (Halted) + { + if (Halted == 1 && NDS.ARM7Timestamp < NDS.ARM7Target) { - Cycles = 0; NDS.ARM7Timestamp = NDS.ARM7Target; } - IdleLoop = 0; break; } + /*if (NDS::IF[1] & NDS::IE[1]) + { + if (NDS::IME[1] & 0x1) + TriggerIRQ(); + }*/ + if (IRQ) TriggerIRQ(); } NDS.ARM7Timestamp += Cycles; @@ -902,6 +853,11 @@ void ARMv4::ExecuteJIT() Halted = 2; } } + +template void ARMv4::Execute(); +template void ARMv4::Execute(); +#ifdef JIT_ENABLED +template void ARMv4::Execute(); #endif void ARMv5::FillPipeline() diff --git a/src/ARM.h b/src/ARM.h index f2a1d1d7..b652e74d 100644 --- a/src/ARM.h +++ b/src/ARM.h @@ -43,6 +43,15 @@ enum RWFlags_ForceUser = (1<<21), }; +enum class CPUExecuteMode : u32 +{ + Interpreter, + InterpreterGDB, +#ifdef JIT_ENABLED + JIT +#endif +}; + struct GDBArgs; class ARMJIT; class GPU; @@ -75,10 +84,6 @@ public: } void NocashPrint(u32 addr) noexcept; - virtual void Execute() = 0; -#ifdef JIT_ENABLED - virtual void ExecuteJIT() = 0; -#endif bool CheckCondition(u32 code) const { @@ -241,10 +246,8 @@ public: void PrefetchAbort(); void DataAbort(); - void Execute() override; -#ifdef JIT_ENABLED - void ExecuteJIT() override; -#endif + template + void Execute(); // all code accesses are forced nonseq 32bit u32 CodeRead32(u32 addr, bool branch); @@ -383,10 +386,8 @@ public: void JumpTo(u32 addr, bool restorecpsr = false) override; - void Execute() override; -#ifdef JIT_ENABLED - void ExecuteJIT() override; -#endif + template + void Execute(); u16 CodeRead16(u32 addr) { diff --git a/src/NDS.cpp b/src/NDS.cpp index 5cfd167c..1023d3c0 100644 --- a/src/NDS.cpp +++ b/src/NDS.cpp @@ -107,6 +107,9 @@ NDS::NDS(NDSArgs&& args, int type, void* userdata) noexcept : AREngine(*this), ARM9(*this, args.GDB, args.JIT.has_value()), ARM7(*this, args.GDB, args.JIT.has_value()), +#ifdef GDBSTUB_ENABLED + EnableGDBStub(args.GDB.has_value()), +#endif #ifdef JIT_ENABLED EnableJIT(args.JIT.has_value()), #endif @@ -886,7 +889,7 @@ void NDS::RunSystemSleep(u64 timestamp) } } -template +template u32 NDS::RunFrame() { FrameStartTimestamp = SysTimestamp; @@ -927,8 +930,11 @@ u32 NDS::RunFrame() } else { - ARM9.CheckGdbIncoming(); - ARM7.CheckGdbIncoming(); + if (cpuMode == CPUExecuteMode::InterpreterGDB) + { + ARM9.CheckGdbIncoming(); + ARM7.CheckGdbIncoming(); + } if (!(CPUStop & CPUStop_Wakeup)) { @@ -963,12 +969,7 @@ u32 NDS::RunFrame() } else { -#ifdef JIT_ENABLED - if (EnableJIT) - ARM9.ExecuteJIT(); - else -#endif - ARM9.Execute(); + ARM9.Execute(); } RunTimers(0); @@ -995,12 +996,7 @@ u32 NDS::RunFrame() } else { -#ifdef JIT_ENABLED - if (EnableJIT) - ARM7.ExecuteJIT(); - else -#endif - ARM7.Execute(); + ARM7.Execute(); } RunTimers(1); @@ -1045,10 +1041,18 @@ u32 NDS::RunFrame() { #ifdef JIT_ENABLED if (EnableJIT) - return RunFrame(); + return RunFrame(); else #endif - return RunFrame(); +#ifdef GDBSTUB_ENABLED + if (EnableGDBStub) + { + return RunFrame(); + } else +#endif + { + return RunFrame(); + } } void NDS::Reschedule(u64 target) diff --git a/src/NDS.h b/src/NDS.h index 264f222b..b2bfb385 100644 --- a/src/NDS.h +++ b/src/NDS.h @@ -228,6 +228,9 @@ private: #ifdef JIT_ENABLED bool EnableJIT; #endif +#ifdef GDBSTUB_ENABLED + bool EnableGDBStub = false; +#endif public: // TODO: Encapsulate the rest of these members void* UserData; @@ -522,8 +525,9 @@ private: void SetWifiWaitCnt(u16 val); void SetGBASlotTimings(); void EnterSleepMode(); - template + template u32 RunFrame(); + public: NDS(NDSArgs&& args, void* userdata = nullptr) noexcept : NDS(std::move(args), 0, userdata) {} NDS() noexcept;