summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOxore <oxore@protonmail.com>2022-09-25 16:37:03 +0300
committerOxore <oxore@protonmail.com>2022-09-25 16:37:03 +0300
commit9c78f70071daa8d4d65ffe335c21af0e4b523841 (patch)
tree8a10d95459027035b49f815ae891da85fa3e0d03
parentbf5c361ed5ff57c077bb3b45d794325e8bdadc9a (diff)
Impl read and write watchpoints
-rw-r--r--bus.cpp9
-rw-r--r--emulator.cpp39
-rw-r--r--m68k_debugging.cpp36
3 files changed, 84 insertions, 0 deletions
diff --git a/bus.cpp b/bus.cpp
index 444749c..9697c09 100644
--- a/bus.cpp
+++ b/bus.cpp
@@ -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: {