Merge pull request #6624 from spycrab/qt_dbg_jit

Qt/Debugger: Implement "JIT" widget
This commit is contained in:
Léo Lam 2018-05-12 13:02:47 +02:00 committed by GitHub
commit a712cfe339
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 475 additions and 1 deletions

View File

@ -72,6 +72,7 @@ add_executable(dolphin-emu
Debugger/BreakpointWidget.cpp
Debugger/CodeViewWidget.cpp
Debugger/CodeWidget.cpp
Debugger/JITWidget.cpp
Debugger/MemoryViewWidget.cpp
Debugger/MemoryWidget.cpp
Debugger/NewBreakpointDialog.cpp

View File

@ -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 =

View File

@ -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()

View File

@ -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();

View File

@ -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);
}

View File

@ -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;
};

View File

@ -95,6 +95,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" />
@ -173,6 +174,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" />
@ -254,6 +256,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" />

View File

@ -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"
@ -215,6 +216,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);
@ -235,6 +237,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);
@ -446,6 +449,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);
@ -453,6 +457,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()

View File

@ -30,6 +30,7 @@ class FIFOPlayerWindow;
class GCTASInputWindow;
class GraphicsWindow;
class HotkeyScheduler;
class JITWidget;
class LogConfigWidget;
class LogWidget;
class MappingWindow;
@ -186,6 +187,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;

View File

@ -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() && running);
// 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());
}

View File

@ -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;
};

View File

@ -376,6 +376,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)

View File

@ -113,6 +113,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);
@ -148,6 +150,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);