mirror of
https://github.com/zoriya/ComSquare.git
synced 2026-05-28 16:43:35 +00:00
Reworking the instruction history
This commit is contained in:
@@ -42,6 +42,12 @@ namespace ComSquare::Debugger
|
||||
this->_ui.stackView->verticalHeader()->setSectionResizeMode (QHeaderView::Fixed);
|
||||
this->_ui.stackView->verticalHeader()->setHighlightSections(false);
|
||||
|
||||
|
||||
this->_ui.history->setModel(&this->_historyModel);
|
||||
this->_ui.history->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents);
|
||||
this->_ui.history->verticalHeader()->setSectionResizeMode(QHeaderView::Fixed);
|
||||
this->_ui.history->verticalHeader()->hide();
|
||||
|
||||
QMainWindow::connect(this->_ui.actionPause, &QAction::triggered, this, &CPUDebug::pause);
|
||||
QMainWindow::connect(this->_ui.actionStep, &QAction::triggered, this, &CPUDebug::step);
|
||||
QMainWindow::connect(this->_ui.actionNext, &QAction::triggered, this, &CPUDebug::next);
|
||||
@@ -108,7 +114,10 @@ namespace ComSquare::Debugger
|
||||
uint24_t pc = (this->_registers.pbr << 16u) | (this->_registers.pc - 1u);
|
||||
DisassemblyContext ctx = this->_getDisassemblyContext();
|
||||
DisassembledInstruction instruction = this->_parseInstruction(pc, ctx);
|
||||
this->_ui.logger->append((instruction.toString() + " - " + Utility::to_hex(opcode)).c_str());
|
||||
this->_registers.pc--;
|
||||
this->_historyModel.log({opcode, instruction.name, instruction.argument, this->getProceededParameters()});
|
||||
this->_ui.history->scrollToBottom();
|
||||
this->_registers.pc++;
|
||||
unsigned ret = CPU::_executeInstruction(opcode);
|
||||
this->_updateRegistersPanel();
|
||||
return ret;
|
||||
@@ -204,7 +213,7 @@ namespace ComSquare::Debugger
|
||||
|
||||
void CPUDebug::clearHistory()
|
||||
{
|
||||
this->_ui.logger->clear();
|
||||
this->_historyModel.clear();
|
||||
}
|
||||
|
||||
void CPUDebug::_updateDisassembly(uint24_t start, uint24_t refreshSize)
|
||||
@@ -260,6 +269,19 @@ namespace ComSquare::Debugger
|
||||
{
|
||||
return this->_registers.s;
|
||||
}
|
||||
|
||||
std::string CPUDebug::getProceededParameters()
|
||||
{
|
||||
uint24_t pac = this->_registers.pac;
|
||||
this->_bus->forceSilence = true;
|
||||
Instruction instruction = this->_instructions[this->readPC()];
|
||||
uint24_t valueAddr = this->_getValueAddr(instruction);
|
||||
this->_registers.pac = pac;
|
||||
this->_bus->forceSilence = false;
|
||||
if (instruction.size == 1)
|
||||
return "";
|
||||
return "[" + Utility::to_hex(valueAddr, Utility::AsmPrefix) + "]";
|
||||
}
|
||||
}
|
||||
|
||||
DisassemblyModel::DisassemblyModel(ComSquare::Debugger::CPUDebug &cpu) : QAbstractTableModel(), _cpu(cpu){ }
|
||||
@@ -276,21 +298,28 @@ int DisassemblyModel::rowCount(const QModelIndex &) const
|
||||
|
||||
QVariant DisassemblyModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if (role != Qt::DisplayRole && role != Qt::DecorationRole)
|
||||
return QVariant();
|
||||
ComSquare::Debugger::DisassembledInstruction instruction = this->_cpu.disassembledInstructions[index.row()];
|
||||
if (role == Qt::DecorationRole) {
|
||||
if (index.column() == 3 && instruction.level == ComSquare::Debugger::TrustLevel::Unsafe)
|
||||
|
||||
switch (role) {
|
||||
case Qt::DecorationRole:
|
||||
if (index.column() == 2 && instruction.level == ComSquare::Debugger::TrustLevel::Unsafe)
|
||||
return QColor(Qt::yellow);
|
||||
if (index.column() == 3 && instruction.level == ComSquare::Debugger::TrustLevel::Compromised)
|
||||
if (index.column() == 2 && instruction.level == ComSquare::Debugger::TrustLevel::Compromised)
|
||||
return QColor(Qt::red);
|
||||
return QVariant();
|
||||
}
|
||||
switch (index.column()) {
|
||||
case 0:
|
||||
return QString(instruction.name.c_str());
|
||||
case 1:
|
||||
return QString(instruction.argument.c_str());
|
||||
case Qt::DisplayRole:
|
||||
switch (index.column()) {
|
||||
case 0:
|
||||
return QString(instruction.name.c_str());
|
||||
case 1:
|
||||
return QString(instruction.argument.c_str());
|
||||
case 3:
|
||||
if (instruction.address != this->_cpu.getPC())
|
||||
return QVariant();
|
||||
return QString(this->_cpu.getProceededParameters().c_str());
|
||||
default:
|
||||
return QVariant();
|
||||
}
|
||||
default:
|
||||
return QVariant();
|
||||
}
|
||||
@@ -377,3 +406,71 @@ QVariant StackModel::headerData(int section, Qt::Orientation orientation, int ro
|
||||
uint16_t addr = section * 2;
|
||||
return QString(ComSquare::Utility::to_hex(addr, ComSquare::Utility::HexString::NoPrefix).c_str());
|
||||
}
|
||||
|
||||
HistoryModel::HistoryModel() = default;
|
||||
|
||||
int HistoryModel::rowCount(const QModelIndex &) const
|
||||
{
|
||||
return this->_instructions.size();
|
||||
}
|
||||
|
||||
int HistoryModel::columnCount(const QModelIndex &) const
|
||||
{
|
||||
return 4;
|
||||
}
|
||||
|
||||
QVariant HistoryModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if (role == Qt::TextAlignmentRole)
|
||||
return Qt::AlignCenter;
|
||||
if (role != Qt::DisplayRole)
|
||||
return QVariant();
|
||||
|
||||
ComSquare::Debugger::ExecutedInstruction instruction = this->_instructions[index.row()];
|
||||
switch (index.column()) {
|
||||
case 0:
|
||||
return QString(ComSquare::Utility::to_hex(instruction.opcode, ComSquare::Utility::NoPrefix).c_str());
|
||||
case 1:
|
||||
return QString(instruction.name.c_str());
|
||||
case 2:
|
||||
return QString(instruction.params.c_str());
|
||||
case 3:
|
||||
return QString(instruction.proceededParams.c_str());
|
||||
default:
|
||||
return QVariant();
|
||||
}
|
||||
}
|
||||
|
||||
QVariant HistoryModel::headerData(int section, Qt::Orientation orientation, int role) const
|
||||
{
|
||||
if (orientation == Qt::Vertical || role != Qt::DisplayRole)
|
||||
return QVariant();
|
||||
switch (section) {
|
||||
case 0:
|
||||
return QString("OP");
|
||||
case 1:
|
||||
return QString("INST");
|
||||
case 2:
|
||||
return QString("Parameter");
|
||||
case 3:
|
||||
return QString("Data Addr");
|
||||
default:
|
||||
return QVariant();
|
||||
}
|
||||
}
|
||||
|
||||
void HistoryModel::log(const ComSquare::Debugger::ExecutedInstruction& instruction)
|
||||
{
|
||||
int row = this->_instructions.size();
|
||||
this->beginInsertRows(QModelIndex(), row, row);
|
||||
this->_instructions.push_back(instruction);
|
||||
this->insertRow(row);
|
||||
this->endInsertRows();
|
||||
}
|
||||
|
||||
void HistoryModel::clear()
|
||||
{
|
||||
this->beginResetModel();
|
||||
this->_instructions.clear();
|
||||
this->endResetModel();
|
||||
}
|
||||
@@ -15,6 +15,18 @@
|
||||
namespace ComSquare::Debugger
|
||||
{
|
||||
class CPUDebug;
|
||||
|
||||
//! @brief An instruction that has already been executed. Used for the history viewer
|
||||
struct ExecutedInstruction {
|
||||
//! @brief Opcode of the instruction
|
||||
uint8_t opcode;
|
||||
//! @brief The name of the instruction
|
||||
std::string name;
|
||||
//! @brief Readable parameters (disassembly style)
|
||||
std::string params;
|
||||
//! @brief The address to read from after processing the parameter.
|
||||
std::string proceededParams;
|
||||
};
|
||||
}
|
||||
|
||||
//! @brief The qt model that show the stack.
|
||||
@@ -40,6 +52,33 @@ public:
|
||||
QVariant headerData(int section, Qt::Orientation orientation, int role) const override;
|
||||
};
|
||||
|
||||
//! @brief The qt model that show the history.
|
||||
class HistoryModel : public QAbstractTableModel
|
||||
{
|
||||
Q_OBJECT
|
||||
private:
|
||||
std::vector<ComSquare::Debugger::ExecutedInstruction> _instructions = {};
|
||||
public:
|
||||
HistoryModel();
|
||||
HistoryModel(const HistoryModel &) = delete;
|
||||
const HistoryModel &operator=(const HistoryModel &) = delete;
|
||||
~HistoryModel() override = default;
|
||||
|
||||
//! @brief Log a new instruction
|
||||
void log(const ComSquare::Debugger::ExecutedInstruction &);
|
||||
//! @brief Remove every instructions of the history.
|
||||
void clear();
|
||||
|
||||
//! @brief The number of row the table has.
|
||||
int rowCount(const QModelIndex &parent) const override;
|
||||
//! @brief The number of column the table has.
|
||||
int columnCount(const QModelIndex &parent) const override;
|
||||
//! @brief Return a data representing the table cell.
|
||||
QVariant data(const QModelIndex &index, int role) const override;
|
||||
//! @brief Override the headers to use hex values.
|
||||
QVariant headerData(int section, Qt::Orientation orientation, int role) const override;
|
||||
};
|
||||
|
||||
//! @brief The qt model that show the disassembly.
|
||||
class DisassemblyModel : public QAbstractTableModel
|
||||
{
|
||||
@@ -139,6 +178,8 @@ namespace ComSquare::Debugger
|
||||
RowPainter _painter;
|
||||
//! @brief The stack viewer's model.
|
||||
StackModel _stackModel;
|
||||
//! @brief The history model.
|
||||
HistoryModel _historyModel;
|
||||
//! @brief If this is set to true, the execution of the CPU will be paused.
|
||||
bool _isPaused = true;
|
||||
//! @brief If this is set to true, the CPU will execute one instruction and pause itself.
|
||||
@@ -220,6 +261,8 @@ namespace ComSquare::Debugger
|
||||
std::vector<DisassembledInstruction> disassembledInstructions;
|
||||
//! @brief The list of breakpoints the user has set.
|
||||
std::vector<Breakpoint> breakpoints;
|
||||
//! @brief Get a string representing the actual value of the arguments of the next instruction to execute.
|
||||
std::string getProceededParameters();
|
||||
//! @brief Return the current program counter of this CPU.
|
||||
uint24_t getPC();
|
||||
//! @brief Return the current stack pointer.
|
||||
|
||||
Reference in New Issue
Block a user