2024-07-30 11:42:36 +00:00
|
|
|
// SPDX-FileCopyrightText: 2002-2024 PCSX2 Dev Team
|
|
|
|
// SPDX-License-Identifier: GPL-3.0+
|
2023-01-07 02:35:57 +00:00
|
|
|
|
|
|
|
#include "StackModel.h"
|
|
|
|
#include "DebugTools/MipsStackWalk.h"
|
|
|
|
#include "DebugTools/BiosDebugData.h"
|
|
|
|
#include "QtUtils.h"
|
|
|
|
|
|
|
|
StackModel::StackModel(DebugInterface& cpu, QObject* parent)
|
|
|
|
: QAbstractTableModel(parent)
|
|
|
|
, m_cpu(cpu)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
int StackModel::rowCount(const QModelIndex&) const
|
|
|
|
{
|
|
|
|
return m_stackFrames.size();
|
|
|
|
}
|
|
|
|
|
|
|
|
int StackModel::columnCount(const QModelIndex&) const
|
|
|
|
{
|
|
|
|
return StackModel::COLUMN_COUNT;
|
|
|
|
}
|
|
|
|
|
|
|
|
QVariant StackModel::data(const QModelIndex& index, int role) const
|
|
|
|
{
|
|
|
|
if (role == Qt::DisplayRole)
|
|
|
|
{
|
|
|
|
const auto& stackFrame = m_stackFrames.at(index.row());
|
|
|
|
|
|
|
|
switch (index.column())
|
|
|
|
{
|
|
|
|
case StackModel::ENTRY:
|
|
|
|
return QtUtils::FilledQStringFromValue(stackFrame.entry, 16);
|
|
|
|
case StackModel::ENTRY_LABEL:
|
2024-08-26 19:23:03 +00:00
|
|
|
return QString::fromStdString(m_cpu.GetSymbolGuardian().FunctionStartingAtAddress(stackFrame.entry).name);
|
2023-01-07 02:35:57 +00:00
|
|
|
case StackModel::PC:
|
|
|
|
return QtUtils::FilledQStringFromValue(stackFrame.pc, 16);
|
|
|
|
case StackModel::PC_OPCODE:
|
|
|
|
return m_cpu.disasm(stackFrame.pc, true).c_str();
|
|
|
|
case StackModel::SP:
|
|
|
|
return QtUtils::FilledQStringFromValue(stackFrame.sp, 16);
|
|
|
|
case StackModel::SIZE:
|
|
|
|
return QString::number(stackFrame.stackSize);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (role == Qt::UserRole)
|
|
|
|
{
|
|
|
|
const auto& stackFrame = m_stackFrames.at(index.row());
|
|
|
|
switch (index.column())
|
|
|
|
{
|
|
|
|
case StackModel::ENTRY:
|
|
|
|
return stackFrame.entry;
|
|
|
|
case StackModel::ENTRY_LABEL:
|
2024-08-26 19:23:03 +00:00
|
|
|
return QString::fromStdString(m_cpu.GetSymbolGuardian().FunctionStartingAtAddress(stackFrame.entry).name);
|
2023-01-07 02:35:57 +00:00
|
|
|
case StackModel::PC:
|
|
|
|
return stackFrame.pc;
|
|
|
|
case StackModel::PC_OPCODE:
|
|
|
|
return m_cpu.disasm(stackFrame.pc, true).c_str();
|
|
|
|
case StackModel::SP:
|
|
|
|
return stackFrame.sp;
|
|
|
|
case StackModel::SIZE:
|
|
|
|
return stackFrame.stackSize;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return QVariant();
|
|
|
|
}
|
|
|
|
|
|
|
|
QVariant StackModel::headerData(int section, Qt::Orientation orientation, int role) const
|
|
|
|
{
|
|
|
|
if (role == Qt::DisplayRole && orientation == Qt::Horizontal)
|
|
|
|
{
|
|
|
|
switch (section)
|
|
|
|
{
|
|
|
|
case StackColumns::ENTRY:
|
2023-03-18 21:14:55 +00:00
|
|
|
//: Warning: short space limit. Abbreviate if needed.
|
2023-01-07 02:35:57 +00:00
|
|
|
return tr("ENTRY");
|
|
|
|
case StackColumns::ENTRY_LABEL:
|
2023-03-18 21:14:55 +00:00
|
|
|
//: Warning: short space limit. Abbreviate if needed.
|
2023-01-07 02:35:57 +00:00
|
|
|
return tr("LABEL");
|
|
|
|
case StackColumns::PC:
|
2023-03-18 21:14:55 +00:00
|
|
|
//: Warning: short space limit. Abbreviate if needed. PC = Program Counter (location where the CPU is executing).
|
2023-01-07 02:35:57 +00:00
|
|
|
return tr("PC");
|
|
|
|
case StackColumns::PC_OPCODE:
|
2023-03-18 21:14:55 +00:00
|
|
|
//: Warning: short space limit. Abbreviate if needed.
|
2023-01-07 02:35:57 +00:00
|
|
|
return tr("INSTRUCTION");
|
|
|
|
case StackColumns::SP:
|
2023-03-18 21:14:55 +00:00
|
|
|
//: Warning: short space limit. Abbreviate if needed.
|
2023-01-07 02:35:57 +00:00
|
|
|
return tr("STACK POINTER");
|
|
|
|
case StackColumns::SIZE:
|
2023-03-18 21:14:55 +00:00
|
|
|
//: Warning: short space limit. Abbreviate if needed.
|
2023-01-07 02:35:57 +00:00
|
|
|
return tr("SIZE");
|
|
|
|
default:
|
|
|
|
return QVariant();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return QVariant();
|
|
|
|
}
|
|
|
|
|
|
|
|
void StackModel::refreshData()
|
|
|
|
{
|
|
|
|
// Hopefully in the near future we can get a stack frame for
|
|
|
|
// each thread
|
|
|
|
beginResetModel();
|
2021-10-08 11:12:03 +00:00
|
|
|
for (const auto& thread : m_cpu.GetThreadList())
|
2023-01-07 02:35:57 +00:00
|
|
|
{
|
2021-10-08 11:12:03 +00:00
|
|
|
if (thread->Status() == ThreadStatus::THS_RUN)
|
2023-01-07 02:35:57 +00:00
|
|
|
{
|
|
|
|
m_stackFrames = MipsStackWalk::Walk(&m_cpu, m_cpu.getPC(), m_cpu.getRegister(0, 31), m_cpu.getRegister(0, 29),
|
2021-10-08 11:12:03 +00:00
|
|
|
thread->EntryPoint(), thread->StackTop());
|
2023-01-07 02:35:57 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
endResetModel();
|
|
|
|
}
|