dingusppc/debugger/debugger.cpp

176 lines
5.4 KiB
C++
Raw Normal View History

2020-01-05 17:38:32 +00:00
//DingusPPC
//Written by divingkatae and maximum
//(c)2018-20 (theweirdo) spatium
//Please ask for permission
//if you want to distribute this.
//(divingkatae#1017 or powermax#2286 on Discord)
2019-07-17 13:24:34 +00:00
#include <stdio.h>
#include <string>
#include <sstream>
#include <iostream>
#include <fstream>
2019-07-17 13:24:34 +00:00
#include <map>
#include "ppcemu.h"
2019-12-27 19:00:53 +00:00
#include "../cpu/ppc/ppcmmu.h"
2020-01-22 11:28:42 +00:00
#include "../cpu/ppc/ppcdisasm.h"
2019-07-17 13:24:34 +00:00
using namespace std;
static uint32_t str2addr(string& addr_str)
{
try {
return stoul(addr_str, NULL, 0);
}
catch (invalid_argument& exc) {
throw invalid_argument(string("Cannot convert ") + addr_str);
}
}
static void show_help()
2019-07-17 13:24:34 +00:00
{
cout << "Debugger commands:" << endl;
cout << " step -- execute single instruction" << endl;
cout << " si -- shortcut for step" << endl;
cout << " next -- same as step but treats subroutine calls" << endl;
cout << " as single instructions." << endl;
cout << " ni -- shortcut for next" << endl;
2019-07-17 13:24:34 +00:00
cout << " until X -- execute until address X is reached" << endl;
cout << " regs -- dump content of the GRPs" << endl;
2020-01-16 11:29:01 +00:00
cout << " set R=X -- assign value X to register R" << endl;
2020-01-22 11:28:42 +00:00
cout << " memdump -- dump content of the system memory to memdump.bin" << endl;
2020-01-15 03:50:01 +00:00
#ifdef PROFILER
cout << " profiler -- show stats related to the processor" << endl;
#endif
cout << " disas N,X -- disassemble N instructions starting at address X" << endl;
cout << " X can be any number or a known register name" << endl;
cout << " disas with no arguments defaults to disas 1,pc" << endl;
2019-07-17 13:24:34 +00:00
cout << " quit -- quit the debugger" << endl << endl;
cout << "Pressing ENTER will repeat last command." << endl;
}
static void disasm(uint32_t inst_num = 1UL, uint32_t address = ppc_state.ppc_pc)
2020-01-22 11:28:42 +00:00
{
PPCDisasmContext ctx;
ctx.instr_addr = address;
2020-01-22 11:28:42 +00:00
ctx.simplified = true;
for (int i = 0; i < inst_num; i++) {
ctx.instr_code = mem_read_dbg(ctx.instr_addr, 4);
cout << uppercase << hex << ctx.instr_addr << " "
<< disassemble_single(&ctx) << endl;
}
2020-01-22 11:28:42 +00:00
}
2019-07-17 13:24:34 +00:00
void enter_debugger()
{
string inp, cmd, addr_str, expr_str, reg_expr, last_cmd, reg_value_str, inst_string, inst_num_str;
2020-02-06 13:41:17 +00:00
uint32_t addr, inst_grab;
2019-07-17 13:24:34 +00:00
std::stringstream ss;
cout << "Welcome to the DingusPPC command line debugger." << endl;
2019-07-17 13:24:34 +00:00
cout << "Please enter a command or 'help'." << endl << endl;
while (1) {
cout << "ppcdbg> ";
/* reset string stream */
ss.str("");
ss.clear();
cmd = "";
getline(cin, inp, '\n');
ss.str(inp);
ss >> cmd;
if (cmd.empty() && !last_cmd.empty()) {
cmd = last_cmd;
cout << cmd << endl;
}
if (cmd == "help") {
show_help();
2020-01-22 11:28:42 +00:00
}
else if (cmd == "quit") {
2019-07-17 13:24:34 +00:00
break;
}
2020-01-15 03:50:01 +00:00
#ifdef PROFILER
else if (cmd == "profiler") {
cout << "Number of Supervisor Instructions Executed:" << supervisor_inst_num << endl;
cout << "Exception Handler Ran:" << exceptions_performed << endl;
cout << "Number of MMU Translations:" << mmu_translations_num << endl;
2020-01-16 11:29:01 +00:00
}
2020-01-15 03:50:01 +00:00
#endif
else if (cmd == "regs") {
print_gprs();
2020-01-22 11:28:42 +00:00
}
else if (cmd == "set") {
2020-01-16 11:29:01 +00:00
ss >> expr_str;
try {
reg_expr = expr_str.substr(0, expr_str.find("="));
2020-01-16 11:29:01 +00:00
addr_str = expr_str.substr(expr_str.find("=") + 1);
addr = str2addr(addr_str);
set_reg(reg_expr, addr);
2020-01-22 11:28:42 +00:00
}
catch (invalid_argument& exc) {
cout << exc.what() << endl;
2020-01-16 11:29:01 +00:00
}
2020-01-22 11:28:42 +00:00
}
else if (cmd == "step" || cmd == "si") {
ppc_exec_single();
2020-01-22 11:28:42 +00:00
}
else if (cmd == "next" || cmd == "ni") {
addr_str = "PC";
addr = get_reg(addr_str) + 4;
ppc_exec_until(addr);
}
2020-01-22 11:28:42 +00:00
else if (cmd == "until") {
2019-07-17 13:24:34 +00:00
ss >> addr_str;
try {
addr = str2addr(addr_str);
ppc_exec_until(addr);
}
catch (invalid_argument& exc) {
cout << exc.what() << endl;
}
2020-01-22 11:28:42 +00:00
}
else if (cmd == "disas") {
2020-02-06 13:41:17 +00:00
expr_str = "";
ss >> expr_str;
if (expr_str.length() > 0) {
inst_num_str = expr_str.substr(0, expr_str.find(","));
inst_grab = stol(inst_num_str, NULL, 0);
addr_str = expr_str.substr(expr_str.find(",") + 1);
try {
addr = str2addr(addr_str);
}
catch (invalid_argument& exc) {
try {
/* number conversion failed, trying reg name */
addr = get_reg(addr_str);
}
catch (invalid_argument& exc) {
cout << exc.what() << endl;
continue;
}
}
try {
disasm(inst_grab, addr);
}
catch (invalid_argument& exc) {
cout << exc.what() << endl;
}
2020-02-06 13:41:17 +00:00
}
else {
disasm();
}
2020-01-22 11:28:42 +00:00
}
else {
2019-07-17 13:24:34 +00:00
cout << "Unknown command: " << cmd << endl;
continue;
}
last_cmd = cmd;
}
}