Tidy up Debugger + breakpoints initial work
This commit is contained in:
@@ -3,6 +3,7 @@
|
||||
#include <backend/core/Interpreter.hpp>
|
||||
#include <backend/core/JIT.hpp>
|
||||
#include <string>
|
||||
#include <set>
|
||||
|
||||
namespace n64 {
|
||||
struct Core {
|
||||
@@ -26,8 +27,16 @@ struct Core {
|
||||
void Run(float volumeL, float volumeR);
|
||||
void TogglePause() { pause = !pause; }
|
||||
[[nodiscard]] VI &GetVI() const { return cpu->GetMem().mmio.vi; }
|
||||
inline void ToggleBreakpoint(s64 addr) {
|
||||
if(breakpoints.contains(addr)){
|
||||
breakpoints.erase(addr);
|
||||
return;
|
||||
}
|
||||
|
||||
breakpoints.insert(addr);
|
||||
}
|
||||
|
||||
u32 breakpoint = 0;
|
||||
std::set<s64> breakpoints{};
|
||||
|
||||
bool pause = true;
|
||||
u32 cycles = 0;
|
||||
|
||||
@@ -67,12 +67,22 @@ Disassembler::DisassemblyResult Disassembler::DisassembleDetailed(const u32 addr
|
||||
}
|
||||
};
|
||||
|
||||
auto formatComment = [&](const cs_mips_op &operand) {
|
||||
return "";
|
||||
auto formatComment = [&](const cs_mips_op &operand) -> std::string {
|
||||
switch (operand.type) {
|
||||
case MIPS_OP_IMM:
|
||||
return std::format("#{:X}", operand.is_unsigned ? operand.uimm : operand.imm);
|
||||
case MIPS_OP_MEM:
|
||||
return std::format("{}(0x{:X})", CapstoneToRegValue(operand.mem.base), operand.mem.disp);
|
||||
case MIPS_OP_REG:
|
||||
return std::format("{}", CapstoneToRegValue(operand.reg));
|
||||
default:
|
||||
return "! Unknown !";
|
||||
}
|
||||
};
|
||||
|
||||
for (u8 i = 0; i < details->mips.op_count && i < 3; i++) {
|
||||
result.ops[i] = formatOperand(details->mips.operands[i]);
|
||||
result.comment += formatComment(details->mips.operands[i]) + " ";
|
||||
result.full += result.ops[i].str + "\t";
|
||||
}
|
||||
|
||||
@@ -82,3 +92,107 @@ Disassembler::DisassemblyResult Disassembler::DisassembleDetailed(const u32 addr
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string Disassembler::CapstoneToRegValue(mips_reg reg) const {
|
||||
n64::Registers& regs = n64::Core::GetInstance().cpu->GetRegs();
|
||||
u64 val = 0;
|
||||
switch(reg) {
|
||||
case MIPS_REG_ZERO: case MIPS_REG_ZERO_64: case MIPS_REG_ZERO_NM:
|
||||
val = 0;
|
||||
break;
|
||||
case MIPS_REG_AT: case MIPS_REG_AT_64: case MIPS_REG_AT_NM:
|
||||
val = regs.Read<u64>(1);
|
||||
break;
|
||||
case MIPS_REG_V0: case MIPS_REG_V0_64:
|
||||
val = regs.Read<u64>(2);
|
||||
break;
|
||||
case MIPS_REG_V1: case MIPS_REG_V1_64:
|
||||
val = regs.Read<u64>(3);
|
||||
break;
|
||||
case MIPS_REG_A0: case MIPS_REG_A0_64:
|
||||
val = regs.Read<u64>(4);
|
||||
break;
|
||||
case MIPS_REG_A1: case MIPS_REG_A1_64:
|
||||
val = regs.Read<u64>(5);
|
||||
break;
|
||||
case MIPS_REG_A2: case MIPS_REG_A2_64:
|
||||
val = regs.Read<u64>(6);
|
||||
break;
|
||||
case MIPS_REG_A3: case MIPS_REG_A3_64:
|
||||
val = regs.Read<u64>(7);
|
||||
break;
|
||||
case MIPS_REG_T0: case MIPS_REG_T0_64:
|
||||
val = regs.Read<u64>(8);
|
||||
break;
|
||||
case MIPS_REG_T1: case MIPS_REG_T1_64:
|
||||
val = regs.Read<u64>(9);
|
||||
break;
|
||||
case MIPS_REG_T2: case MIPS_REG_T2_64:
|
||||
val = regs.Read<u64>(10);
|
||||
break;
|
||||
case MIPS_REG_T3: case MIPS_REG_T3_64:
|
||||
val = regs.Read<u64>(11);
|
||||
break;
|
||||
case MIPS_REG_T4: case MIPS_REG_T4_64:
|
||||
val = regs.Read<u64>(12);
|
||||
break;
|
||||
case MIPS_REG_T5: case MIPS_REG_T5_64:
|
||||
val = regs.Read<u64>(13);
|
||||
break;
|
||||
case MIPS_REG_T6: case MIPS_REG_T6_64:
|
||||
val = regs.Read<u64>(14);
|
||||
break;
|
||||
case MIPS_REG_T7: case MIPS_REG_T7_64:
|
||||
val = regs.Read<u64>(15);
|
||||
break;
|
||||
case MIPS_REG_S0: case MIPS_REG_S0_64:
|
||||
val = regs.Read<u64>(16);
|
||||
break;
|
||||
case MIPS_REG_S1: case MIPS_REG_S1_64:
|
||||
val = regs.Read<u64>(17);
|
||||
break;
|
||||
case MIPS_REG_S2: case MIPS_REG_S2_64:
|
||||
val = regs.Read<u64>(18);
|
||||
break;
|
||||
case MIPS_REG_S3: case MIPS_REG_S3_64:
|
||||
val = regs.Read<u64>(19);
|
||||
break;
|
||||
case MIPS_REG_S4: case MIPS_REG_S4_64:
|
||||
val = regs.Read<u64>(20);
|
||||
break;
|
||||
case MIPS_REG_S5: case MIPS_REG_S5_64:
|
||||
val = regs.Read<u64>(21);
|
||||
break;
|
||||
case MIPS_REG_S6: case MIPS_REG_S6_64:
|
||||
val = regs.Read<u64>(22);
|
||||
break;
|
||||
case MIPS_REG_S7: case MIPS_REG_S7_64:
|
||||
val = regs.Read<u64>(23);
|
||||
break;
|
||||
case MIPS_REG_T8: case MIPS_REG_T8_64:
|
||||
val = regs.Read<u64>(24);
|
||||
break;
|
||||
case MIPS_REG_T9: case MIPS_REG_T9_64:
|
||||
val = regs.Read<u64>(25);
|
||||
break;
|
||||
case MIPS_REG_K0: case MIPS_REG_K0_64:
|
||||
val = regs.Read<u64>(26);
|
||||
break;
|
||||
case MIPS_REG_K1: case MIPS_REG_K1_64:
|
||||
val = regs.Read<u64>(27);
|
||||
break;
|
||||
case MIPS_REG_GP: case MIPS_REG_GP_64:
|
||||
val = regs.Read<u64>(28);
|
||||
break;
|
||||
case MIPS_REG_SP: case MIPS_REG_SP_64:
|
||||
val = regs.Read<u64>(29);
|
||||
break;
|
||||
case MIPS_REG_RA: case MIPS_REG_RA_64:
|
||||
val = regs.Read<u64>(31);
|
||||
break;
|
||||
default:
|
||||
return "! Unknown !";
|
||||
}
|
||||
|
||||
return std::format("{} (= 0x{:016X})", cs_reg_name(handle, reg), val);
|
||||
}
|
||||
@@ -25,10 +25,12 @@ struct Disassembler {
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
[[nodiscard]] DisassemblyResult Disassemble(const u32 address) const;
|
||||
[[nodiscard]] DisassemblyResult DisassembleDetailed(u32 address, u32 instruction) const;
|
||||
[[nodiscard]] DisassemblyResult DisassembleSimple(u32 address, u32 instruction) const;
|
||||
private:
|
||||
std::string CapstoneToRegValue(mips_reg reg) const;
|
||||
explicit Disassembler(const bool rsp) : rsp(rsp) {
|
||||
if (cs_open(CS_ARCH_MIPS, static_cast<cs_mode>((rsp ? CS_MODE_32 : CS_MODE_64) | CS_MODE_BIG_ENDIAN), &handle) !=
|
||||
CS_ERR_OK) {
|
||||
|
||||
Reference in New Issue
Block a user