DSPAnalyzer: Break tight coupling to SDSP
Allows the analyzer to exist independently of the DSP structure. This allows for unit-tests to be created in a nicer manner. SDSP is only necessary during the analysis phase, so we only need to keep a reference around to it then as opposed to the entire lifecycle of the analyzer. This also allows the copy/move assignment operators to be defaulted, as a reference member variable prevents that.
This commit is contained in:
parent
f9c488f0d9
commit
cc512a7524
|
@ -61,17 +61,14 @@ constexpr u16 idle_skip_sigs[NUM_IDLE_SIGS][MAX_IDLE_SIG_SIZE + 1] = {
|
|||
0, 0},
|
||||
};
|
||||
|
||||
Analyzer::Analyzer(const SDSP& dsp) : m_dsp{dsp}
|
||||
{
|
||||
}
|
||||
|
||||
Analyzer::Analyzer() = default;
|
||||
Analyzer::~Analyzer() = default;
|
||||
|
||||
void Analyzer::Analyze()
|
||||
void Analyzer::Analyze(const SDSP& dsp)
|
||||
{
|
||||
Reset();
|
||||
AnalyzeRange(0x0000, 0x1000); // IRAM
|
||||
AnalyzeRange(0x8000, 0x9000); // IROM
|
||||
AnalyzeRange(dsp, 0x0000, 0x1000); // IRAM
|
||||
AnalyzeRange(dsp, 0x8000, 0x9000); // IROM
|
||||
}
|
||||
|
||||
void Analyzer::Reset()
|
||||
|
@ -79,7 +76,7 @@ void Analyzer::Reset()
|
|||
m_code_flags.fill(0);
|
||||
}
|
||||
|
||||
void Analyzer::AnalyzeRange(u16 start_addr, u16 end_addr)
|
||||
void Analyzer::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.
|
||||
|
@ -89,7 +86,7 @@ void Analyzer::AnalyzeRange(u16 start_addr, u16 end_addr)
|
|||
u16 last_arithmetic = 0;
|
||||
for (u16 addr = start_addr; addr < end_addr;)
|
||||
{
|
||||
const UDSPInstruction inst = m_dsp.ReadIMEM(addr);
|
||||
const UDSPInstruction inst = dsp.ReadIMEM(addr);
|
||||
const DSPOPCTemplate* opcode = GetOpTemplate(inst);
|
||||
if (!opcode)
|
||||
{
|
||||
|
@ -101,7 +98,7 @@ void Analyzer::AnalyzeRange(u16 start_addr, u16 end_addr)
|
|||
if ((inst & 0xffe0) == 0x0060 || (inst & 0xff00) == 0x1100)
|
||||
{
|
||||
// BLOOP, BLOOPI
|
||||
const u16 loop_end = m_dsp.ReadIMEM(addr + 1);
|
||||
const u16 loop_end = dsp.ReadIMEM(addr + 1);
|
||||
m_code_flags[addr] |= CODE_LOOP_START;
|
||||
m_code_flags[loop_end] |= CODE_LOOP_END;
|
||||
}
|
||||
|
@ -148,7 +145,7 @@ void Analyzer::AnalyzeRange(u16 start_addr, u16 end_addr)
|
|||
found = true;
|
||||
if (idle_skip_sigs[s][i] == 0xFFFF)
|
||||
continue;
|
||||
if (idle_skip_sigs[s][i] != m_dsp.ReadIMEM(static_cast<u16>(addr + i)))
|
||||
if (idle_skip_sigs[s][i] != dsp.ReadIMEM(static_cast<u16>(addr + i)))
|
||||
break;
|
||||
}
|
||||
if (found)
|
||||
|
|
|
@ -20,14 +20,14 @@ namespace DSP
|
|||
class Analyzer
|
||||
{
|
||||
public:
|
||||
explicit Analyzer(const SDSP& dsp);
|
||||
explicit Analyzer();
|
||||
~Analyzer();
|
||||
|
||||
Analyzer(const Analyzer&) = default;
|
||||
Analyzer& operator=(const Analyzer&) = delete;
|
||||
Analyzer& operator=(const Analyzer&) = default;
|
||||
|
||||
Analyzer(Analyzer&&) = default;
|
||||
Analyzer& operator=(Analyzer&&) = delete;
|
||||
Analyzer& operator=(Analyzer&&) = default;
|
||||
|
||||
// This one should be called every time IRAM changes - which is basically
|
||||
// every time that a new ucode gets uploaded, and never else. At that point,
|
||||
|
@ -35,7 +35,7 @@ public:
|
|||
// 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);
|
||||
|
||||
// Whether or not the given address indicates the start of an instruction.
|
||||
[[nodiscard]] bool IsStartOfInstruction(u16 address) const
|
||||
|
@ -90,15 +90,12 @@ private:
|
|||
|
||||
// Analyzes a region of DSP memory.
|
||||
// Note: start is inclusive, end is exclusive.
|
||||
void AnalyzeRange(u16 start_addr, u16 end_addr);
|
||||
void AnalyzeRange(const SDSP& dsp, u16 start_addr, u16 end_addr);
|
||||
|
||||
// Retrieves the flags set during analysis for code in memory.
|
||||
[[nodiscard]] u8 GetCodeFlags(u16 address) const { return m_code_flags[address]; }
|
||||
|
||||
// Holds data about all instructions in RAM.
|
||||
std::array<u8, 65536> m_code_flags{};
|
||||
|
||||
// DSP context for analysis to be run under.
|
||||
const SDSP& m_dsp;
|
||||
};
|
||||
} // namespace DSP
|
||||
|
|
|
@ -115,7 +115,7 @@ private:
|
|||
SDSP& m_dsp;
|
||||
};
|
||||
|
||||
SDSP::SDSP(DSPCore& core) : m_dsp_core{core}, m_analyzer{*this}
|
||||
SDSP::SDSP(DSPCore& core) : m_dsp_core{core}
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -487,7 +487,7 @@ void DSPCore::Step()
|
|||
void DSPCore::Reset()
|
||||
{
|
||||
m_dsp.Reset();
|
||||
m_dsp.GetAnalyzer().Analyze();
|
||||
m_dsp.GetAnalyzer().Analyze(m_dsp);
|
||||
}
|
||||
|
||||
void DSPCore::ClearIRAM()
|
||||
|
|
|
@ -93,7 +93,7 @@ void CodeLoaded(DSPCore& dsp, const u8* ptr, size_t size)
|
|||
UpdateDebugger();
|
||||
|
||||
dsp.ClearIRAM();
|
||||
state.GetAnalyzer().Analyze();
|
||||
state.GetAnalyzer().Analyze(state);
|
||||
}
|
||||
|
||||
void UpdateDebugger()
|
||||
|
|
Loading…
Reference in New Issue