mirror of
https://git.suyu.dev/suyu/dynarmic.git
synced 2026-02-19 14:52:57 +00:00
Optionally disassemble x86_64 code using LLVM
This commit is contained in:
@@ -48,13 +48,13 @@ static void EraseInstruction(IR::Block& block, IR::Inst* inst) {
|
||||
block.instructions.erase(block.instructions.iterator_to(*inst));
|
||||
}
|
||||
|
||||
CodePtr EmitX64::Emit(const Arm::LocationDescriptor descriptor, Dynarmic::IR::Block& block) {
|
||||
EmitX64::BlockDescriptor* EmitX64::Emit(const Arm::LocationDescriptor descriptor, Dynarmic::IR::Block& block) {
|
||||
inhibit_emission.clear();
|
||||
reg_alloc.Reset();
|
||||
|
||||
code->INT3();
|
||||
CodePtr code_ptr = code->GetCodePtr();
|
||||
basic_blocks[descriptor] = code_ptr;
|
||||
basic_blocks[descriptor].code_ptr = code_ptr;
|
||||
|
||||
EmitCondPrelude(block.cond, block.cond_failed, block.location);
|
||||
|
||||
@@ -84,7 +84,8 @@ CodePtr EmitX64::Emit(const Arm::LocationDescriptor descriptor, Dynarmic::IR::Bl
|
||||
|
||||
reg_alloc.AssertNoMoreUses();
|
||||
|
||||
return code_ptr;
|
||||
basic_blocks[descriptor].size = code->GetCodePtr() - code_ptr;
|
||||
return &basic_blocks[descriptor];
|
||||
}
|
||||
|
||||
void EmitX64::EmitIdentity(IR::Block& block, IR::Inst* inst) {
|
||||
|
||||
@@ -23,11 +23,15 @@ public:
|
||||
EmitX64(Gen::XEmitter* code, Routines* routines, UserCallbacks cb, Jit* jit_interface)
|
||||
: reg_alloc(code), code(code), routines(routines), cb(cb), jit_interface(jit_interface) {}
|
||||
|
||||
CodePtr Emit(const Arm::LocationDescriptor descriptor, IR::Block& ir);
|
||||
struct BlockDescriptor {
|
||||
CodePtr code_ptr;
|
||||
size_t size;
|
||||
};
|
||||
BlockDescriptor* Emit(const Arm::LocationDescriptor descriptor, IR::Block& ir);
|
||||
|
||||
CodePtr GetBasicBlock(Arm::LocationDescriptor descriptor) {
|
||||
BlockDescriptor* GetBasicBlock(Arm::LocationDescriptor descriptor) {
|
||||
auto iter = basic_blocks.find(descriptor);
|
||||
return iter != basic_blocks.end() ? iter->second : nullptr;
|
||||
return iter != basic_blocks.end() ? &iter->second : nullptr;
|
||||
}
|
||||
|
||||
void ClearCache();
|
||||
@@ -62,7 +66,7 @@ private:
|
||||
Routines* routines;
|
||||
UserCallbacks cb;
|
||||
Jit* jit_interface;
|
||||
std::unordered_map<Arm::LocationDescriptor, CodePtr, Arm::LocationDescriptorHash> basic_blocks;
|
||||
std::unordered_map<Arm::LocationDescriptor, BlockDescriptor, Arm::LocationDescriptorHash> basic_blocks;
|
||||
};
|
||||
|
||||
} // namespace BackendX64
|
||||
|
||||
@@ -6,6 +6,11 @@
|
||||
|
||||
#include <memory>
|
||||
|
||||
#ifdef DYNARMIC_USE_LLVM
|
||||
#include <llvm-c/Disassembler.h>
|
||||
#include <llvm-c/Target.h>
|
||||
#endif
|
||||
|
||||
#include "backend_x64/emit_x64.h"
|
||||
#include "backend_x64/jitstate.h"
|
||||
#include "backend_x64/routines.h"
|
||||
@@ -13,6 +18,7 @@
|
||||
#include "common/bit_util.h"
|
||||
#include "common/common_types.h"
|
||||
#include "common/scope_exit.h"
|
||||
#include "common/string_util.h"
|
||||
#include "frontend/arm_types.h"
|
||||
#include "frontend/translate/translate.h"
|
||||
#include "interface/interface.h"
|
||||
@@ -44,14 +50,52 @@ struct Jit::Impl {
|
||||
|
||||
Arm::LocationDescriptor descriptor{pc, TFlag, EFlag, jit_state.Fpscr};
|
||||
|
||||
CodePtr code_ptr = GetBasicBlock(descriptor);
|
||||
CodePtr code_ptr = GetBasicBlock(descriptor)->code_ptr;
|
||||
return routines.RunCode(&jit_state, code_ptr, cycle_count);
|
||||
}
|
||||
|
||||
std::string Disassemble(Arm::LocationDescriptor descriptor) {
|
||||
auto block = GetBasicBlock(descriptor);
|
||||
std::string result = Common::StringFromFormat("address: %p\nsize: %zu bytes\n", block->code_ptr, block->size);
|
||||
|
||||
#ifdef DYNARMIC_USE_LLVM
|
||||
CodePtr end = block->code_ptr + block->size;
|
||||
size_t remaining = block->size;
|
||||
|
||||
LLVMInitializeX86TargetInfo();
|
||||
LLVMInitializeX86TargetMC();
|
||||
LLVMInitializeX86Disassembler();
|
||||
LLVMDisasmContextRef llvm_ctx = LLVMCreateDisasm("x86_64", nullptr, 0, nullptr, nullptr);
|
||||
LLVMSetDisasmOptions(llvm_ctx, LLVMDisassembler_Option_AsmPrinterVariant);
|
||||
|
||||
for (CodePtr pos = block->code_ptr; pos < end;) {
|
||||
char buffer[80];
|
||||
size_t inst_size = LLVMDisasmInstruction(llvm_ctx, const_cast<u8*>(pos), remaining, (u64)pos, buffer, sizeof(buffer));
|
||||
assert(inst_size);
|
||||
for (CodePtr i = pos; i < pos + inst_size; i++)
|
||||
result.append(Common::StringFromFormat("%02x ", *i));
|
||||
for (size_t i = inst_size; i < 10; i++)
|
||||
result.append(" ");
|
||||
result.append(buffer);
|
||||
result.append("\n");
|
||||
|
||||
pos += inst_size;
|
||||
remaining -= inst_size;
|
||||
}
|
||||
|
||||
LLVMDisasmDispose(llvm_ctx);
|
||||
#else
|
||||
result.append("(recompile with DYNARMIC_USE_LLVM=ON to disassemble the generated x86_64 code)\n");
|
||||
#endif
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private:
|
||||
CodePtr GetBasicBlock(Arm::LocationDescriptor descriptor) {
|
||||
CodePtr code_ptr = emitter.GetBasicBlock(descriptor);
|
||||
if (code_ptr)
|
||||
return code_ptr;
|
||||
EmitX64::BlockDescriptor* GetBasicBlock(Arm::LocationDescriptor descriptor) {
|
||||
auto block = emitter.GetBasicBlock(descriptor);
|
||||
if (block)
|
||||
return block;
|
||||
|
||||
IR::Block ir_block = Arm::Translate(descriptor, callbacks.MemoryRead32);
|
||||
Optimization::GetSetElimination(ir_block);
|
||||
@@ -113,4 +157,8 @@ u32 Jit::Cpsr() const {
|
||||
return impl->jit_state.Cpsr;
|
||||
}
|
||||
|
||||
std::string Jit::Disassemble(Arm::LocationDescriptor descriptor) {
|
||||
return impl->Disassemble(descriptor);
|
||||
}
|
||||
|
||||
} // namespace Dynarmic
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "frontend/arm_types.h"
|
||||
#include "common/common_types.h"
|
||||
|
||||
namespace Dynarmic {
|
||||
@@ -75,6 +76,8 @@ public:
|
||||
return is_executing;
|
||||
}
|
||||
|
||||
std::string Disassemble(Arm::LocationDescriptor descriptor);
|
||||
|
||||
private:
|
||||
bool halt_requested = false;
|
||||
bool is_executing = false;
|
||||
|
||||
Reference in New Issue
Block a user