mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2024-11-15 05:47:56 -07:00
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},
|
0, 0},
|
||||||
};
|
};
|
||||||
|
|
||||||
Analyzer::Analyzer(const SDSP& dsp) : m_dsp{dsp}
|
Analyzer::Analyzer() = default;
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
Analyzer::~Analyzer() = default;
|
Analyzer::~Analyzer() = default;
|
||||||
|
|
||||||
void Analyzer::Analyze()
|
void Analyzer::Analyze(const SDSP& dsp)
|
||||||
{
|
{
|
||||||
Reset();
|
Reset();
|
||||||
AnalyzeRange(0x0000, 0x1000); // IRAM
|
AnalyzeRange(dsp, 0x0000, 0x1000); // IRAM
|
||||||
AnalyzeRange(0x8000, 0x9000); // IROM
|
AnalyzeRange(dsp, 0x8000, 0x9000); // IROM
|
||||||
}
|
}
|
||||||
|
|
||||||
void Analyzer::Reset()
|
void Analyzer::Reset()
|
||||||
@ -79,7 +76,7 @@ void Analyzer::Reset()
|
|||||||
m_code_flags.fill(0);
|
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
|
// First we run an extremely simplified version of a disassembler to find
|
||||||
// where all instructions start.
|
// where all instructions start.
|
||||||
@ -89,7 +86,7 @@ void Analyzer::AnalyzeRange(u16 start_addr, u16 end_addr)
|
|||||||
u16 last_arithmetic = 0;
|
u16 last_arithmetic = 0;
|
||||||
for (u16 addr = start_addr; addr < end_addr;)
|
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);
|
const DSPOPCTemplate* opcode = GetOpTemplate(inst);
|
||||||
if (!opcode)
|
if (!opcode)
|
||||||
{
|
{
|
||||||
@ -101,7 +98,7 @@ void Analyzer::AnalyzeRange(u16 start_addr, u16 end_addr)
|
|||||||
if ((inst & 0xffe0) == 0x0060 || (inst & 0xff00) == 0x1100)
|
if ((inst & 0xffe0) == 0x0060 || (inst & 0xff00) == 0x1100)
|
||||||
{
|
{
|
||||||
// BLOOP, BLOOPI
|
// 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[addr] |= CODE_LOOP_START;
|
||||||
m_code_flags[loop_end] |= CODE_LOOP_END;
|
m_code_flags[loop_end] |= CODE_LOOP_END;
|
||||||
}
|
}
|
||||||
@ -148,7 +145,7 @@ void Analyzer::AnalyzeRange(u16 start_addr, u16 end_addr)
|
|||||||
found = true;
|
found = true;
|
||||||
if (idle_skip_sigs[s][i] == 0xFFFF)
|
if (idle_skip_sigs[s][i] == 0xFFFF)
|
||||||
continue;
|
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;
|
break;
|
||||||
}
|
}
|
||||||
if (found)
|
if (found)
|
||||||
|
@ -20,14 +20,14 @@ namespace DSP
|
|||||||
class Analyzer
|
class Analyzer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit Analyzer(const SDSP& dsp);
|
explicit Analyzer();
|
||||||
~Analyzer();
|
~Analyzer();
|
||||||
|
|
||||||
Analyzer(const Analyzer&) = default;
|
Analyzer(const Analyzer&) = default;
|
||||||
Analyzer& operator=(const Analyzer&) = delete;
|
Analyzer& operator=(const Analyzer&) = default;
|
||||||
|
|
||||||
Analyzer(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
|
// 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,
|
// 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
|
// 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
|
// words and the actual code space 8K instructions in total, so we can do
|
||||||
// some pretty expensive analysis if necessary.
|
// 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.
|
// Whether or not the given address indicates the start of an instruction.
|
||||||
[[nodiscard]] bool IsStartOfInstruction(u16 address) const
|
[[nodiscard]] bool IsStartOfInstruction(u16 address) const
|
||||||
@ -90,15 +90,12 @@ private:
|
|||||||
|
|
||||||
// Analyzes a region of DSP memory.
|
// Analyzes a region of DSP memory.
|
||||||
// Note: start is inclusive, end is exclusive.
|
// 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.
|
// Retrieves the flags set during analysis for code in memory.
|
||||||
[[nodiscard]] u8 GetCodeFlags(u16 address) const { return m_code_flags[address]; }
|
[[nodiscard]] u8 GetCodeFlags(u16 address) const { return m_code_flags[address]; }
|
||||||
|
|
||||||
// Holds data about all instructions in RAM.
|
// Holds data about all instructions in RAM.
|
||||||
std::array<u8, 65536> m_code_flags{};
|
std::array<u8, 65536> m_code_flags{};
|
||||||
|
|
||||||
// DSP context for analysis to be run under.
|
|
||||||
const SDSP& m_dsp;
|
|
||||||
};
|
};
|
||||||
} // namespace DSP
|
} // namespace DSP
|
||||||
|
@ -115,7 +115,7 @@ private:
|
|||||||
SDSP& m_dsp;
|
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()
|
void DSPCore::Reset()
|
||||||
{
|
{
|
||||||
m_dsp.Reset();
|
m_dsp.Reset();
|
||||||
m_dsp.GetAnalyzer().Analyze();
|
m_dsp.GetAnalyzer().Analyze(m_dsp);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DSPCore::ClearIRAM()
|
void DSPCore::ClearIRAM()
|
||||||
|
@ -93,7 +93,7 @@ void CodeLoaded(DSPCore& dsp, const u8* ptr, size_t size)
|
|||||||
UpdateDebugger();
|
UpdateDebugger();
|
||||||
|
|
||||||
dsp.ClearIRAM();
|
dsp.ClearIRAM();
|
||||||
state.GetAnalyzer().Analyze();
|
state.GetAnalyzer().Analyze(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
void UpdateDebugger()
|
void UpdateDebugger()
|
||||||
|
Loading…
Reference in New Issue
Block a user