Reworking the instruction history

This commit is contained in:
Anonymus Raccoon
2020-04-04 23:17:31 +02:00
parent 84f964111c
commit 218935b5bb
8 changed files with 252 additions and 118 deletions
+110 -13
View File
@@ -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();
}
+43
View File
@@ -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.