Qt/Debugger: Implement "JIT" widget
This commit is contained in:
parent
dabfecfd74
commit
1dfcffcce2
|
@ -72,6 +72,7 @@ add_executable(dolphin-emu-qt2
|
||||||
Debugger/BreakpointWidget.cpp
|
Debugger/BreakpointWidget.cpp
|
||||||
Debugger/CodeViewWidget.cpp
|
Debugger/CodeViewWidget.cpp
|
||||||
Debugger/CodeWidget.cpp
|
Debugger/CodeWidget.cpp
|
||||||
|
Debugger/JITWidget.cpp
|
||||||
Debugger/MemoryViewWidget.cpp
|
Debugger/MemoryViewWidget.cpp
|
||||||
Debugger/MemoryWidget.cpp
|
Debugger/MemoryWidget.cpp
|
||||||
Debugger/NewBreakpointDialog.cpp
|
Debugger/NewBreakpointDialog.cpp
|
||||||
|
|
|
@ -250,7 +250,7 @@ void CodeViewWidget::OnContextMenu()
|
||||||
AddAction(menu, tr("Run &To Here"), this, &CodeViewWidget::OnRunToHere);
|
AddAction(menu, tr("Run &To Here"), this, &CodeViewWidget::OnRunToHere);
|
||||||
auto* function_action =
|
auto* function_action =
|
||||||
AddAction(menu, tr("&Add function"), this, &CodeViewWidget::OnAddFunction);
|
AddAction(menu, tr("&Add function"), this, &CodeViewWidget::OnAddFunction);
|
||||||
auto* ppc_action = AddAction(menu, tr("PPC vs x86"), this, &CodeViewWidget::OnPPCComparison);
|
auto* ppc_action = AddAction(menu, tr("PPC vs Host"), this, &CodeViewWidget::OnPPCComparison);
|
||||||
auto* insert_blr_action = AddAction(menu, tr("&Insert blr"), this, &CodeViewWidget::OnInsertBLR);
|
auto* insert_blr_action = AddAction(menu, tr("&Insert blr"), this, &CodeViewWidget::OnInsertBLR);
|
||||||
auto* insert_nop_action = AddAction(menu, tr("Insert &nop"), this, &CodeViewWidget::OnInsertNOP);
|
auto* insert_nop_action = AddAction(menu, tr("Insert &nop"), this, &CodeViewWidget::OnInsertNOP);
|
||||||
auto* replace_action =
|
auto* replace_action =
|
||||||
|
|
|
@ -152,6 +152,9 @@ void CodeWidget::ConnectWidgets()
|
||||||
connect(m_code_view, &CodeViewWidget::SymbolsChanged, this, &CodeWidget::UpdateSymbols);
|
connect(m_code_view, &CodeViewWidget::SymbolsChanged, this, &CodeWidget::UpdateSymbols);
|
||||||
connect(m_code_view, &CodeViewWidget::BreakpointsChanged, this,
|
connect(m_code_view, &CodeViewWidget::BreakpointsChanged, this,
|
||||||
[this] { emit BreakpointsChanged(); });
|
[this] { emit BreakpointsChanged(); });
|
||||||
|
|
||||||
|
connect(m_code_view, &CodeViewWidget::RequestPPCComparison, this,
|
||||||
|
&CodeWidget::RequestPPCComparison);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CodeWidget::OnSearchAddress()
|
void CodeWidget::OnSearchAddress()
|
||||||
|
|
|
@ -7,6 +7,8 @@
|
||||||
#include <QDockWidget>
|
#include <QDockWidget>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
|
|
||||||
|
#include "Common/CommonTypes.h"
|
||||||
|
|
||||||
class CodeViewWidget;
|
class CodeViewWidget;
|
||||||
class QCloseEvent;
|
class QCloseEvent;
|
||||||
class QLineEdit;
|
class QLineEdit;
|
||||||
|
@ -35,6 +37,7 @@ public:
|
||||||
void Update();
|
void Update();
|
||||||
signals:
|
signals:
|
||||||
void BreakpointsChanged();
|
void BreakpointsChanged();
|
||||||
|
void RequestPPCComparison(u32 addr);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void CreateWidgets();
|
void CreateWidgets();
|
||||||
|
|
|
@ -0,0 +1,205 @@
|
||||||
|
// Copyright 2018 Dolphin Emulator Project
|
||||||
|
// Licensed under GPLv2+
|
||||||
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#include "DolphinQt2/Debugger/JITWidget.h"
|
||||||
|
|
||||||
|
#include <QPushButton>
|
||||||
|
#include <QSplitter>
|
||||||
|
#include <QTableWidget>
|
||||||
|
#include <QTextBrowser>
|
||||||
|
#include <QVBoxLayout>
|
||||||
|
|
||||||
|
#include "Common/GekkoDisassembler.h"
|
||||||
|
#include "Common/StringUtil.h"
|
||||||
|
#include "Core/PowerPC/PPCAnalyst.h"
|
||||||
|
#include "UICommon/Disassembler.h"
|
||||||
|
|
||||||
|
#include "DolphinQt2/Settings.h"
|
||||||
|
|
||||||
|
JITWidget::JITWidget(QWidget* parent) : QDockWidget(parent)
|
||||||
|
{
|
||||||
|
setWindowTitle(tr("JIT Blocks"));
|
||||||
|
setAllowedAreas(Qt::AllDockWidgetAreas);
|
||||||
|
|
||||||
|
auto& settings = Settings::GetQSettings();
|
||||||
|
|
||||||
|
CreateWidgets();
|
||||||
|
|
||||||
|
restoreGeometry(settings.value(QStringLiteral("jitwidget/geometry")).toByteArray());
|
||||||
|
setFloating(settings.value(QStringLiteral("jitwidget/floating")).toBool());
|
||||||
|
|
||||||
|
m_table_splitter->restoreState(
|
||||||
|
settings.value(QStringLiteral("jitwidget/tablesplitter")).toByteArray());
|
||||||
|
m_asm_splitter->restoreState(
|
||||||
|
settings.value(QStringLiteral("jitwidget/asmsplitter")).toByteArray());
|
||||||
|
|
||||||
|
connect(&Settings::Instance(), &Settings::JITVisibilityChanged,
|
||||||
|
[this](bool visible) { setHidden(!visible); });
|
||||||
|
|
||||||
|
connect(&Settings::Instance(), &Settings::DebugModeToggled,
|
||||||
|
[this](bool enabled) { setHidden(!enabled || !Settings::Instance().IsJITVisible()); });
|
||||||
|
|
||||||
|
connect(&Settings::Instance(), &Settings::EmulationStateChanged, this, &JITWidget::Update);
|
||||||
|
|
||||||
|
setHidden(!Settings::Instance().IsJITVisible() || !Settings::Instance().IsDebugModeEnabled());
|
||||||
|
|
||||||
|
ConnectWidgets();
|
||||||
|
|
||||||
|
#if defined(_M_X86)
|
||||||
|
m_disassembler = GetNewDisassembler("x86");
|
||||||
|
#elif defined(_M_ARM_64)
|
||||||
|
m_disassembler = GetNewDisassembler("aarch64");
|
||||||
|
#else
|
||||||
|
m_disassembler = GetNewDisassembler("UNK");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
Update();
|
||||||
|
}
|
||||||
|
|
||||||
|
JITWidget::~JITWidget()
|
||||||
|
{
|
||||||
|
auto& settings = Settings::GetQSettings();
|
||||||
|
|
||||||
|
settings.setValue(QStringLiteral("jitwidget/geometry"), saveGeometry());
|
||||||
|
settings.setValue(QStringLiteral("jitwidget/floating"), isFloating());
|
||||||
|
settings.setValue(QStringLiteral("jitwidget/tablesplitter"), m_table_splitter->saveState());
|
||||||
|
settings.setValue(QStringLiteral("jitwidget/asmsplitter"), m_asm_splitter->saveState());
|
||||||
|
}
|
||||||
|
|
||||||
|
void JITWidget::CreateWidgets()
|
||||||
|
{
|
||||||
|
m_table_widget = new QTableWidget;
|
||||||
|
|
||||||
|
m_table_widget->setColumnCount(7);
|
||||||
|
m_table_widget->setHorizontalHeaderLabels(
|
||||||
|
{tr("Address"), tr("PPC Size"), tr("Host Size"),
|
||||||
|
// i18n: The symbolic name of a code block
|
||||||
|
tr("Symbol"),
|
||||||
|
// i18n: These are the kinds of flags that a CPU uses (e.g. carry),
|
||||||
|
// not the kinds of flags that represent e.g. countries
|
||||||
|
tr("Flags"),
|
||||||
|
// i18n: The number of times a code block has been executed
|
||||||
|
tr("NumExec"),
|
||||||
|
// i18n: Performance cost, not monetary cost
|
||||||
|
tr("Cost")});
|
||||||
|
|
||||||
|
m_ppc_asm_widget = new QTextBrowser;
|
||||||
|
m_host_asm_widget = new QTextBrowser;
|
||||||
|
|
||||||
|
m_table_splitter = new QSplitter(Qt::Vertical);
|
||||||
|
m_asm_splitter = new QSplitter(Qt::Horizontal);
|
||||||
|
|
||||||
|
m_refresh_button = new QPushButton(tr("Refresh"));
|
||||||
|
|
||||||
|
m_table_splitter->addWidget(m_table_widget);
|
||||||
|
m_table_splitter->addWidget(m_asm_splitter);
|
||||||
|
|
||||||
|
m_asm_splitter->addWidget(m_ppc_asm_widget);
|
||||||
|
m_asm_splitter->addWidget(m_host_asm_widget);
|
||||||
|
|
||||||
|
QWidget* widget = new QWidget;
|
||||||
|
auto* layout = new QVBoxLayout;
|
||||||
|
widget->setLayout(layout);
|
||||||
|
|
||||||
|
layout->addWidget(m_table_splitter);
|
||||||
|
layout->addWidget(m_refresh_button);
|
||||||
|
|
||||||
|
setWidget(widget);
|
||||||
|
}
|
||||||
|
|
||||||
|
void JITWidget::ConnectWidgets()
|
||||||
|
{
|
||||||
|
connect(m_refresh_button, &QPushButton::pressed, this, &JITWidget::Update);
|
||||||
|
}
|
||||||
|
|
||||||
|
void JITWidget::Compare(u32 address)
|
||||||
|
{
|
||||||
|
m_address = address;
|
||||||
|
Update();
|
||||||
|
}
|
||||||
|
|
||||||
|
void JITWidget::Update()
|
||||||
|
{
|
||||||
|
if (!m_address)
|
||||||
|
{
|
||||||
|
m_ppc_asm_widget->setHtml(QStringLiteral("<i>%1</i>").arg(tr("(ppc)")));
|
||||||
|
m_host_asm_widget->setHtml(QStringLiteral("<i>%1</i>").arg(tr("(host)")));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Actually do something with the table (Wx doesn't)
|
||||||
|
|
||||||
|
// Get host side code disassembly
|
||||||
|
u32 host_instructions_count = 0;
|
||||||
|
u32 host_code_size = 0;
|
||||||
|
std::string host_instructions_disasm;
|
||||||
|
host_instructions_disasm =
|
||||||
|
DisassembleBlock(m_disassembler.get(), &m_address, &host_instructions_count, &host_code_size);
|
||||||
|
|
||||||
|
m_host_asm_widget->setHtml(
|
||||||
|
QStringLiteral("<pre>%1</pre>").arg(QString::fromStdString(host_instructions_disasm)));
|
||||||
|
|
||||||
|
// == Fill in ppc box
|
||||||
|
u32 ppc_addr = m_address;
|
||||||
|
PPCAnalyst::CodeBuffer code_buffer(32000);
|
||||||
|
PPCAnalyst::BlockStats st;
|
||||||
|
PPCAnalyst::BlockRegStats gpa;
|
||||||
|
PPCAnalyst::BlockRegStats fpa;
|
||||||
|
PPCAnalyst::CodeBlock code_block;
|
||||||
|
PPCAnalyst::PPCAnalyzer analyzer;
|
||||||
|
analyzer.SetOption(PPCAnalyst::PPCAnalyzer::OPTION_CONDITIONAL_CONTINUE);
|
||||||
|
analyzer.SetOption(PPCAnalyst::PPCAnalyzer::OPTION_BRANCH_FOLLOW);
|
||||||
|
|
||||||
|
code_block.m_stats = &st;
|
||||||
|
code_block.m_gpa = &gpa;
|
||||||
|
code_block.m_fpa = &fpa;
|
||||||
|
|
||||||
|
if (analyzer.Analyze(ppc_addr, &code_block, &code_buffer, 32000) != 0xFFFFFFFF)
|
||||||
|
{
|
||||||
|
std::ostringstream ppc_disasm;
|
||||||
|
for (u32 i = 0; i < code_block.m_num_instructions; i++)
|
||||||
|
{
|
||||||
|
const PPCAnalyst::CodeOp& op = code_buffer.codebuffer[i];
|
||||||
|
std::string opcode = GekkoDisassembler::Disassemble(op.inst.hex, op.address);
|
||||||
|
ppc_disasm << std::setfill('0') << std::setw(8) << std::hex << op.address;
|
||||||
|
ppc_disasm << " " << opcode << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add stats to the end of the ppc box since it's generally the shortest.
|
||||||
|
ppc_disasm << std::dec << std::endl;
|
||||||
|
|
||||||
|
// Add some generic analysis
|
||||||
|
if (st.isFirstBlockOfFunction)
|
||||||
|
ppc_disasm << "(first block of function)" << std::endl;
|
||||||
|
if (st.isLastBlockOfFunction)
|
||||||
|
ppc_disasm << "(last block of function)" << std::endl;
|
||||||
|
|
||||||
|
ppc_disasm << st.numCycles << " estimated cycles" << std::endl;
|
||||||
|
|
||||||
|
ppc_disasm << "Num instr: PPC: " << code_block.m_num_instructions
|
||||||
|
<< " Host: " << host_instructions_count << " (blowup: "
|
||||||
|
<< 100 * host_instructions_count / code_block.m_num_instructions - 100 << "%)"
|
||||||
|
<< std::endl;
|
||||||
|
|
||||||
|
ppc_disasm << "Num bytes: PPC: " << code_block.m_num_instructions * 4
|
||||||
|
<< " Host: " << host_code_size
|
||||||
|
<< " (blowup: " << 100 * host_code_size / (4 * code_block.m_num_instructions) - 100
|
||||||
|
<< "%)" << std::endl;
|
||||||
|
|
||||||
|
m_ppc_asm_widget->setHtml(
|
||||||
|
QStringLiteral("<pre>%1</pre>").arg(QString::fromStdString(ppc_disasm.str())));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_host_asm_widget->setHtml(
|
||||||
|
QStringLiteral("<pre>%1</pre>")
|
||||||
|
.arg(QString::fromStdString(StringFromFormat("(non-code address: %08x)", m_address))));
|
||||||
|
m_ppc_asm_widget->setHtml(QStringLiteral("<i>---</i>"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void JITWidget::closeEvent(QCloseEvent*)
|
||||||
|
{
|
||||||
|
Settings::Instance().SetJITVisible(false);
|
||||||
|
}
|
|
@ -0,0 +1,44 @@
|
||||||
|
// Copyright 2018 Dolphin Emulator Project
|
||||||
|
// Licensed under GPLv2+
|
||||||
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QDockWidget>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include "Common/CommonTypes.h"
|
||||||
|
|
||||||
|
class QCloseEvent;
|
||||||
|
class QSplitter;
|
||||||
|
class QTextBrowser;
|
||||||
|
class QTableWidget;
|
||||||
|
class QPushButton;
|
||||||
|
class HostDisassembler;
|
||||||
|
|
||||||
|
class JITWidget : public QDockWidget
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit JITWidget(QWidget* parent = nullptr);
|
||||||
|
~JITWidget();
|
||||||
|
|
||||||
|
void Compare(u32 address);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void Update();
|
||||||
|
void CreateWidgets();
|
||||||
|
void ConnectWidgets();
|
||||||
|
|
||||||
|
void closeEvent(QCloseEvent*) override;
|
||||||
|
|
||||||
|
QTableWidget* m_table_widget;
|
||||||
|
QTextBrowser* m_ppc_asm_widget;
|
||||||
|
QTextBrowser* m_host_asm_widget;
|
||||||
|
QSplitter* m_table_splitter;
|
||||||
|
QSplitter* m_asm_splitter;
|
||||||
|
QPushButton* m_refresh_button;
|
||||||
|
|
||||||
|
std::unique_ptr<HostDisassembler> m_disassembler;
|
||||||
|
u32 m_address = 0;
|
||||||
|
};
|
|
@ -98,6 +98,7 @@
|
||||||
<QtMoc Include="Debugger\BreakpointWidget.h" />
|
<QtMoc Include="Debugger\BreakpointWidget.h" />
|
||||||
<QtMoc Include="Debugger\CodeWidget.h" />
|
<QtMoc Include="Debugger\CodeWidget.h" />
|
||||||
<QtMoc Include="Debugger\CodeViewWidget.h" />
|
<QtMoc Include="Debugger\CodeViewWidget.h" />
|
||||||
|
<QtMoc Include="Debugger\JITWidget.h" />
|
||||||
<QtMoc Include="Debugger\MemoryWidget.h" />
|
<QtMoc Include="Debugger\MemoryWidget.h" />
|
||||||
<QtMoc Include="Debugger\MemoryViewWidget.h" />
|
<QtMoc Include="Debugger\MemoryViewWidget.h" />
|
||||||
<QtMoc Include="Debugger\NewBreakpointDialog.h" />
|
<QtMoc Include="Debugger\NewBreakpointDialog.h" />
|
||||||
|
@ -176,6 +177,7 @@
|
||||||
<ClCompile Include="$(QtMocOutPrefix)InfoWidget.cpp" />
|
<ClCompile Include="$(QtMocOutPrefix)InfoWidget.cpp" />
|
||||||
<ClCompile Include="$(QtMocOutPrefix)InterfacePane.cpp" />
|
<ClCompile Include="$(QtMocOutPrefix)InterfacePane.cpp" />
|
||||||
<ClCompile Include="$(QtMocOutPrefix)IOWindow.cpp" />
|
<ClCompile Include="$(QtMocOutPrefix)IOWindow.cpp" />
|
||||||
|
<ClCompile Include="$(QtMocOutPrefix)JITWidget.cpp" />
|
||||||
<ClCompile Include="$(QtMocOutPrefix)GridProxyModel.cpp" />
|
<ClCompile Include="$(QtMocOutPrefix)GridProxyModel.cpp" />
|
||||||
<ClCompile Include="$(QtMocOutPrefix)ListProxyModel.cpp" />
|
<ClCompile Include="$(QtMocOutPrefix)ListProxyModel.cpp" />
|
||||||
<ClCompile Include="$(QtMocOutPrefix)LogConfigWidget.cpp" />
|
<ClCompile Include="$(QtMocOutPrefix)LogConfigWidget.cpp" />
|
||||||
|
@ -257,6 +259,7 @@
|
||||||
<ClCompile Include="Config\SettingsWindow.cpp" />
|
<ClCompile Include="Config\SettingsWindow.cpp" />
|
||||||
<ClCompile Include="Debugger\CodeViewWidget.cpp" />
|
<ClCompile Include="Debugger\CodeViewWidget.cpp" />
|
||||||
<ClCompile Include="Debugger\CodeWidget.cpp" />
|
<ClCompile Include="Debugger\CodeWidget.cpp" />
|
||||||
|
<ClCompile Include="Debugger\JITWidget.cpp" />
|
||||||
<ClCompile Include="Debugger\MemoryWidget.cpp" />
|
<ClCompile Include="Debugger\MemoryWidget.cpp" />
|
||||||
<ClCompile Include="Debugger\MemoryViewWidget.cpp" />
|
<ClCompile Include="Debugger\MemoryViewWidget.cpp" />
|
||||||
<ClCompile Include="FIFOPlayerWindow.cpp" />
|
<ClCompile Include="FIFOPlayerWindow.cpp" />
|
||||||
|
|
|
@ -55,6 +55,7 @@
|
||||||
#include "DolphinQt2/Config/SettingsWindow.h"
|
#include "DolphinQt2/Config/SettingsWindow.h"
|
||||||
#include "DolphinQt2/Debugger/BreakpointWidget.h"
|
#include "DolphinQt2/Debugger/BreakpointWidget.h"
|
||||||
#include "DolphinQt2/Debugger/CodeWidget.h"
|
#include "DolphinQt2/Debugger/CodeWidget.h"
|
||||||
|
#include "DolphinQt2/Debugger/JITWidget.h"
|
||||||
#include "DolphinQt2/Debugger/MemoryWidget.h"
|
#include "DolphinQt2/Debugger/MemoryWidget.h"
|
||||||
#include "DolphinQt2/Debugger/RegisterWidget.h"
|
#include "DolphinQt2/Debugger/RegisterWidget.h"
|
||||||
#include "DolphinQt2/Debugger/WatchWidget.h"
|
#include "DolphinQt2/Debugger/WatchWidget.h"
|
||||||
|
@ -202,6 +203,7 @@ void MainWindow::CreateComponents()
|
||||||
|
|
||||||
m_hotkey_window = new MappingWindow(this, MappingWindow::Type::MAPPING_HOTKEYS, 0);
|
m_hotkey_window = new MappingWindow(this, MappingWindow::Type::MAPPING_HOTKEYS, 0);
|
||||||
|
|
||||||
|
m_jit_widget = new JITWidget(this);
|
||||||
m_log_widget = new LogWidget(this);
|
m_log_widget = new LogWidget(this);
|
||||||
m_log_config_widget = new LogConfigWidget(this);
|
m_log_config_widget = new LogConfigWidget(this);
|
||||||
m_fifo_window = new FIFOPlayerWindow(this);
|
m_fifo_window = new FIFOPlayerWindow(this);
|
||||||
|
@ -222,6 +224,7 @@ void MainWindow::CreateComponents()
|
||||||
|
|
||||||
connect(m_code_widget, &CodeWidget::BreakpointsChanged, m_breakpoint_widget,
|
connect(m_code_widget, &CodeWidget::BreakpointsChanged, m_breakpoint_widget,
|
||||||
&BreakpointWidget::Update);
|
&BreakpointWidget::Update);
|
||||||
|
connect(m_code_widget, &CodeWidget::RequestPPCComparison, m_jit_widget, &JITWidget::Compare);
|
||||||
connect(m_memory_widget, &MemoryWidget::BreakpointsChanged, m_breakpoint_widget,
|
connect(m_memory_widget, &MemoryWidget::BreakpointsChanged, m_breakpoint_widget,
|
||||||
&BreakpointWidget::Update);
|
&BreakpointWidget::Update);
|
||||||
|
|
||||||
|
@ -430,6 +433,7 @@ void MainWindow::ConnectStack()
|
||||||
addDockWidget(Qt::RightDockWidgetArea, m_watch_widget);
|
addDockWidget(Qt::RightDockWidgetArea, m_watch_widget);
|
||||||
addDockWidget(Qt::RightDockWidgetArea, m_breakpoint_widget);
|
addDockWidget(Qt::RightDockWidgetArea, m_breakpoint_widget);
|
||||||
addDockWidget(Qt::RightDockWidgetArea, m_memory_widget);
|
addDockWidget(Qt::RightDockWidgetArea, m_memory_widget);
|
||||||
|
addDockWidget(Qt::RightDockWidgetArea, m_jit_widget);
|
||||||
|
|
||||||
tabifyDockWidget(m_log_widget, m_log_config_widget);
|
tabifyDockWidget(m_log_widget, m_log_config_widget);
|
||||||
tabifyDockWidget(m_log_widget, m_code_widget);
|
tabifyDockWidget(m_log_widget, m_code_widget);
|
||||||
|
@ -437,6 +441,7 @@ void MainWindow::ConnectStack()
|
||||||
tabifyDockWidget(m_log_widget, m_watch_widget);
|
tabifyDockWidget(m_log_widget, m_watch_widget);
|
||||||
tabifyDockWidget(m_log_widget, m_breakpoint_widget);
|
tabifyDockWidget(m_log_widget, m_breakpoint_widget);
|
||||||
tabifyDockWidget(m_log_widget, m_memory_widget);
|
tabifyDockWidget(m_log_widget, m_memory_widget);
|
||||||
|
tabifyDockWidget(m_log_widget, m_jit_widget);
|
||||||
}
|
}
|
||||||
|
|
||||||
QString MainWindow::PromptFileName()
|
QString MainWindow::PromptFileName()
|
||||||
|
|
|
@ -30,6 +30,7 @@ class FIFOPlayerWindow;
|
||||||
class GCTASInputWindow;
|
class GCTASInputWindow;
|
||||||
class GraphicsWindow;
|
class GraphicsWindow;
|
||||||
class HotkeyScheduler;
|
class HotkeyScheduler;
|
||||||
|
class JITWidget;
|
||||||
class LogConfigWidget;
|
class LogConfigWidget;
|
||||||
class LogWidget;
|
class LogWidget;
|
||||||
class MappingWindow;
|
class MappingWindow;
|
||||||
|
@ -184,6 +185,7 @@ private:
|
||||||
|
|
||||||
BreakpointWidget* m_breakpoint_widget;
|
BreakpointWidget* m_breakpoint_widget;
|
||||||
CodeWidget* m_code_widget;
|
CodeWidget* m_code_widget;
|
||||||
|
JITWidget* m_jit_widget;
|
||||||
LogWidget* m_log_widget;
|
LogWidget* m_log_widget;
|
||||||
LogConfigWidget* m_log_config_widget;
|
LogConfigWidget* m_log_config_widget;
|
||||||
MemoryWidget* m_memory_widget;
|
MemoryWidget* m_memory_widget;
|
||||||
|
|
|
@ -33,8 +33,10 @@
|
||||||
#include "Core/IOS/IOS.h"
|
#include "Core/IOS/IOS.h"
|
||||||
#include "Core/IOS/USB/Bluetooth/BTEmu.h"
|
#include "Core/IOS/USB/Bluetooth/BTEmu.h"
|
||||||
#include "Core/Movie.h"
|
#include "Core/Movie.h"
|
||||||
|
#include "Core/PowerPC/JitInterface.h"
|
||||||
#include "Core/PowerPC/PPCAnalyst.h"
|
#include "Core/PowerPC/PPCAnalyst.h"
|
||||||
#include "Core/PowerPC/PPCSymbolDB.h"
|
#include "Core/PowerPC/PPCSymbolDB.h"
|
||||||
|
#include "Core/PowerPC/PowerPC.h"
|
||||||
#include "Core/PowerPC/SignatureDB/SignatureDB.h"
|
#include "Core/PowerPC/SignatureDB/SignatureDB.h"
|
||||||
#include "Core/State.h"
|
#include "Core/State.h"
|
||||||
#include "Core/TitleDatabase.h"
|
#include "Core/TitleDatabase.h"
|
||||||
|
@ -57,6 +59,7 @@ MenuBar::MenuBar(QWidget* parent) : QMenuBar(parent)
|
||||||
AddOptionsMenu();
|
AddOptionsMenu();
|
||||||
AddToolsMenu();
|
AddToolsMenu();
|
||||||
AddViewMenu();
|
AddViewMenu();
|
||||||
|
AddJITMenu();
|
||||||
AddSymbolsMenu();
|
AddSymbolsMenu();
|
||||||
AddHelpMenu();
|
AddHelpMenu();
|
||||||
|
|
||||||
|
@ -102,6 +105,22 @@ void MenuBar::OnEmulationStateChanged(Core::State state)
|
||||||
// Tools
|
// Tools
|
||||||
m_show_cheat_manager->setEnabled(Settings::Instance().GetCheatsEnabled());
|
m_show_cheat_manager->setEnabled(Settings::Instance().GetCheatsEnabled());
|
||||||
|
|
||||||
|
// JIT
|
||||||
|
m_jit_interpreter_core->setEnabled(running);
|
||||||
|
m_jit_block_linking->setEnabled(!running);
|
||||||
|
m_jit_disable_cache->setEnabled(!running);
|
||||||
|
m_jit_clear_cache->setEnabled(running);
|
||||||
|
m_jit_log_coverage->setEnabled(!running);
|
||||||
|
m_jit_search_instruction->setEnabled(running);
|
||||||
|
|
||||||
|
for (QAction* action :
|
||||||
|
{m_jit_off, m_jit_loadstore_off, m_jit_loadstore_lbzx_off, m_jit_loadstore_lxz_off,
|
||||||
|
m_jit_loadstore_lwz_off, m_jit_loadstore_floating_off, m_jit_loadstore_paired_off,
|
||||||
|
m_jit_floatingpoint_off, m_jit_integer_off, m_jit_paired_off, m_jit_systemregisters_off})
|
||||||
|
{
|
||||||
|
action->setEnabled(running);
|
||||||
|
}
|
||||||
|
|
||||||
// Symbols
|
// Symbols
|
||||||
m_symbols->setEnabled(running);
|
m_symbols->setEnabled(running);
|
||||||
|
|
||||||
|
@ -124,11 +143,18 @@ void MenuBar::OnDebugModeToggled(bool enabled)
|
||||||
m_show_watch->setVisible(enabled);
|
m_show_watch->setVisible(enabled);
|
||||||
m_show_breakpoints->setVisible(enabled);
|
m_show_breakpoints->setVisible(enabled);
|
||||||
m_show_memory->setVisible(enabled);
|
m_show_memory->setVisible(enabled);
|
||||||
|
m_show_jit->setVisible(enabled);
|
||||||
|
|
||||||
if (enabled)
|
if (enabled)
|
||||||
|
{
|
||||||
|
addMenu(m_jit);
|
||||||
addMenu(m_symbols);
|
addMenu(m_symbols);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
removeAction(m_jit->menuAction());
|
||||||
removeAction(m_symbols->menuAction());
|
removeAction(m_symbols->menuAction());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MenuBar::AddDVDBackupMenu(QMenu* file_menu)
|
void MenuBar::AddDVDBackupMenu(QMenu* file_menu)
|
||||||
|
@ -410,6 +436,12 @@ void MenuBar::AddViewMenu()
|
||||||
connect(&Settings::Instance(), &Settings::MemoryVisibilityChanged, m_show_memory,
|
connect(&Settings::Instance(), &Settings::MemoryVisibilityChanged, m_show_memory,
|
||||||
&QAction::setChecked);
|
&QAction::setChecked);
|
||||||
|
|
||||||
|
m_show_jit = view_menu->addAction(tr("&JIT"));
|
||||||
|
m_show_jit->setCheckable(true);
|
||||||
|
m_show_jit->setChecked(Settings::Instance().IsJITVisible());
|
||||||
|
connect(m_show_jit, &QAction::toggled, &Settings::Instance(), &Settings::SetJITVisible);
|
||||||
|
connect(&Settings::Instance(), &Settings::JITVisibilityChanged, m_show_jit, &QAction::setChecked);
|
||||||
|
|
||||||
view_menu->addSeparator();
|
view_menu->addSeparator();
|
||||||
|
|
||||||
AddGameListTypeSection(view_menu);
|
AddGameListTypeSection(view_menu);
|
||||||
|
@ -654,6 +686,106 @@ void MenuBar::AddMovieMenu()
|
||||||
[](bool value) { SConfig::GetInstance().m_DumpAudio = value; });
|
[](bool value) { SConfig::GetInstance().m_DumpAudio = value; });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MenuBar::AddJITMenu()
|
||||||
|
{
|
||||||
|
m_jit = addMenu(tr("JIT"));
|
||||||
|
|
||||||
|
m_jit_interpreter_core = m_jit->addAction(tr("Interpreter Core"));
|
||||||
|
m_jit_interpreter_core->setCheckable(true);
|
||||||
|
m_jit_interpreter_core->setChecked(SConfig::GetInstance().iCPUCore == PowerPC::CORE_INTERPRETER);
|
||||||
|
|
||||||
|
m_jit->addSeparator();
|
||||||
|
|
||||||
|
m_jit_block_linking = m_jit->addAction(tr("JIT Block Linking Off"));
|
||||||
|
m_jit_block_linking->setCheckable(true);
|
||||||
|
m_jit_block_linking->setChecked(SConfig::GetInstance().bJITNoBlockLinking);
|
||||||
|
connect(m_jit_block_linking, &QAction::toggled,
|
||||||
|
[](bool enabled) { SConfig::GetInstance().bJITNoBlockLinking = enabled; });
|
||||||
|
|
||||||
|
m_jit_disable_cache = m_jit->addAction(tr("Disable JIT Cache"));
|
||||||
|
m_jit_disable_cache->setCheckable(true);
|
||||||
|
m_jit_disable_cache->setChecked(SConfig::GetInstance().bJITNoBlockCache);
|
||||||
|
connect(m_jit_disable_cache, &QAction::toggled,
|
||||||
|
[](bool enabled) { SConfig::GetInstance().bJITNoBlockCache = enabled; });
|
||||||
|
|
||||||
|
m_jit_clear_cache = AddAction(m_jit, tr("Clear Cache"), this, &MenuBar::ClearCache);
|
||||||
|
|
||||||
|
m_jit->addSeparator();
|
||||||
|
|
||||||
|
m_jit_log_coverage =
|
||||||
|
AddAction(m_jit, tr("Log JIT Instruction Coverage"), this, &MenuBar::LogInstructions);
|
||||||
|
m_jit_search_instruction =
|
||||||
|
AddAction(m_jit, tr("Search for an Instruction"), this, &MenuBar::SearchInstruction);
|
||||||
|
|
||||||
|
m_jit->addSeparator();
|
||||||
|
|
||||||
|
m_jit_off = m_jit->addAction(tr("JIT Off (JIT Core)"));
|
||||||
|
m_jit_off->setCheckable(true);
|
||||||
|
m_jit_off->setChecked(SConfig::GetInstance().bJITOff);
|
||||||
|
connect(m_jit_off, &QAction::toggled,
|
||||||
|
[](bool enabled) { SConfig::GetInstance().bJITOff = enabled; });
|
||||||
|
|
||||||
|
m_jit_loadstore_off = m_jit->addAction(tr("JIT LoadStore Off"));
|
||||||
|
m_jit_loadstore_off->setCheckable(true);
|
||||||
|
m_jit_loadstore_off->setChecked(SConfig::GetInstance().bJITLoadStoreOff);
|
||||||
|
connect(m_jit_loadstore_off, &QAction::toggled,
|
||||||
|
[](bool enabled) { SConfig::GetInstance().bJITLoadStoreOff = enabled; });
|
||||||
|
|
||||||
|
m_jit_loadstore_lbzx_off = m_jit->addAction(tr("JIT LoadStore lbzx Off"));
|
||||||
|
m_jit_loadstore_lbzx_off->setCheckable(true);
|
||||||
|
m_jit_loadstore_lbzx_off->setChecked(SConfig::GetInstance().bJITLoadStorelbzxOff);
|
||||||
|
connect(m_jit_loadstore_lbzx_off, &QAction::toggled,
|
||||||
|
[](bool enabled) { SConfig::GetInstance().bJITLoadStorelbzxOff = enabled; });
|
||||||
|
|
||||||
|
m_jit_loadstore_lxz_off = m_jit->addAction(tr("JIT LoadStore lXz Off"));
|
||||||
|
m_jit_loadstore_lxz_off->setCheckable(true);
|
||||||
|
m_jit_loadstore_lxz_off->setChecked(SConfig::GetInstance().bJITLoadStorelXzOff);
|
||||||
|
connect(m_jit_loadstore_lxz_off, &QAction::toggled,
|
||||||
|
[](bool enabled) { SConfig::GetInstance().bJITLoadStorelXzOff = enabled; });
|
||||||
|
|
||||||
|
m_jit_loadstore_lwz_off = m_jit->addAction(tr("JIT LoadStore lwz Off"));
|
||||||
|
m_jit_loadstore_lwz_off->setCheckable(true);
|
||||||
|
m_jit_loadstore_lwz_off->setChecked(SConfig::GetInstance().bJITLoadStorelwzOff);
|
||||||
|
connect(m_jit_loadstore_lwz_off, &QAction::toggled,
|
||||||
|
[](bool enabled) { SConfig::GetInstance().bJITLoadStorelwzOff = enabled; });
|
||||||
|
|
||||||
|
m_jit_loadstore_floating_off = m_jit->addAction(tr("JIT LoadStore Floating Off"));
|
||||||
|
m_jit_loadstore_floating_off->setCheckable(true);
|
||||||
|
m_jit_loadstore_floating_off->setChecked(SConfig::GetInstance().bJITLoadStoreFloatingOff);
|
||||||
|
connect(m_jit_loadstore_floating_off, &QAction::toggled,
|
||||||
|
[](bool enabled) { SConfig::GetInstance().bJITLoadStoreFloatingOff = enabled; });
|
||||||
|
|
||||||
|
m_jit_loadstore_paired_off = m_jit->addAction(tr("JIT LoadStore Paired Off"));
|
||||||
|
m_jit_loadstore_paired_off->setCheckable(true);
|
||||||
|
m_jit_loadstore_paired_off->setChecked(SConfig::GetInstance().bJITLoadStorePairedOff);
|
||||||
|
connect(m_jit_loadstore_paired_off, &QAction::toggled,
|
||||||
|
[](bool enabled) { SConfig::GetInstance().bJITLoadStorePairedOff = enabled; });
|
||||||
|
|
||||||
|
m_jit_floatingpoint_off = m_jit->addAction(tr("JIT FloatingPoint Off"));
|
||||||
|
m_jit_floatingpoint_off->setCheckable(true);
|
||||||
|
m_jit_floatingpoint_off->setChecked(SConfig::GetInstance().bJITFloatingPointOff);
|
||||||
|
connect(m_jit_floatingpoint_off, &QAction::toggled,
|
||||||
|
[](bool enabled) { SConfig::GetInstance().bJITFloatingPointOff = enabled; });
|
||||||
|
|
||||||
|
m_jit_integer_off = m_jit->addAction(tr("JIT Integer Off"));
|
||||||
|
m_jit_integer_off->setCheckable(true);
|
||||||
|
m_jit_integer_off->setChecked(SConfig::GetInstance().bJITIntegerOff);
|
||||||
|
connect(m_jit_integer_off, &QAction::toggled,
|
||||||
|
[](bool enabled) { SConfig::GetInstance().bJITIntegerOff = enabled; });
|
||||||
|
|
||||||
|
m_jit_paired_off = m_jit->addAction(tr("JIT Paired Off"));
|
||||||
|
m_jit_paired_off->setCheckable(true);
|
||||||
|
m_jit_paired_off->setChecked(SConfig::GetInstance().bJITPairedOff);
|
||||||
|
connect(m_jit_paired_off, &QAction::toggled,
|
||||||
|
[](bool enabled) { SConfig::GetInstance().bJITPairedOff = enabled; });
|
||||||
|
|
||||||
|
m_jit_systemregisters_off = m_jit->addAction(tr("JIT SystemRegisters Off"));
|
||||||
|
m_jit_systemregisters_off->setCheckable(true);
|
||||||
|
m_jit_systemregisters_off->setChecked(SConfig::GetInstance().bJITSystemRegistersOff);
|
||||||
|
connect(m_jit_systemregisters_off, &QAction::toggled,
|
||||||
|
[](bool enabled) { SConfig::GetInstance().bJITSystemRegistersOff = enabled; });
|
||||||
|
}
|
||||||
|
|
||||||
void MenuBar::AddSymbolsMenu()
|
void MenuBar::AddSymbolsMenu()
|
||||||
{
|
{
|
||||||
m_symbols = addMenu(tr("Symbols"));
|
m_symbols = addMenu(tr("Symbols"));
|
||||||
|
@ -1041,3 +1173,37 @@ void MenuBar::PatchHLEFunctions()
|
||||||
{
|
{
|
||||||
HLE::PatchFunctions();
|
HLE::PatchFunctions();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MenuBar::ClearCache()
|
||||||
|
{
|
||||||
|
Core::RunAsCPUThread(JitInterface::ClearCache);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MenuBar::LogInstructions()
|
||||||
|
{
|
||||||
|
PPCTables::LogCompiledInstructions();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MenuBar::SearchInstruction()
|
||||||
|
{
|
||||||
|
bool good;
|
||||||
|
QString op = QInputDialog::getText(this, tr("Search instruction"), tr("Instruction:"),
|
||||||
|
QLineEdit::Normal, QStringLiteral(""), &good);
|
||||||
|
|
||||||
|
if (!good)
|
||||||
|
return;
|
||||||
|
|
||||||
|
bool found = false;
|
||||||
|
for (u32 addr = 0x80000000; addr < 0x81800000; addr += 4)
|
||||||
|
{
|
||||||
|
auto ins_name =
|
||||||
|
QString::fromStdString(PPCTables::GetInstructionName(PowerPC::HostRead_U32(addr)));
|
||||||
|
if (op == ins_name)
|
||||||
|
{
|
||||||
|
NOTICE_LOG(POWERPC, "Found %s at %08x", op.toStdString().c_str(), addr);
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!found)
|
||||||
|
NOTICE_LOG(POWERPC, "Opcode %s not found", op.toStdString().c_str());
|
||||||
|
}
|
||||||
|
|
|
@ -123,6 +123,7 @@ private:
|
||||||
void AddToolsMenu();
|
void AddToolsMenu();
|
||||||
void AddHelpMenu();
|
void AddHelpMenu();
|
||||||
void AddMovieMenu();
|
void AddMovieMenu();
|
||||||
|
void AddJITMenu();
|
||||||
void AddSymbolsMenu();
|
void AddSymbolsMenu();
|
||||||
|
|
||||||
void InstallWAD();
|
void InstallWAD();
|
||||||
|
@ -144,6 +145,9 @@ private:
|
||||||
void SaveCode();
|
void SaveCode();
|
||||||
void CreateSignatureFile();
|
void CreateSignatureFile();
|
||||||
void PatchHLEFunctions();
|
void PatchHLEFunctions();
|
||||||
|
void ClearCache();
|
||||||
|
void LogInstructions();
|
||||||
|
void SearchInstruction();
|
||||||
|
|
||||||
void OnSelectionChanged(std::shared_ptr<const UICommon::GameFile> game_file);
|
void OnSelectionChanged(std::shared_ptr<const UICommon::GameFile> game_file);
|
||||||
void OnRecordingStatusChanged(bool recording);
|
void OnRecordingStatusChanged(bool recording);
|
||||||
|
@ -204,7 +208,28 @@ private:
|
||||||
QAction* m_show_watch;
|
QAction* m_show_watch;
|
||||||
QAction* m_show_breakpoints;
|
QAction* m_show_breakpoints;
|
||||||
QAction* m_show_memory;
|
QAction* m_show_memory;
|
||||||
|
QAction* m_show_jit;
|
||||||
|
|
||||||
|
// JIT
|
||||||
|
QMenu* m_jit;
|
||||||
|
|
||||||
// Symbols
|
// Symbols
|
||||||
QMenu* m_symbols;
|
QMenu* m_symbols;
|
||||||
|
QAction* m_jit_interpreter_core;
|
||||||
|
QAction* m_jit_block_linking;
|
||||||
|
QAction* m_jit_disable_cache;
|
||||||
|
QAction* m_jit_clear_cache;
|
||||||
|
QAction* m_jit_log_coverage;
|
||||||
|
QAction* m_jit_search_instruction;
|
||||||
|
QAction* m_jit_off;
|
||||||
|
QAction* m_jit_loadstore_off;
|
||||||
|
QAction* m_jit_loadstore_lbzx_off;
|
||||||
|
QAction* m_jit_loadstore_lxz_off;
|
||||||
|
QAction* m_jit_loadstore_lwz_off;
|
||||||
|
QAction* m_jit_loadstore_floating_off;
|
||||||
|
QAction* m_jit_loadstore_paired_off;
|
||||||
|
QAction* m_jit_floatingpoint_off;
|
||||||
|
QAction* m_jit_integer_off;
|
||||||
|
QAction* m_jit_paired_off;
|
||||||
|
QAction* m_jit_systemregisters_off;
|
||||||
};
|
};
|
||||||
|
|
|
@ -319,6 +319,20 @@ bool Settings::IsMemoryVisible() const
|
||||||
return QSettings().value(QStringLiteral("debugger/showmemory")).toBool();
|
return QSettings().value(QStringLiteral("debugger/showmemory")).toBool();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Settings::SetJITVisible(bool enabled)
|
||||||
|
{
|
||||||
|
if (IsJITVisible() == enabled)
|
||||||
|
return;
|
||||||
|
QSettings().setValue(QStringLiteral("debugger/showjit"), enabled);
|
||||||
|
|
||||||
|
emit JITVisibilityChanged(enabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Settings::IsJITVisible() const
|
||||||
|
{
|
||||||
|
return QSettings().value(QStringLiteral("debugger/showjit")).toBool();
|
||||||
|
}
|
||||||
|
|
||||||
void Settings::SetDebugFont(QFont font)
|
void Settings::SetDebugFont(QFont font)
|
||||||
{
|
{
|
||||||
if (GetDebugFont() != font)
|
if (GetDebugFont() != font)
|
||||||
|
|
|
@ -103,6 +103,8 @@ public:
|
||||||
bool IsCodeVisible() const;
|
bool IsCodeVisible() const;
|
||||||
void SetMemoryVisible(bool enabled);
|
void SetMemoryVisible(bool enabled);
|
||||||
bool IsMemoryVisible() const;
|
bool IsMemoryVisible() const;
|
||||||
|
void SetJITVisible(bool enabled);
|
||||||
|
bool IsJITVisible() const;
|
||||||
QFont GetDebugFont() const;
|
QFont GetDebugFont() const;
|
||||||
void SetDebugFont(QFont font);
|
void SetDebugFont(QFont font);
|
||||||
|
|
||||||
|
@ -136,6 +138,7 @@ signals:
|
||||||
void BreakpointsVisibilityChanged(bool visible);
|
void BreakpointsVisibilityChanged(bool visible);
|
||||||
void CodeVisibilityChanged(bool visible);
|
void CodeVisibilityChanged(bool visible);
|
||||||
void MemoryVisibilityChanged(bool visible);
|
void MemoryVisibilityChanged(bool visible);
|
||||||
|
void JITVisibilityChanged(bool visible);
|
||||||
void DebugModeToggled(bool enabled);
|
void DebugModeToggled(bool enabled);
|
||||||
void DebugFontChanged(QFont font);
|
void DebugFontChanged(QFont font);
|
||||||
void AutoUpdateTrackChanged(const QString& mode);
|
void AutoUpdateTrackChanged(const QString& mode);
|
||||||
|
|
Loading…
Reference in New Issue