aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/citra_qt/debugger
diff options
context:
space:
mode:
authorGravatar Mathieu Vaillancourt <vaillancourtm@gmail.com>2014-04-18 18:30:53 -0400
committerGravatar Mathieu Vaillancourt <vaillancourtm@gmail.com>2014-04-18 18:34:23 -0400
commite5f09b8be65c06927164428b5d400024e2388dbc (patch)
tree0f0fd4035bcc88c0de5a47a7d3c64b4f67453897 /src/citra_qt/debugger
parent958bca606e80110e05d7c142dda3097fddc96503 (diff)
UI/debugger changes
Diffstat (limited to 'src/citra_qt/debugger')
-rw-r--r--src/citra_qt/debugger/callstack.cpp66
-rw-r--r--src/citra_qt/debugger/callstack.hxx19
-rw-r--r--src/citra_qt/debugger/callstack.ui36
-rw-r--r--src/citra_qt/debugger/disassembler.cpp161
-rw-r--r--src/citra_qt/debugger/disassembler.hxx42
-rw-r--r--src/citra_qt/debugger/disassembler.ui88
-rw-r--r--src/citra_qt/debugger/ramview.cpp13
-rw-r--r--src/citra_qt/debugger/ramview.hxx12
-rw-r--r--src/citra_qt/debugger/registers.cpp63
-rw-r--r--src/citra_qt/debugger/registers.hxx25
-rw-r--r--src/citra_qt/debugger/registers.ui40
11 files changed, 565 insertions, 0 deletions
diff --git a/src/citra_qt/debugger/callstack.cpp b/src/citra_qt/debugger/callstack.cpp
new file mode 100644
index 00000000..f59f2d8c
--- /dev/null
+++ b/src/citra_qt/debugger/callstack.cpp
@@ -0,0 +1,66 @@
+#include <QStandardItemModel>
+
+#include "callstack.hxx"
+
+#include "core/core.h"
+#include "core/arm/arm_interface.h"
+#include "core/mem_map.h"
+#include "common/symbols.h"
+#include "core/arm/disassembler/arm_disasm.h"
+
+CallstackWidget::CallstackWidget(QWidget* parent): QDockWidget(parent)
+{
+ ui.setupUi(this);
+
+ callstack_model = new QStandardItemModel(this);
+ callstack_model->setColumnCount(4);
+ callstack_model->setHeaderData(0, Qt::Horizontal, "Stack pointer");
+ callstack_model->setHeaderData(2, Qt::Horizontal, "Return address");
+ callstack_model->setHeaderData(1, Qt::Horizontal, "Call address");
+ callstack_model->setHeaderData(3, Qt::Horizontal, "Function");
+ ui.treeView->setModel(callstack_model);
+}
+
+void CallstackWidget::OnCPUStepped()
+{
+ ARM_Disasm* disasm = new ARM_Disasm();
+ ARM_Interface* app_core = Core::g_app_core;
+
+ u32 sp = app_core->GetReg(13); //stack pointer
+ u32 addr, ret_addr, call_addr, func_addr;
+
+ int counter = 0;
+ for (int addr = 0x10000000; addr >= sp; addr -= 4)
+ {
+ ret_addr = Memory::Read32(addr);
+ call_addr = ret_addr - 4; //get call address???
+
+ /* TODO (mattvail) clean me, move to debugger interface */
+ u32 insn = Memory::Read32(call_addr);
+ if (disasm->decode(insn) == OP_BL)
+ {
+ std::string name;
+ // ripped from disasm
+ uint8_t cond = (insn >> 28) & 0xf;
+ uint32_t i_offset = insn & 0xffffff;
+ // Sign-extend the 24-bit offset
+ if ((i_offset >> 23) & 1)
+ i_offset |= 0xff000000;
+
+ // Pre-compute the left-shift and the prefetch offset
+ i_offset <<= 2;
+ i_offset += 8;
+ func_addr = call_addr + i_offset;
+
+ callstack_model->setItem(counter, 0, new QStandardItem(QString("0x%1").arg(addr, 8, 16, QLatin1Char('0'))));
+ callstack_model->setItem(counter, 1, new QStandardItem(QString("0x%1").arg(ret_addr, 8, 16, QLatin1Char('0'))));
+ callstack_model->setItem(counter, 2, new QStandardItem(QString("0x%1").arg(call_addr, 8, 16, QLatin1Char('0'))));
+
+ name = Symbols::HasSymbol(func_addr) ? Symbols::GetSymbol(func_addr).name : "unknown";
+ callstack_model->setItem(counter, 3, new QStandardItem(QString("%1_%2").arg(QString::fromStdString(name))
+ .arg(QString("0x%1").arg(func_addr, 8, 16, QLatin1Char('0')))));
+
+ counter++;
+ }
+ }
+} \ No newline at end of file
diff --git a/src/citra_qt/debugger/callstack.hxx b/src/citra_qt/debugger/callstack.hxx
new file mode 100644
index 00000000..3ad2af28
--- /dev/null
+++ b/src/citra_qt/debugger/callstack.hxx
@@ -0,0 +1,19 @@
+#include <QDockWidget>
+#include "../ui_callstack.h"
+
+class QStandardItemModel;
+
+class CallstackWidget : public QDockWidget
+{
+ Q_OBJECT
+
+public:
+ CallstackWidget(QWidget* parent = 0);
+
+public slots:
+ void OnCPUStepped();
+
+private:
+ Ui::CallStack ui;
+ QStandardItemModel* callstack_model;
+};
diff --git a/src/citra_qt/debugger/callstack.ui b/src/citra_qt/debugger/callstack.ui
new file mode 100644
index 00000000..b3c4db63
--- /dev/null
+++ b/src/citra_qt/debugger/callstack.ui
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>CallStack</class>
+ <widget class="QDockWidget" name="CallStack">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>400</width>
+ <height>300</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Call stack</string>
+ </property>
+ <widget class="QWidget" name="dockWidgetContents">
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QTreeView" name="treeView">
+ <property name="alternatingRowColors">
+ <bool>true</bool>
+ </property>
+ <property name="rootIsDecorated">
+ <bool>false</bool>
+ </property>
+ <property name="itemsExpandable">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/src/citra_qt/debugger/disassembler.cpp b/src/citra_qt/debugger/disassembler.cpp
new file mode 100644
index 00000000..cc4cb13f
--- /dev/null
+++ b/src/citra_qt/debugger/disassembler.cpp
@@ -0,0 +1,161 @@
+#include <QtGui>
+
+#include "disassembler.hxx"
+
+#include "../bootmanager.hxx"
+#include "../hotkeys.hxx"
+
+#include "common/common.h"
+#include "core/mem_map.h"
+
+#include "core/core.h"
+#include "common/break_points.h"
+#include "common/symbols.h"
+#include "core/arm/interpreter/armdefs.h"
+#include "core/arm/disassembler/arm_disasm.h"
+
+DisassemblerWidget::DisassemblerWidget(QWidget* parent, EmuThread& emu_thread) : QDockWidget(parent), base_addr(0), emu_thread(emu_thread)
+{
+ disasm_ui.setupUi(this);
+
+ breakpoints = new BreakPoints();
+
+ model = new QStandardItemModel(this);
+ model->setColumnCount(3);
+ disasm_ui.treeView->setModel(model);
+ disasm_ui.tableView->setModel(model);
+ RegisterHotkey("Disassembler", "Start/Stop", QKeySequence(Qt::Key_F5), Qt::ApplicationShortcut);
+ RegisterHotkey("Disassembler", "Step", QKeySequence(Qt::Key_F10), Qt::ApplicationShortcut);
+ RegisterHotkey("Disassembler", "Step into", QKeySequence(Qt::Key_F11), Qt::ApplicationShortcut);
+ RegisterHotkey("Disassembler", "Set Breakpoint", QKeySequence(Qt::Key_F9), Qt::ApplicationShortcut);
+
+ connect(disasm_ui.button_breakpoint, SIGNAL(clicked()), this, SLOT(OnSetBreakpoint()));
+ connect(disasm_ui.button_step, SIGNAL(clicked()), this, SLOT(OnStep()));
+ connect(disasm_ui.button_pause, SIGNAL(clicked()), this, SLOT(OnPause()));
+ connect(disasm_ui.button_continue, SIGNAL(clicked()), this, SLOT(OnContinue()));
+
+ connect(GetHotkey("Disassembler", "Start/Stop", this), SIGNAL(activated()), this, SLOT(OnToggleStartStop()));
+ connect(GetHotkey("Disassembler", "Step", this), SIGNAL(activated()), this, SLOT(OnStep()));
+ connect(GetHotkey("Disassembler", "Step into", this), SIGNAL(activated()), this, SLOT(OnStepInto()));
+ connect(GetHotkey("Disassembler", "Set Breakpoint", this), SIGNAL(activated()), this, SLOT(OnSetBreakpoint()));
+}
+
+void DisassemblerWidget::Init()
+{
+ ARM_Disasm* disasm = new ARM_Disasm();
+
+ base_addr = Core::g_app_core->GetPC();
+ unsigned int curInstAddr = base_addr;
+ char result[255];
+
+ for (int i = 0; i < 10000; i++) // fixed for now
+ {
+ disasm->disasm(curInstAddr, Memory::Read32(curInstAddr), result);
+ model->setItem(i, 0, new QStandardItem(QString("0x%1").arg((uint)(curInstAddr), 8, 16, QLatin1Char('0'))));
+ model->setItem(i, 1, new QStandardItem(QString(result)));
+ if (Symbols::HasSymbol(curInstAddr))
+ {
+ TSymbol symbol = Symbols::GetSymbol(curInstAddr);
+ model->setItem(i, 2, new QStandardItem(QString("%1 - Size:%2").arg(QString::fromStdString(symbol.name))
+ .arg(symbol.size / 4))); // divide by 4 to get instruction count
+
+ }
+ curInstAddr += 4;
+ }
+ disasm_ui.treeView->resizeColumnToContents(0);
+ disasm_ui.treeView->resizeColumnToContents(1);
+ disasm_ui.treeView->resizeColumnToContents(2);
+ disasm_ui.tableView->resizeColumnToContents(0);
+ disasm_ui.tableView->resizeColumnToContents(1);
+ disasm_ui.tableView->resizeColumnToContents(2);
+
+ QModelIndex model_index = model->index(0, 0);
+ disasm_ui.treeView->scrollTo(model_index);
+ disasm_ui.treeView->selectionModel()->setCurrentIndex(model_index, QItemSelectionModel::SelectCurrent | QItemSelectionModel::Rows);
+
+ disasm_ui.tableView->scrollTo(model_index);
+ disasm_ui.tableView->selectionModel()->setCurrentIndex(model_index, QItemSelectionModel::SelectCurrent | QItemSelectionModel::Rows);
+}
+
+void DisassemblerWidget::OnSetBreakpoint()
+{
+ int selected_row = SelectedRow();
+
+ if (selected_row == -1)
+ return;
+
+ u32 address = base_addr + (selected_row * 4);
+ if (breakpoints->IsAddressBreakPoint(address))
+ {
+ breakpoints->Remove(address);
+ model->item(selected_row, 0)->setBackground(QBrush());
+ model->item(selected_row, 1)->setBackground(QBrush());
+ }
+ else
+ {
+ breakpoints->Add(address);
+ model->item(selected_row, 0)->setBackground(QBrush(QColor(0xFF, 0x99, 0x99)));
+ model->item(selected_row, 1)->setBackground(QBrush(QColor(0xFF, 0x99, 0x99)));
+ }
+}
+
+void DisassemblerWidget::OnContinue()
+{
+ emu_thread.SetCpuRunning(true);
+}
+
+void DisassemblerWidget::OnStep()
+{
+ OnStepInto(); // change later
+}
+
+void DisassemblerWidget::OnStepInto()
+{
+ emu_thread.SetCpuRunning(false);
+ emu_thread.ExecStep();
+}
+
+void DisassemblerWidget::OnPause()
+{
+ emu_thread.SetCpuRunning(false);
+}
+
+void DisassemblerWidget::OnToggleStartStop()
+{
+ emu_thread.SetCpuRunning(!emu_thread.IsCpuRunning());
+}
+
+void DisassemblerWidget::OnCPUStepped()
+{
+ ARMword next_instr = Core::g_app_core->GetPC();
+
+ if (breakpoints->IsAddressBreakPoint(next_instr))
+ {
+ emu_thread.SetCpuRunning(false);
+ }
+
+ unsigned int index = (next_instr - base_addr) / 4;
+ QModelIndex model_index = model->index(index, 0);
+ disasm_ui.treeView->scrollTo(model_index);
+ disasm_ui.treeView->selectionModel()->setCurrentIndex(model_index, QItemSelectionModel::SelectCurrent | QItemSelectionModel::Rows);
+
+ disasm_ui.tableView->scrollTo(model_index);
+ disasm_ui.tableView->selectionModel()->setCurrentIndex(model_index, QItemSelectionModel::SelectCurrent | QItemSelectionModel::Rows);
+ disasm_ui.tableView->selectionModel()->select(model_index, QItemSelectionModel::SelectCurrent | QItemSelectionModel::Rows);
+}
+
+int DisassemblerWidget::SelectedRow()
+{
+ QModelIndex index = disasm_ui.treeView->selectionModel()->currentIndex();
+ if (!index.isValid())
+ return -1;
+
+ return model->itemFromIndex(disasm_ui.treeView->selectionModel()->currentIndex())->row();
+}
+/*
+void DisassemblerWidget::paintEvent()
+{
+ QPainter painter(this);
+ painter.drawRect(10, 10, 50, 50);
+}
+*/ \ No newline at end of file
diff --git a/src/citra_qt/debugger/disassembler.hxx b/src/citra_qt/debugger/disassembler.hxx
new file mode 100644
index 00000000..e5b152d2
--- /dev/null
+++ b/src/citra_qt/debugger/disassembler.hxx
@@ -0,0 +1,42 @@
+#include <QDockWidget>
+#include "../ui_disassembler.h"
+
+#include "common/common.h"
+#include "common/break_points.h"
+
+class QAction;
+class QStandardItemModel;
+class EmuThread;
+
+class DisassemblerWidget : public QDockWidget
+{
+ Q_OBJECT
+
+public:
+ DisassemblerWidget(QWidget* parent, EmuThread& emu_thread);
+
+ void Init();
+
+public slots:
+ void OnSetBreakpoint();
+ void OnContinue();
+ void OnStep();
+ void OnStepInto();
+ void OnPause();
+ void OnToggleStartStop();
+
+ void OnCPUStepped();
+
+private:
+ // returns -1 if no row is selected
+ int SelectedRow();
+
+ Ui::DockWidget disasm_ui;
+ QStandardItemModel* model;
+
+ u32 base_addr;
+
+ BreakPoints* breakpoints;
+
+ EmuThread& emu_thread;
+};
diff --git a/src/citra_qt/debugger/disassembler.ui b/src/citra_qt/debugger/disassembler.ui
new file mode 100644
index 00000000..e65b0aa9
--- /dev/null
+++ b/src/citra_qt/debugger/disassembler.ui
@@ -0,0 +1,88 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>DockWidget</class>
+ <widget class="QDockWidget" name="DockWidget">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>430</width>
+ <height>401</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Disassembly</string>
+ </property>
+ <widget class="QWidget" name="dockWidgetContents">
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <widget class="QPushButton" name="button_step">
+ <property name="text">
+ <string>Step</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="button_pause">
+ <property name="text">
+ <string>Pause</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="button_continue">
+ <property name="text">
+ <string>Continue</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="pushButton">
+ <property name="text">
+ <string>Step Into</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="button_breakpoint">
+ <property name="text">
+ <string>Set Breakpoint</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <widget class="QTreeView" name="treeView">
+ <property name="alternatingRowColors">
+ <bool>true</bool>
+ </property>
+ <property name="indentation">
+ <number>20</number>
+ </property>
+ <property name="rootIsDecorated">
+ <bool>false</bool>
+ </property>
+ <attribute name="headerVisible">
+ <bool>false</bool>
+ </attribute>
+ </widget>
+ </item>
+ <item>
+ <widget class="QTableView" name="tableView">
+ <property name="alternatingRowColors">
+ <bool>true</bool>
+ </property>
+ <attribute name="headerVisible">
+ <bool>false</bool>
+ </attribute>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/src/citra_qt/debugger/ramview.cpp b/src/citra_qt/debugger/ramview.cpp
new file mode 100644
index 00000000..3f899b95
--- /dev/null
+++ b/src/citra_qt/debugger/ramview.cpp
@@ -0,0 +1,13 @@
+#include "ramview.hxx"
+
+#include "common/common.h"
+#include "core/mem_map.h"
+GRamView::GRamView(QWidget* parent) : QHexEdit(parent)
+{
+}
+
+void GRamView::OnCPUStepped()
+{
+ // TODO: QHexEdit doesn't show vertical scroll bars for > 10MB data streams...
+ //setData(QByteArray((const char*)Mem_RAM,sizeof(Mem_RAM)/8));
+} \ No newline at end of file
diff --git a/src/citra_qt/debugger/ramview.hxx b/src/citra_qt/debugger/ramview.hxx
new file mode 100644
index 00000000..1db1546a
--- /dev/null
+++ b/src/citra_qt/debugger/ramview.hxx
@@ -0,0 +1,12 @@
+#include "qhexedit.h"
+
+class GRamView : public QHexEdit
+{
+ Q_OBJECT
+
+public:
+ GRamView(QWidget* parent = NULL);
+
+public slots:
+ void OnCPUStepped();
+};
diff --git a/src/citra_qt/debugger/registers.cpp b/src/citra_qt/debugger/registers.cpp
new file mode 100644
index 00000000..96ceed48
--- /dev/null
+++ b/src/citra_qt/debugger/registers.cpp
@@ -0,0 +1,63 @@
+#include "registers.hxx"
+
+#include "core/core.h"
+#include "core/arm/arm_interface.h"
+
+RegistersWidget::RegistersWidget(QWidget* parent) : QDockWidget(parent)
+{
+ cpu_regs_ui.setupUi(this);
+
+ tree = cpu_regs_ui.treeWidget;
+ tree->addTopLevelItem(registers = new QTreeWidgetItem(QStringList("Registers")));
+ tree->addTopLevelItem(CSPR = new QTreeWidgetItem(QStringList("CSPR")));
+
+ registers->setExpanded(true);
+ CSPR->setExpanded(true);
+
+ for (int i = 0; i < 16; ++i)
+ {
+ QTreeWidgetItem* child = new QTreeWidgetItem(QStringList(QString("R[%1]").arg(i, 2, 10, QLatin1Char('0'))));
+ registers->addChild(child);
+ }
+
+ CSPR->addChild(new QTreeWidgetItem(QStringList("M")));
+ CSPR->addChild(new QTreeWidgetItem(QStringList("T")));
+ CSPR->addChild(new QTreeWidgetItem(QStringList("F")));
+ CSPR->addChild(new QTreeWidgetItem(QStringList("I")));
+ CSPR->addChild(new QTreeWidgetItem(QStringList("A")));
+ CSPR->addChild(new QTreeWidgetItem(QStringList("E")));
+ CSPR->addChild(new QTreeWidgetItem(QStringList("IT")));
+ CSPR->addChild(new QTreeWidgetItem(QStringList("GE")));
+ CSPR->addChild(new QTreeWidgetItem(QStringList("DNM")));
+ CSPR->addChild(new QTreeWidgetItem(QStringList("J")));
+ CSPR->addChild(new QTreeWidgetItem(QStringList("Q")));
+ CSPR->addChild(new QTreeWidgetItem(QStringList("V")));
+ CSPR->addChild(new QTreeWidgetItem(QStringList("C")));
+ CSPR->addChild(new QTreeWidgetItem(QStringList("Z")));
+ CSPR->addChild(new QTreeWidgetItem(QStringList("N")));
+}
+
+void RegistersWidget::OnCPUStepped()
+{
+ ARM_Interface* app_core = Core::g_app_core;
+
+ for (int i = 0; i < 16; ++i)
+ registers->child(i)->setText(1, QString("0x%1").arg(app_core->GetReg(i), 8, 16, QLatin1Char('0')));
+
+ CSPR->setText(1, QString("0x%1").arg(app_core->GetCPSR(), 8, 16, QLatin1Char('0')));
+ CSPR->child(0)->setText(1, QString("b%1").arg(app_core->GetCPSR() & 0x1F, 5, 2, QLatin1Char('0'))); // M - Mode
+ CSPR->child(1)->setText(1, QString("%1").arg((app_core->GetCPSR() >> 5) & 0x1)); // T - State
+ CSPR->child(2)->setText(1, QString("%1").arg((app_core->GetCPSR() >> 6) & 0x1)); // F - FIQ disable
+ CSPR->child(3)->setText(1, QString("%1").arg((app_core->GetCPSR() >> 7) & 0x1)); // I - IRQ disable
+ CSPR->child(4)->setText(1, QString("%1").arg((app_core->GetCPSR() >> 8) & 0x1)); // A - Imprecise abort
+ CSPR->child(5)->setText(1, QString("%1").arg((app_core->GetCPSR() >> 9) & 0x1)); // E - Data endianess
+ CSPR->child(6)->setText(1, QString("%1").arg((app_core->GetCPSR() >> 10) & 0x3F)); // IT - If-Then state (DNM)
+ CSPR->child(7)->setText(1, QString("%1").arg((app_core->GetCPSR() >> 16) & 0xF)); // GE - Greater-than-or-Equal
+ CSPR->child(8)->setText(1, QString("%1").arg((app_core->GetCPSR() >> 20) & 0xF)); // DNM - Do not modify
+ CSPR->child(9)->setText(1, QString("%1").arg((app_core->GetCPSR() >> 24) & 0x1)); // J - Java state
+ CSPR->child(10)->setText(1, QString("%1").arg((app_core->GetCPSR() >> 27) & 0x1)); // Q - Sticky overflow
+ CSPR->child(11)->setText(1, QString("%1").arg((app_core->GetCPSR() >> 28) & 0x1)); // V - Overflow
+ CSPR->child(12)->setText(1, QString("%1").arg((app_core->GetCPSR() >> 29) & 0x1)); // C - Carry/Borrow/Extend
+ CSPR->child(13)->setText(1, QString("%1").arg((app_core->GetCPSR() >> 30) & 0x1)); // Z - Zero
+ CSPR->child(14)->setText(1, QString("%1").arg((app_core->GetCPSR() >> 31) & 0x1)); // N - Negative/Less than
+}
diff --git a/src/citra_qt/debugger/registers.hxx b/src/citra_qt/debugger/registers.hxx
new file mode 100644
index 00000000..318d9582
--- /dev/null
+++ b/src/citra_qt/debugger/registers.hxx
@@ -0,0 +1,25 @@
+#include "../ui_registers.h"
+
+#include <QDockWidget>
+#include <QTreeWidgetItem>
+
+class QTreeWidget;
+
+class RegistersWidget : public QDockWidget
+{
+ Q_OBJECT
+
+public:
+ RegistersWidget(QWidget* parent = NULL);
+
+public slots:
+ void OnCPUStepped();
+
+private:
+ Ui::ARMRegisters cpu_regs_ui;
+
+ QTreeWidget* tree;
+
+ QTreeWidgetItem* registers;
+ QTreeWidgetItem* CSPR;
+};
diff --git a/src/citra_qt/debugger/registers.ui b/src/citra_qt/debugger/registers.ui
new file mode 100644
index 00000000..6537c9cd
--- /dev/null
+++ b/src/citra_qt/debugger/registers.ui
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>ARMRegisters</class>
+ <widget class="QDockWidget" name="ARMRegisters">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>400</width>
+ <height>300</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>ARM registers</string>
+ </property>
+ <widget class="QWidget" name="dockWidgetContents">
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QTreeWidget" name="treeWidget">
+ <property name="alternatingRowColors">
+ <bool>true</bool>
+ </property>
+ <column>
+ <property name="text">
+ <string>Register</string>
+ </property>
+ </column>
+ <column>
+ <property name="text">
+ <string>Value</string>
+ </property>
+ </column>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>