use templates to only execute GDB stub related code if enabled

This commit is contained in:
RSDuck 2024-08-05 03:23:49 +02:00
parent 76c2723f5c
commit dd386d12a9
4 changed files with 218 additions and 253 deletions

View File

@ -582,9 +582,11 @@ void ARM::CheckGdbIncoming()
GdbCheckA(); GdbCheckA();
} }
template <CPUExecuteMode mode>
void ARMv5::Execute() void ARMv5::Execute()
{ {
GdbCheckB(); if constexpr (mode == CPUExecuteMode::InterpreterGDB)
GdbCheckB();
if (Halted) if (Halted)
{ {
@ -607,231 +609,123 @@ void ARMv5::Execute()
while (NDS.ARM9Timestamp < NDS.ARM9Target) while (NDS.ARM9Timestamp < NDS.ARM9Target)
{ {
if (CPSR & 0x20) // THUMB if constexpr (mode == CPUExecuteMode::JIT)
{ {
GdbCheckC(); u32 instrAddr = R[15] - ((CPSR&0x20)?2:4);
// prefetch if ((instrAddr < FastBlockLookupStart || instrAddr >= (FastBlockLookupStart + FastBlockLookupSize))
R[15] += 2; && !NDS.JIT.SetupExecutableRegion(0, instrAddr, FastBlockLookup, FastBlockLookupStart, FastBlockLookupSize))
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)
{ {
NDS.ARM9Timestamp = NDS.ARM9Target; 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; JitBlockEntry block = NDS.JIT.LookUpBlock(0, FastBlockLookup,
Cycles = 0; instrAddr - FastBlockLookupStart, instrAddr);
} if (block)
ARM_Dispatch(this, block);
else
NDS.JIT.CompileBlock(this);
if (Halted == 2) if (StopExecution)
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 ((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; if ((Halted == 1 || IdleLoop) && NDS.ARM9Timestamp < NDS.ARM9Target)
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 else
{ {
NDS.ARM7Timestamp = NDS.ARM7Target; if (CPSR & 0x20) // THUMB
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))
{ {
u32 icode = ((CurInstr >> 4) & 0xF) | ((CurInstr >> 16) & 0xFF0); if constexpr (mode == CPUExecuteMode::InterpreterGDB)
ARMInterpreter::ARMInstrTable[icode](this); 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 else
AddCycles_C();
}
// TODO optimize this shit!!!
if (Halted)
{
if (Halted == 1 && NDS.ARM7Timestamp < NDS.ARM7Target)
{ {
NDS.ARM7Timestamp = NDS.ARM7Target; if constexpr (mode == CPUExecuteMode::InterpreterGDB)
} GdbCheckC();
break;
}
/*if (NDS::IF[1] & NDS::IE[1])
{
if (NDS::IME[1] & 0x1)
TriggerIRQ();
}*/
if (IRQ) TriggerIRQ();
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; Cycles = 0;
} }
if (Halted == 2) if (Halted == 2)
Halted = 0; Halted = 0;
if (Halted == 4)
{
assert(NDS.ConsoleType == 1);
auto& dsi = dynamic_cast<melonDS::DSi&>(NDS);
dsi.SoftReset();
Halted = 2;
}
} }
template void ARMv5::Execute<CPUExecuteMode::Interpreter>();
template void ARMv5::Execute<CPUExecuteMode::InterpreterGDB>();
#ifdef JIT_ENABLED #ifdef JIT_ENABLED
void ARMv4::ExecuteJIT() template void ARMv5::Execute<CPUExecuteMode::JIT>();
#endif
template <CPUExecuteMode mode>
void ARMv4::Execute()
{ {
if constexpr (mode == CPUExecuteMode::InterpreterGDB)
GdbCheckB();
if (Halted) if (Halted)
{ {
if (Halted == 2) if (Halted == 2)
@ -853,38 +747,95 @@ void ARMv4::ExecuteJIT()
while (NDS.ARM7Timestamp < NDS.ARM7Target) while (NDS.ARM7Timestamp < NDS.ARM7Target)
{ {
u32 instrAddr = R[15] - ((CPSR&0x20)?2:4); if constexpr (mode == CPUExecuteMode::JIT)
if ((instrAddr < FastBlockLookupStart || instrAddr >= (FastBlockLookupStart + FastBlockLookupSize))
&& !NDS.JIT.SetupExecutableRegion(1, instrAddr, FastBlockLookup, FastBlockLookupStart, FastBlockLookupSize))
{ {
NDS.ARM7Timestamp = NDS.ARM7Target; u32 instrAddr = R[15] - ((CPSR&0x20)?2:4);
Log(LogLevel::Error, "ARMv4 PC in non executable region %08X\n", R[15]);
return;
}
JitBlockEntry block = NDS.JIT.LookUpBlock(1, FastBlockLookup, if ((instrAddr < FastBlockLookupStart || instrAddr >= (FastBlockLookupStart + FastBlockLookupSize))
instrAddr - FastBlockLookupStart, instrAddr); && !NDS.JIT.SetupExecutableRegion(1, instrAddr, FastBlockLookup, FastBlockLookupStart, FastBlockLookupSize))
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) 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; NDS.ARM7Timestamp = NDS.ARM7Target;
} }
IdleLoop = 0;
break; break;
} }
/*if (NDS::IF[1] & NDS::IE[1])
{
if (NDS::IME[1] & 0x1)
TriggerIRQ();
}*/
if (IRQ) TriggerIRQ();
} }
NDS.ARM7Timestamp += Cycles; NDS.ARM7Timestamp += Cycles;
@ -902,6 +853,11 @@ void ARMv4::ExecuteJIT()
Halted = 2; Halted = 2;
} }
} }
template void ARMv4::Execute<CPUExecuteMode::Interpreter>();
template void ARMv4::Execute<CPUExecuteMode::InterpreterGDB>();
#ifdef JIT_ENABLED
template void ARMv4::Execute<CPUExecuteMode::JIT>();
#endif #endif
void ARMv5::FillPipeline() void ARMv5::FillPipeline()

View File

@ -43,6 +43,15 @@ enum
RWFlags_ForceUser = (1<<21), RWFlags_ForceUser = (1<<21),
}; };
enum class CPUExecuteMode : u32
{
Interpreter,
InterpreterGDB,
#ifdef JIT_ENABLED
JIT
#endif
};
struct GDBArgs; struct GDBArgs;
class ARMJIT; class ARMJIT;
class GPU; class GPU;
@ -75,10 +84,6 @@ public:
} }
void NocashPrint(u32 addr) noexcept; void NocashPrint(u32 addr) noexcept;
virtual void Execute() = 0;
#ifdef JIT_ENABLED
virtual void ExecuteJIT() = 0;
#endif
bool CheckCondition(u32 code) const bool CheckCondition(u32 code) const
{ {
@ -241,10 +246,8 @@ public:
void PrefetchAbort(); void PrefetchAbort();
void DataAbort(); void DataAbort();
void Execute() override; template <CPUExecuteMode mode>
#ifdef JIT_ENABLED void Execute();
void ExecuteJIT() override;
#endif
// all code accesses are forced nonseq 32bit // all code accesses are forced nonseq 32bit
u32 CodeRead32(u32 addr, bool branch); u32 CodeRead32(u32 addr, bool branch);
@ -383,10 +386,8 @@ public:
void JumpTo(u32 addr, bool restorecpsr = false) override; void JumpTo(u32 addr, bool restorecpsr = false) override;
void Execute() override; template <CPUExecuteMode mode>
#ifdef JIT_ENABLED void Execute();
void ExecuteJIT() override;
#endif
u16 CodeRead16(u32 addr) u16 CodeRead16(u32 addr)
{ {

View File

@ -107,6 +107,9 @@ NDS::NDS(NDSArgs&& args, int type, void* userdata) noexcept :
AREngine(*this), AREngine(*this),
ARM9(*this, args.GDB, args.JIT.has_value()), ARM9(*this, args.GDB, args.JIT.has_value()),
ARM7(*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 #ifdef JIT_ENABLED
EnableJIT(args.JIT.has_value()), EnableJIT(args.JIT.has_value()),
#endif #endif
@ -886,7 +889,7 @@ void NDS::RunSystemSleep(u64 timestamp)
} }
} }
template <bool EnableJIT> template <CPUExecuteMode cpuMode>
u32 NDS::RunFrame() u32 NDS::RunFrame()
{ {
FrameStartTimestamp = SysTimestamp; FrameStartTimestamp = SysTimestamp;
@ -927,8 +930,11 @@ u32 NDS::RunFrame()
} }
else else
{ {
ARM9.CheckGdbIncoming(); if (cpuMode == CPUExecuteMode::InterpreterGDB)
ARM7.CheckGdbIncoming(); {
ARM9.CheckGdbIncoming();
ARM7.CheckGdbIncoming();
}
if (!(CPUStop & CPUStop_Wakeup)) if (!(CPUStop & CPUStop_Wakeup))
{ {
@ -963,12 +969,7 @@ u32 NDS::RunFrame()
} }
else else
{ {
#ifdef JIT_ENABLED ARM9.Execute<cpuMode>();
if (EnableJIT)
ARM9.ExecuteJIT();
else
#endif
ARM9.Execute();
} }
RunTimers(0); RunTimers(0);
@ -995,12 +996,7 @@ u32 NDS::RunFrame()
} }
else else
{ {
#ifdef JIT_ENABLED ARM7.Execute<cpuMode>();
if (EnableJIT)
ARM7.ExecuteJIT();
else
#endif
ARM7.Execute();
} }
RunTimers(1); RunTimers(1);
@ -1045,10 +1041,18 @@ u32 NDS::RunFrame()
{ {
#ifdef JIT_ENABLED #ifdef JIT_ENABLED
if (EnableJIT) if (EnableJIT)
return RunFrame<true>(); return RunFrame<CPUExecuteMode::JIT>();
else else
#endif #endif
return RunFrame<false>(); #ifdef GDBSTUB_ENABLED
if (EnableGDBStub)
{
return RunFrame<CPUExecuteMode::InterpreterGDB>();
} else
#endif
{
return RunFrame<CPUExecuteMode::Interpreter>();
}
} }
void NDS::Reschedule(u64 target) void NDS::Reschedule(u64 target)

View File

@ -228,6 +228,9 @@ private:
#ifdef JIT_ENABLED #ifdef JIT_ENABLED
bool EnableJIT; bool EnableJIT;
#endif #endif
#ifdef GDBSTUB_ENABLED
bool EnableGDBStub = false;
#endif
public: // TODO: Encapsulate the rest of these members public: // TODO: Encapsulate the rest of these members
void* UserData; void* UserData;
@ -522,8 +525,9 @@ private:
void SetWifiWaitCnt(u16 val); void SetWifiWaitCnt(u16 val);
void SetGBASlotTimings(); void SetGBASlotTimings();
void EnterSleepMode(); void EnterSleepMode();
template <bool EnableJIT> template <CPUExecuteMode cpuMode>
u32 RunFrame(); u32 RunFrame();
public: public:
NDS(NDSArgs&& args, void* userdata = nullptr) noexcept : NDS(std::move(args), 0, userdata) {} NDS(NDSArgs&& args, void* userdata = nullptr) noexcept : NDS(std::move(args), 0, userdata) {}
NDS() noexcept; NDS() noexcept;