diff --git a/src/core/cpu_core.cpp b/src/core/cpu_core.cpp index 28012dd5a..1e78d698e 100644 --- a/src/core/cpu_core.cpp +++ b/src/core/cpu_core.cpp @@ -51,9 +51,9 @@ static bool BreakpointCheck(); static void TracePrintInstruction(); #endif -static void DisassembleAndPrint(u32 addr, const char* prefix); -static void PrintInstruction(u32 bits, u32 pc, Registers* regs, const char* prefix); -static void LogInstruction(u32 bits, u32 pc, Registers* regs); +static void DisassembleAndPrint(u32 addr, bool regs, const char* prefix); +static void PrintInstruction(u32 bits, u32 pc, bool regs, const char* prefix); +static void LogInstruction(u32 bits, u32 pc, bool regs); static void HandleWriteSyscall(); static void HandlePutcSyscall(); @@ -314,7 +314,7 @@ ALWAYS_INLINE_RELEASE void CPU::RaiseException(u32 CAUSE_bits, u32 EPC, u32 vect static_cast(g_state.cop0_regs.cause.Excode.GetValue()), g_state.current_instruction_pc, g_state.cop0_regs.EPC, g_state.cop0_regs.cause.BD ? "true" : "false", g_state.cop0_regs.cause.CE.GetValue()); - DisassembleAndPrint(g_state.current_instruction_pc, 4, 0); + DisassembleAndPrint(g_state.current_instruction_pc, 4u, 0u); if (s_trace_to_log) { CPU::WriteToExecutionLog("Exception %u at 0x%08X (epc=0x%08X, BD=%s, CE=%u)\n", @@ -669,7 +669,7 @@ void CPU::TracePrintInstruction() TinyString instr; TinyString comment; DisassembleInstruction(&instr, pc, bits); - DisassembleInstructionComment(&comment, pc, bits, &g_state.regs); + DisassembleInstructionComment(&comment, pc, bits); if (!comment.empty()) { for (u32 i = instr.length(); i < 30; i++) @@ -683,35 +683,41 @@ void CPU::TracePrintInstruction() #endif -void CPU::PrintInstruction(u32 bits, u32 pc, Registers* regs, const char* prefix) +void CPU::PrintInstruction(u32 bits, u32 pc, bool regs, const char* prefix) { TinyString instr; - TinyString comment; DisassembleInstruction(&instr, pc, bits); - DisassembleInstructionComment(&comment, pc, bits, regs); - if (!comment.empty()) + if (regs) { - for (u32 i = instr.length(); i < 30; i++) - instr.append(' '); - instr.append("; "); - instr.append(comment); + TinyString comment; + DisassembleInstructionComment(&comment, pc, bits); + if (!comment.empty()) + { + for (u32 i = instr.length(); i < 30; i++) + instr.append(' '); + instr.append("; "); + instr.append(comment); + } } Log_DevPrintf("%s%08x: %08x %s", prefix, pc, bits, instr.c_str()); } -void CPU::LogInstruction(u32 bits, u32 pc, Registers* regs) +void CPU::LogInstruction(u32 bits, u32 pc, bool regs) { TinyString instr; - TinyString comment; DisassembleInstruction(&instr, pc, bits); - DisassembleInstructionComment(&comment, pc, bits, regs); - if (!comment.empty()) + if (regs) { - for (u32 i = instr.length(); i < 30; i++) - instr.append(' '); - instr.append("; "); - instr.append(comment); + TinyString comment; + DisassembleInstructionComment(&comment, pc, bits); + if (!comment.empty()) + { + for (u32 i = instr.length(); i < 30; i++) + instr.append(' '); + instr.append("; "); + instr.append(comment); + } } WriteToExecutionLog("%08x: %08x %s\n", pc, bits, instr.c_str()); @@ -899,11 +905,11 @@ ALWAYS_INLINE static constexpr bool SubOverflow(u32 old_value, u32 sub_value, u3 return (((new_value ^ old_value) & (old_value ^ sub_value)) & UINT32_C(0x80000000)) != 0; } -void CPU::DisassembleAndPrint(u32 addr, const char* prefix) +void CPU::DisassembleAndPrint(u32 addr, bool regs, const char* prefix) { u32 bits = 0; SafeReadMemoryWord(addr, &bits); - PrintInstruction(bits, addr, &g_state.regs, prefix); + PrintInstruction(bits, addr, regs, prefix); } void CPU::DisassembleAndPrint(u32 addr, u32 instructions_before /* = 0 */, u32 instructions_after /* = 0 */) @@ -911,14 +917,14 @@ void CPU::DisassembleAndPrint(u32 addr, u32 instructions_before /* = 0 */, u32 i u32 disasm_addr = addr - (instructions_before * sizeof(u32)); for (u32 i = 0; i < instructions_before; i++) { - DisassembleAndPrint(disasm_addr, ""); + DisassembleAndPrint(disasm_addr, false, ""); disasm_addr += sizeof(u32); } // <= to include the instruction itself for (u32 i = 0; i <= instructions_after; i++) { - DisassembleAndPrint(disasm_addr, (i == 0) ? "---->" : ""); + DisassembleAndPrint(disasm_addr, (i == 0), (i == 0) ? "---->" : ""); disasm_addr += sizeof(u32); } } @@ -2227,7 +2233,7 @@ template if constexpr (debug) { if (s_trace_to_log) - LogInstruction(g_state.current_instruction.bits, g_state.current_instruction_pc, &g_state.regs); + LogInstruction(g_state.current_instruction.bits, g_state.current_instruction_pc, true); if (g_state.current_instruction_pc == 0xA0) [[unlikely]] HandleA0Syscall(); diff --git a/src/core/cpu_disasm.cpp b/src/core/cpu_disasm.cpp index e88ef7e0c..76693b7bb 100644 --- a/src/core/cpu_disasm.cpp +++ b/src/core/cpu_disasm.cpp @@ -42,14 +42,14 @@ struct GTEInstructionTable } // namespace static void FormatInstruction(SmallStringBase* dest, const Instruction inst, u32 pc, const char* format); -static void FormatComment(SmallStringBase* dest, const Instruction inst, u32 pc, Registers* regs, const char* format); +static void FormatComment(SmallStringBase* dest, const Instruction inst, u32 pc, const char* format); template static void FormatCopInstruction(SmallStringBase* dest, u32 pc, const Instruction inst, const std::pair* table, size_t table_size, T table_key); template -static void FormatCopComment(SmallStringBase* dest, u32 pc, Registers* regs, const Instruction inst, +static void FormatCopComment(SmallStringBase* dest, u32 pc, const Instruction inst, const std::pair* table, size_t table_size, T table_key); static void FormatGTEInstruction(SmallStringBase* dest, u32 pc, const Instruction inst); @@ -189,10 +189,10 @@ static const std::array s_special_table = {{ }}; static const std::array, 4> s_cop_common_table = { - {{CopCommonInstruction::mfcn, "mfc$cop $rt, $coprd"}, - {CopCommonInstruction::cfcn, "cfc$cop $rt, $coprd"}, + {{CopCommonInstruction::mfcn, "mfc$cop $rt_, $coprd"}, + {CopCommonInstruction::cfcn, "cfc$cop $rt_, $coprdc"}, {CopCommonInstruction::mtcn, "mtc$cop $rt, $coprd"}, - {CopCommonInstruction::ctcn, "ctc$cop $rt, $coprd"}}}; + {CopCommonInstruction::ctcn, "ctc$cop $rt, $coprdc"}}}; static const std::array, 1> s_cop0_table = {{{Cop0Instruction::rfe, "rfe"}}}; @@ -291,6 +291,11 @@ void CPU::FormatInstruction(SmallStringBase* dest, const Instruction inst, u32 p dest->append(GetRegName(inst.r.rs)); str += 2; } + else if (std::strncmp(str, "rt_", 3) == 0) + { + dest->append(GetRegName(inst.r.rt)); + str += 3; + } else if (std::strncmp(str, "rt", 2) == 0) { dest->append(GetRegName(inst.r.rt)); @@ -340,6 +345,14 @@ void CPU::FormatInstruction(SmallStringBase* dest, const Instruction inst, u32 p dest->append(((inst.bits & (UINT32_C(1) << 24)) != 0) ? 't' : 'f'); str += 5; } + else if (std::strncmp(str, "coprdc", 6) == 0) + { + if (inst.IsCop2Instruction()) + dest->append(GetGTERegisterName(static_cast(inst.r.rd.GetValue()) + 32)); + else + dest->append_format("{}", ZeroExtend32(static_cast(inst.r.rd.GetValue()))); + str += 6; + } else if (std::strncmp(str, "coprd", 5) == 0) { if (inst.IsCop2Instruction()) @@ -368,8 +381,10 @@ void CPU::FormatInstruction(SmallStringBase* dest, const Instruction inst, u32 p } } -void CPU::FormatComment(SmallStringBase* dest, const Instruction inst, u32 pc, Registers* regs, const char* format) +void CPU::FormatComment(SmallStringBase* dest, const Instruction inst, u32 pc, const char* format) { + const CPU::Registers* regs = &CPU::g_state.regs; + const char* str = format; while (*str != '\0') { @@ -384,6 +399,10 @@ void CPU::FormatComment(SmallStringBase* dest, const Instruction inst, u32 pc, R str += 2; } + else if (std::strncmp(str, "rt_", 3) == 0) + { + str += 3; + } else if (std::strncmp(str, "rt", 2) == 0) { dest->append_format("{}{}=0x{:08X}", dest->empty() ? "" : ", ", GetRegName(inst.r.rt), @@ -427,12 +446,36 @@ void CPU::FormatComment(SmallStringBase* dest, const Instruction inst, u32 pc, R { str += 5; } + else if (std::strncmp(str, "coprdc", 6) == 0) + { + if (inst.IsCop2Instruction()) + { + dest->append_format("{}{}=0x{:08X}", dest->empty() ? "" : ", ", + GetGTERegisterName(static_cast(inst.r.rd.GetValue()) + 32), + g_state.gte_regs.cr32[static_cast(inst.r.rd.GetValue())]); + } + str += 6; + } else if (std::strncmp(str, "coprd", 5) == 0) { + if (inst.IsCop2Instruction()) + { + dest->append_format("{}{}=0x{:08X}", dest->empty() ? "" : ", ", + GetGTERegisterName(static_cast(inst.r.rd.GetValue())), + g_state.gte_regs.dr32[static_cast(inst.r.rd.GetValue())]); + } + str += 5; } else if (std::strncmp(str, "coprt", 5) == 0) { + if (inst.IsCop2Instruction()) + { + dest->append_format("{}{}=0x{:08X}", dest->empty() ? "" : ", ", + GetGTERegisterName(static_cast(inst.r.rt.GetValue())), + g_state.gte_regs.dr32[static_cast(inst.r.rt.GetValue())]); + } + str += 5; } else if (std::strncmp(str, "cop", 3) == 0) @@ -463,14 +506,14 @@ void CPU::FormatCopInstruction(SmallStringBase* dest, u32 pc, const Instruction } template -void CPU::FormatCopComment(SmallStringBase* dest, u32 pc, Registers* regs, const Instruction inst, +void CPU::FormatCopComment(SmallStringBase* dest, u32 pc, const Instruction inst, const std::pair* table, size_t table_size, T table_key) { for (size_t i = 0; i < table_size; i++) { if (table[i].first == table_key) { - FormatComment(dest, inst, pc, regs, table[i].second); + FormatComment(dest, inst, pc, table[i].second); return; } } @@ -560,13 +603,13 @@ void CPU::DisassembleInstruction(SmallStringBase* dest, u32 pc, u32 bits) } } -void CPU::DisassembleInstructionComment(SmallStringBase* dest, u32 pc, u32 bits, Registers* regs) +void CPU::DisassembleInstructionComment(SmallStringBase* dest, u32 pc, u32 bits) { const Instruction inst{bits}; switch (inst.op) { case InstructionOp::funct: - FormatComment(dest, inst, pc, regs, s_special_table[static_cast(inst.r.funct.GetValue())]); + FormatComment(dest, inst, pc, s_special_table[static_cast(inst.r.funct.GetValue())]); return; case InstructionOp::cop0: @@ -576,8 +619,7 @@ void CPU::DisassembleInstructionComment(SmallStringBase* dest, u32 pc, u32 bits, { if (inst.cop.IsCommonInstruction()) { - FormatCopComment(dest, pc, regs, inst, s_cop_common_table.data(), s_cop_common_table.size(), - inst.cop.CommonOp()); + FormatCopComment(dest, pc, inst, s_cop_common_table.data(), s_cop_common_table.size(), inst.cop.CommonOp()); } else { @@ -585,7 +627,7 @@ void CPU::DisassembleInstructionComment(SmallStringBase* dest, u32 pc, u32 bits, { case InstructionOp::cop0: { - FormatCopComment(dest, pc, regs, inst, s_cop0_table.data(), s_cop0_table.size(), inst.cop.Cop0Op()); + FormatCopComment(dest, pc, inst, s_cop0_table.data(), s_cop0_table.size(), inst.cop.Cop0Op()); } break; @@ -612,14 +654,14 @@ void CPU::DisassembleInstructionComment(SmallStringBase* dest, u32 pc, u32 bits, const bool bgez = ConvertToBoolUnchecked(rt & u8(1)); const bool link = ConvertToBoolUnchecked((rt >> 4) & u8(1)); if (link) - FormatComment(dest, inst, pc, regs, bgez ? "bgezal $rs, $rel" : "bltzal $rs, $rel"); + FormatComment(dest, inst, pc, bgez ? "bgezal $rs, $rel" : "bltzal $rs, $rel"); else - FormatComment(dest, inst, pc, regs, bgez ? "bgez $rs, $rel" : "bltz $rs, $rel"); + FormatComment(dest, inst, pc, bgez ? "bgez $rs, $rel" : "bltz $rs, $rel"); } break; default: - FormatComment(dest, inst, pc, regs, s_base_table[static_cast(inst.op.GetValue())]); + FormatComment(dest, inst, pc, s_base_table[static_cast(inst.op.GetValue())]); break; } } diff --git a/src/core/cpu_disasm.h b/src/core/cpu_disasm.h index 9cff8ed71..460b1b97d 100644 --- a/src/core/cpu_disasm.h +++ b/src/core/cpu_disasm.h @@ -9,7 +9,7 @@ class SmallStringBase; namespace CPU { void DisassembleInstruction(SmallStringBase* dest, u32 pc, u32 bits); -void DisassembleInstructionComment(SmallStringBase* dest, u32 pc, u32 bits, Registers* regs); +void DisassembleInstructionComment(SmallStringBase* dest, u32 pc, u32 bits); const char* GetGTERegisterName(u32 index); diff --git a/src/duckstation-qt/debuggermodels.cpp b/src/duckstation-qt/debuggermodels.cpp index 592508fbe..c8b3f3c51 100644 --- a/src/duckstation-qt/debuggermodels.cpp +++ b/src/duckstation-qt/debuggermodels.cpp @@ -112,7 +112,7 @@ QVariant DebuggerCodeModel::data(const QModelIndex& index, int role /*= Qt::Disp return tr(""); TinyString str; - CPU::DisassembleInstructionComment(&str, address, instruction_bits, &CPU::g_state.regs); + CPU::DisassembleInstructionComment(&str, address, instruction_bits); return QString::fromUtf8(str.c_str(), static_cast(str.length())); }