Merge pull request #11316 from Pokechu22/jit-widget-fixes

Jit widget fixes
This commit is contained in:
Mai 2022-12-02 20:54:48 +00:00 committed by GitHub
commit 6b514e81f9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 101 additions and 60 deletions

View File

@ -146,43 +146,42 @@ void GetProfileResults(Profiler::ProfileStats* prof_stats)
}); });
} }
int GetHostCode(u32* address, const u8** code, u32* code_size) std::variant<GetHostCodeError, GetHostCodeResult> GetHostCode(u32 address)
{ {
if (!g_jit) if (!g_jit)
{ {
*code_size = 0; return GetHostCodeError::NoJitActive;
return 1;
} }
JitBlock* block = g_jit->GetBlockCache()->GetBlockFromStartAddress(*address, MSR.Hex); JitBlock* block = g_jit->GetBlockCache()->GetBlockFromStartAddress(address, MSR.Hex);
if (!block) if (!block)
{ {
for (int i = 0; i < 500; i++) for (int i = 0; i < 500; i++)
{ {
block = g_jit->GetBlockCache()->GetBlockFromStartAddress(*address - 4 * i, MSR.Hex); block = g_jit->GetBlockCache()->GetBlockFromStartAddress(address - 4 * i, MSR.Hex);
if (block) if (block)
break; break;
} }
if (block) if (block)
{ {
if (!(block->effectiveAddress <= *address && if (!(block->effectiveAddress <= address &&
block->originalSize + block->effectiveAddress >= *address)) block->originalSize + block->effectiveAddress >= address))
block = nullptr; block = nullptr;
} }
// Do not merge this "if" with the above - block_num changes inside it. // Do not merge this "if" with the above - block changes inside it.
if (!block) if (!block)
{ {
*code_size = 0; return GetHostCodeError::NoTranslation;
return 2;
} }
} }
*code = block->checkedEntry; GetHostCodeResult result;
*code_size = block->codeSize; result.code = block->checkedEntry;
*address = block->effectiveAddress; result.code_size = block->codeSize;
return 0; result.entry_address = block->effectiveAddress;
return result;
} }
bool HandleFault(uintptr_t access_address, SContext* ctx) bool HandleFault(uintptr_t access_address, SContext* ctx)

View File

@ -4,6 +4,7 @@
#pragma once #pragma once
#include <string> #include <string>
#include <variant>
#include "Common/CommonTypes.h" #include "Common/CommonTypes.h"
#include "Core/MachineContext.h" #include "Core/MachineContext.h"
@ -43,10 +44,22 @@ enum class ProfilingState
Disabled Disabled
}; };
enum class GetHostCodeError
{
NoJitActive,
NoTranslation,
};
struct GetHostCodeResult
{
const u8* code;
u32 code_size;
u32 entry_address;
};
void SetProfilingState(ProfilingState state); void SetProfilingState(ProfilingState state);
void WriteProfileResults(const std::string& filename); void WriteProfileResults(const std::string& filename);
void GetProfileResults(Profiler::ProfileStats* prof_stats); void GetProfileResults(Profiler::ProfileStats* prof_stats);
int GetHostCode(u32* address, const u8** code, u32* code_size); std::variant<GetHostCodeError, GetHostCodeResult> GetHostCode(u32 address);
// Memory Utilities // Memory Utilities
bool HandleFault(uintptr_t access_address, SContext* ctx); bool HandleFault(uintptr_t access_address, SContext* ctx);

View File

