Skip to content

Commit

Permalink
JITs: Revamp LogGeneratedX86
Browse files Browse the repository at this point in the history
Debug logging of recompiled code is now a feature of all three JITs.
  • Loading branch information
mitaclaw committed Aug 27, 2024
1 parent feeefdb commit b7a6352
Show file tree
Hide file tree
Showing 8 changed files with 90 additions and 52 deletions.
5 changes: 0 additions & 5 deletions Source/Core/Core/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
33 changes: 31 additions & 2 deletions Source/Core/Core/PowerPC/CachedInterpreter/CachedInterpreter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -289,14 +297,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;
}
}
Expand Down Expand Up @@ -432,3 +442,22 @@ void CachedInterpreter::ClearCache()
RefreshConfig();
JitBase::ClearCache();
}

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());
}
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ class CachedInterpreter : public JitBase, public CachedInterpreterCodeBlock
void FreeRanges();
void ResetFreeMemoryRanges();

void LogGeneratedCode() const;

struct StartProfiledBlockOperands;
template <bool profiled>
struct EndBlockOperands;
Expand Down
58 changes: 21 additions & 37 deletions Source/Core/Core/PowerPC/Jit64/Jit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,12 @@
#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>

// for the PROFILER stuff
#ifdef _WIN32
Expand Down Expand Up @@ -831,6 +832,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;
}
}
Expand Down Expand Up @@ -1196,12 +1201,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;
}

Expand Down Expand Up @@ -1328,39 +1327,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++)
{
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);
}

disassembler x64disasm;
x64disasm.set_syntax_intel();
std::ostringstream stream;

u64 disasmPtr = reinterpret_cast<u64>(normalEntry);
const u8* end = normalEntry + b->codeSize;

while (reinterpret_cast<u8*>(disasmPtr) < end)
stream << "\nPPC Code Buffer:\n";
for (const PPCAnalyst::CodeOp& op :
std::span{m_code_buffer.data(), code_block.m_num_instructions})
{
char sptr[1000] = "";
disasmPtr += x64disasm.disasm64(disasmPtr, disasmPtr, reinterpret_cast<u8*>(disasmPtr), sptr);
DEBUG_LOG_FMT(DYNA_REC, "IR_X86 x86: {}", sptr);
fmt::print(stream, "0x{:08x}\t\t{}\n", op.address,
Common::GekkoDisassembler::Disassemble(op.inst.hex, op.address));
}

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());
}
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());
}
5 changes: 2 additions & 3 deletions Source/Core/Core/PowerPC/Jit64/Jit.h
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,8 @@ class Jit64 : public JitBase, public QuantizedMemoryRoutines
void FreeRanges();
void ResetFreeMemoryRanges();

void LogGeneratedCode() const;

static void ImHere(Jit64& jit);

JitBlockCache blocks{*this};
Expand All @@ -294,6 +296,3 @@ class Jit64 : public JitBase, public QuantizedMemoryRoutines
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);
34 changes: 32 additions & 2 deletions Source/Core/Core/PowerPC/JitArm64/Jit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -1020,6 +1026,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;
}
}
Expand Down Expand Up @@ -1380,10 +1390,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());
}
2 changes: 2 additions & 0 deletions Source/Core/Core/PowerPC/JitArm64/Jit.h
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,8 @@ class JitArm64 : public JitBase, public Arm64Gen::ARM64CodeBlock, public CommonA

void IntializeSpeculativeConstants();

void LogGeneratedCode() const;

// AsmRoutines
void GenerateAsm();
void GenerateCommonAsm();
Expand Down
3 changes: 0 additions & 3 deletions Source/Core/Core/PowerPC/JitCommon/JitCache.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down

0 comments on commit b7a6352

Please sign in to comment.