add a very basic debugger UI

This commit is contained in:
Ash Wolf 2019-12-19 14:11:31 +00:00
parent 1d6e77ced8
commit 6a41ed1d76
5 changed files with 177 additions and 29 deletions

View File

@ -6,7 +6,6 @@
Emu::Emu() { Emu::Emu() {
configure();
} }
@ -464,7 +463,10 @@ void Emu::loadROM(const char *path) {
} }
void Emu::executeUntil(int64_t cycles) { void Emu::executeUntil(int64_t cycles) {
while (!asleep && cpu.cycles <= cycles) { if (!configured)
configure();
while (!asleep && cpu.cycles < cycles) {
if (cpu.cycles >= nextTickAt) { if (cpu.cycles >= nextTickAt) {
// increment RTCDIV // increment RTCDIV
if ((pwrsr & 0x3F) == 0x3F) { if ((pwrsr & 0x3F) == 0x3F) {

View File

@ -82,4 +82,5 @@ public:
void dumpRAM(const char *path); void dumpRAM(const char *path);
void executeUntil(int64_t cycles); void executeUntil(int64_t cycles);
int64_t currentCycles() const { return cpu.cycles; } int64_t currentCycles() const { return cpu.cycles; }
uint32_t getGPR(int index) const { return cpu.gprs[index]; }
}; };

View File

@ -3,6 +3,7 @@
#include "../WindCore/wind.h" #include "../WindCore/wind.h"
#include <QTimer> #include <QTimer>
#include <QKeyEvent> #include <QKeyEvent>
#include "../WindCore/decoder.h"
MainWindow::MainWindow(QWidget *parent) : MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent), QMainWindow(parent),
@ -14,8 +15,10 @@ MainWindow::MainWindow(QWidget *parent) :
emu->loadROM("/Users/ash/src/psion/Sys$rom.bin"); emu->loadROM("/Users/ash/src/psion/Sys$rom.bin");
timer = new QTimer(this); timer = new QTimer(this);
timer->start(1000/64); timer->setInterval(1000/64);
connect(timer, SIGNAL(timeout()), SLOT(execTimer())); connect(timer, SIGNAL(timeout()), SLOT(execTimer()));
updateScreen();
} }
MainWindow::~MainWindow() MainWindow::~MainWindow()
@ -23,22 +26,54 @@ MainWindow::~MainWindow()
delete ui; delete ui;
} }
void MainWindow::execTimer()
{
emu->executeUntil(emu->currentCycles() + (CLOCK_SPEED / 64));
ui->cycleCounter->setText(QString("Cycles: %1").arg(emu->currentCycles()));
updateScreen();
}
void MainWindow::on_stepButton_clicked()
{
emu->executeUntil(emu->currentCycles() + (CLOCK_SPEED * 2));
ui->cycleCounter->setText(QString("Cycles: %1").arg(emu->currentCycles()));
updateScreen();
}
void MainWindow::updateScreen() void MainWindow::updateScreen()
{ {
ui->cycleCounter->setText(QString("Cycles: %1").arg(emu->currentCycles()));
ui->regsLabel->setText(
QString("R0: %1 / R1: %2 / R2: %3 / R3: %4 / R4: %5 / R5: %6 / R6: %7 / R7: %8 / R8: %9\nR9: %10 / R10:%11 / R11:%12 / R12:%13 / SP: %14 / LR: %15 / PC: %16")
.arg(emu->getGPR(0), 8, 16)
.arg(emu->getGPR(1), 8, 16)
.arg(emu->getGPR(2), 8, 16)
.arg(emu->getGPR(3), 8, 16)
.arg(emu->getGPR(4), 8, 16)
.arg(emu->getGPR(5), 8, 16)
.arg(emu->getGPR(6), 8, 16)
.arg(emu->getGPR(7), 8, 16)
.arg(emu->getGPR(8), 8, 16)
.arg(emu->getGPR(9), 8, 16)
.arg(emu->getGPR(10), 8, 16)
.arg(emu->getGPR(11), 8, 16)
.arg(emu->getGPR(12), 8, 16)
.arg(emu->getGPR(13), 8, 16)
.arg(emu->getGPR(14), 8, 16)
.arg(emu->getGPR(15), 8, 16)
);
// show a crude disassembly
const int context = 8 * 4;
uint32_t pc = emu->getGPR(15) - 4;
uint32_t minCode = pc - context;
if (minCode >= (UINT32_MAX - context))
minCode = 0;
uint32_t maxCode = pc + context;
if (maxCode < context)
maxCode = UINT32_MAX;
QStringList codeLines;
for (uint32_t addr = minCode; addr >= minCode && addr <= maxCode; addr += 4) {
const char *prefix = (addr == pc) ? "==>" : " ";
struct ARMInstructionInfo info;
char buffer[512];
uint32_t opcode = emu->readVirt32(addr);
ARMDecodeARM(opcode, &info);
ARMDisassemble(&info, addr, buffer, sizeof(buffer));
codeLines.append(QString("%1 %2 | %3 | %4").arg(prefix).arg(addr, 8, 16).arg(opcode, 8, 16).arg(buffer));
}
ui->codeLabel->setText(codeLines.join('\n'));
// now, the actual screen
const uint8_t *lcdBuf = emu->getLCDBuffer(); const uint8_t *lcdBuf = emu->getLCDBuffer();
if (lcdBuf) { if (lcdBuf) {
QImage img(640, 240, QImage::Format_Grayscale8); QImage img(640, 240, QImage::Format_Grayscale8);
@ -169,3 +204,42 @@ void MainWindow::keyReleaseEvent(QKeyEvent *event)
if (k >= 0) if (k >= 0)
emu->keyboardKeys[k] = false; emu->keyboardKeys[k] = false;
} }
void MainWindow::on_startButton_clicked()
{
timer->start();
ui->startButton->setEnabled(false);
ui->stopButton->setEnabled(true);
ui->stepInsnButton->setEnabled(false);
ui->stepTickButton->setEnabled(false);
}
void MainWindow::on_stopButton_clicked()
{
timer->stop();
ui->startButton->setEnabled(true);
ui->stopButton->setEnabled(false);
ui->stepInsnButton->setEnabled(true);
ui->stepTickButton->setEnabled(true);
}
void MainWindow::on_stepTickButton_clicked()
{
emu->executeUntil(emu->currentCycles() + (CLOCK_SPEED * 2));
updateScreen();
}
void MainWindow::on_stepInsnButton_clicked()
{
emu->executeUntil(emu->currentCycles() + 1);
updateScreen();
}
void MainWindow::execTimer()
{
emu->executeUntil(emu->currentCycles() + (CLOCK_SPEED / 64));
updateScreen();
}

View File

@ -17,9 +17,13 @@ public:
~MainWindow() override; ~MainWindow() override;
private slots: private slots:
void on_stepButton_clicked();
void execTimer(); void execTimer();
void on_startButton_clicked();
void on_stopButton_clicked();
void on_stepInsnButton_clicked();
void on_stepTickButton_clicked();
private: private:
Ui::MainWindow *ui; Ui::MainWindow *ui;
Emu *emu; Emu *emu;

View File

@ -15,6 +15,75 @@
</property> </property>
<widget class="QWidget" name="centralWidget"> <widget class="QWidget" name="centralWidget">
<layout class="QGridLayout" name="gridLayout"> <layout class="QGridLayout" name="gridLayout">
<item row="1" column="4">
<widget class="QPushButton" name="stopButton">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Stop</string>
</property>
</widget>
</item>
<item row="2" column="3">
<widget class="QPushButton" name="stepInsnButton">
<property name="text">
<string>Step (Insn)</string>
</property>
</widget>
</item>
<item row="4" column="0" colspan="5">
<widget class="QTabWidget" name="tabWidget">
<property name="currentIndex">
<number>1</number>
</property>
<widget class="QWidget" name="tab">
<attribute name="title">
<string>Memory</string>
</attribute>
</widget>
<widget class="QWidget" name="tab_2">
<attribute name="title">
<string>Code</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLabel" name="codeLabel">
<property name="font">
<font>
<family>Courier New</family>
</font>
</property>
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
</item>
<item row="0" column="0" colspan="6">
<widget class="QLabel" name="screen">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="1" column="3">
<widget class="QPushButton" name="startButton">
<property name="text">
<string>Start</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="cycleCounter">
<property name="text">
<string>Cycles</string>
</property>
</widget>
</item>
<item row="1" column="2"> <item row="1" column="2">
<spacer name="horizontalSpacer"> <spacer name="horizontalSpacer">
<property name="orientation"> <property name="orientation">
@ -28,22 +97,20 @@
</property> </property>
</spacer> </spacer>
</item> </item>
<item row="1" column="3"> <item row="2" column="4">
<widget class="QPushButton" name="stepButton"> <widget class="QPushButton" name="stepTickButton">
<property name="text"> <property name="text">
<string>Step</string> <string>Step (Tick)</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="1" column="0"> <item row="3" column="0" colspan="5">
<widget class="QLabel" name="cycleCounter"> <widget class="QLabel" name="regsLabel">
<property name="text"> <property name="font">
<string>Cycles</string> <font>
<family>Courier New</family>
</font>
</property> </property>
</widget>
</item>
<item row="0" column="0" colspan="4">
<widget class="QLabel" name="screen">
<property name="text"> <property name="text">
<string/> <string/>
</property> </property>