summaryrefslogtreecommitdiff
path: root/emulator.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'emulator.cpp')
-rw-r--r--emulator.cpp68
1 files changed, 55 insertions, 13 deletions
diff --git a/emulator.cpp b/emulator.cpp
index 6557120..67566b9 100644
--- a/emulator.cpp
+++ b/emulator.cpp
@@ -29,10 +29,35 @@
#define MESSAGE_BUFFER_SIZE 1024
+template<typename T, size_t S>
+struct Backtrace {
+ static_assert(S > 0, "Backtrace size cannot be zero");
+ void Push(T value)
+ {
+ head = (head < S) ? head + 1 : 0;
+ buffer[head] = value;
+ }
+ void Normalize(void)
+ {
+ constexpr auto last_offset = S - 1;
+ for (; head < last_offset; head++) {
+ const T tmp = buffer[last_offset];
+ memmove(&buffer[1], &buffer[0], (S - 1) * sizeof(buffer[0]));
+ buffer[0] = tmp;
+ }
+ }
+ static constexpr size_t Size(void) {
+ return S;
+ }
+ T buffer[S]{};
+ size_t head{};
+};
+
static constexpr struct timespec kOneMillisecond{0, 1000000};
-char msg_buf[MESSAGE_BUFFER_SIZE];
-M68KDebuggingControl g_m68k_debug{};
-bool g_no_ack_mode{};
+static char msg_buf[MESSAGE_BUFFER_SIZE];
+static M68KDebuggingControl g_m68k_debug{};
+static bool g_no_ack_mode{};
+static Backtrace<uint32_t, 10> g_pc_backtrace{};
static int set_socket_reuseaddr(const int socket_fd)
{
@@ -164,7 +189,7 @@ static std::string CreateResponse(
case PacketType::kEnableExtendedMode:
break;
case PacketType::kInterrupt:
- m68k_debug.SetRunning(false);
+ g_m68k_debug.RaiseBreakpoint();
return "S05"; // TODO real reason
case PacketType::kContinue:
m68k_debug.SetRunning(true);
@@ -270,36 +295,52 @@ static void make_hex(char* buff, unsigned int pc, unsigned int length)
}
}
+static void PrintInstructionTrace(const uint32_t pc)
+{
+ char buff[100];
+ const unsigned int instr_size =
+ m68k_disassemble(buff, pc, M68K_CPU_TYPE_68000);
+ char buff2[100];
+ make_hex(buff2, pc, instr_size);
+ printf(" %08x: %-20s: %s\n", pc, buff2, buff);
+ fflush(stdout);
+}
+
// TODO m68k_set_illg_instr_callback for true software breakpoint "4e4f"
int m68k_instr_callback(const int pc)
{
+ g_pc_backtrace.Push(pc);
const auto it = std::find_if(
code_bkpts.begin(),
code_bkpts.end(),
[&](const Breakpoint& b) { return b.offset == static_cast<uint32_t>(pc); });
if (it != code_bkpts.end()) {
- g_m68k_debug.SetRunning(false);
g_m68k_debug.RaiseBreakpoint();
m68k_end_timeslice();
printf("Breakpoint @ 0x%08x\n", pc);
+ g_pc_backtrace.Normalize();
+ printf("PC backtrace (size=%zu):\n", g_pc_backtrace.Size());
+ for (size_t i = 0; i < g_pc_backtrace.Size(); i++)
+ {
+ PrintInstructionTrace(g_pc_backtrace.buffer[i]);
+ }
return 1;
}
if (DEBUG_TRACE_INSTRUCTIONS) {
- char buff[100];
- const unsigned int instr_size =
- m68k_disassemble(buff, pc, M68K_CPU_TYPE_68000);
- char buff2[100];
- make_hex(buff2, pc, instr_size);
- printf(" %08X: %-20s: %s\n", pc, buff2, buff);
- fflush(stdout);
+ PrintInstructionTrace(pc);
}
return 0;
}
void m68k_breakpoint_callback(void)
{
- g_m68k_debug.SetRunning(false);
+ g_pc_backtrace.Normalize();
+ printf("PC backtrace (size=%zu):\n", g_pc_backtrace.Size());
+ for (size_t i = 0; i < g_pc_backtrace.Size(); i++)
+ {
+ PrintInstructionTrace(g_pc_backtrace.buffer[i]);
+ }
g_m68k_debug.RaiseBreakpoint();
m68k_end_timeslice();
}
@@ -389,6 +430,7 @@ int emulator(M68KDebuggingControl& m68k_debug)
m68k_execute(10000);
}
if (m68k_debug.HasBreakpoint()) {
+ m68k_debug.SetRunning(false);
m68k_debug.ResetPendingBreakpoint();
const auto response =
exchange_ctx.WrapDataToSend("S05");