diff --git a/core/hostevents_sdl.cpp b/core/hostevents_sdl.cpp index b3a0b38..27daa94 100644 --- a/core/hostevents_sdl.cpp +++ b/core/hostevents_sdl.cpp @@ -40,6 +40,7 @@ void EventManager::poll_events() switch (event.type) { case SDL_QUIT: power_on = false; + power_off_reason = po_shut_down; break; case SDL_WINDOWEVENT: { diff --git a/cpu/ppc/ppcemu.h b/cpu/ppc/ppcemu.h index d152609..a0553a6 100644 --- a/cpu/ppc/ppcemu.h +++ b/cpu/ppc/ppcemu.h @@ -320,7 +320,20 @@ extern jmp_buf exc_env; extern bool grab_return; +enum Po_Cause : int { + po_none, + po_starting_up, + po_shut_down, + po_shutting_down, + po_disassemble_on, + po_disassemble_off, + po_enter_debugger, + po_entered_debugger, + po_signal_interrupt, +}; + extern bool power_on; +extern Po_Cause power_off_reason; extern bool int_pin; extern bool dec_exception_pending; diff --git a/cpu/ppc/ppcexec.cpp b/cpu/ppc/ppcexec.cpp index 4fc7d90..0844906 100644 --- a/cpu/ppc/ppcexec.cpp +++ b/cpu/ppc/ppcexec.cpp @@ -39,7 +39,8 @@ MemCtrlBase* mem_ctrl_instance = 0; bool is_601 = false; -bool power_on = 1; +bool power_on = false; +Po_Cause power_off_reason = po_enter_debugger; SetPRS ppc_state; @@ -340,15 +341,13 @@ static void ppc_exec_inner() pc_real = mmu_translate_imem(eb_start); // interpret execution block - while (ppc_state.pc < eb_end) { + while (power_on && ppc_state.pc < eb_end) { ppc_main_opcode(); if (g_icycles++ >= max_cycles) { max_cycles = process_events(); } if (exec_flags) { - if (!power_on) - break; // reload cycle counter if requested if (exec_flags & EXEF_TIMER) { max_cycles = process_events(); @@ -445,7 +444,7 @@ static void ppc_exec_until_inner(const uint32_t goal_addr) pc_real = mmu_translate_imem(eb_start); // interpret execution block - while ((ppc_state.pc < eb_end)) { + while (power_on && ppc_state.pc < eb_end) { ppc_main_opcode(); if (g_icycles++ >= max_cycles) { max_cycles = process_events(); @@ -484,7 +483,7 @@ static void ppc_exec_until_inner(const uint32_t goal_addr) if (ppc_state.pc == goal_addr) break; } - } while (ppc_state.pc != goal_addr); + } while (power_on && ppc_state.pc != goal_addr); } // outer interpreter loop @@ -498,7 +497,7 @@ void ppc_exec_until(volatile uint32_t goal_addr) do { ppc_exec_until_inner(goal_addr); - } while (ppc_state.pc != goal_addr); + } while (power_on && ppc_state.pc != goal_addr); } /** Execute PPC code until control is reached the specified region. */ @@ -512,7 +511,7 @@ static void ppc_exec_dbg_inner(const uint32_t start_addr, const uint32_t size) max_cycles = 0; - while (ppc_state.pc < start_addr || ppc_state.pc >= start_addr + size) { + while (power_on && (ppc_state.pc < start_addr || ppc_state.pc >= start_addr + size)) { // define boundaries of the next execution block // max execution block length = one memory page eb_start = ppc_state.pc; @@ -523,7 +522,7 @@ static void ppc_exec_dbg_inner(const uint32_t start_addr, const uint32_t size) pc_real = mmu_translate_imem(eb_start); // interpret execution block - while ((ppc_state.pc < start_addr || ppc_state.pc >= start_addr + size) + while (power_on && (ppc_state.pc < start_addr || ppc_state.pc >= start_addr + size) && (ppc_state.pc < eb_end)) { ppc_main_opcode(); if (g_icycles++ >= max_cycles) { @@ -572,7 +571,7 @@ void ppc_exec_dbg(volatile uint32_t start_addr, volatile uint32_t size) ppc_state.pc = ppc_next_instruction_address; } - while (ppc_state.pc < start_addr || ppc_state.pc >= start_addr + size) { + while (power_on && (ppc_state.pc < start_addr || ppc_state.pc >= start_addr + size)) { ppc_exec_dbg_inner(start_addr, size); } } diff --git a/debugger/debugger.cpp b/debugger/debugger.cpp index f613db6..2cdf33c 100644 --- a/debugger/debugger.cpp +++ b/debugger/debugger.cpp @@ -121,7 +121,7 @@ static void disasm_68k(uint32_t count, uint32_t address) { cs_insn* insn = cs_malloc(cs_handle); - for (; count > 0; count--) { + for (; power_on && count > 0; count--) { /* prefetch opcode bytes (a 68k instruction can occupy 2...10 bytes) */ for (int i = 0; i < sizeof(code); i++) { code[i] = mem_read_dbg(address + i, 1); @@ -180,10 +180,10 @@ void exec_single_68k() //printf("cur_instr_tab_entry = %X\n", cur_instr_tab_entry); - /* because the first two PPC instructions for each emulated 68k once + /* because the first two PPC instructions for each emulated 68k opcode are resided in the emulator opcode table, we need to execute them one by one until the execution goes outside the opcode table. */ - while (ppc_pc >= cur_instr_tab_entry && ppc_pc < cur_instr_tab_entry + 8) { + while (power_on && ppc_pc >= cur_instr_tab_entry && ppc_pc < cur_instr_tab_entry + 8) { ppc_exec_single(); ppc_pc = get_reg(string("PC")); } @@ -200,8 +200,8 @@ void exec_until_68k(uint32_t target_addr) emu_table_virt = get_reg(string("R29")) & 0xFFF80000; - while (target_addr != (get_reg(string("R24")) - 2)) { - ppc_pc = get_reg(string("PC")); + while (power_on && target_addr != (get_reg(string("R24")) - 2)) { + ppc_pc = static_cast(get_reg(string("PC"))); if (ppc_pc >= emu_table_virt && ppc_pc < (emu_table_virt + EMU_68K_TABLE_SIZE - 1)) { ppc_exec_single(); @@ -442,44 +442,82 @@ void enter_debugger() { std::stringstream ss; int log_level, context; size_t separator_pos; + bool did_message = false; unique_ptr ofnvram = unique_ptr(new OfConfigUtils); context = 1; /* start with the PowerPC context */ - cout << "Welcome to the DingusPPC command line debugger." << endl; - cout << "Please enter a command or 'help'." << endl << endl; - #ifndef _WIN32 struct winsize win_size_previous; ioctl(0, TIOCGWINSZ, &win_size_previous); #endif while (1) { - cout << "dingusdbg> "; + if (power_off_reason == po_shut_down) { + power_off_reason = po_shutting_down; + break; + } + power_on = true; - while (1) { - /* reset string stream */ + if (power_off_reason == po_starting_up) { + power_off_reason = po_none; + cmd = "go"; + } + else if (power_off_reason == po_disassemble_on) { + inp = "si 1000000000"; ss.str(""); ss.clear(); - - cmd = ""; - std::cin.clear(); - getline(cin, inp, '\n'); ss.str(inp); ss >> cmd; - -#ifndef _WIN32 - struct winsize win_size_current; - ioctl(0, TIOCGWINSZ, &win_size_current); - if (win_size_current.ws_col != win_size_previous.ws_col || win_size_current.ws_row != win_size_previous.ws_row) { - win_size_previous = win_size_current; - if (cmd.empty()) { - continue; - } + } + else if (power_off_reason == po_disassemble_off) { + power_off_reason = po_none; + cmd = "go"; + } + else + { + if (power_off_reason == po_enter_debugger) { + power_off_reason = po_entered_debugger; } -#endif - break; + if (!did_message) { + cout << "Welcome to the DingusPPC command line debugger." << endl; + cout << "Please enter a command or 'help'." << endl << endl; + did_message = true; + } + + printf("%08X: dingusdbg> ", ppc_state.pc); + + while (power_on) { + /* reset string stream */ + ss.str(""); + ss.clear(); + + cmd = ""; + std::cin.clear(); + getline(cin, inp, '\n'); + ss.str(inp); + ss >> cmd; + + #ifndef _WIN32 + struct winsize win_size_current; + ioctl(0, TIOCGWINSZ, &win_size_current); + if (win_size_current.ws_col != win_size_previous.ws_col || win_size_current.ws_row != win_size_previous.ws_row) { + win_size_previous = win_size_current; + if (cmd.empty()) { + continue; + } + } + #endif + break; + } + } + + if (power_off_reason == po_signal_interrupt) { + power_off_reason = po_enter_debugger; + // ignore command if interrupt happens because the input line is probably incomplete. + last_cmd = ""; + continue; } if (cmd.empty() && !last_cmd.empty()) { @@ -591,7 +629,7 @@ void enter_debugger() { } else if (cmd == "go") { cmd = ""; power_on = true; - ppc_exec(); // won't return! + ppc_exec(); } else if (cmd == "disas" || cmd == "da") { expr_str = ""; ss >> expr_str; diff --git a/debugger/debugger.h b/debugger/debugger.h index 1768206..0744b73 100644 --- a/debugger/debugger.h +++ b/debugger/debugger.h @@ -22,6 +22,6 @@ along with this program. If not, see . #ifndef DEBUGGER_H_ #define DEBUGGER_H_ -void enter_debugger(void); +void enter_debugger(); #endif // DEBUGGER_H_ diff --git a/main.cpp b/main.cpp index c6103ff..784af16 100644 --- a/main.cpp +++ b/main.cpp @@ -41,13 +41,8 @@ along with this program. If not, see . using namespace std; void sigint_handler(int signum) { - enter_debugger(); - - LOG_F(INFO, "Shutting down..."); - - delete gMachineObj.release(); - cleanup(); - exit(0); + power_on = false; + power_off_reason = po_signal_interrupt; } void sigabrt_handler(int signum) { @@ -180,6 +175,7 @@ int main(int argc, char** argv) { // Make sure the reason for the failure is visible (it may have been // sent to the logfile only). cerr << message.preamble << message.indentation << message.prefix << message.message << endl; + power_off_reason = po_enter_debugger; enter_debugger(); abort(); @@ -199,9 +195,11 @@ int main(int argc, char** argv) { switch (execution_mode) { case interpreter: - ppc_exec(); + power_off_reason = po_starting_up; + enter_debugger(); break; case debugger: + power_off_reason = po_enter_debugger; enter_debugger(); break; default: