Skip to content

Commit

Permalink
DolphinQt: JIT Widget Refresh
Browse files Browse the repository at this point in the history
Fulfilling a certain six-year-old todo, and revamping LogGeneratedX86 as a bonus.
  • Loading branch information
mitaclaw committed May 8, 2024
1 parent 95d9827 commit 49534f4
Show file tree
Hide file tree
Showing 48 changed files with 2,126 additions and 581 deletions.
8 changes: 8 additions & 0 deletions Source/Android/jni/MainAndroid.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,14 @@ void Host_UpdateDisasmDialog()
{
}

void Host_JitCacheCleared()
{
}

void Host_JitProfileDataWiped()
{
}

void Host_UpdateMainFrame()
{
}
Expand Down
28 changes: 28 additions & 0 deletions Source/Core/Common/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@ add_library(common
Hash.cpp
Hash.h
HookableEvent.h
HostDisassembler.cpp
HostDisassembler.h
HttpRequest.cpp
HttpRequest.h
Image.cpp
Expand Down Expand Up @@ -143,6 +145,7 @@ add_library(common
TraversalClient.h
TraversalProto.h
TypeUtils.h
Unreachable.h
UPnP.cpp
UPnP.h
VariantUtil.h
Expand Down Expand Up @@ -178,6 +181,11 @@ PRIVATE
${VTUNE_LIBRARIES}
)

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(common PRIVATE bdisasm)
endif()

if (APPLE)
target_link_libraries(common
PRIVATE
Expand Down Expand Up @@ -328,6 +336,26 @@ if(OPROFILE_FOUND)
target_link_libraries(common PRIVATE OProfile::OProfile)
endif()

if(ENABLE_LLVM)
find_package(LLVM CONFIG)
if(LLVM_FOUND)
message(STATUS "LLVM found, enabling LLVM support in disassembler")
# Minimal documentation about LLVM's CMake functions is available here:
# https://releases.llvm.org/16.0.0/docs/CMake.html#embedding-llvm-in-your-project
# https://groups.google.com/g/llvm-dev/c/YeEVe7HTasQ?pli=1
#
# However, you have to read the source code in any case.
# Look for LLVM-Config.cmake in your (Unix) system:
# $ find /usr -name LLVM-Config\\.cmake 2>/dev/null
llvm_expand_pseudo_components(LLVM_EXPAND_COMPONENTS
AllTargetsInfos AllTargetsDisassemblers AllTargetsCodeGens
)
llvm_config(common USE_SHARED
mcdisassembler target ${LLVM_EXPAND_COMPONENTS}
)
endif()
endif()

if(UNIX)
# Posix networking code needs to be fixed for Windows
add_executable(traversal_server TraversalServer.cpp)
Expand Down
177 changes: 177 additions & 0 deletions Source/Core/Common/HostDisassembler.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
// Copyright 2008 Dolphin Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later

#include "Common/HostDisassembler.h"

#include <cstdint>
#include <span>
#include <sstream>

#include <fmt/format.h>
#include <fmt/ostream.h>

#if defined(HAVE_LLVM)
#include <llvm-c/Disassembler.h>
#include <llvm-c/Target.h>
#elif defined(_M_X86_64)
#include <disasm.h> // Bochs
#endif

#if defined(HAVE_LLVM)
class HostDisassemblerLLVM final : public HostDisassembler
{
public:
explicit HostDisassemblerLLVM(const char* host_disasm, const char* cpu = "",
std::size_t inst_size = 0);
~HostDisassemblerLLVM();

private:
LLVMDisasmContextRef m_llvm_context;
std::size_t m_instruction_size;

void Disassemble(const u8* begin, const u8* end, std::ostream& stream,
std::size_t& instruction_count) override;
};

HostDisassemblerLLVM::HostDisassemblerLLVM(const char* host_disasm, const char* cpu,
std::size_t inst_size)
: m_instruction_size(inst_size)
{
LLVMInitializeAllTargetInfos();
LLVMInitializeAllTargetMCs();
LLVMInitializeAllDisassemblers();

m_llvm_context = LLVMCreateDisasmCPU(host_disasm, cpu, nullptr, 0, nullptr, nullptr);

// Couldn't create llvm context
if (!m_llvm_context)
return;

LLVMSetDisasmOptions(m_llvm_context, LLVMDisassembler_Option_AsmPrinterVariant |
LLVMDisassembler_Option_PrintLatency);
}

HostDisassemblerLLVM::~HostDisassemblerLLVM()
{
if (m_llvm_context)
LLVMDisasmDispose(m_llvm_context);
}

void HostDisassemblerLLVM::Disassemble(const u8* begin, const u8* end, std::ostream& stream,
std::size_t& instruction_count)
{
instruction_count = 0;
if (!m_llvm_context)
return;

while (begin < end)
{
char inst_disasm[256];

const auto inst_size = LLVMDisasmInstruction(
m_llvm_context, const_cast<u8*>(begin), static_cast<u64>(end - begin),
reinterpret_cast<std::uintptr_t>(begin), inst_disasm, sizeof(inst_disasm));
if (inst_size == 0)
{
if (m_instruction_size != 0)
{
// If we are on an architecture that has a fixed instruction
// size, we can continue onward past this bad instruction.
fmt::println(stream, "{}\tInvalid inst: {:02x}", fmt::ptr(begin),
fmt::join(std::span{begin, m_instruction_size}, ""));
begin += m_instruction_size;
}
else
{
// We can't continue if we are on an architecture that has flexible
// instruction sizes. Dump the rest of the block instead.
fmt::println(stream, "{}\tInvalid inst: {:02x}", fmt::ptr(begin),
fmt::join(std::span{begin, end}, ""));
break;
}
}
else
{
fmt::println(stream, "{}{}", fmt::ptr(begin), inst_disasm);
begin += inst_size;
}

++instruction_count;
}
}
#elif defined(_M_X86_64)
class HostDisassemblerBochs final : public HostDisassembler
{
public:
explicit HostDisassemblerBochs();
~HostDisassemblerBochs() = default;

private:
disassembler m_disasm;

void Disassemble(const u8* begin, const u8* end, std::ostream& stream,
std::size_t& instruction_count) override;
};

HostDisassemblerBochs::HostDisassemblerBochs()
{
m_disasm.set_syntax_intel();
}

void HostDisassemblerBochs::Disassemble(const u8* begin, const u8* end, std::ostream& stream,
std::size_t& instruction_count)
{
instruction_count = 0;

while (begin < end)
{
char inst_disasm[256];
const auto inst_size = m_disasm.disasm64(reinterpret_cast<std::uintptr_t>(begin),
reinterpret_cast<std::uintptr_t>(begin),
const_cast<u8*>(begin), inst_disasm);
fmt::println(stream, "{}\t{}", fmt::ptr(begin), inst_disasm);
begin += inst_size;
++instruction_count;
}
}
#endif

std::unique_ptr<HostDisassembler> HostDisassembler::Factory(Platform arch)
{
switch (arch)
{
#if defined(HAVE_LLVM)
case Platform::x86_64:
return std::make_unique<HostDisassemblerLLVM>("x86_64-none-unknown");
case Platform::aarch64:
return std::make_unique<HostDisassemblerLLVM>("aarch64-none-unknown", "cortex-a57", 4);
#elif defined(_M_X86_64)
case Platform::x86_64:
return std::make_unique<HostDisassemblerBochs>();
#else
case Platform{}: // warning C4065: "switch statement contains 'default' but no 'case' labels"
#endif
default:
return std::make_unique<HostDisassembler>();
}
}

void HostDisassembler::Disassemble(const u8* begin, const u8* end, std::ostream& stream,
std::size_t& instruction_count)
{
instruction_count = 0;
return fmt::println(stream, "{}\t{:02x}", fmt::ptr(begin), fmt::join(std::span{begin, end}, ""));
}

void HostDisassembler::Disassemble(const u8* begin, const u8* end, std::ostream& stream)
{
std::size_t instruction_count;
Disassemble(begin, end, stream, instruction_count);
}

std::string HostDisassembler::Disassemble(const u8* begin, const u8* end)
{
std::ostringstream stream;
Disassemble(begin, end, stream);
return std::move(stream).str();
}
30 changes: 30 additions & 0 deletions Source/Core/Common/HostDisassembler.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// Copyright 2008 Dolphin Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later

#pragma once

#include <cstddef>
#include <iosfwd>
#include <memory>
#include <string>

#include "Common/CommonTypes.h"

class HostDisassembler
{
public:
enum class Platform
{
x86_64,
aarch64,
};

virtual ~HostDisassembler() = default;

static std::unique_ptr<HostDisassembler> Factory(Platform arch);

virtual void Disassemble(const u8* begin, const u8* end, std::ostream& stream,
std::size_t& instruction_count);
void Disassemble(const u8* begin, const u8* end, std::ostream& stream);
std::string Disassemble(const u8* begin, const u8* end);
};
21 changes: 21 additions & 0 deletions Source/Core/Common/Unreachable.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// Copyright 2024 Dolphin Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later

#pragma once

#include "Common/CommonFuncs.h"

namespace Common
{
// TODO C++23: Replace with std::unreachable.
[[noreturn]] inline void Unreachable()
{
#ifdef _DEBUG
Crash();
#elif defined(_MSC_VER) && !defined(__clang__)
__assume(false);
#else
__builtin_unreachable();
#endif
}
} // namespace Common
5 changes: 0 additions & 5 deletions Source/Core/Core/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -652,11 +652,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
5 changes: 5 additions & 0 deletions Source/Core/Core/HLE/HLE.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,11 @@ u32 GetHookByFunctionAddress(PPCSymbolDB& ppc_symbol_db, u32 address)
return (symbol && symbol->address == address) ? index : 0;
}

const char* GetHookNameByIndex(u32 index)
{
return os_patches[index].name;
}

HookType GetHookTypeByIndex(u32 index)
{
return os_patches[index].type;
Expand Down
1 change: 1 addition & 0 deletions Source/Core/Core/HLE/HLE.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ void ExecuteFromJIT(u32 current_pc, u32 hook_index, Core::System& system);
u32 GetHookByAddress(u32 address);
// Returns the HLE hook index if the address matches the function start
u32 GetHookByFunctionAddress(PPCSymbolDB& ppc_symbol_db, u32 address);
const char* GetHookNameByIndex(u32 index);
HookType GetHookTypeByIndex(u32 index);
HookFlag GetHookFlagsByIndex(u32 index);

Expand Down
2 changes: 2 additions & 0 deletions Source/Core/Core/Host.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ void Host_PPCSymbolsChanged();
void Host_RefreshDSPDebuggerWindow();
void Host_RequestRenderWindowSize(int width, int height);
void Host_UpdateDisasmDialog();
void Host_JitCacheCleared();
void Host_JitProfileDataWiped();
void Host_UpdateMainFrame();
void Host_UpdateTitle(const std::string& title);
void Host_YieldToUI();
Expand Down

0 comments on commit 49534f4

Please sign in to comment.