diff --git a/src/core/cpu_core.cpp b/src/core/cpu_core.cpp index 8603aebca..427ba36da 100644 --- a/src/core/cpu_core.cpp +++ b/src/core/cpu_core.cpp @@ -599,6 +599,114 @@ static void LogInstruction(u32 bits, u32 pc, Registers* regs) WriteToExecutionLog("%08x: %08x %s\n", pc, bits, instr.GetCharArray()); } +const std::array g_debugger_register_list = { + {{"zero", &CPU::g_state.regs.zero}, + {"at", &CPU::g_state.regs.at}, + {"v0", &CPU::g_state.regs.v0}, + {"v1", &CPU::g_state.regs.v1}, + {"a0", &CPU::g_state.regs.a0}, + {"a1", &CPU::g_state.regs.a1}, + {"a2", &CPU::g_state.regs.a2}, + {"a3", &CPU::g_state.regs.a3}, + {"t0", &CPU::g_state.regs.t0}, + {"t1", &CPU::g_state.regs.t1}, + {"t2", &CPU::g_state.regs.t2}, + {"t3", &CPU::g_state.regs.t3}, + {"t4", &CPU::g_state.regs.t4}, + {"t5", &CPU::g_state.regs.t5}, + {"t6", &CPU::g_state.regs.t6}, + {"t7", &CPU::g_state.regs.t7}, + {"s0", &CPU::g_state.regs.s0}, + {"s1", &CPU::g_state.regs.s1}, + {"s2", &CPU::g_state.regs.s2}, + {"s3", &CPU::g_state.regs.s3}, + {"s4", &CPU::g_state.regs.s4}, + {"s5", &CPU::g_state.regs.s5}, + {"s6", &CPU::g_state.regs.s6}, + {"s7", &CPU::g_state.regs.s7}, + {"t8", &CPU::g_state.regs.t8}, + {"t9", &CPU::g_state.regs.t9}, + {"k0", &CPU::g_state.regs.k0}, + {"k1", &CPU::g_state.regs.k1}, + {"gp", &CPU::g_state.regs.gp}, + {"sp", &CPU::g_state.regs.sp}, + {"fp", &CPU::g_state.regs.fp}, + {"ra", &CPU::g_state.regs.ra}, + {"hi", &CPU::g_state.regs.hi}, + {"lo", &CPU::g_state.regs.lo}, + {"pc", &CPU::g_state.regs.pc}, + {"npc", &CPU::g_state.regs.npc}, + + {"COP0_SR", &CPU::g_state.cop0_regs.sr.bits}, + {"COP0_CAUSE", &CPU::g_state.cop0_regs.cause.bits}, + {"COP0_EPC", &CPU::g_state.cop0_regs.EPC}, + {"COP0_BadVAddr", &CPU::g_state.cop0_regs.BadVaddr}, + + {"V0_XY", &CPU::g_state.gte_regs.r32[0]}, + {"V0_Z", &CPU::g_state.gte_regs.r32[1]}, + {"V1_XY", &CPU::g_state.gte_regs.r32[2]}, + {"V1_Z", &CPU::g_state.gte_regs.r32[3]}, + {"V2_XY", &CPU::g_state.gte_regs.r32[4]}, + {"V2_Z", &CPU::g_state.gte_regs.r32[5]}, + {"RGBC", &CPU::g_state.gte_regs.r32[6]}, + {"OTZ", &CPU::g_state.gte_regs.r32[7]}, + {"IR0", &CPU::g_state.gte_regs.r32[8]}, + {"IR1", &CPU::g_state.gte_regs.r32[9]}, + {"IR2", &CPU::g_state.gte_regs.r32[10]}, + {"IR3", &CPU::g_state.gte_regs.r32[11]}, + {"SXY0", &CPU::g_state.gte_regs.r32[12]}, + {"SXY1", &CPU::g_state.gte_regs.r32[13]}, + {"SXY2", &CPU::g_state.gte_regs.r32[14]}, + {"SXYP", &CPU::g_state.gte_regs.r32[15]}, + {"SZ0", &CPU::g_state.gte_regs.r32[16]}, + {"SZ1", &CPU::g_state.gte_regs.r32[17]}, + {"SZ2", &CPU::g_state.gte_regs.r32[18]}, + {"SZ3", &CPU::g_state.gte_regs.r32[19]}, + {"RGB0", &CPU::g_state.gte_regs.r32[20]}, + {"RGB1", &CPU::g_state.gte_regs.r32[21]}, + {"RGB2", &CPU::g_state.gte_regs.r32[22]}, + {"RES1", &CPU::g_state.gte_regs.r32[23]}, + {"MAC0", &CPU::g_state.gte_regs.r32[24]}, + {"MAC1", &CPU::g_state.gte_regs.r32[25]}, + {"MAC2", &CPU::g_state.gte_regs.r32[26]}, + {"MAC3", &CPU::g_state.gte_regs.r32[27]}, + {"IRGB", &CPU::g_state.gte_regs.r32[28]}, + {"ORGB", &CPU::g_state.gte_regs.r32[29]}, + {"LZCS", &CPU::g_state.gte_regs.r32[30]}, + {"LZCR", &CPU::g_state.gte_regs.r32[31]}, + {"RT_0", &CPU::g_state.gte_regs.r32[32]}, + {"RT_1", &CPU::g_state.gte_regs.r32[33]}, + {"RT_2", &CPU::g_state.gte_regs.r32[34]}, + {"RT_3", &CPU::g_state.gte_regs.r32[35]}, + {"RT_4", &CPU::g_state.gte_regs.r32[36]}, + {"TRX", &CPU::g_state.gte_regs.r32[37]}, + {"TRY", &CPU::g_state.gte_regs.r32[38]}, + {"TRZ", &CPU::g_state.gte_regs.r32[39]}, + {"LLM_0", &CPU::g_state.gte_regs.r32[40]}, + {"LLM_1", &CPU::g_state.gte_regs.r32[41]}, + {"LLM_2", &CPU::g_state.gte_regs.r32[42]}, + {"LLM_3", &CPU::g_state.gte_regs.r32[43]}, + {"LLM_4", &CPU::g_state.gte_regs.r32[44]}, + {"RBK", &CPU::g_state.gte_regs.r32[45]}, + {"GBK", &CPU::g_state.gte_regs.r32[46]}, + {"BBK", &CPU::g_state.gte_regs.r32[47]}, + {"LCM_0", &CPU::g_state.gte_regs.r32[48]}, + {"LCM_1", &CPU::g_state.gte_regs.r32[49]}, + {"LCM_2", &CPU::g_state.gte_regs.r32[50]}, + {"LCM_3", &CPU::g_state.gte_regs.r32[51]}, + {"LCM_4", &CPU::g_state.gte_regs.r32[52]}, + {"RFC", &CPU::g_state.gte_regs.r32[53]}, + {"GFC", &CPU::g_state.gte_regs.r32[54]}, + {"BFC", &CPU::g_state.gte_regs.r32[55]}, + {"OFX", &CPU::g_state.gte_regs.r32[56]}, + {"OFY", &CPU::g_state.gte_regs.r32[57]}, + {"H", &CPU::g_state.gte_regs.r32[58]}, + {"DQA", &CPU::g_state.gte_regs.r32[59]}, + {"DQB", &CPU::g_state.gte_regs.r32[60]}, + {"ZSF3", &CPU::g_state.gte_regs.r32[61]}, + {"ZSF4", &CPU::g_state.gte_regs.r32[62]}, + {"FLAG", &CPU::g_state.gte_regs.r32[63]}}}; + ALWAYS_INLINE static constexpr bool AddOverflow(u32 old_value, u32 add_value, u32 new_value) { return (((new_value ^ old_value) & (new_value ^ add_value)) & UINT32_C(0x80000000)) != 0; diff --git a/src/core/cpu_core.h b/src/core/cpu_core.h index 36a0dc889..d2e0e07e1 100644 --- a/src/core/cpu_core.h +++ b/src/core/cpu_core.h @@ -195,4 +195,14 @@ bool AddStepOutBreakpoint(u32 max_instructions_to_search = 1000); extern bool TRACE_EXECUTION; +// Debug register introspection +struct DebuggerRegisterListEntry +{ + const char* name; + u32* value_ptr; +}; + +static constexpr u32 NUM_DEBUGGER_REGISTER_LIST_ENTRIES = 104; +extern const std::array g_debugger_register_list; + } // namespace CPU diff --git a/src/duckstation-qt/debuggermodels.cpp b/src/duckstation-qt/debuggermodels.cpp index 9f111a208..56038b179 100644 --- a/src/duckstation-qt/debuggermodels.cpp +++ b/src/duckstation-qt/debuggermodels.cpp @@ -293,7 +293,7 @@ DebuggerRegistersModel::~DebuggerRegistersModel() {} int DebuggerRegistersModel::rowCount(const QModelIndex& parent /*= QModelIndex()*/) const { - return static_cast(CPU::Reg::count); + return static_cast(CPU::NUM_DEBUGGER_REGISTER_LIST_ENTRIES); } int DebuggerRegistersModel::columnCount(const QModelIndex& parent /*= QModelIndex()*/) const @@ -304,7 +304,7 @@ int DebuggerRegistersModel::columnCount(const QModelIndex& parent /*= QModelInde QVariant DebuggerRegistersModel::data(const QModelIndex& index, int role /*= Qt::DisplayRole*/) const { u32 reg_index = static_cast(index.row()); - if (reg_index >= static_cast(CPU::Reg::count)) + if (reg_index >= CPU::NUM_DEBUGGER_REGISTER_LIST_ENTRIES) return QVariant(); if (index.column() < 0 || index.column() > 1) @@ -314,8 +314,8 @@ QVariant DebuggerRegistersModel::data(const QModelIndex& index, int role /*= Qt: { case 0: // address { - if (role == Qt::DisplayRole) - return QString::fromUtf8(CPU::GetRegName(static_cast(reg_index))); + if (role == Qt::DisplayRole) + return QString::fromUtf8(CPU::g_debugger_register_list[reg_index].name); } break; @@ -323,11 +323,11 @@ QVariant DebuggerRegistersModel::data(const QModelIndex& index, int role /*= Qt: { if (role == Qt::DisplayRole) { - return QString::asprintf("0x%08X", CPU::g_state.regs.r[reg_index]); + return QString::asprintf("0x%08X", *CPU::g_debugger_register_list[reg_index].value_ptr); } else if (role == Qt::ForegroundRole) { - if (CPU::g_state.regs.r[reg_index] != m_old_reg_values[reg_index]) + if (*CPU::g_debugger_register_list[reg_index].value_ptr != m_old_reg_values[reg_index]) return QColor(255, 50, 50); } } diff --git a/src/duckstation-qt/debuggermodels.h b/src/duckstation-qt/debuggermodels.h index e752cc61c..2836b5497 100644 --- a/src/duckstation-qt/debuggermodels.h +++ b/src/duckstation-qt/debuggermodels.h @@ -3,6 +3,7 @@ #pragma once #include "core/bus.h" +#include "core/cpu_core.h" #include "core/cpu_types.h" #include #include @@ -67,7 +68,7 @@ public: void saveCurrentValues(); private: - u32 m_old_reg_values[static_cast(CPU::Reg::count)] = {}; + u32 m_old_reg_values[CPU::NUM_DEBUGGER_REGISTER_LIST_ENTRIES] = {}; }; class DebuggerStackModel : public QAbstractListModel