mirror of https://github.com/Treeki/WindEmu.git
add basic breakpoint support
This commit is contained in:
parent
883197000d
commit
e96c438003
|
@ -4,7 +4,7 @@
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
|
||||||
|
|
||||||
//#define INCLUDE_BANK1
|
#define INCLUDE_BANK1
|
||||||
|
|
||||||
Emu::Emu() {
|
Emu::Emu() {
|
||||||
}
|
}
|
||||||
|
@ -184,7 +184,7 @@ void Emu::writeReg32(uint32_t reg, uint32_t value) {
|
||||||
|
|
||||||
uint32_t Emu::readPhys8(uint32_t physAddress) {
|
uint32_t Emu::readPhys8(uint32_t physAddress) {
|
||||||
uint32_t result = 0xFF;
|
uint32_t result = 0xFF;
|
||||||
uint8_t region = (physAddress >> 24) & 0xF8;
|
uint8_t region = (physAddress >> 24) & 0xF1;
|
||||||
if (region == 0)
|
if (region == 0)
|
||||||
result = ROM[physAddress & 0xFFFFFF];
|
result = ROM[physAddress & 0xFFFFFF];
|
||||||
else if (region == 0x80 && physAddress <= 0x80000FFF)
|
else if (region == 0x80 && physAddress <= 0x80000FFF)
|
||||||
|
@ -207,7 +207,7 @@ uint32_t Emu::readPhys8(uint32_t physAddress) {
|
||||||
}
|
}
|
||||||
uint32_t Emu::readPhys16(uint32_t physAddress) {
|
uint32_t Emu::readPhys16(uint32_t physAddress) {
|
||||||
uint32_t result = 0xFFFFFFFF;
|
uint32_t result = 0xFFFFFFFF;
|
||||||
uint8_t region = (physAddress >> 24) & 0xF8;
|
uint8_t region = (physAddress >> 24) & 0xF1;
|
||||||
if (region == 0)
|
if (region == 0)
|
||||||
LOAD_16LE(result, physAddress & 0xFFFFFF, ROM);
|
LOAD_16LE(result, physAddress & 0xFFFFFF, ROM);
|
||||||
else if (region == 0xC0)
|
else if (region == 0xC0)
|
||||||
|
@ -228,7 +228,7 @@ uint32_t Emu::readPhys16(uint32_t physAddress) {
|
||||||
}
|
}
|
||||||
uint32_t Emu::readPhys32(uint32_t physAddress) {
|
uint32_t Emu::readPhys32(uint32_t physAddress) {
|
||||||
uint32_t result = 0xFFFFFFFF;
|
uint32_t result = 0xFFFFFFFF;
|
||||||
uint8_t region = (physAddress >> 24) & 0xF8;
|
uint8_t region = (physAddress >> 24) & 0xF1;
|
||||||
if (region == 0)
|
if (region == 0)
|
||||||
LOAD_32LE(result, physAddress & 0xFFFFFF, ROM);
|
LOAD_32LE(result, physAddress & 0xFFFFFF, ROM);
|
||||||
else if (region == 0x80 && physAddress <= 0x80000FFF)
|
else if (region == 0x80 && physAddress <= 0x80000FFF)
|
||||||
|
@ -251,7 +251,7 @@ uint32_t Emu::readPhys32(uint32_t physAddress) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Emu::writePhys8(uint32_t physAddress, uint8_t value) {
|
void Emu::writePhys8(uint32_t physAddress, uint8_t value) {
|
||||||
uint8_t region = (physAddress >> 24) & 0xF8;
|
uint8_t region = (physAddress >> 24) & 0xF1;
|
||||||
if (region == 0xC0)
|
if (region == 0xC0)
|
||||||
MemoryBlockC0[physAddress & MemoryBlockMask] = (uint8_t)value;
|
MemoryBlockC0[physAddress & MemoryBlockMask] = (uint8_t)value;
|
||||||
#ifdef INCLUDE_BANK1
|
#ifdef INCLUDE_BANK1
|
||||||
|
@ -270,7 +270,7 @@ void Emu::writePhys8(uint32_t physAddress, uint8_t value) {
|
||||||
// printf("<%08x> unmapped write8 addr p:%08x :: %02x\n", cpu.gprs[ARM_PC] - 4, physAddress, value);
|
// printf("<%08x> unmapped write8 addr p:%08x :: %02x\n", cpu.gprs[ARM_PC] - 4, physAddress, value);
|
||||||
}
|
}
|
||||||
void Emu::writePhys16(uint32_t physAddress, uint16_t value) {
|
void Emu::writePhys16(uint32_t physAddress, uint16_t value) {
|
||||||
uint8_t region = (physAddress >> 24) & 0xF8;
|
uint8_t region = (physAddress >> 24) & 0xF1;
|
||||||
if (region == 0xC0)
|
if (region == 0xC0)
|
||||||
STORE_16LE(value, physAddress & MemoryBlockMask, MemoryBlockC0);
|
STORE_16LE(value, physAddress & MemoryBlockMask, MemoryBlockC0);
|
||||||
#ifdef INCLUDE_BANK1
|
#ifdef INCLUDE_BANK1
|
||||||
|
@ -287,7 +287,7 @@ void Emu::writePhys16(uint32_t physAddress, uint16_t value) {
|
||||||
// printf("<%08x> unmapped write16 addr p:%08x :: %04x\n", cpu.gprs[ARM_PC] - 4, physAddress, value);
|
// printf("<%08x> unmapped write16 addr p:%08x :: %04x\n", cpu.gprs[ARM_PC] - 4, physAddress, value);
|
||||||
}
|
}
|
||||||
void Emu::writePhys32(uint32_t physAddress, uint32_t value) {
|
void Emu::writePhys32(uint32_t physAddress, uint32_t value) {
|
||||||
uint8_t region = (physAddress >> 24) & 0xF8;
|
uint8_t region = (physAddress >> 24) & 0xF1;
|
||||||
if (region == 0xC0)
|
if (region == 0xC0)
|
||||||
STORE_32LE(value, physAddress & MemoryBlockMask, MemoryBlockC0);
|
STORE_32LE(value, physAddress & MemoryBlockMask, MemoryBlockC0);
|
||||||
#ifdef INCLUDE_BANK1
|
#ifdef INCLUDE_BANK1
|
||||||
|
@ -556,6 +556,10 @@ void Emu::executeUntil(int64_t cycles) {
|
||||||
uint32_t phys_pc = virtToPhys(pc);
|
uint32_t phys_pc = virtToPhys(pc);
|
||||||
debugPC(phys_pc);
|
debugPC(phys_pc);
|
||||||
ARMRun(&cpu);
|
ARMRun(&cpu);
|
||||||
|
|
||||||
|
uint32_t new_pc = cpu.gprs[ARM_PC] - 4;
|
||||||
|
if (_breakpoints.find(new_pc) != _breakpoints.end())
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "arm.h"
|
#include "arm.h"
|
||||||
#include "wind_hw.h"
|
#include "wind_hw.h"
|
||||||
|
#include <unordered_set>
|
||||||
|
|
||||||
class Emu {
|
class Emu {
|
||||||
uint8_t ROM[0x1000000];
|
uint8_t ROM[0x1000000];
|
||||||
|
@ -28,6 +29,8 @@ class Emu {
|
||||||
UART uart1, uart2;
|
UART uart1, uart2;
|
||||||
bool asleep = false;
|
bool asleep = false;
|
||||||
|
|
||||||
|
std::unordered_set<uint32_t> _breakpoints;
|
||||||
|
|
||||||
struct ARMCore cpu;
|
struct ARMCore cpu;
|
||||||
|
|
||||||
inline bool isMMU() {
|
inline bool isMMU() {
|
||||||
|
@ -84,4 +87,5 @@ public:
|
||||||
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]; }
|
uint32_t getGPR(int index) const { return cpu.gprs[index]; }
|
||||||
|
std::unordered_set<uint32_t> &breakpoints() { return _breakpoints; }
|
||||||
};
|
};
|
||||||
|
|
|
@ -31,7 +31,7 @@ void MainWindow::updateScreen()
|
||||||
ui->cycleCounter->setText(QString("Cycles: %1").arg(emu->currentCycles()));
|
ui->cycleCounter->setText(QString("Cycles: %1").arg(emu->currentCycles()));
|
||||||
|
|
||||||
ui->regsLabel->setText(
|
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")
|
QString("R0: %1 / R1: %2 / R2: %3 / R3: %4 / R4: %5 / R5: %6 / R6: %7 / R7: %8\nR8: %9 / R9: %10 / R10:%11 / R11:%12 / R12:%13 / SP: %14 / LR: %15 / PC: %16")
|
||||||
.arg(emu->getGPR(0), 8, 16)
|
.arg(emu->getGPR(0), 8, 16)
|
||||||
.arg(emu->getGPR(1), 8, 16)
|
.arg(emu->getGPR(1), 8, 16)
|
||||||
.arg(emu->getGPR(2), 8, 16)
|
.arg(emu->getGPR(2), 8, 16)
|
||||||
|
@ -243,3 +243,25 @@ void MainWindow::execTimer()
|
||||||
emu->executeUntil(emu->currentCycles() + (CLOCK_SPEED / 64));
|
emu->executeUntil(emu->currentCycles() + (CLOCK_SPEED / 64));
|
||||||
updateScreen();
|
updateScreen();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MainWindow::on_addBreakButton_clicked()
|
||||||
|
{
|
||||||
|
uint32_t addr = ui->breakpointAddress->text().toUInt(nullptr, 16);
|
||||||
|
emu->breakpoints().insert(addr);
|
||||||
|
updateBreakpointsList();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::on_removeBreakButton_clicked()
|
||||||
|
{
|
||||||
|
uint32_t addr = ui->breakpointAddress->text().toUInt(nullptr, 16);
|
||||||
|
emu->breakpoints().erase(addr);
|
||||||
|
updateBreakpointsList();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::updateBreakpointsList()
|
||||||
|
{
|
||||||
|
ui->breakpointsList->clear();
|
||||||
|
for (uint32_t addr : emu->breakpoints()) {
|
||||||
|
ui->breakpointsList->addItem(QString::number(addr, 16));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -24,12 +24,16 @@ private slots:
|
||||||
void on_stepInsnButton_clicked();
|
void on_stepInsnButton_clicked();
|
||||||
void on_stepTickButton_clicked();
|
void on_stepTickButton_clicked();
|
||||||
|
|
||||||
|
void on_addBreakButton_clicked();
|
||||||
|
|
||||||
|
void on_removeBreakButton_clicked();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Ui::MainWindow *ui;
|
Ui::MainWindow *ui;
|
||||||
Emu *emu;
|
Emu *emu;
|
||||||
QTimer *timer;
|
QTimer *timer;
|
||||||
void updateScreen();
|
void updateScreen();
|
||||||
|
void updateBreakpointsList();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void keyPressEvent(QKeyEvent *event) override;
|
void keyPressEvent(QKeyEvent *event) override;
|
||||||
|
|
|
@ -35,7 +35,7 @@
|
||||||
<item row="4" column="0" colspan="5">
|
<item row="4" column="0" colspan="5">
|
||||||
<widget class="QTabWidget" name="tabWidget">
|
<widget class="QTabWidget" name="tabWidget">
|
||||||
<property name="currentIndex">
|
<property name="currentIndex">
|
||||||
<number>1</number>
|
<number>2</number>
|
||||||
</property>
|
</property>
|
||||||
<widget class="QWidget" name="tab">
|
<widget class="QWidget" name="tab">
|
||||||
<attribute name="title">
|
<attribute name="title">
|
||||||
|
@ -61,10 +61,66 @@
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
|
<widget class="QWidget" name="tab_3">
|
||||||
|
<attribute name="title">
|
||||||
|
<string>Breakpoints</string>
|
||||||
|
</attribute>
|
||||||
|
<layout class="QGridLayout" name="gridLayout_2">
|
||||||
|
<item row="0" column="1">
|
||||||
|
<widget class="QGroupBox" name="groupBox">
|
||||||
|
<property name="title">
|
||||||
|
<string>Edit</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QGridLayout" name="gridLayout_3">
|
||||||
|
<item row="1" column="0">
|
||||||
|
<widget class="QPushButton" name="addBreakButton">
|
||||||
|
<property name="text">
|
||||||
|
<string>Add</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="1">
|
||||||
|
<widget class="QPushButton" name="removeBreakButton">
|
||||||
|
<property name="text">
|
||||||
|
<string>Remove</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="0" colspan="2">
|
||||||
|
<widget class="QLineEdit" name="breakpointAddress">
|
||||||
|
<property name="placeholderText">
|
||||||
|
<string>hex address, no prefix</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="1">
|
||||||
|
<spacer name="verticalSpacer">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Vertical</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>20</width>
|
||||||
|
<height>40</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="0" rowspan="2">
|
||||||
|
<widget class="QListWidget" name="breakpointsList"/>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="0" column="0" colspan="6">
|
<item row="0" column="0" colspan="6">
|
||||||
<widget class="QLabel" name="screen">
|
<widget class="QLabel" name="screen">
|
||||||
|
<property name="focusPolicy">
|
||||||
|
<enum>Qt::ClickFocus</enum>
|
||||||
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string/>
|
<string/>
|
||||||
</property>
|
</property>
|
||||||
|
|
Loading…
Reference in New Issue