From a6556b3ab791da12e009ed2683f0d4afe2fbbec2 Mon Sep 17 00:00:00 2001
From: Anonymus Raccoon
Date: Sat, 28 Mar 2020 17:20:52 +0100
Subject: [PATCH] Adding a next
---
sources/Debugger/CPUDebug.cpp | 42 +++++++++++++++++++++++++++++++----
sources/Debugger/CPUDebug.hpp | 12 ++++++++++
2 files changed, 50 insertions(+), 4 deletions(-)
diff --git a/sources/Debugger/CPUDebug.cpp b/sources/Debugger/CPUDebug.cpp
index cb8392f..eb5bd12 100644
--- a/sources/Debugger/CPUDebug.cpp
+++ b/sources/Debugger/CPUDebug.cpp
@@ -38,6 +38,7 @@ namespace ComSquare::Debugger
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);
QMainWindow::connect(this->_ui.clear, &QPushButton::released, this, &CPUDebug::clearHistory);
this->_window->show();
this->_updateRegistersPanel();
@@ -56,14 +57,30 @@ namespace ComSquare::Debugger
unsigned CPUDebug::update()
{
try {
+ unsigned cycles = 0;
+
if (this->_isPaused)
return 0xFF;
if (this->_isStepping) {
- unsigned ret = this->_executeInstruction(this->readPC());
+ cycles = this->_executeInstruction(this->readPC());
this->_updateDisassembly();
- return ret;
+ return cycles;
}
- return CPU::update();
+
+ for (int i = 0; i < 0xFF; i++) {
+ auto breakpoint = std::find_if(this->breakpoints.begin(), this->breakpoints.end(), [this](Breakpoint &brk) {
+ return brk.address == this->_registers.pac;
+ });
+ if (i != 0 && breakpoint != this->breakpoints.end()) {
+ if (breakpoint->oneTime)
+ this->breakpoints.erase(breakpoint);
+ this->_isPaused = false;
+ this->pause();
+ return cycles;
+ }
+ cycles += this->_executeInstruction(this->readPC());
+ }
+ return cycles;
} catch (InvalidOpcode &e) {
if (!this->_isPaused)
this->pause();
@@ -105,6 +122,15 @@ namespace ComSquare::Debugger
this->_isPaused = false;
}
+ void CPUDebug::next()
+ {
+ auto next = std::find_if(this->disassembledInstructions.begin(), this->disassembledInstructions.end(), [this](DisassembledInstruction &i) {
+ return i.address > this->_registers.pac;
+ });
+ this->breakpoints.push_back({next->address, true});
+ this->_isPaused = false;
+ }
+
void CPUDebug::_updateRegistersPanel()
{
if (!this->_registers.p.m)
@@ -378,10 +404,18 @@ RowPainter::RowPainter(ComSquare::Debugger::CPUDebug &cpu, QObject *parent) : QS
void RowPainter::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
ComSquare::Debugger::DisassembledInstruction instruction = this->_cpu.disassembledInstructions[index.row()];
+ bool isBreakpoint = false;
+
+ auto breakpoint = std::find_if(this->_cpu.breakpoints.begin(), this->_cpu.breakpoints.end(), [instruction](ComSquare::Debugger::Breakpoint brk) {
+ return brk.address == instruction.address;
+ });
+ if (breakpoint != this->_cpu.breakpoints.end())
+ isBreakpoint = true;
if (instruction.address == this->_cpu.getPC())
painter->fillRect(option.rect,QColor(Qt::darkGreen));
- // TODO display breakpoints with the Qt::darkRed color.
+ if (isBreakpoint && !breakpoint->oneTime)
+ painter->fillRect(option.rect,QColor(Qt::darkRed));
QStyledItemDelegate::paint(painter, option, index);
}
diff --git a/sources/Debugger/CPUDebug.hpp b/sources/Debugger/CPUDebug.hpp
index 2ee125b..5cc42ee 100644
--- a/sources/Debugger/CPUDebug.hpp
+++ b/sources/Debugger/CPUDebug.hpp
@@ -95,6 +95,14 @@ namespace ComSquare::Debugger
std::string toString();
};
+ //! @brief Struct representing a breakpoint set by the user or by the app
+ struct Breakpoint {
+ //! @brief The address of the breakpoint
+ uint24_t address;
+ //! @brief If this is true, the breakpoint will be deleted on first hit and won't be shown on the disassembly view.
+ bool oneTime;
+ };
+
//! @brief A custom CPU with a window that show it's registers and the disassembly.
class CPUDebug : public CPU::CPU, public QObject {
private:
@@ -147,12 +155,16 @@ namespace ComSquare::Debugger
void pause();
//! @brief Step - Execute a single instruction.
void step();
+ //! @brief Next - Continue running instructions until the next line is reached.
+ void next();
//! @brief Clear the history panel.
void clearHistory();
//! @brief Called when the window is closed. Turn off the debugger and revert to a basic CPU.
void disableDebugger();
//! @brief The list of disassembled instructions to show on the debugger.
std::vector disassembledInstructions;
+ //! @brief The list of breakpoints the user has set.
+ std::vector breakpoints;
//! @brief Return the current program counter of this CPU.
uint24_t getPC();
//! @brief Update the UI when resetting the CPU.