diff options
Diffstat (limited to 'emulator.cpp')
-rw-r--r-- | emulator.cpp | 68 |
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"); |