diff options
author | Oxore <oxore@protonmail.com> | 2022-09-25 16:37:03 +0300 |
---|---|---|
committer | Oxore <oxore@protonmail.com> | 2022-09-25 16:37:03 +0300 |
commit | 9c78f70071daa8d4d65ffe335c21af0e4b523841 (patch) | |
tree | 8a10d95459027035b49f815ae891da85fa3e0d03 | |
parent | bf5c361ed5ff57c077bb3b45d794325e8bdadc9a (diff) |
Impl read and write watchpoints
-rw-r--r-- | bus.cpp | 9 | ||||
-rw-r--r-- | emulator.cpp | 39 | ||||
-rw-r--r-- | m68k_debugging.cpp | 36 |
3 files changed, 84 insertions, 0 deletions
@@ -142,9 +142,13 @@ static inline bool memory_write( #define MASK_24(X) ((X) & (0xFF << 24)) +extern void m68k_read_callback(const uint32_t address, const uint32_t size); +extern void m68k_write_callback(const uint32_t address, const uint32_t size); + unsigned int m68k_read_memory_8(unsigned int address) { assert(MASK_24(address) == 0); // Just curious + m68k_read_callback(address, 4); const struct read_result ret = memory_read(BITNESS_8, address); if (!ret.successful) exit_error("Read error u8 @%08x", address); @@ -153,6 +157,7 @@ unsigned int m68k_read_memory_8(unsigned int address) unsigned int m68k_read_memory_16(unsigned int address) { + m68k_read_callback(address, 2); assert(MASK_24(address) == 0); // Just curious const struct read_result ret = memory_read(BITNESS_16, address); if (!ret.successful) @@ -162,6 +167,7 @@ unsigned int m68k_read_memory_16(unsigned int address) unsigned int m68k_read_memory_32(unsigned int address) { + m68k_read_callback(address, 1); assert(MASK_24(address) == 0); // Just curious const struct read_result ret = memory_read(BITNESS_32, address); if (!ret.successful) @@ -190,6 +196,7 @@ unsigned int m68k_read_disassembler_32(unsigned int address) void m68k_write_memory_8(unsigned int address, unsigned int value) { assert(MASK_24(address) == 0); // Just curious + m68k_write_callback(address, 1); const bool successful = memory_write(BITNESS_8, address, value); if (!successful) exit_error("Attempted to write %02x (u8) to address %08x", value&0xff, address); @@ -198,6 +205,7 @@ void m68k_write_memory_8(unsigned int address, unsigned int value) void m68k_write_memory_16(unsigned int address, unsigned int value) { assert(MASK_24(address) == 0); // Just curious + m68k_write_callback(address, 2); const bool successful = memory_write(BITNESS_16, address, value); if (!successful) exit_error("Attempted to write %04x (u16) to address %08x", value&0xffff, address); @@ -206,6 +214,7 @@ void m68k_write_memory_16(unsigned int address, unsigned int value) void m68k_write_memory_32(unsigned int address, unsigned int value) { assert(MASK_24(address) == 0); // Just curious + m68k_write_callback(address, 4); const bool successful = memory_write(BITNESS_16, address, value); if (!successful) exit_error("Attempted to write %08x (u32) to address %08x", value, address); diff --git a/emulator.cpp b/emulator.cpp index 7a1dffa..ea2c051 100644 --- a/emulator.cpp +++ b/emulator.cpp @@ -287,6 +287,45 @@ int m68k_instr_callback(int pc) return 0; } +static inline bool ranges_overlap( + const uint32_t a_start, + const uint32_t a_len, + const uint32_t b_start, + const uint32_t b_len) +{ + return (a_start < b_start + b_len && b_start < a_start + a_len); +} + +// XXX Maybe better move it to bus.cpp? +void m68k_read_callback(const uint32_t address, const uint32_t size) +{ + const auto it = std::find_if( + read_bkpts.begin(), + read_bkpts.end(), + [&](const Breakpoint& b) { return ranges_overlap(address, size, b.offset, b.length); }); + if (it != read_bkpts.end()) { + g_m68k_debug.SetRunning(false); + g_m68k_debug.RaiseBreakpoint(); + m68k_end_timeslice(); + printf("Read watchpoint @ 0x%08x\n", address); + } +} + +// XXX Maybe better move it to bus.cpp? +void m68k_write_callback(const uint32_t address, const uint32_t size) +{ + const auto it = std::find_if( + write_bkpts.begin(), + write_bkpts.end(), + [&](const Breakpoint& b) { return ranges_overlap(address, size, b.offset, b.length); }); + if (it != write_bkpts.end()) { + g_m68k_debug.SetRunning(false); + g_m68k_debug.RaiseBreakpoint(); + m68k_end_timeslice(); + printf("Write watchpoint @ 0x%08x\n", address); + } +} + void ParseAndReact( int conn_fd, GDBRemote::ExchangeContext& exchange_ctx, diff --git a/m68k_debugging.cpp b/m68k_debugging.cpp index 509299d..d02e463 100644 --- a/m68k_debugging.cpp +++ b/m68k_debugging.cpp @@ -157,10 +157,28 @@ void M68KDebuggingControl::SetBreakpoint(BreakpointType type, uint32_t address, code_bkpts.push_back(Breakpoint{address, length}); } break; case BreakpointType::kWriteWatchpoint: { + const auto it = std::find_if( + write_bkpts.begin(), + write_bkpts.end(), + [&](const Breakpoint& b) { return b.offset == address && b.length == length; }); + if (it == write_bkpts.end()) + write_bkpts.push_back(Breakpoint{address, length}); } break; case BreakpointType::kReadWatchpoint: { + const auto it = std::find_if( + read_bkpts.begin(), + read_bkpts.end(), + [&](const Breakpoint& b) { return b.offset == address && b.length == length; }); + if (it == read_bkpts.end()) + read_bkpts.push_back(Breakpoint{address, length}); } break; case BreakpointType::kAccessWatchpoint: { + const auto it = std::find_if( + access_bkpts.begin(), + access_bkpts.end(), + [&](const Breakpoint& b) { return b.offset == address && b.length == length; }); + if (it == access_bkpts.end()) + access_bkpts.push_back(Breakpoint{address, length}); } break; break; case BreakpointType::kUnsupported: { @@ -182,10 +200,28 @@ void M68KDebuggingControl::RemoveBreakpoint(BreakpointType type, uint32_t addres code_bkpts.erase(it); } break; case BreakpointType::kWriteWatchpoint: { + const auto it = std::find_if( + write_bkpts.begin(), + write_bkpts.end(), + [&](const Breakpoint& b) { return b.offset == address && b.length == length; }); + if (it != write_bkpts.end()) + write_bkpts.erase(it); } break; case BreakpointType::kReadWatchpoint: { + const auto it = std::find_if( + read_bkpts.begin(), + read_bkpts.end(), + [&](const Breakpoint& b) { return b.offset == address && b.length == length; }); + if (it != read_bkpts.end()) + read_bkpts.erase(it); } break; case BreakpointType::kAccessWatchpoint: { + const auto it = std::find_if( + access_bkpts.begin(), + access_bkpts.end(), + [&](const Breakpoint& b) { return b.offset == address && b.length == length; }); + if (it != access_bkpts.end()) + access_bkpts.erase(it); } break; break; case BreakpointType::kUnsupported: { |