mirror of
https://github.com/AlexSutila/IroGB.git
synced 2026-10-27 09:49:14 +00:00
80 lines
2.4 KiB
C++
80 lines
2.4 KiB
C++
#ifndef GBC_BREAKPOINT_HPP
|
|
#define GBC_BREAKPOINT_HPP
|
|
|
|
#include "emu_types.hpp"
|
|
#include "schedule.hpp"
|
|
#include <cstdint>
|
|
#include <string>
|
|
#include <variant>
|
|
|
|
namespace Debug {
|
|
|
|
/**
|
|
* A comprehensive list of reasons for a breakpoint to stop execution. User
|
|
* configured breakpoints are, obviously, configurable and specified via UI.
|
|
* Other reasons include the actual hardware event that is being evaluated.
|
|
* -------------------------------------------------------------------------
|
|
* Reasons are treated like bitmasks, hence, sometimes multiple reasons may
|
|
* be required for a given breakpoint to stop execution. Details vary based
|
|
* on the nature of each breakpoint.
|
|
*/
|
|
enum BreakReason : std::uint32_t {
|
|
BRK_CONTINUE = 0,
|
|
|
|
// User configured or hardware specified reasons
|
|
BRK_ADDRESS_EXECUTED = 1 << 1,
|
|
BRK_ADDRESS_READ = 1 << 2,
|
|
BRK_ADDRESS_WRITTEN = 1 << 3,
|
|
|
|
// User configured scheduler event reasons
|
|
BRK_EVENT_QUEUED = 1 << 4,
|
|
BRK_EVENT_POPPED = 1 << 5, // Analogous to event handling
|
|
|
|
// Hardware specified reasons only
|
|
BRK_STEP_CLOCK_CYCLE = 1 << 6,
|
|
BRK_STEP_INSTRUCTION = 1 << 7,
|
|
BRK_STEP_SCANLINE = 1 << 8,
|
|
BRK_STEP_FRAME = 1 << 9,
|
|
};
|
|
|
|
constexpr BreakReason operator|(const BreakReason a, const BreakReason b) {
|
|
return static_cast<BreakReason>(static_cast<std::uint32_t>(a) | static_cast<std::uint32_t>(b));
|
|
}
|
|
|
|
constexpr bool operator&(const BreakReason a, const BreakReason b) {
|
|
return static_cast<std::uint32_t>(a) & static_cast<std::uint32_t>(b);
|
|
}
|
|
|
|
/* The rationale here, is the user likely expects to see the `current` CPU state
|
|
* right as they press `break` (or whatever it is, based on frontend details).
|
|
* Pausing on other events might be confusing, and this event happens frequently
|
|
* enough to still come across as seamless to the naked eye. */
|
|
constexpr auto BRK_STOPPED_BY_UI = BRK_STEP_INSTRUCTION;
|
|
|
|
struct Context {
|
|
BreakReason reason;
|
|
time_type time;
|
|
|
|
// Additional context depends on breakpoint type
|
|
std::variant<std::monostate, event, addr_t> data;
|
|
};
|
|
|
|
class Breakpoint {
|
|
public:
|
|
explicit Breakpoint(BreakReason reason_flags, addr_t watch_addr);
|
|
explicit Breakpoint(BreakReason reason_flags, event e);
|
|
|
|
[[nodiscard]] bool eval(BreakReason reason_flags) const;
|
|
[[nodiscard]] bool has_flag(BreakReason flag) const;
|
|
|
|
[[nodiscard]] std::string to_string() const;
|
|
|
|
private:
|
|
std::variant<std::monostate, event, addr_t> context;
|
|
BreakReason reasons{};
|
|
};
|
|
|
|
}; // namespace Debug
|
|
|
|
#endif // GBC_BREAKPOINT_HPP
|