JITs: Revamp LogGeneratedX86
Debug logging of recompiled code is now a feature of all three JITs.
This commit is contained in:
parent
9afd09598c
commit
a035bd95e4
|
@ -653,11 +653,6 @@ PRIVATE
|
|||
ZLIB::ZLIB
|
||||
)
|
||||
|
||||
if ((DEFINED CMAKE_ANDROID_ARCH_ABI AND CMAKE_ANDROID_ARCH_ABI MATCHES "x86|x86_64") OR
|
||||
(NOT DEFINED CMAKE_ANDROID_ARCH_ABI AND _M_X86_64))
|
||||
target_link_libraries(core PRIVATE bdisasm)
|
||||
endif()
|
||||
|
||||
if (APPLE)
|
||||
target_link_libraries(core
|
||||
PRIVATE
|
||||
|
|
|
@ -3,7 +3,15 @@
|
|||
|
||||
#include "Core/PowerPC/CachedInterpreter/CachedInterpreter.h"
|
||||
|
||||
#include <span>
|
||||
#include <sstream>
|
||||
#include <utility>
|
||||
|
||||
#include <fmt/format.h>
|
||||
#include <fmt/ostream.h>
|
||||
|
||||
#include "Common/CommonTypes.h"
|
||||
#include "Common/GekkoDisassembler.h"
|
||||
#include "Common/Logging/Log.h"
|
||||
#include "Core/ConfigManager.h"
|
||||
#include "Core/Core.h"
|
||||
|
@ -290,14 +298,16 @@ void CachedInterpreter::Jit(u32 em_address, bool clear_cache_and_retry_on_failur
|
|||
b->near_end = GetWritableCodePtr();
|
||||
b->far_begin = b->far_end = nullptr;
|
||||
|
||||
b->codeSize = static_cast<u32>(b->near_end - b->normalEntry);
|
||||
|
||||
// Mark the memory region that this code block uses in the RangeSizeSet.
|
||||
if (b->near_begin != b->near_end)
|
||||
m_free_ranges.erase(b->near_begin, b->near_end);
|
||||
|
||||
m_block_cache.FinalizeBlock(*b, jo.enableBlocklink, code_block, m_code_buffer);
|
||||
|
||||
#ifdef JIT_LOG_GENERATED_CODE
|
||||
LogGeneratedCode();
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -434,3 +444,22 @@ void CachedInterpreter::ClearCache()
|
|||
RefreshConfig();
|
||||
Host_JitCacheCleared();
|
||||
}
|
||||
|
||||
void CachedInterpreter::LogGeneratedCode() const
|
||||
{
|
||||
std::ostringstream stream;
|
||||
|
||||
stream << "\nPPC Code Buffer:\n";
|
||||
for (const PPCAnalyst::CodeOp& op :
|
||||
std::span{m_code_buffer.data(), code_block.m_num_instructions})
|
||||
{
|
||||
fmt::print(stream, "0x{:08x}\t\t{}\n", op.address,
|
||||
Common::GekkoDisassembler::Disassemble(op.inst.hex, op.address));
|
||||
}
|
||||
|
||||
stream << "\nHost Code:\n";
|
||||
Disassemble(*js.curBlock, stream);
|
||||
|
||||
// TODO C++20: std::ostringstream::view()
|
||||
DEBUG_LOG_FMT(DYNA_REC, "{}", std::move(stream).str());
|
||||
}
|
||||
|
|
|
@ -71,6 +71,8 @@ private:
|
|||
void FreeRanges();
|
||||
void ResetFreeMemoryRanges();
|
||||
|
||||
void LogGeneratedCode() const;
|
||||
|
||||
struct StartProfiledBlockOperands;
|
||||
template <bool profiled>
|
||||
struct EndBlockOperands;
|
||||
|
|
|
@ -4,10 +4,10 @@
|
|||
#include "Core/PowerPC/Jit64/Jit.h"
|
||||
|
||||
#include <map>
|
||||
#include <span>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
#include <disasm.h>
|
||||
#include <fmt/format.h>
|
||||
#include <fmt/ostream.h>
|
||||
|
||||
|
@ -833,6 +833,10 @@ void Jit64::Jit(u32 em_address, bool clear_cache_and_retry_on_failure)
|
|||
b->far_end = far_end;
|
||||
|
||||
blocks.FinalizeBlock(*b, jo.enableBlocklink, code_block, m_code_buffer);
|
||||
|
||||
#ifdef JIT_LOG_GENERATED_CODE
|
||||
LogGeneratedCode();
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -1198,12 +1202,6 @@ bool Jit64::DoJit(u32 em_address, JitBlock* b, u32 nextPC)
|
|||
return false;
|
||||
}
|
||||
|
||||
b->codeSize = static_cast<u32>(GetCodePtr() - b->normalEntry);
|
||||
|
||||
#ifdef JIT_LOG_GENERATED_CODE
|
||||
LogGeneratedX86(code_block.m_num_instructions, m_code_buffer, start, b);
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1330,39 +1328,24 @@ bool Jit64::HandleFunctionHooking(u32 address)
|
|||
return true;
|
||||
}
|
||||
|
||||
void LogGeneratedX86(size_t size, const PPCAnalyst::CodeBuffer& code_buffer, const u8* normalEntry,
|
||||
const JitBlock* b)
|
||||
void Jit64::LogGeneratedCode() const
|
||||
{
|
||||
for (size_t i = 0; i < size; i++)
|
||||
std::ostringstream stream;
|
||||
|
||||
stream << "\nPPC Code Buffer:\n";
|
||||
for (const PPCAnalyst::CodeOp& op :
|
||||
std::span{m_code_buffer.data(), code_block.m_num_instructions})
|
||||
{
|
||||
const PPCAnalyst::CodeOp& op = code_buffer[i];
|
||||
const std::string disasm = Common::GekkoDisassembler::Disassemble(op.inst.hex, op.address);
|
||||
DEBUG_LOG_FMT(DYNA_REC, "IR_X86 PPC: {:08x} {}\n", op.address, disasm);
|
||||
fmt::print(stream, "0x{:08x}\t\t{}\n", op.address,
|
||||
Common::GekkoDisassembler::Disassemble(op.inst.hex, op.address));
|
||||
}
|
||||
|
||||
disassembler x64disasm;
|
||||
x64disasm.set_syntax_intel();
|
||||
const JitBlock* const block = js.curBlock;
|
||||
stream << "\nHost Near Code:\n";
|
||||
m_disassembler->Disassemble(block->normalEntry, block->near_end, stream);
|
||||
stream << "\nHost Far Code:\n";
|
||||
m_disassembler->Disassemble(block->far_begin, block->far_end, stream);
|
||||
|
||||
u64 disasmPtr = reinterpret_cast<u64>(normalEntry);
|
||||
const u8* end = normalEntry + b->codeSize;
|
||||
|
||||
while (reinterpret_cast<u8*>(disasmPtr) < end)
|
||||
{
|
||||
char sptr[1000] = "";
|
||||
disasmPtr += x64disasm.disasm64(disasmPtr, disasmPtr, reinterpret_cast<u8*>(disasmPtr), sptr);
|
||||
DEBUG_LOG_FMT(DYNA_REC, "IR_X86 x86: {}", sptr);
|
||||
}
|
||||
|
||||
if (b->codeSize <= 250)
|
||||
{
|
||||
std::ostringstream ss;
|
||||
ss << std::hex;
|
||||
for (u8 i = 0; i <= b->codeSize; i++)
|
||||
{
|
||||
ss.width(2);
|
||||
ss.fill('0');
|
||||
ss << static_cast<u32>(*(normalEntry + i));
|
||||
}
|
||||
DEBUG_LOG_FMT(DYNA_REC, "IR_X86 bin: {}\n\n\n", ss.str());
|
||||
}
|
||||
// TODO C++20: std::ostringstream::view()
|
||||
DEBUG_LOG_FMT(DYNA_REC, "{}", std::move(stream).str());
|
||||
}
|
||||
|
|
|
@ -276,6 +276,8 @@ private:
|
|||
void FreeRanges();
|
||||
void ResetFreeMemoryRanges();
|
||||
|
||||
void LogGeneratedCode() const;
|
||||
|
||||
static void ImHere(Jit64& jit);
|
||||
|
||||
JitBlockCache blocks{*this};
|
||||
|
@ -294,6 +296,3 @@ private:
|
|||
std::map<u32, int> m_been_here;
|
||||
std::unique_ptr<HostDisassembler> m_disassembler;
|
||||
};
|
||||
|
||||
void LogGeneratedX86(size_t size, const PPCAnalyst::CodeBuffer& code_buffer, const u8* normalEntry,
|
||||
const JitBlock* b);
|
||||
|
|
|
@ -5,10 +5,16 @@
|
|||
|
||||
#include <cstdio>
|
||||
#include <optional>
|
||||
#include <span>
|
||||
#include <sstream>
|
||||
|
||||
#include <fmt/format.h>
|
||||
#include <fmt/ostream.h>
|
||||
|
||||
#include "Common/Arm64Emitter.h"
|
||||
#include "Common/CommonTypes.h"
|
||||
#include "Common/EnumUtils.h"
|
||||
#include "Common/GekkoDisassembler.h"
|
||||
#include "Common/HostDisassembler.h"
|
||||
#include "Common/Logging/Log.h"
|
||||
#include "Common/MathUtil.h"
|
||||
|
@ -1021,6 +1027,10 @@ void JitArm64::Jit(u32 em_address, bool clear_cache_and_retry_on_failure)
|
|||
b->far_end = far_end;
|
||||
|
||||
blocks.FinalizeBlock(*b, jo.enableBlocklink, code_block, m_code_buffer);
|
||||
|
||||
#ifdef JIT_LOG_GENERATED_CODE
|
||||
LogGeneratedCode();
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -1381,10 +1391,30 @@ bool JitArm64::DoJit(u32 em_address, JitBlock* b, u32 nextPC)
|
|||
return false;
|
||||
}
|
||||
|
||||
b->codeSize = static_cast<u32>(GetCodePtr() - b->normalEntry);
|
||||
|
||||
FlushIcache();
|
||||
m_far_code.FlushIcache();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void JitArm64::LogGeneratedCode() const
|
||||
{
|
||||
std::ostringstream stream;
|
||||
|
||||
stream << "\nPPC Code Buffer:\n";
|
||||
for (const PPCAnalyst::CodeOp& op :
|
||||
std::span{m_code_buffer.data(), code_block.m_num_instructions})
|
||||
{
|
||||
fmt::print(stream, "0x{:08x}\t\t{}\n", op.address,
|
||||
Common::GekkoDisassembler::Disassemble(op.inst.hex, op.address));
|
||||
}
|
||||
|
||||
const JitBlock* const block = js.curBlock;
|
||||
stream << "\nHost Near Code:\n";
|
||||
m_disassembler->Disassemble(block->normalEntry, block->near_end, stream);
|
||||
stream << "\nHost Far Code:\n";
|
||||
m_disassembler->Disassemble(block->far_begin, block->far_end, stream);
|
||||
|
||||
// TODO C++20: std::ostringstream::view()
|
||||
DEBUG_LOG_FMT(DYNA_REC, "{}", std::move(stream).str());
|
||||
}
|
||||
|
|
|
@ -308,6 +308,8 @@ protected:
|
|||
|
||||
void IntializeSpeculativeConstants();
|
||||
|
||||
void LogGeneratedCode() const;
|
||||
|
||||
// AsmRoutines
|
||||
void GenerateAsm();
|
||||
void GenerateCommonAsm();
|
||||
|
|
|
@ -45,9 +45,6 @@ struct JitBlockData
|
|||
// and valid_block in particular). This is useful because of
|
||||
// of the way the instruction cache works on PowerPC.
|
||||
u32 physicalAddress;
|
||||
// The number of bytes of JIT'ed code contained in this block. Mostly
|
||||
// useful for logging.
|
||||
u32 codeSize;
|
||||
// The number of PPC instructions represented by this block. Mostly
|
||||
// useful for logging.
|
||||
u32 originalSize;
|
||||
|
|
Loading…
Reference in New Issue