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/CodeViewWidget.cpp
|
||||
Debugger/CodeWidget.cpp
|
||||
Debugger/JITWidget.cpp
|
||||
Debugger/MemoryViewWidget.cpp
|
||||
Debugger/MemoryWidget.cpp
|
||||
Debugger/NewBreakpointDialog.cpp
|
||||
|
|
|
@ -250,7 +250,7 @@ void CodeViewWidget::OnContextMenu()
|
|||
AddAction(menu, tr("Run &To Here"), this, &CodeViewWidget::OnRunToHere);
|
||||
auto* function_action =
|
||||
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_nop_action = AddAction(menu, tr("Insert &nop"), this, &CodeViewWidget::OnInsertNOP);
|
||||
auto* replace_action =
|
||||
|
|
|
@ -152,6 +152,9 @@ void CodeWidget::ConnectWidgets()
|
|||
connect(m_code_view, &CodeViewWidget::SymbolsChanged, this, &CodeWidget::UpdateSymbols);
|
||||
connect(m_code_view, &CodeViewWidget::BreakpointsChanged, this,
|
||||
[this] { emit BreakpointsChanged(); });
|
||||
|
||||
connect(m_code_view, &CodeViewWidget::RequestPPCComparison, this,
|
||||
&CodeWidget::RequestPPCComparison);
|
||||
}
|
||||
|
||||
void CodeWidget::OnSearchAddress()
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
#include <QDockWidget>
|
||||
#include <QString>
|
||||
|
||||
#include "Common/CommonTypes.h"
|
||||
|
||||
class CodeViewWidget;
|
||||
class QCloseEvent;
|
||||
class QLineEdit;
|
||||
|
@ -35,6 +37,7 @@ public:
|
|||
void Update();
|
||||
signals:
|
||||
void BreakpointsChanged();
|
||||
void RequestPPCComparison(u32 addr);
|
||||
|
||||
private:
|
||||
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\CodeWidget.h" />
|
||||
<QtMoc Include="Debugger\CodeViewWidget.h" />
|
||||
<QtMoc Include="Debugger\JITWidget.h" />
|
||||
<QtMoc Include="Debugger\MemoryWidget.h" />
|
||||
<QtMoc Include="Debugger\MemoryViewWidget.h" />
|
||||
<QtMoc Include="Debugger\NewBreakpointDialog.h" />
|
||||
|
@ -176,6 +177,7 @@
|
|||
<ClCompile Include="$(QtMocOutPrefix)InfoWidget.cpp" />
|
||||
<ClCompile Include="$(QtMocOutPrefix)InterfacePane.cpp" />
|
||||
<ClCompile Include="$(QtMocOutPrefix)IOWindow.cpp" />
|
||||
<ClCompile Include="$(QtMocOutPrefix)JITWidget.cpp" />
|
||||
<ClCompile Include="$(QtMocOutPrefix)GridProxyModel.cpp" />
|
||||
<ClCompile Include="$(QtMocOutPrefix)ListProxyModel.cpp" />
|
||||
<ClCompile Include="$(QtMocOutPrefix)LogConfigWidget.cpp" />
|
||||
|
@ -257,6 +259,7 @@
|
|||
<ClCompile Include="Config\SettingsWindow.cpp" />
|
||||
<ClCompile Include="Debugger\CodeViewWidget.cpp" />
|
||||
<ClCompile Include="Debugger\CodeWidget.cpp" />
|
||||
<ClCompile Include="Debugger\JITWidget.cpp" />
|
||||
<ClCompile Include="Debugger\MemoryWidget.cpp" />
|
||||
<ClCompile Include="Debugger\MemoryViewWidget.cpp" />
|
||||
<ClCompile Include="FIFOPlayerWindow.cpp" />
|
||||
|
|
|
@ -55,6 +55,7 @@
|
|||
#include "DolphinQt2/Config/SettingsWindow.h"
|
||||
#include "DolphinQt2/Debugger/BreakpointWidget.h"
|
||||
#include "DolphinQt2/Debugger/CodeWidget.h"
|
||||
#include "DolphinQt2/Debugger/JITWidget.h"
|
||||
#include "DolphinQt2/Debugger/MemoryWidget.h"
|
||||
#include "DolphinQt2/Debugger/RegisterWidget.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_jit_widget = new JITWidget(this);
|
||||
m_log_widget = new LogWidget(this);
|
||||
m_log_config_widget = new LogConfigWidget(this);
|
||||
m_fifo_window = new FIFOPlayerWindow(this);
|
||||
|
@ -222,6 +224,7 @@ void MainWindow::CreateComponents()
|
|||
|
||||
connect(m_code_widget, &CodeWidget::BreakpointsChanged, m_breakpoint_widget,
|
||||
&BreakpointWidget::Update);
|
||||
connect(m_code_widget, &CodeWidget::RequestPPCComparison, m_jit_widget, &JITWidget::Compare);
|
||||
connect(m_memory_widget, &MemoryWidget::BreakpointsChanged, m_breakpoint_widget,
|
||||
&BreakpointWidget::Update);
|
||||
|
||||
|
@ -430,6 +433,7 @@ void MainWindow::ConnectStack()
|
|||
addDockWidget(Qt::RightDockWidgetArea, m_watch_widget);
|
||||
addDockWidget(Qt::RightDockWidgetArea, m_breakpoint_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_code_widget);
|
||||
|
@ -437,6 +441,7 @@ void MainWindow::ConnectStack()
|
|||
tabifyDockWidget(m_log_widget, m_watch_widget);
|
||||
tabifyDockWidget(m_log_widget, m_breakpoint_widget);
|
||||
tabifyDockWidget(m_log_widget, m_memory_widget);
|
||||
tabifyDockWidget(m_log_widget, m_jit_widget);
|
||||
}
|
||||
|
||||
QString MainWindow::PromptFileName()
|
||||
|
|
|
@ -30,6 +30,7 @@ class FIFOPlayerWindow;
|
|||
class GCTASInputWindow;
|
||||
class GraphicsWindow;
|
||||
class HotkeyScheduler;
|
||||
class JITWidget;
|
||||
class LogConfigWidget;
|
||||
class LogWidget;
|
||||
class MappingWindow;
|
||||
|
@ -184,6 +185,7 @@ private:
|
|||
|
||||
BreakpointWidget* m_breakpoint_widget;
|
||||
CodeWidget* m_code_widget;
|
||||
JITWidget* m_jit_widget;
|
||||
LogWidget* m_log_widget;
|
||||
LogConfigWidget* m_log_config_widget;
|
||||
MemoryWidget* m_memory_widget;
|
||||
|
|
|
@ -33,8 +33,10 @@
|
|||
#include "Core/IOS/IOS.h"
|
||||
#include "Core/IOS/USB/Bluetooth/BTEmu.h"
|
||||
#include "Core/Movie.h"
|
||||
#include "Core/PowerPC/JitInterface.h"
|
||||
#include "Core/PowerPC/PPCAnalyst.h"
|
||||
#include "Core/PowerPC/PPCSymbolDB.h"
|
||||
#include "Core/PowerPC/PowerPC.h"
|
||||
#include "Core/PowerPC/SignatureDB/SignatureDB.h"
|
||||
#include "Core/State.h"
|
||||
#include "Core/TitleDatabase.h"
|
||||
|
@ -57,6 +59,7 @@ MenuBar::MenuBar(QWidget* parent) : QMenuBar(parent)
|
|||
AddOptionsMenu();
|
||||
AddToolsMenu();
|
||||
AddViewMenu();
|
||||
AddJITMenu();
|
||||
AddSymbolsMenu();
|
||||
AddHelpMenu();
|
||||
|
||||
|
@ -102,6 +105,22 @@ void MenuBar::OnEmulationStateChanged(Core::State state)
|
|||
// Tools
|
||||
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
|
||||
m_symbols->setEnabled(running);
|
||||
|
||||
|
@ -124,12 +143,19 @@ void MenuBar::OnDebugModeToggled(bool enabled)
|
|||
m_show_watch->setVisible(enabled);
|
||||
m_show_breakpoints->setVisible(enabled);
|
||||
m_show_memory->setVisible(enabled);
|
||||
m_show_jit->setVisible(enabled);
|
||||
|
||||
if (enabled)
|
||||
{
|
||||
addMenu(m_jit);
|
||||
addMenu(m_symbols);
|
||||
}
|
||||
else
|
||||
{
|
||||
removeAction(m_jit->menuAction());
|
||||
removeAction(m_symbols->menuAction());
|
||||
}
|
||||
}
|
||||
|
||||
void MenuBar::AddDVDBackupMenu(QMenu* file_menu)
|
||||
{
|
||||
|
@ -410,6 +436,12 @@ void MenuBar::AddViewMenu()
|
|||
connect(&Settings::Instance(), &Settings::MemoryVisibilityChanged, m_show_memory,
|
||||
&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();
|
||||
|
||||
AddGameListTypeSection(view_menu);
|
||||
|
@ -654,6 +686,106 @@ void MenuBar::AddMovieMenu()
|
|||
[](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()
|
||||
{
|
||||
m_symbols = addMenu(tr("Symbols"));
|
||||
|
@ -1041,3 +1173,37 @@ void MenuBar::PatchHLEFunctions()
|
|||
{
|
||||
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 AddHelpMenu();
|
||||
void AddMovieMenu();
|
||||
void AddJITMenu();
|
||||
void AddSymbolsMenu();
|
||||
|
||||
void InstallWAD();
|
||||
|
@ -144,6 +145,9 @@ private:
|
|||
void SaveCode();
|
||||
void CreateSignatureFile();
|
||||
void PatchHLEFunctions();
|
||||
void ClearCache();
|
||||
void LogInstructions();
|
||||
void SearchInstruction();
|
||||
|
||||
void OnSelectionChanged(std::shared_ptr<const UICommon::GameFile> game_file);
|
||||
void OnRecordingStatusChanged(bool recording);
|
||||
|
@ -204,7 +208,28 @@ private:
|
|||
QAction* m_show_watch;
|
||||
QAction* m_show_breakpoints;
|
||||
QAction* m_show_memory;
|
||||
QAction* m_show_jit;
|
||||
|
||||
// JIT
|
||||
QMenu* m_jit;
|
||||
|
||||
// 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();
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
if (GetDebugFont() != font)
|
||||
|
|
|
@ -103,6 +103,8 @@ public:
|
|||
bool IsCodeVisible() const;
|
||||
void SetMemoryVisible(bool enabled);
|
||||
bool IsMemoryVisible() const;
|
||||
void SetJITVisible(bool enabled);
|
||||
bool IsJITVisible() const;
|
||||
QFont GetDebugFont() const;
|
||||
void SetDebugFont(QFont font);
|
||||
|
||||
|
@ -136,6 +138,7 @@ signals:
|
|||
void BreakpointsVisibilityChanged(bool visible);
|
||||
void CodeVisibilityChanged(bool visible);
|
||||
void MemoryVisibilityChanged(bool visible);
|
||||
void JITVisibilityChanged(bool visible);
|
||||
void DebugModeToggled(bool enabled);
|
||||
void DebugFontChanged(QFont font);
|
||||
void AutoUpdateTrackChanged(const QString& mode);
|
||||
|
|
Loading…
Reference in New Issue