aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--qtmips_gui/MainWindow.ui9
-rw-r--r--qtmips_gui/cop0dock.cpp96
-rw-r--r--qtmips_gui/cop0dock.h67
-rw-r--r--qtmips_gui/mainwindow.cpp5
-rw-r--r--qtmips_gui/mainwindow.h4
-rw-r--r--qtmips_gui/qtmips_gui.pro6
-rw-r--r--qtmips_machine/cop0state.cpp81
-rw-r--r--qtmips_machine/cop0state.h24
-rw-r--r--qtmips_machine/core.cpp4
-rw-r--r--qtmips_machine/qtmipsmachine.cpp18
-rw-r--r--qtmips_machine/qtmipsmachine.h3
11 files changed, 281 insertions, 36 deletions
diff --git a/qtmips_gui/MainWindow.ui b/qtmips_gui/MainWindow.ui
index 1b9bfbd..4847304 100644
--- a/qtmips_gui/MainWindow.ui
+++ b/qtmips_gui/MainWindow.ui
@@ -70,6 +70,7 @@
<addaction name="actionData_Cache"/>
<addaction name="actionPeripherals"/>
<addaction name="actionTerminal"/>
+ <addaction name="actionCop0State"/>
</widget>
<widget class="QMenu" name="menuMachine">
<property name="title">
@@ -295,6 +296,14 @@
<string>Ctrl+D</string>
</property>
</action>
+ <action name="actionCop0State">
+ <property name="text">
+ <string>Cop0 State</string>
+ </property>
+ <property name="shortcut">
+ <string>Ctrl+C</string>
+ </property>
+ </action>
<action name="actionReload">
<property name="icon">
<iconset resource="icons.qrc">
diff --git a/qtmips_gui/cop0dock.cpp b/qtmips_gui/cop0dock.cpp
new file mode 100644
index 0000000..1070444
--- /dev/null
+++ b/qtmips_gui/cop0dock.cpp
@@ -0,0 +1,96 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*******************************************************************************
+ * QtMips - MIPS 32-bit Architecture Subset Simulator
+ *
+ * Implemented to support following courses:
+ *
+ * B35APO - Computer Architectures
+ * https://cw.fel.cvut.cz/wiki/courses/b35apo
+ *
+ * B4M35PAP - Advanced Computer Architectures
+ * https://cw.fel.cvut.cz/wiki/courses/b4m35pap/start
+ *
+ * Copyright (c) 2017-2019 Karel Koci<cynerd@email.cz>
+ * Copyright (c) 2019 Pavel Pisa <pisa@cmp.felk.cvut.cz>
+ *
+ * Faculty of Electrical Engineering (http://www.fel.cvut.cz)
+ * Czech Technical University (http://www.cvut.cz/)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ ******************************************************************************/
+
+#include "cop0dock.h"
+
+
+Cop0Dock::Cop0Dock(QWidget *parent) : QDockWidget(parent) {
+ scrollarea = new QScrollArea(this);
+ scrollarea->setWidgetResizable(true);
+ widg = new StaticTable(scrollarea);
+
+#define INIT(X, LABEL) do{ \
+ X = new QLabel("0x00000000", widg); \
+ X->setFixedSize(X->sizeHint()); \
+ X->setText(""); \
+ X->setTextInteractionFlags(Qt::TextSelectableByMouse); \
+ widg->addRow({new QLabel(LABEL, widg), X}); \
+ } while(false)
+
+ cop0reg[0] = nullptr;
+ for (int i = 1; i < machine::Cop0State::COP0REGS_CNT; i++)
+ INIT(cop0reg[i], machine::Cop0State::cop0reg_name((machine::Cop0State::Cop0Registers)i));
+#undef INIT
+ scrollarea->setWidget(widg);
+
+ setWidget(scrollarea);
+ setObjectName("Coprocessor0");
+ setWindowTitle("Coprocessor0");
+}
+
+Cop0Dock::~Cop0Dock() {
+ for (int i = 1; i < machine::Cop0State::COP0REGS_CNT; i++)
+ delete cop0reg[i];
+ delete widg;
+ delete scrollarea;
+}
+
+void Cop0Dock::setup(machine::QtMipsMachine *machine) {
+ if (machine == nullptr) {
+ // Reset data
+ for (int i = 1; i < machine::Cop0State::COP0REGS_CNT; i++)
+ cop0reg[i]->setText("");
+ return;
+ }
+
+ const machine::Cop0State *cop0state = machine->cop0state();
+ connect(cop0state, &machine::Cop0State::cop0reg_update,
+ this, &Cop0Dock::cop0reg_changed);
+
+ for (int i = 1; i < machine::Cop0State::COP0REGS_CNT; i++)
+ labelVal(cop0reg[i], cop0state->read_cop0reg((machine::Cop0State::Cop0Registers)i));
+}
+
+void Cop0Dock::cop0reg_changed(enum machine::Cop0State::Cop0Registers reg, std::uint32_t val) {
+ SANITY_ASSERT((uint)reg < machine::Cop0State::COP0REGS_CNT && (uint)reg,
+ QString("Cop0Dock received signal with invalid cop0 register: ") +
+ QString::number((uint)reg));
+ labelVal(cop0reg[(uint)reg], val);
+}
+
+void Cop0Dock::labelVal(QLabel *label, std::uint32_t value) {
+ QString t = QString("0x") + QString::number(value, 16);
+ label->setText(t);
+}
diff --git a/qtmips_gui/cop0dock.h b/qtmips_gui/cop0dock.h
new file mode 100644
index 0000000..5dfa058
--- /dev/null
+++ b/qtmips_gui/cop0dock.h
@@ -0,0 +1,67 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*******************************************************************************
+ * QtMips - MIPS 32-bit Architecture Subset Simulator
+ *
+ * Implemented to support following courses:
+ *
+ * B35APO - Computer Architectures
+ * https://cw.fel.cvut.cz/wiki/courses/b35apo
+ *
+ * B4M35PAP - Advanced Computer Architectures
+ * https://cw.fel.cvut.cz/wiki/courses/b4m35pap/start
+ *
+ * Copyright (c) 2017-2019 Karel Koci<cynerd@email.cz>
+ * Copyright (c) 2019 Pavel Pisa <pisa@cmp.felk.cvut.cz>
+ *
+ * Faculty of Electrical Engineering (http://www.fel.cvut.cz)
+ * Czech Technical University (http://www.cvut.cz/)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ ******************************************************************************/
+
+#ifndef COP0DOCK_H
+#define COP0DOCK_H
+
+#include <QDockWidget>
+#include <QLabel>
+#include <QFormLayout>
+#include <QScrollArea>
+#include <QPropertyAnimation>
+#include "qtmipsmachine.h"
+#include "statictable.h"
+
+class Cop0Dock : public QDockWidget {
+ Q_OBJECT
+public:
+ Cop0Dock(QWidget *parent);
+ ~Cop0Dock();
+
+ void setup(machine::QtMipsMachine *machine);
+
+private slots:
+ void cop0reg_changed(enum machine::Cop0State::Cop0Registers reg, std::uint32_t val);
+
+private:
+ StaticTable *widg;
+ QScrollArea *scrollarea;
+
+ QLabel *cop0reg[machine::Cop0State::COP0REGS_CNT];
+
+ void labelVal(QLabel *label, std::uint32_t val);
+};
+
+#endif // COP0DOCK_H
diff --git a/qtmips_gui/mainwindow.cpp b/qtmips_gui/mainwindow.cpp
index 01321cf..3cefe94 100644
--- a/qtmips_gui/mainwindow.cpp
+++ b/qtmips_gui/mainwindow.cpp
@@ -67,6 +67,8 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) {
peripherals->hide();
terminal = new TerminalDock(this, settings);
terminal->hide();
+ cop0dock = new Cop0Dock(this);
+ cop0dock->hide();
// Execution speed actions
speed_group = new QActionGroup(this);
@@ -90,6 +92,7 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) {
connect(ui->actionData_Cache, SIGNAL(triggered(bool)), this, SLOT(show_cache_data()));
connect(ui->actionPeripherals, SIGNAL(triggered(bool)), this, SLOT(show_peripherals()));
connect(ui->actionTerminal, SIGNAL(triggered(bool)), this, SLOT(show_terminal()));
+ connect(ui->actionCop0State, SIGNAL(triggered(bool)), this, SLOT(show_cop0dock()));
connect(ui->actionAbout, SIGNAL(triggered(bool)), this, SLOT(about_qtmips()));
connect(ui->actionAboutQt, SIGNAL(triggered(bool)), this, SLOT(about_qt()));
connect(ui->ips1, SIGNAL(toggled(bool)), this, SLOT(set_speed()));
@@ -187,6 +190,7 @@ void MainWindow::create_core(const machine::MachineConfig &config) {
cache_data->setup(machine->cache_data());
terminal->setup(machine->serial_port());
peripherals->setup(machine->peripheral_spi_led());
+ cop0dock->setup(machine);
// Connect signals for instruction address followup
connect(machine->core(), SIGNAL(fetch_inst_addr_value(std::uint32_t)),
@@ -237,6 +241,7 @@ SHOW_HANDLER(cache_program)
SHOW_HANDLER(cache_data)
SHOW_HANDLER(peripherals)
SHOW_HANDLER(terminal)
+SHOW_HANDLER(cop0dock)
#undef SHOW_HANDLER
void MainWindow::show_symbol_dialog(){
diff --git a/qtmips_gui/mainwindow.h b/qtmips_gui/mainwindow.h
index 796dd33..84c9d08 100644
--- a/qtmips_gui/mainwindow.h
+++ b/qtmips_gui/mainwindow.h
@@ -47,6 +47,7 @@
#include "cachedock.h"
#include "peripheralsdock.h"
#include "terminaldock.h"
+#include "cop0dock.h"
#include "qtmipsmachine.h"
#include "machineconfig.h"
@@ -74,6 +75,7 @@ public slots:
void show_cache_program();
void show_peripherals();
void show_terminal();
+ void show_cop0dock();
void show_symbol_dialog();
// Actions - help menu
void about_qtmips();
@@ -102,6 +104,8 @@ private:
CacheDock *cache_program, *cache_data;
PeripheralsDock *peripherals;
TerminalDock *terminal;
+ Cop0Dock *cop0dock;
+
QActionGroup *speed_group;
diff --git a/qtmips_gui/qtmips_gui.pro b/qtmips_gui/qtmips_gui.pro
index acdbd55..e10631b 100644
--- a/qtmips_gui/qtmips_gui.pro
+++ b/qtmips_gui/qtmips_gui.pro
@@ -62,7 +62,8 @@ SOURCES += \
peripheralsview.cpp \
coreview/multitext.cpp \
fontsize.cpp \
- gotosymboldialog.cpp
+ gotosymboldialog.cpp \
+ cop0dock.cpp
HEADERS += \
mainwindow.h \
@@ -100,7 +101,8 @@ HEADERS += \
peripheralsview.h \
coreview/multitext.h \
fontsize.h \
- gotosymboldialog.h
+ gotosymboldialog.h \
+ cop0dock.h
FORMS += \
NewDialog.ui \
diff --git a/qtmips_machine/cop0state.cpp b/qtmips_machine/cop0state.cpp
index 9957560..35f78d1 100644
--- a/qtmips_machine/cop0state.cpp
+++ b/qtmips_machine/cop0state.cpp
@@ -40,9 +40,11 @@
using namespace machine;
+#define COUNTER_IRQ_LEVEL 7
+
// sorry, unimplemented: non-trivial designated initializers not supported
-static enum Cop0State::Cop0Regsisters cop0reg_map[32][8] = {
+static enum Cop0State::Cop0Registers cop0reg_map[32][8] = {
/*0*/ {},
/*1*/ {},
/*2*/ {},
@@ -83,13 +85,13 @@ const Cop0State::cop0reg_desc_t Cop0State::cop0reg_desc[Cop0State::COP0REGS_CNT]
[Cop0State::Unsupported] = {"Unsupported", 0x00000000, 0x00000000,
&Cop0State::read_cop0reg_default, &Cop0State::write_cop0reg_default},
[Cop0State::UserLocal] = {"UserLocal", 0xffffffff, 0x00000000,
- &Cop0State::read_cop0reg_default, &Cop0State::write_cop0reg_default},
+ &Cop0State::read_cop0reg_default, &Cop0State::write_cop0reg_user_local},
[Cop0State::BadVAddr] = {"BadVAddr", 0x00000000, 0x00000000,
&Cop0State::read_cop0reg_default, &Cop0State::write_cop0reg_default},
- [Cop0State::Count] = {"Count", 0x00000000, 0x00000000,
- &Cop0State::read_cop0reg_default, &Cop0State::write_cop0reg_default},
- [Cop0State::Compare] = {"Compare", 0x00000000, 0x00000000,
- &Cop0State::read_cop0reg_default, &Cop0State::write_cop0reg_default},
+ [Cop0State::Count] = {"Count", 0xffffffff, 0x00000000,
+ &Cop0State::read_cop0reg_default, &Cop0State::write_cop0reg_count_compare},
+ [Cop0State::Compare] = {"Compare", 0xffffffff, 0x00000000,
+ &Cop0State::read_cop0reg_default, &Cop0State::write_cop0reg_count_compare},
[Cop0State::Status] = {"Status", Status_IE | Status_IntMask, 0x00000000,
&Cop0State::read_cop0reg_default, &Cop0State::write_cop0reg_default},
[Cop0State::Cause] = {"Cause", 0x00000000, 0x00000000,
@@ -110,7 +112,7 @@ Cop0State::Cop0State(Core *core) : QObject() {
Cop0State::Cop0State(const Cop0State &orig) : QObject() {
this->core = orig.core;
for (int i = 0; i < COP0REGS_CNT; i++)
- this->cop0reg[i] = orig.read_cop0reg((enum Cop0Regsisters)i);
+ this->cop0reg[i] = orig.read_cop0reg((enum Cop0Registers)i);
}
void Cop0State::setup_core(Core *core) {
@@ -120,7 +122,7 @@ void Cop0State::setup_core(Core *core) {
std::uint32_t Cop0State::read_cop0reg(std::uint8_t rd, std::uint8_t sel) const {
SANITY_ASSERT(rd < 32, QString("Trying to read from cop0 register ") + QString(rd) + ',' + QString(sel));
SANITY_ASSERT(sel < 8, QString("Trying to read from cop0 register ") + QString(rd) + ',' + QString(sel));
- enum Cop0Regsisters reg = cop0reg_map[rd][sel];
+ enum Cop0Registers reg = cop0reg_map[rd][sel];
SANITY_ASSERT(reg != 0, QString("Cop0 register ") + QString(rd) + ',' + QString(sel) + "unsupported");
return read_cop0reg(reg);
}
@@ -128,33 +130,38 @@ std::uint32_t Cop0State::read_cop0reg(std::uint8_t rd, std::uint8_t sel) const {
void Cop0State::write_cop0reg(std::uint8_t rd, std::uint8_t sel, std::uint32_t value) {
SANITY_ASSERT(rd < 32, QString("Trying to write to cop0 register ") + QString(rd) + ',' + QString(sel));
SANITY_ASSERT(sel < 8, QString("Trying to write to cop0 register ") + QString(rd) + ',' + QString(sel));
- enum Cop0Regsisters reg = cop0reg_map[rd][sel];
+ enum Cop0Registers reg = cop0reg_map[rd][sel];
SANITY_ASSERT(reg != 0, QString("Cop0 register ") + QString(rd) + ',' + QString(sel) + "unsupported");
write_cop0reg(reg, value);
}
-std::uint32_t Cop0State::read_cop0reg(enum Cop0Regsisters reg) const {
- SANITY_ASSERT(reg < COP0REGS_CNT, QString("Trying to read from cop0 register ") + QString(reg));
- return cop0reg[(int)reg];
+std::uint32_t Cop0State::read_cop0reg(enum Cop0Registers reg) const {
+ SANITY_ASSERT(reg != Unsupported && reg < COP0REGS_CNT, QString("Trying to read from cop0 register ") + QString(reg));
+ return (this->*cop0reg_desc[reg].reg_read)(reg);
}
-void Cop0State::write_cop0reg(enum Cop0Regsisters reg, std::uint32_t value) {
- SANITY_ASSERT(reg < COP0REGS_CNT, QString("Trying to write to cop0 register ") + QString(reg));
- cop0reg[(int)reg] = value;
+void Cop0State::write_cop0reg(enum Cop0Registers reg, std::uint32_t value) {
+ SANITY_ASSERT(reg != Unsupported && reg < COP0REGS_CNT, QString("Trying to write to cop0 register ") + QString(reg));
+ (this->*cop0reg_desc[reg].reg_write)(reg, value);
}
-std::uint32_t Cop0State::read_cop0reg_default(enum Cop0Regsisters reg) const {
+QString Cop0State::cop0reg_name(enum Cop0Registers reg) {
+ return QString(cop0reg_desc[(int)reg].name);
+}
+
+std::uint32_t Cop0State::read_cop0reg_default(enum Cop0Registers reg) const {
return cop0reg[(int)reg];
}
-void Cop0State::write_cop0reg_default(enum Cop0Regsisters reg, std::uint32_t value) {
+void Cop0State::write_cop0reg_default(enum Cop0Registers reg, std::uint32_t value) {
std::uint32_t mask = cop0reg_desc[(int)reg].write_mask;
cop0reg[(int)reg] = (value & mask) | (cop0reg[(int)reg] & ~mask);
+ emit cop0reg_update(reg, cop0reg[(int)reg]);
}
bool Cop0State::operator==(const Cop0State &c) const {
for (int i = 0; i < COP0REGS_CNT; i++)
- if (read_cop0reg((enum Cop0Regsisters)i) != c.read_cop0reg((enum Cop0Regsisters)i))
+ if (read_cop0reg((enum Cop0Registers)i) != c.read_cop0reg((enum Cop0Registers)i))
return false;
return true;
}
@@ -164,8 +171,11 @@ bool Cop0State::operator!=(const Cop0State &c) const {
}
void Cop0State::reset() {
- for (int i = 0; i < COP0REGS_CNT; i++)
+ for (int i = 1; i < COP0REGS_CNT; i++) {
this->cop0reg[i] = cop0reg_desc[i].init_value;
+ emit cop0reg_update((enum Cop0Registers)i, cop0reg[i]);
+ }
+ last_core_cycles = 0;
}
void Cop0State::update_execption_cause(enum ExceptionCause excause, bool in_delay_slot) {
@@ -176,6 +186,7 @@ void Cop0State::update_execption_cause(enum ExceptionCause excause, bool in_dela
cop0reg[(int)Cause] &= ~0x0000007f;
if (excause != EXCAUSE_INT)
cop0reg[(int)Cause] |= (int)excause << 2;
+ emit cop0reg_update(Cause, cop0reg[(int)Cause]);
}
void Cop0State::set_interrupt_signal(uint irq_num, bool active) {
@@ -187,10 +198,14 @@ void Cop0State::set_interrupt_signal(uint irq_num, bool active) {
cop0reg[(int)Cause] |= mask;
else
cop0reg[(int)Cause] &= ~mask;
+ emit cop0reg_update(Cause, cop0reg[(int)Cause]);
}
bool Cop0State::core_interrupt_request() {
std::uint32_t irqs;
+
+ update_count_and_compare_irq();
+
irqs = cop0reg[(int)Status];
irqs &= cop0reg[(int)Cause];
irqs &= Status_IntMask;
@@ -205,8 +220,36 @@ void Cop0State::set_status_exl(bool value) {
cop0reg[(int)Status] |= Status_EXL;
else
cop0reg[(int)Status] &= ~Status_EXL;
+ emit cop0reg_update(Status, cop0reg[(int)Status]);
}
std::uint32_t Cop0State::exception_pc_address() {
return cop0reg[(int)EBase] + 0x180;
}
+
+void Cop0State::write_cop0reg_count_compare(enum Cop0Registers reg, std::uint32_t value) {
+ set_interrupt_signal(COUNTER_IRQ_LEVEL, false);
+ write_cop0reg_default(reg, value);
+}
+
+void Cop0State::update_count_and_compare_irq() {
+ std::uint32_t core_cycles;
+ std::uint32_t count_orig;
+ if (core == nullptr)
+ return;
+ count_orig = cop0reg[(int)Count];
+ core_cycles = core->cycles();
+ cop0reg[(int)Count] += core_cycles - last_core_cycles;
+ last_core_cycles = core_cycles;
+ emit cop0reg_update(Count, cop0reg[(int)Count]);
+
+ if ((std::int32_t)(cop0reg[(int)Compare] - count_orig) > 0 &&
+ (std::int32_t)(cop0reg[(int)Compare] - cop0reg[(int)Count]) <= 0)
+ set_interrupt_signal(COUNTER_IRQ_LEVEL, true);
+}
+
+void Cop0State::write_cop0reg_user_local(enum Cop0Registers reg, std::uint32_t value) {
+ write_cop0reg_default(reg, value);
+ if (core != nullptr)
+ core->set_c0_userlocal(value);
+}
diff --git a/qtmips_machine/cop0state.h b/qtmips_machine/cop0state.h
index 06be9a7..0fd3d3f 100644
--- a/qtmips_machine/cop0state.h
+++ b/qtmips_machine/cop0state.h
@@ -37,6 +37,7 @@
#define COP0STATE_H
#include <QObject>
+#include <QString>
#include <cstdint>
#include <machinedefs.h>
namespace machine {
@@ -47,7 +48,7 @@ class Cop0State : public QObject {
Q_OBJECT
friend class Core;
public:
- enum Cop0Regsisters {
+ enum Cop0Registers {
Unsupported = 0,
UserLocal,
BadVAddr, // Reports the address for the most recent address-related exception
@@ -72,10 +73,11 @@ public:
Cop0State(Core *core = nullptr);
Cop0State(const Cop0State&);
- std::uint32_t read_cop0reg(enum Cop0Regsisters reg) const;
+ std::uint32_t read_cop0reg(enum Cop0Registers reg) const;
std::uint32_t read_cop0reg(std::uint8_t rd, std::uint8_t sel) const; // Read coprocessor 0 register
- void write_cop0reg(enum Cop0Regsisters reg, std::uint32_t value);
+ void write_cop0reg(enum Cop0Registers reg, std::uint32_t value);
void write_cop0reg(std::uint8_t reg, std::uint8_t sel, std::uint32_t value); // Write coprocessor 0 register
+ static QString cop0reg_name(enum Cop0Registers reg);
bool operator ==(const Cop0State &c) const;
bool operator !=(const Cop0State &c) const;
@@ -85,6 +87,9 @@ public:
bool core_interrupt_request();
std::uint32_t exception_pc_address();
+signals:
+ void cop0reg_update(enum Cop0Registers reg, std::uint32_t val);
+
public slots:
void set_interrupt_signal(uint irq_num, bool active);
void set_status_exl(bool value);
@@ -92,14 +97,15 @@ public slots:
protected:
void setup_core(Core *core);
void update_execption_cause(enum ExceptionCause excause, bool in_delay_slot);
+ void update_count_and_compare_irq();
private:
typedef std::uint32_t (Cop0State::*reg_read_t)
- (enum Cop0Regsisters reg) const;
+ (enum Cop0Registers reg) const;
typedef void (Cop0State::*reg_write_t)
- (enum Cop0Regsisters reg, std::uint32_t value);
+ (enum Cop0Registers reg, std::uint32_t value);
struct cop0reg_desc_t {
const char *name;
@@ -112,14 +118,18 @@ private:
static const cop0reg_desc_t cop0reg_desc[COP0REGS_CNT];
- std::uint32_t read_cop0reg_default(enum Cop0Regsisters reg) const;
- void write_cop0reg_default(enum Cop0Regsisters reg, std::uint32_t value);
+ std::uint32_t read_cop0reg_default(enum Cop0Registers reg) const;
+ void write_cop0reg_default(enum Cop0Registers reg, std::uint32_t value);
+ void write_cop0reg_count_compare(enum Cop0Registers reg, std::uint32_t value);
+ void write_cop0reg_user_local(enum Cop0Registers reg, std::uint32_t value);
Core *core;
std::uint32_t cop0reg[COP0REGS_CNT]; // coprocessor 0 registers
+ std::uint32_t last_core_cycles;
};
}
Q_DECLARE_METATYPE(machine::Cop0State)
+Q_DECLARE_METATYPE(machine::Cop0State::Cop0Registers)
#endif // COP0STATE_H
diff --git a/qtmips_machine/core.cpp b/qtmips_machine/core.cpp
index 351ffb0..2ba8d34 100644
--- a/qtmips_machine/core.cpp
+++ b/qtmips_machine/core.cpp
@@ -160,6 +160,10 @@ bool Core::handle_exception(Core *core, Registers *regs, ExceptionCause excause,
void Core::set_c0_userlocal(std::uint32_t address) {
hwr_userlocal = address;
+ if (cop0state != nullptr) {
+ if (address != cop0state->read_cop0reg(Cop0State::UserLocal))
+ cop0state->write_cop0reg(Cop0State::UserLocal, address);
+ }
}
enum ExceptionCause Core::memory_special(enum AccessControl memctl,
diff --git a/qtmips_machine/qtmipsmachine.cpp b/qtmips_machine/qtmipsmachine.cpp
index 41ca56f..afcae54 100644
--- a/qtmips_machine/qtmipsmachine.cpp
+++ b/qtmips_machine/qtmipsmachine.cpp
@@ -81,16 +81,16 @@ QtMipsMachine::QtMipsMachine(const MachineConfig &cc, bool load_symtab) :
cc.cache_program().blocks() < min_cache_row_size)
min_cache_row_size = cc.cache_program().blocks() * 4;
- cop0state = new Cop0State();
+ cop0st = new Cop0State();
if (cc.pipelined())
cr = new CorePipelined(regs, cch_program, cch_data, cc.hazard_unit(),
- min_cache_row_size, cop0state);
+ min_cache_row_size, cop0st);
else
cr = new CoreSingle(regs, cch_program, cch_data, cc.delay_slot(),
- min_cache_row_size, cop0state);
+ min_cache_row_size, cop0st);
connect(this, SIGNAL(set_interrupt_signal(uint,bool)),
- cop0state, SLOT(set_interrupt_signal(uint,bool)));
+ cop0st, SLOT(set_interrupt_signal(uint,bool)));
run_t = new QTimer(this);
set_speed(0); // In default run as fast as possible
@@ -104,9 +104,9 @@ QtMipsMachine::~QtMipsMachine() {
if (cr != nullptr)
delete cr;
cr = nullptr;
- if (cop0state != nullptr)
- delete cop0state;
- cop0state = nullptr;
+ if (cop0st != nullptr)
+ delete cop0st;
+ cop0st = nullptr;
if (regs != nullptr)
delete regs;
regs = nullptr;
@@ -143,6 +143,10 @@ const Registers *QtMipsMachine::registers() {
return regs;
}
+const Cop0State *QtMipsMachine::cop0state() {
+ return cop0st;
+}
+
const Memory *QtMipsMachine::memory() {
return mem;
}
diff --git a/qtmips_machine/qtmipsmachine.h b/qtmips_machine/qtmipsmachine.h
index 60291a8..349e0df 100644
--- a/qtmips_machine/qtmipsmachine.h
+++ b/qtmips_machine/qtmipsmachine.h
@@ -63,6 +63,7 @@ public:
void set_speed(unsigned int ips, unsigned int time_chunk = 0);
const Registers *registers();
+ const Cop0State *cop0state();
const Memory *memory();
Memory *memory_rw();
const Cache *cache_program();
@@ -120,7 +121,7 @@ private:
SerialPort *ser_port;
PeripSpiLed *perip_spi_led;
Cache *cch_program, *cch_data;
- Cop0State *cop0state;
+ Cop0State *cop0st;
Core *cr;
QTimer *run_t;