summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOxore <oxore@protonmail.com>2022-09-23 10:00:55 +0300
committerOxore <oxore@protonmail.com>2022-09-25 15:06:52 +0300
commit2e363155df0380bed5210e41d395015320a9bb74 (patch)
treeda88603bdb250e40aa4c6853d6c37325a2d04aa4
parent2233177e7ada45838dc61d1a5f98ff44f7fbc3a6 (diff)
Impl monitor reset and reset halt commands
-rw-r--r--emulator.cpp24
-rw-r--r--gdbremote_parser.cpp28
-rw-r--r--gdbremote_parser.hpp9
3 files changed, 60 insertions, 1 deletions
diff --git a/emulator.cpp b/emulator.cpp
index 051c6db..5dd266a 100644
--- a/emulator.cpp
+++ b/emulator.cpp
@@ -95,11 +95,20 @@ static int setup_socket(uint16_t port)
return socket_fd;
}
+static inline bool IsReset(const std::string& command)
+{
+ if (command == "reset") return true;
+ if (command == "reset halt") return true;
+ if (command == "system_reset") return true;
+ return false;
+}
+
static std::string CreateResponse(
M68KDebuggingControl& m68k_debug,
const GDBRemote::Packet& packet)
{
using namespace GDBRemote;
+ // TODO use switch-case
if (0) {
} else if (packet.type == PacketType::kQueryHaltReason) {
return "S05"; // TODO real reason
@@ -116,6 +125,20 @@ static std::string CreateResponse(
return "OK";
} else if (packet.type == PacketType::kQueryAttached) {
return "1";
+ } else if (packet.type == PacketType::kQueryRcmd) {
+ const auto * const packet_data =
+ static_cast<const PacketDataRcmd*>(packet.data.get());
+ if (IsReset(packet_data->data)) {
+ m68k_pulse_reset();
+ // I don't want to skip reset cycles here, because GDB does not
+ // re-read registers every time, and if we skip reset cycles here,
+ // the consequent "stepi" in gdb will end up on second instruction
+ // of reset handler. If we don't skip reset cycles, the first
+ // "stepi" after "monitor reset" will land us on the first
+ // instruction in reset handler - I'd prefer this exact behavior for
+ // now.
+ return "OK";
+ }
} else if (packet.type == PacketType::kInterrupt) {
return "OK";
} else if (packet.type == PacketType::kSetBreakpoint) {
@@ -356,6 +379,7 @@ int main(int argc, char* argv[])
m68k_init();
m68k_set_cpu_type(M68K_CPU_TYPE_68000);
m68k_pulse_reset();
+ m68k_execute(1); // Skip reset cycles
emulator(g_m68k_debug);
while (0)
diff --git a/gdbremote_parser.cpp b/gdbremote_parser.cpp
index b9115be..98533c5 100644
--- a/gdbremote_parser.cpp
+++ b/gdbremote_parser.cpp
@@ -79,6 +79,15 @@ struct Token {
}
};
+static std::string DecodeBinaryHex(const std::string& data_hex)
+{
+ std::string data(data_hex.size()/2, '\0');
+ for (size_t i = 0; i < data.size(); i++) {
+ data[i] = Utils::ParseByteFromHexChars(data_hex[i * 2], data_hex[i * 2 + 1]);
+ }
+ return data;
+}
+
struct Command {
std::string name;
Packet (*parse)(const std::vector<Token>&&);
@@ -122,6 +131,22 @@ struct Command {
{
return Packet{PacketType::kQueryTraceStatus};
}
+ static Packet parseQueryRcmd(const std::vector<Token>&& tokens)
+ {
+ if (tokens.size() < 3)
+ return Packet::None();
+ if (tokens[1].type != TokenType::kSeparatorComma)
+ return Packet::None();
+ if (tokens[2].type != TokenType::kHexNumeric)
+ return Packet::None();
+ const std::string& data_encoded = tokens[2].data;
+ const std::string data = DecodeBinaryHex(data_encoded);
+ printf("%s\n", data.c_str());
+ return Packet{
+ PacketType::kQueryRcmd,
+ std::make_unique<const PacketDataRcmd>(std::move(data)),
+ };
+ }
static Packet parseSetThreadForCont(const std::vector<Token>&&)
{
// TODO arguments
@@ -146,7 +171,7 @@ struct Command {
}
static Packet parseContinueVCont(const std::vector<Token>&& tokens)
{
- const std::string first_arg = tokens[1].data;
+ const std::string first_arg = tokens.size() > 1 ? tokens[1].data : "";
// Check if it is "vCont?" command
if (first_arg == "?") {
return Packet{PacketType::kContinueAskSupported};
@@ -260,6 +285,7 @@ static const Command commands[] = {
{ "qL", Command::parseQueryRTOSThreadInfo },
{ "qAttached", Command::parseQueryAttached },
{ "qTStatus", Command::parseQueryTraceStatus },
+ { "qRcmd", Command::parseQueryRcmd },
{ "Hc", Command::parseSetThreadForCont },
{ "Hg", Command::parseSetThreadForOps },
{ "vMustReplyEmpty", Command::parseMustReplyEmpty },
diff --git a/gdbremote_parser.hpp b/gdbremote_parser.hpp
index 370e8cc..a6d76fc 100644
--- a/gdbremote_parser.hpp
+++ b/gdbremote_parser.hpp
@@ -51,6 +51,7 @@ enum class PacketType: int {
kQueryRTOSThreadInfo,
kQueryAttached,
kQueryTraceStatus,
+ kQueryRcmd,
kSetThreadForCont,
kSetThreadForOps,
kVMustReplyEmpty,
@@ -94,6 +95,12 @@ struct PacketDataWriteMemory: public PacketData {
virtual ~PacketDataWriteMemory() {}
};
+struct PacketDataRcmd: public PacketData {
+ PacketDataRcmd(const std::string&& a_data): data(std::move(a_data)) {}
+ std::string data{};
+ virtual ~PacketDataRcmd() {}
+};
+
enum class BreakpointType: uint32_t {
kMin = 0,
kSoftwareBreakpoint = 0,
@@ -146,6 +153,8 @@ struct Packet {
return "qAttached";
case PacketType::kQueryTraceStatus:
return "qTStatus";
+ case PacketType::kQueryRcmd:
+ return "qRcmd";
case PacketType::kSetThreadForCont:
return "Hc";
case PacketType::kSetThreadForOps: