summaryrefslogtreecommitdiff
path: root/Source/Core/Common/Debug/CodeTrace.h
blob: 4f2cb701f29ed720f3bdb1d4f0a524258ab1e255 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
// Copyright 2022 Dolphin Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later

#pragma once

#include <optional>
#include <set>
#include <string>
#include <vector>

#include "Common/CommonTypes.h"

struct InstructionAttributes
{
  u32 address = 0;
  std::string instruction = "";
  std::string reg0 = "";
  std::string reg1 = "";
  std::string reg2 = "";
  std::string reg3 = "";
  std::optional<u32> memory_target = std::nullopt;
  u32 memory_target_size = 4;
  bool is_store = false;
  bool is_load = false;
};

struct TraceOutput
{
  u32 address;
  std::optional<u32> memory_target = std::nullopt;
  std::string instruction;
};

struct AutoStepResults
{
  std::vector<std::string> reg_tracked;
  std::set<u32> 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(bool continue_previous = false, AutoStop stop_on = AutoStop::Always);

private:
  InstructionAttributes GetInstructionAttributes(const TraceOutput& line) const;
  TraceOutput SaveCurrentInstruction() const;
  HitType TraceLogic(const TraceOutput& current_instr, bool first_hit = false);

  bool m_recording = false;
  std::vector<std::string> m_reg_autotrack;
  std::set<u32> m_mem_autotrack;
};