// Copyright 2022 Dolphin Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later #pragma once #include #include #include #include #include "Common/CommonTypes.h" namespace Core { class CPUThreadGuard; } struct InstructionAttributes { u32 address = 0; std::string instruction = ""; std::string reg0 = ""; std::string reg1 = ""; std::string reg2 = ""; std::string reg3 = ""; std::optional memory_target = std::nullopt; u32 memory_target_size = 4; bool is_store = false; bool is_load = false; }; struct TraceOutput { u32 address = 0; std::optional memory_target = std::nullopt; std::string instruction; }; struct AutoStepResults { std::vector reg_tracked; std::set mem_tracked; u32 count = 0; bool timed_out = false; bool trackers_empty = false; }; enum class HitType : u32 { SKIP = (1 << 0), // Not a hit OVERWRITE = (1 << 1), // Tracked value gets overwritten by untracked. Typically skipped. MOVED = (1 << 2), // Target duplicated to another register, unchanged. SAVELOAD = (1 << 3), // Target saved or loaded. Priority over Pointer. POINTER = (1 << 4), // Target used as pointer/offset for save or load PASSIVE = (1 << 5), // Conditional, etc, but not pointer. Unchanged ACTIVE = (1 << 6), // Math, etc. Changed. UPDATED = (1 << 7), // Masked or math without changing register. }; class CodeTrace { public: enum class AutoStop { Always, Used, Changed }; void SetRegTracked(const std::string& reg); AutoStepResults AutoStepping(const Core::CPUThreadGuard& guard, bool continue_previous = false, AutoStop stop_on = AutoStop::Always); private: InstructionAttributes GetInstructionAttributes(const TraceOutput& line) const; TraceOutput SaveCurrentInstruction(const Core::CPUThreadGuard* guard) const; HitType TraceLogic(const TraceOutput& current_instr, bool first_hit = false); bool m_recording = false; std::vector m_reg_autotrack; std::set m_mem_autotrack; };