/* PCSX2 - PS2 Emulator for PCs * Copyright (C) 2002-2023 PCSX2 Dev Team * * PCSX2 is free software: you can redistribute it and/or modify it under the terms * of the GNU Lesser General Public License as published by the Free Software Found- * ation, either version 3 of the License, or (at your option) any later version. * * PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along with PCSX2. * If not, see . */ #include "PrecompiledHeader.h" #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: return m_cpu.GetSymbolMap().GetLabelString(stackFrame.entry).c_str(); 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: return m_cpu.GetSymbolMap().GetLabelString(stackFrame.entry).c_str(); 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: return tr("ENTRY"); case StackColumns::ENTRY_LABEL: return tr("LABEL"); case StackColumns::PC: return tr("PC"); case StackColumns::PC_OPCODE: return tr("INSTRUCTION"); case StackColumns::SP: return tr("STACK POINTER"); case StackColumns::SIZE: return tr("SIZE"); default: return QVariant(); } } return QVariant(); } void StackModel::refreshData() { if (m_cpu.getCpuType() == BREAKPOINT_IOP) return; // Hopefully in the near future we can get a stack frame for // each thread beginResetModel(); for (const auto& thread : getEEThreads()) { if (thread.data.status == THS_RUN) { m_stackFrames = MipsStackWalk::Walk(&m_cpu, m_cpu.getPC(), m_cpu.getRegister(0, 31), m_cpu.getRegister(0, 29), thread.data.entry_init, thread.data.stack); break; } } endResetModel(); }