@ -291,8 +291,10 @@ void CodeWidget::SetAddress(u32 address, CodeViewWidget::SetAddressUpdate update
{ {
m_code_view->SetAddress(address, update); m_code_view->SetAddress(address, update);
if (update == CodeViewWidget::SetAddressUpdate::WithUpdate) if (update == CodeViewWidget::SetAddressUpdate::WithUpdate ||
update == CodeViewWidget::SetAddressUpdate::WithDetailedUpdate)
{ {
Settings::Instance().SetCodeVisible(true);
raise(); raise();
m_code_view->setFocus(); m_code_view->setFocus();
} }

View File

@ -12,6 +12,7 @@
#include <fmt/format.h> #include <fmt/format.h>
#include "Common/GekkoDisassembler.h" #include "Common/GekkoDisassembler.h"
#include "Core/Core.h"
#include "Core/PowerPC/PPCAnalyst.h" #include "Core/PowerPC/PPCAnalyst.h"
#include "UICommon/Disassembler.h" #include "UICommon/Disassembler.h"
@ -122,6 +123,11 @@ void JITWidget::ConnectWidgets()
void JITWidget::Compare(u32 address) void JITWidget::Compare(u32 address)
{ {
m_address = address; m_address = address;
Settings::Instance().SetJITVisible(true);
raise();
m_host_asm_widget->setFocus();
Update(); Update();
} }
@ -130,7 +136,7 @@ void JITWidget::Update()
if (!isVisible()) if (!isVisible())
return; return;
if (!m_address) if (!m_address || (Core::GetState() != Core::State::Paused))
{ {
m_ppc_asm_widget->setHtml(QStringLiteral("<i>%1</i>").arg(tr("(ppc)"))); m_ppc_asm_widget->setHtml(QStringLiteral("<i>%1</i>").arg(tr("(ppc)")));
m_host_asm_widget->setHtml(QStringLiteral("<i>%1</i>").arg(tr("(host)"))); m_host_asm_widget->setHtml(QStringLiteral("<i>%1</i>").arg(tr("(host)")));
@ -140,14 +146,11 @@ void JITWidget::Update()
// TODO: Actually do something with the table (Wx doesn't) // TODO: Actually do something with the table (Wx doesn't)
// Get host side code disassembly // Get host side code disassembly
u32 host_instructions_count = 0; auto host_instructions_disasm = DisassembleBlock(m_disassembler.get(), m_address);
u32 host_code_size = 0; m_address = host_instructions_disasm.entry_address;
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( m_host_asm_widget->setHtml(
QStringLiteral("<pre>%1</pre>").arg(QString::fromStdString(host_instructions_disasm))); QStringLiteral("<pre>%1</pre>").arg(QString::fromStdString(host_instructions_disasm.text)));
// == Fill in ppc box // == Fill in ppc box
u32 ppc_addr = m_address; u32 ppc_addr = m_address;
@ -170,40 +173,37 @@ void JITWidget::Update()
if (analyzer.Analyze(ppc_addr, &code_block, &code_buffer, code_buffer.size()) != 0xFFFFFFFF) if (analyzer.Analyze(ppc_addr, &code_block, &code_buffer, code_buffer.size()) != 0xFFFFFFFF)
{ {
std::ostringstream ppc_disasm; std::string ppc_disasm_str;
auto ppc_disasm = std::back_inserter(ppc_disasm_str);
for (u32 i = 0; i < code_block.m_num_instructions; i++) for (u32 i = 0; i < code_block.m_num_instructions; i++)
{ {
const PPCAnalyst::CodeOp& op = code_buffer[i]; const PPCAnalyst::CodeOp& op = code_buffer[i];
const std::string opcode = Common::GekkoDisassembler::Disassemble(op.inst.hex, op.address); const std::string opcode = Common::GekkoDisassembler::Disassemble(op.inst.hex, op.address);
ppc_disasm << std::setfill('0') << std::setw(8) << std::hex << op.address; fmt::format_to(ppc_disasm, "{:08x} {}\n", op.address, opcode);
ppc_disasm << " " << opcode << std::endl;
} }
// Add stats to the end of the ppc box since it's generally the shortest. // Add stats to the end of the ppc box since it's generally the shortest.
ppc_disasm << std::dec << std::endl; fmt::format_to(ppc_disasm, "\n{} estimated cycles", st.numCycles);
fmt::format_to(ppc_disasm, "\nNum instr: PPC: {} Host: {}", code_block.m_num_instructions,
ppc_disasm << st.numCycles << " estimated cycles" << std::endl; host_instructions_disasm.instruction_count);
if (code_block.m_num_instructions != 0 && host_instructions_disasm.instruction_count != 0)
ppc_disasm << "Num instr: PPC: " << code_block.m_num_instructions
<< " Host: " << host_instructions_count;
if (code_block.m_num_instructions != 0)
{ {
ppc_disasm << " (blowup: " fmt::format_to(
<< 100 * host_instructions_count / code_block.m_num_instructions - 100 << "%)"; ppc_disasm, " (blowup: {}%)",
100 * host_instructions_disasm.instruction_count / code_block.m_num_instructions - 100);
} }
ppc_disasm << std::endl;
ppc_disasm << "Num bytes: PPC: " << code_block.m_num_instructions * 4 fmt::format_to(ppc_disasm, "\nNum bytes: PPC: {} Host: {}", code_block.m_num_instructions * 4,
<< " Host: " << host_code_size; host_instructions_disasm.code_size);
if (code_block.m_num_instructions != 0) if (code_block.m_num_instructions != 0 && host_instructions_disasm.code_size != 0)
{ {
ppc_disasm << " (blowup: " << 100 * host_code_size / (4 * code_block.m_num_instructions) - 100 fmt::format_to(
<< "%)"; ppc_disasm, " (blowup: {}%)",
100 * host_instructions_disasm.code_size / (4 * code_block.m_num_instructions) - 100);
} }
ppc_disasm << std::endl;
m_ppc_asm_widget->setHtml( m_ppc_asm_widget->setHtml(
QStringLiteral("<pre>%1</pre>").arg(QString::fromStdString(ppc_disasm.str()))); QStringLiteral("<pre>%1</pre>").arg(QString::fromStdString(ppc_disasm_str)));
} }
else else
{ {

View File

@ -16,6 +16,8 @@
#include <disasm.h> // Bochs #include <disasm.h> // Bochs
#endif #endif
#include "Common/Assert.h"
#include "Common/VariantUtil.h"
#include "Core/PowerPC/JitInterface.h" #include "Core/PowerPC/JitInterface.h"
#if defined(HAVE_LLVM) #if defined(HAVE_LLVM)
@ -169,21 +171,39 @@ std::unique_ptr<HostDisassembler> GetNewDisassembler(const std::string& arch)
return std::make_unique<HostDisassembler>(); return std::make_unique<HostDisassembler>();
} }
std::string DisassembleBlock(HostDisassembler* disasm, u32* address, u32* host_instructions_count, DisassembleResult DisassembleBlock(HostDisassembler* disasm, u32 address)
u32* code_size)
{ {
const u8* code; auto res = JitInterface::GetHostCode(address);
int res = JitInterface::GetHostCode(address, &code, code_size);
if (res == 1) return std::visit(overloaded{[&](JitInterface::GetHostCodeError error) {
{ DisassembleResult result;
*host_instructions_count = 0; switch (error)
return "(No JIT active)"; {
} case JitInterface::GetHostCodeError::NoJitActive:
else if (res == 2) result.text = "(No JIT active)";
{ break;
*host_instructions_count = 0; case JitInterface::GetHostCodeError::NoTranslation:
return "(No translation)"; result.text = "(No translation)";
} break;
return disasm->DisassembleHostBlock(code, *code_size, host_instructions_count, (u64)code); default:
ASSERT(false);
break;
}
result.entry_address = address;
result.instruction_count = 0;
result.code_size = 0;
return result;
},
[&](JitInterface::GetHostCodeResult host_result) {
DisassembleResult new_result;
u32 instruction_count = 0;
new_result.text = disasm->DisassembleHostBlock(
host_result.code, host_result.code_size, &instruction_count,
(u64)host_result.code);
new_result.entry_address = host_result.entry_address;
new_result.code_size = host_result.code_size;
new_result.instruction_count = instruction_count;
return new_result;
}},
res);
} }

View File

@ -18,6 +18,13 @@ public:
} }
}; };
struct DisassembleResult
{
std::string text;
u32 entry_address;
u32 instruction_count;
u32 code_size;
};
std::unique_ptr<HostDisassembler> GetNewDisassembler(const std::string& arch); std::unique_ptr<HostDisassembler> GetNewDisassembler(const std::string& arch);
std::string DisassembleBlock(HostDisassembler* disasm, u32* address, u32* host_instructions_count, DisassembleResult DisassembleBlock(HostDisassembler* disasm, u32 address);
u32* code_size);