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>
|
2020-01-12 01:43:47 +00:00
|
|
|
#include <fstream>
|
2019-07-17 13:24:34 +00:00
|
|
|
#include <map>
|
2019-12-27 19:10:36 +00:00
|
|
|
#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
|
|
|
|
2020-02-03 02:18:20 +00:00
|
|
|
|
2020-02-04 13:21:59 +00:00
|
|
|
using namespace std;
|
2020-02-03 02:18:20 +00:00
|
|
|
|
2019-07-17 13:24:34 +00:00
|
|
|
void show_help()
|
|
|
|
{
|
|
|
|
cout << "Debugger commands:" << endl;
|
|
|
|
cout << " step -- execute single instruction" << endl;
|
|
|
|
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
|
2020-02-06 05:11:59 +00:00
|
|
|
cout << " disas N,X -- disassemble N instructions starting at address X" << endl;
|
2019-07-17 13:24:34 +00:00
|
|
|
cout << " quit -- quit the debugger" << endl << endl;
|
|
|
|
cout << "Pressing ENTER will repeat last command." << endl;
|
|
|
|
}
|
|
|
|
|
|
|
|
void dump_regs()
|
|
|
|
{
|
|
|
|
for (uint32_t i = 0; i < 32; i++)
|
|
|
|
cout << "GPR " << dec << i << " : " << hex << ppc_state.ppc_gpr[i] << endl;
|
|
|
|
|
2020-01-22 11:28:42 +00:00
|
|
|
cout << "PC: " << hex << ppc_state.ppc_pc << endl;
|
|
|
|
cout << "LR: " << hex << ppc_state.ppc_spr[8] << endl;
|
|
|
|
cout << "CR: " << hex << ppc_state.ppc_cr << endl;
|
|
|
|
cout << "CTR: " << hex << ppc_state.ppc_spr[9] << endl;
|
|
|
|
cout << "XER: " << hex << ppc_state.ppc_spr[1] << endl;
|
|
|
|
cout << "MSR: " << hex << ppc_state.ppc_msr << endl;
|
|
|
|
}
|
|
|
|
|
2020-02-06 13:41:17 +00:00
|
|
|
void disasm(uint32_t inst_num = 1UL, uint32_t address = ppc_state.ppc_pc)
|
2020-01-22 11:28:42 +00:00
|
|
|
{
|
|
|
|
PPCDisasmContext ctx;
|
|
|
|
|
|
|
|
quickinstruction_translate(ppc_state.ppc_pc);
|
|
|
|
|
|
|
|
ctx.instr_addr = ppc_state.ppc_pc;
|
|
|
|
ctx.instr_code = ppc_cur_instruction;
|
|
|
|
ctx.simplified = true;
|
|
|
|
cout << hex << ppc_state.ppc_pc << " " << disassemble_single(&ctx) << endl;
|
|
|
|
}
|
|
|
|
|
2019-07-17 13:24:34 +00:00
|
|
|
void enter_debugger()
|
|
|
|
{
|
2020-02-06 14:17:40 +00:00
|
|
|
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 PowerPC debugger." << endl;
|
|
|
|
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-12 01:43:47 +00:00
|
|
|
}
|
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
|
2020-01-12 01:43:47 +00:00
|
|
|
else if (cmd == "regs") {
|
2019-07-17 13:24:34 +00:00
|
|
|
dump_regs();
|
2020-01-22 11:28:42 +00:00
|
|
|
}
|
|
|
|
else if (cmd == "set") {
|
2020-01-16 11:29:01 +00:00
|
|
|
ss >> expr_str;
|
|
|
|
reg_expr = expr_str.substr(0, expr_str.find("="));
|
|
|
|
if (reg_expr == "pc") {
|
|
|
|
addr_str = expr_str.substr(expr_str.find("=") + 1);
|
2020-01-22 11:28:42 +00:00
|
|
|
addr = stol(addr_str, NULL, 0);
|
2020-01-16 11:29:01 +00:00
|
|
|
ppc_state.ppc_pc = addr;
|
2020-01-22 11:28:42 +00:00
|
|
|
}
|
|
|
|
else {
|
2020-01-16 11:29:01 +00:00
|
|
|
cout << "Unknown register " << reg_expr << endl;
|
|
|
|
}
|
2020-01-22 11:28:42 +00:00
|
|
|
}
|
|
|
|
else if (cmd == "step") {
|
2019-12-28 01:49:58 +00:00
|
|
|
ppc_exec_single();
|
2020-01-22 11:28:42 +00:00
|
|
|
}
|
|
|
|
else if (cmd == "until") {
|
2019-07-17 13:24:34 +00:00
|
|
|
ss >> addr_str;
|
2020-01-22 11:28:42 +00:00
|
|
|
addr = stol(addr_str, NULL, 16);
|
2019-12-28 01:49:58 +00:00
|
|
|
ppc_exec_until(addr);
|
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) {
|
|
|
|
cout << "Parsing disas params." << endl;
|
|
|
|
inst_num_str = expr_str.substr(expr_str.find(" ") + 1, expr_str.find(","));
|
|
|
|
inst_grab = stoul(inst_num_str, NULL, 0);
|
|
|
|
addr_str = expr_str.substr(expr_str.find(",") + 1, expr_str.length() - 1);
|
|
|
|
addr = stoul(addr_str, NULL, 16);
|
|
|
|
disasm(inst_grab, addr);
|
|
|
|
}
|
|
|
|
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;
|
|
|
|
}
|
2020-01-22 11:28:42 +00:00
|
|
|
}
|