summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bus.cpp119
-rw-r--r--emulator.cpp77
-rw-r--r--gdbremote_parser.cpp5
-rw-r--r--gdbremote_parser.hpp3
4 files changed, 124 insertions, 80 deletions
diff --git a/bus.cpp b/bus.cpp
index f611eba..df44164 100644
--- a/bus.cpp
+++ b/bus.cpp
@@ -26,10 +26,6 @@ std::vector<Breakpoint> code_bkpts{}, read_bkpts{}, write_bkpts{}, access_bkpts{
static void exit_error(const char* fmt, ...)
{
- va_list args;
- va_start(args, fmt);
- vfprintf(stderr, fmt, args);
- va_end(args);
static bool in_error = false;
if (in_error)
{
@@ -37,14 +33,35 @@ static void exit_error(const char* fmt, ...)
return;
}
in_error = true;
+ va_list args;
+ va_start(args, fmt);
+ vfprintf(stderr, fmt, args);
+ va_end(args);
fprintf(stderr, "\n");
unsigned int pc = m68k_get_reg(NULL, M68K_REG_PPC);
- char buff[100];
+ char buff[100]{};
m68k_disassemble(buff, pc, M68K_CPU_TYPE_68000);
fprintf(stderr, "%08x: %s\n", pc, buff);
exit(EXIT_FAILURE);
}
+static void report_error(const char* fmt, ...)
+{
+ static bool in_error = false;
+ if (in_error)
+ return;
+ in_error = true;
+ va_list args;
+ va_start(args, fmt);
+ vfprintf(stderr, fmt, args);
+ va_end(args);
+ fprintf(stderr, "\n");
+ unsigned int pc = m68k_get_reg(NULL, M68K_REG_PPC);
+ char buff[100]{};
+ m68k_disassemble(buff, pc, M68K_CPU_TYPE_68000);
+ fprintf(stderr, "%08x: %s\n", pc, buff);
+}
+
static inline bool is_in_range(uint32_t value, uint32_t begin, uint32_t length)
{
return value >= begin && value <= begin + length;
@@ -167,18 +184,68 @@ static inline bool memory_write(
return false;
}
+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);
+}
+
+extern void m68k_breakpoint_callback(void);
+
#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);
+static void m68k_read_callback(const uint32_t address, const uint32_t size)
+{
+ const auto access_it = std::find_if(
+ access_bkpts.begin(),
+ access_bkpts.end(),
+ [&](const Breakpoint& b) { return ranges_overlap(address, size, b.offset, b.length); });
+ if (access_it != access_bkpts.end()) {
+ m68k_breakpoint_callback();
+ printf("Access watchpoint @ 0x%08x\n", address);
+ }
+ 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()) {
+ m68k_breakpoint_callback();
+ printf("Read watchpoint @ 0x%08x\n", address);
+ }
+}
+
+static void m68k_write_callback(const uint32_t address, const uint32_t size)
+{
+ const auto access_it = std::find_if(
+ access_bkpts.begin(),
+ access_bkpts.end(),
+ [&](const Breakpoint& b) { return ranges_overlap(address, size, b.offset, b.length); });
+ if (access_it != access_bkpts.end()) {
+ m68k_breakpoint_callback();
+ printf("Access watchpoint @ 0x%08x\n", address);
+ }
+ 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()) {
+ m68k_breakpoint_callback();
+ printf("Write watchpoint @ 0x%08x\n", address);
+ }
+}
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);
+ if (!ret.successful) {
+ m68k_breakpoint_callback();
+ report_error("Read error u8 @%08x", address);
+ }
return ret.result;
}
@@ -187,8 +254,10 @@ 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)
- exit_error("Read error u16 @%08x", address);
+ if (!ret.successful) {
+ m68k_breakpoint_callback();
+ report_error("Read error u16 @%08x", address);
+ }
return ret.result;
}
@@ -197,8 +266,10 @@ 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)
- exit_error("Read error u32 @%08x", address);
+ if (!ret.successful) {
+ m68k_breakpoint_callback();
+ report_error("Read error u32 @%08x", address);
+ }
return ret.result;
}
@@ -206,7 +277,7 @@ unsigned int m68k_read_disassembler_16(unsigned int address)
{
assert(MASK_24(address) == 0); // Just curious
const struct read_result ret = memory_read(BITNESS_16, address);
- if (!ret.successful)
+ if (0 && !ret.successful)
exit_error("Disasm read error u16 @0x%08x", address);
return ret.result;
}
@@ -215,7 +286,7 @@ unsigned int m68k_read_disassembler_32(unsigned int address)
{
assert(MASK_24(address) == 0); // Just curious
const struct read_result ret = memory_read(BITNESS_32, address);
- if (!ret.successful)
+ if (0 && !ret.successful)
exit_error("Disasm read error u32 @0x%08x", address);
return ret.result;
}
@@ -225,8 +296,10 @@ 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 0x%02x (u8) to address %08x", value&0xff, address);
+ if (!successful) {
+ m68k_breakpoint_callback();
+ report_error("Attempted to write 0x%02x (u8) to address %08x", value&0xff, address);
+ }
}
void m68k_write_memory_16(unsigned int address, unsigned int value)
@@ -234,8 +307,10 @@ 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 0x%04x (u16) to address %08x", value&0xffff, address);
+ if (!successful) {
+ m68k_breakpoint_callback();
+ report_error("Attempted to write 0x%04x (u16) to address %08x", value&0xff, address);
+ }
}
void m68k_write_memory_32(unsigned int address, unsigned int value)
@@ -243,6 +318,8 @@ 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 0x%08x (u32) to address %08x", value, address);
+ if (!successful) {
+ m68k_breakpoint_callback();
+ report_error("Attempted to write 0x%08x (u32) to address %08x", value&0xff, address);
+ }
}
diff --git a/emulator.cpp b/emulator.cpp
index 945a104..ceb4217 100644
--- a/emulator.cpp
+++ b/emulator.cpp
@@ -32,6 +32,7 @@
static constexpr struct timespec kOneMillisecond{0, 1000000};
char msg_buf[MESSAGE_BUFFER_SIZE];
M68KDebuggingControl g_m68k_debug{};
+bool g_no_ack_mode{};
static int set_socket_reuseaddr(const int socket_fd)
{
@@ -113,7 +114,14 @@ static std::string CreateResponse(
case PacketType::kNone:
break;
case PacketType::kQuerySupported:
- break;
+ return "PacketSize=400000" // PacketSize number is in HEX
+ // These commented-out options are from OpenOCD
+ // TODO ";qXfer:memory-map:read+"
+ // TODO ";qXfer:features:read+"
+ // TODO ";qXfer:threads:read+"
+ ";QStartNoAckMode+" // It makes GDB shit fast!
+ ";vContSupported+" // We support "vCont?" packet
+ ;
case PacketType::kQueryHaltReason:
return "S05"; // TODO real reason
case PacketType::kQueryC:
@@ -145,6 +153,9 @@ static std::string CreateResponse(
}
}
break;
+ case PacketType::kQStartNoAckMode:
+ g_no_ack_mode = true;
+ return "OK";
case PacketType::kSetThreadForCont:
return "OK";
case PacketType::kSetThreadForOps:
@@ -287,63 +298,11 @@ int m68k_instr_callback(const 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 access_it = std::find_if(
- access_bkpts.begin(),
- access_bkpts.end(),
- [&](const Breakpoint& b) { return ranges_overlap(address, size, b.offset, b.length); });
- if (access_it != access_bkpts.end()) {
- g_m68k_debug.SetRunning(false);
- g_m68k_debug.RaiseBreakpoint();
- m68k_end_timeslice();
- printf("Access watchpoint @ 0x%08x\n", address);
- }
- 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)
+void m68k_breakpoint_callback(void)
{
- const auto access_it = std::find_if(
- access_bkpts.begin(),
- access_bkpts.end(),
- [&](const Breakpoint& b) { return ranges_overlap(address, size, b.offset, b.length); });
- if (access_it != access_bkpts.end()) {
- g_m68k_debug.SetRunning(false);
- g_m68k_debug.RaiseBreakpoint();
- m68k_end_timeslice();
- printf("Access watchpoint @ 0x%08x\n", address);
- }
- 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);
- }
+ g_m68k_debug.SetRunning(false);
+ g_m68k_debug.RaiseBreakpoint();
+ m68k_end_timeslice();
}
void ParseAndReact(
@@ -363,7 +322,7 @@ void ParseAndReact(
" Packet type: \"%s\"\n",
GDBRemote::Packet::PacketTypeToString(packet.type));
}
- if (res->ack.length() > 0) {
+ if (res->ack.length() > 0 && !g_no_ack_mode) {
printf("-> \"%s\"\n", res->ack.c_str());
if (send(conn_fd, &res->ack[0], res->ack.length(), 0) == -1)
perror("Send failed (ack/nak)");
@@ -428,7 +387,7 @@ int emulator(M68KDebuggingControl& m68k_debug)
break;
}
if (m68k_debug.IsRunning()) {
- m68k_execute(1000);
+ m68k_execute(10000);
}
if (m68k_debug.HasBreakpoint()) {
m68k_debug.ResetPendingBreakpoint();
diff --git a/gdbremote_parser.cpp b/gdbremote_parser.cpp
index 98533c5..2c13668 100644
--- a/gdbremote_parser.cpp
+++ b/gdbremote_parser.cpp
@@ -147,6 +147,10 @@ struct Command {
std::make_unique<const PacketDataRcmd>(std::move(data)),
};
}
+ static Packet parseQStartNoAckMode(const std::vector<Token>&&)
+ {
+ return Packet{PacketType::kQStartNoAckMode};
+ }
static Packet parseSetThreadForCont(const std::vector<Token>&&)
{
// TODO arguments
@@ -286,6 +290,7 @@ static const Command commands[] = {
{ "qAttached", Command::parseQueryAttached },
{ "qTStatus", Command::parseQueryTraceStatus },
{ "qRcmd", Command::parseQueryRcmd },
+ { "QStartNoAckMode", Command::parseQStartNoAckMode },
{ "Hc", Command::parseSetThreadForCont },
{ "Hg", Command::parseSetThreadForOps },
{ "vMustReplyEmpty", Command::parseMustReplyEmpty },
diff --git a/gdbremote_parser.hpp b/gdbremote_parser.hpp
index a6d76fc..d35d78e 100644
--- a/gdbremote_parser.hpp
+++ b/gdbremote_parser.hpp
@@ -52,6 +52,7 @@ enum class PacketType: int {
kQueryAttached,
kQueryTraceStatus,
kQueryRcmd,
+ kQStartNoAckMode,
kSetThreadForCont,
kSetThreadForOps,
kVMustReplyEmpty,
@@ -155,6 +156,8 @@ struct Packet {
return "qTStatus";
case PacketType::kQueryRcmd:
return "qRcmd";
+ case PacketType::kQStartNoAckMode:
+ return "QStartNoAckMode";
case PacketType::kSetThreadForCont:
return "Hc";
case PacketType::kSetThreadForOps: