From bbc058c76be8a7c1275c4cc7be42eb16100a28b6 Mon Sep 17 00:00:00 2001 From: Merry Date: Sun, 28 Jan 2024 15:17:06 +0000 Subject: [PATCH] backend/arm64: Update for oaknut 2.0.0. Also respect DYNARMIC_ENABLE_NO_EXECUTE_SUPPORT. --- .../backend/arm64/a32_address_space.cpp | 24 +++--- .../backend/arm64/a64_address_space.cpp | 36 ++++----- src/dynarmic/backend/arm64/address_space.cpp | 78 ++++++++++--------- src/dynarmic/backend/arm64/address_space.h | 15 +++- src/dynarmic/backend/arm64/emit_arm64.cpp | 8 +- .../backend/arm64/emit_arm64_memory.cpp | 14 ++-- src/dynarmic/common/spin_lock_arm64.cpp | 6 +- tests/A64/fibonacci.cpp | 2 +- 8 files changed, 99 insertions(+), 84 deletions(-) diff --git a/src/dynarmic/backend/arm64/a32_address_space.cpp b/src/dynarmic/backend/arm64/a32_address_space.cpp index 864c4588..cafc4790 100644 --- a/src/dynarmic/backend/arm64/a32_address_space.cpp +++ b/src/dynarmic/backend/arm64/a32_address_space.cpp @@ -28,7 +28,7 @@ static void* EmitCallTrampoline(oaknut::CodeGenerator& code, T* this_) { oaknut::Label l_addr, l_this; - void* target = code.ptr(); + void* target = code.xptr(); code.LDR(X0, l_this); code.LDR(Xscratch0, l_addr); code.BR(Xscratch0); @@ -52,7 +52,7 @@ static void* EmitWrappedReadCallTrampoline(oaknut::CodeGenerator& code, T* this_ constexpr u64 save_regs = ABI_CALLER_SAVE & ~ToRegList(Xscratch0); - void* target = code.ptr(); + void* target = code.xptr(); ABI_PushRegisters(code, save_regs, 0); code.LDR(X0, l_this); code.MOV(X1, Xscratch0); @@ -83,7 +83,7 @@ static void* EmitExclusiveReadCallTrampoline(oaknut::CodeGenerator& code, const }); }; - void* target = code.ptr(); + void* target = code.xptr(); code.LDR(X0, l_this); code.LDR(Xscratch0, l_addr); code.BR(Xscratch0); @@ -107,7 +107,7 @@ static void* EmitWrappedWriteCallTrampoline(oaknut::CodeGenerator& code, T* this constexpr u64 save_regs = ABI_CALLER_SAVE; - void* target = code.ptr(); + void* target = code.xptr(); ABI_PushRegisters(code, save_regs, 0); code.LDR(X0, l_this); code.MOV(X1, Xscratch0); @@ -141,7 +141,7 @@ static void* EmitExclusiveWriteCallTrampoline(oaknut::CodeGenerator& code, const : 1; }; - void* target = code.ptr(); + void* target = code.xptr(); code.LDR(X0, l_this); code.LDR(Xscratch0, l_addr); code.BR(Xscratch0); @@ -188,7 +188,7 @@ void A32AddressSpace::InvalidateCacheRanges(const boost::icl::interval_set& void A32AddressSpace::EmitPrelude() { using namespace oaknut::util; - mem.unprotect(); + UnprotectCodeMemory(); prelude_info.read_memory_8 = EmitCallTrampoline<&A32::UserCallbacks::MemoryRead8>(code, conf.callbacks); prelude_info.read_memory_16 = EmitCallTrampoline<&A32::UserCallbacks::MemoryRead16>(code, conf.callbacks); @@ -222,7 +222,7 @@ void A32AddressSpace::EmitPrelude() { oaknut::Label return_from_run_code, l_return_to_dispatcher; - prelude_info.run_code = code.ptr(); + prelude_info.run_code = code.xptr(); { ABI_PushRegisters(code, ABI_CALLEE_SAVE | (1 << 30), sizeof(StackLayout)); @@ -261,7 +261,7 @@ void A32AddressSpace::EmitPrelude() { code.BR(X19); } - prelude_info.step_code = code.ptr(); + prelude_info.step_code = code.xptr(); { ABI_PushRegisters(code, ABI_CALLEE_SAVE | (1 << 30), sizeof(StackLayout)); @@ -304,7 +304,7 @@ void A32AddressSpace::EmitPrelude() { code.BR(X19); } - prelude_info.return_to_dispatcher = code.ptr(); + prelude_info.return_to_dispatcher = code.xptr(); { oaknut::Label l_this, l_addr; @@ -333,7 +333,7 @@ void A32AddressSpace::EmitPrelude() { code.dx(mcl::bit_cast(Common::FptrCast(fn))); } - prelude_info.return_from_run_code = code.ptr(); + prelude_info.return_from_run_code = code.xptr(); { code.l(return_from_run_code); @@ -360,10 +360,10 @@ void A32AddressSpace::EmitPrelude() { code.l(l_return_to_dispatcher); code.dx(mcl::bit_cast(prelude_info.return_to_dispatcher)); - prelude_info.end_of_prelude = code.ptr(); + prelude_info.end_of_prelude = code.offset(); mem.invalidate_all(); - mem.protect(); + ProtectCodeMemory(); } EmitConfig A32AddressSpace::GetEmitConfig() { diff --git a/src/dynarmic/backend/arm64/a64_address_space.cpp b/src/dynarmic/backend/arm64/a64_address_space.cpp index 1e5632ab..f2e20c3d 100644 --- a/src/dynarmic/backend/arm64/a64_address_space.cpp +++ b/src/dynarmic/backend/arm64/a64_address_space.cpp @@ -27,7 +27,7 @@ static void* EmitCallTrampoline(oaknut::CodeGenerator& code, T* this_) { oaknut::Label l_addr, l_this; - void* target = code.ptr(); + void* target = code.xptr(); code.LDR(X0, l_this); code.LDR(Xscratch0, l_addr); code.BR(Xscratch0); @@ -51,7 +51,7 @@ static void* EmitWrappedReadCallTrampoline(oaknut::CodeGenerator& code, T* this_ constexpr u64 save_regs = ABI_CALLER_SAVE & ~ToRegList(Xscratch0); - void* target = code.ptr(); + void* target = code.xptr(); ABI_PushRegisters(code, save_regs, 0); code.LDR(X0, l_this); code.MOV(X1, Xscratch0); @@ -82,7 +82,7 @@ static void* EmitExclusiveReadCallTrampoline(oaknut::CodeGenerator& code, const }); }; - void* target = code.ptr(); + void* target = code.xptr(); code.LDR(X0, l_this); code.LDR(Xscratch0, l_addr); code.BR(Xscratch0); @@ -106,7 +106,7 @@ static void* EmitWrappedWriteCallTrampoline(oaknut::CodeGenerator& code, T* this constexpr u64 save_regs = ABI_CALLER_SAVE; - void* target = code.ptr(); + void* target = code.xptr(); ABI_PushRegisters(code, save_regs, 0); code.LDR(X0, l_this); code.MOV(X1, Xscratch0); @@ -140,7 +140,7 @@ static void* EmitExclusiveWriteCallTrampoline(oaknut::CodeGenerator& code, const : 1; }; - void* target = code.ptr(); + void* target = code.xptr(); code.LDR(X0, l_this); code.LDR(Xscratch0, l_addr); code.BR(Xscratch0); @@ -161,7 +161,7 @@ static void* EmitRead128CallTrampoline(oaknut::CodeGenerator& code, A64::UserCal oaknut::Label l_addr, l_this; - void* target = code.ptr(); + void* target = code.xptr(); ABI_PushRegisters(code, (1ull << 29) | (1ull << 30), 0); code.LDR(X0, l_this); code.LDR(Xscratch0, l_addr); @@ -189,7 +189,7 @@ static void* EmitWrappedRead128CallTrampoline(oaknut::CodeGenerator& code, A64:: constexpr u64 save_regs = ABI_CALLER_SAVE & ~ToRegList(Q0); - void* target = code.ptr(); + void* target = code.xptr(); ABI_PushRegisters(code, save_regs, 0); code.LDR(X0, l_this); code.MOV(X1, Xscratch0); @@ -220,7 +220,7 @@ static void* EmitExclusiveRead128CallTrampoline(oaknut::CodeGenerator& code, con }); }; - void* target = code.ptr(); + void* target = code.xptr(); ABI_PushRegisters(code, (1ull << 29) | (1ull << 30), 0); code.LDR(X0, l_this); code.LDR(Xscratch0, l_addr); @@ -246,7 +246,7 @@ static void* EmitWrite128CallTrampoline(oaknut::CodeGenerator& code, A64::UserCa oaknut::Label l_addr, l_this; - void* target = code.ptr(); + void* target = code.xptr(); code.LDR(X0, l_this); code.FMOV(X2, D0); code.FMOV(X3, V0.D()[1]); @@ -271,7 +271,7 @@ static void* EmitWrappedWrite128CallTrampoline(oaknut::CodeGenerator& code, A64: constexpr u64 save_regs = ABI_CALLER_SAVE; - void* target = code.ptr(); + void* target = code.xptr(); ABI_PushRegisters(code, save_regs, 0); code.LDR(X0, l_this); code.MOV(X1, Xscratch0); @@ -305,7 +305,7 @@ static void* EmitExclusiveWrite128CallTrampoline(oaknut::CodeGenerator& code, co : 1; }; - void* target = code.ptr(); + void* target = code.xptr(); code.LDR(X0, l_this); code.FMOV(X2, D0); code.FMOV(X3, V0.D()[1]); @@ -357,7 +357,7 @@ void A64AddressSpace::InvalidateCacheRanges(const boost::icl::interval_set& void A64AddressSpace::EmitPrelude() { using namespace oaknut::util; - mem.unprotect(); + UnprotectCodeMemory(); prelude_info.read_memory_8 = EmitCallTrampoline<&A64::UserCallbacks::MemoryRead8>(code, conf.callbacks); prelude_info.read_memory_16 = EmitCallTrampoline<&A64::UserCallbacks::MemoryRead16>(code, conf.callbacks); @@ -400,7 +400,7 @@ void A64AddressSpace::EmitPrelude() { oaknut::Label return_from_run_code, l_return_to_dispatcher; - prelude_info.run_code = code.ptr(); + prelude_info.run_code = code.xptr(); { ABI_PushRegisters(code, ABI_CALLEE_SAVE | (1 << 30), sizeof(StackLayout)); @@ -438,7 +438,7 @@ void A64AddressSpace::EmitPrelude() { code.BR(X19); } - prelude_info.step_code = code.ptr(); + prelude_info.step_code = code.xptr(); { ABI_PushRegisters(code, ABI_CALLEE_SAVE | (1 << 30), sizeof(StackLayout)); @@ -480,7 +480,7 @@ void A64AddressSpace::EmitPrelude() { code.BR(X19); } - prelude_info.return_to_dispatcher = code.ptr(); + prelude_info.return_to_dispatcher = code.xptr(); { oaknut::Label l_this, l_addr; @@ -509,7 +509,7 @@ void A64AddressSpace::EmitPrelude() { code.dx(mcl::bit_cast(Common::FptrCast(fn))); } - prelude_info.return_from_run_code = code.ptr(); + prelude_info.return_from_run_code = code.xptr(); { code.l(return_from_run_code); @@ -536,10 +536,10 @@ void A64AddressSpace::EmitPrelude() { code.l(l_return_to_dispatcher); code.dx(mcl::bit_cast(prelude_info.return_to_dispatcher)); - prelude_info.end_of_prelude = code.ptr(); + prelude_info.end_of_prelude = code.offset(); mem.invalidate_all(); - mem.protect(); + ProtectCodeMemory(); } EmitConfig A64AddressSpace::GetEmitConfig() { diff --git a/src/dynarmic/backend/arm64/address_space.cpp b/src/dynarmic/backend/arm64/address_space.cpp index fdb4efe1..4ba579f0 100644 --- a/src/dynarmic/backend/arm64/address_space.cpp +++ b/src/dynarmic/backend/arm64/address_space.cpp @@ -18,7 +18,7 @@ namespace Dynarmic::Backend::Arm64 { AddressSpace::AddressSpace(size_t code_cache_size) : code_cache_size(code_cache_size) , mem(code_cache_size) - , code(mem.ptr()) + , code(mem.ptr(), mem.ptr()) , fastmem_manager(exception_handler) { ASSERT_MSG(code_cache_size <= 128 * 1024 * 1024, "code_cache_size > 128 MiB not currently supported"); @@ -66,7 +66,7 @@ CodePtr AddressSpace::GetOrEmit(IR::LocationDescriptor descriptor) { } void AddressSpace::InvalidateBasicBlocks(const tsl::robin_set& descriptors) { - mem.unprotect(); + UnprotectCodeMemory(); for (const auto& descriptor : descriptors) { const auto iter = block_entries.find(descriptor); @@ -81,7 +81,7 @@ void AddressSpace::InvalidateBasicBlocks(const tsl::robin_set() - reinterpret_cast(mem.ptr())); + return code_cache_size - static_cast(code.offset()); } EmittedBlockInfo AddressSpace::Emit(IR::Block block) { @@ -101,7 +101,7 @@ EmittedBlockInfo AddressSpace::Emit(IR::Block block) { ClearCache(); } - mem.unprotect(); + UnprotectCodeMemory(); EmittedBlockInfo block_info = EmitArm64(code, std::move(block), GetEmitConfig(), fastmem_manager); @@ -113,47 +113,20 @@ EmittedBlockInfo AddressSpace::Emit(IR::Block block) { RelinkForDescriptor(block.Location(), block_info.entry_point); mem.invalidate(reinterpret_cast(block_info.entry_point), block_info.size); - mem.protect(); + ProtectCodeMemory(); RegisterNewBasicBlock(block, block_info); return block_info; } -static void LinkBlockLinks(const CodePtr entry_point, const CodePtr target_ptr, const std::vector& block_relocations_list, void* return_to_dispatcher) { - using namespace oaknut; - using namespace oaknut::util; - - for (auto [ptr_offset, type] : block_relocations_list) { - CodeGenerator c{reinterpret_cast(entry_point + ptr_offset)}; - - switch (type) { - case BlockRelocationType::Branch: - if (target_ptr) { - c.B((void*)target_ptr); - } else { - c.NOP(); - } - break; - case BlockRelocationType::MoveToScratch1: - if (target_ptr) { - c.ADRL(Xscratch1, (void*)target_ptr); - } else { - c.ADRL(Xscratch1, return_to_dispatcher); - } - break; - default: - ASSERT_FALSE("Invalid BlockRelocationType"); - } - } -} - void AddressSpace::Link(EmittedBlockInfo& block_info) { using namespace oaknut; using namespace oaknut::util; for (auto [ptr_offset, target] : block_info.relocations) { - CodeGenerator c{reinterpret_cast(block_info.entry_point + ptr_offset)}; + CodeGenerator c{mem.ptr(), mem.ptr()}; + c.set_xptr(reinterpret_cast(block_info.entry_point + ptr_offset)); switch (target) { case LinkTarget::ReturnToDispatcher: @@ -283,7 +256,36 @@ void AddressSpace::Link(EmittedBlockInfo& block_info) { for (auto [target_descriptor, list] : block_info.block_relocations) { block_references[target_descriptor].emplace(block_info.entry_point); - LinkBlockLinks(block_info.entry_point, Get(target_descriptor), list, prelude_info.return_to_dispatcher); + LinkBlockLinks(block_info.entry_point, Get(target_descriptor), list); + } +} + +void AddressSpace::LinkBlockLinks(const CodePtr entry_point, const CodePtr target_ptr, const std::vector& block_relocations_list) { + using namespace oaknut; + using namespace oaknut::util; + + for (auto [ptr_offset, type] : block_relocations_list) { + CodeGenerator c{mem.ptr(), mem.ptr()}; + c.set_xptr(reinterpret_cast(entry_point + ptr_offset)); + + switch (type) { + case BlockRelocationType::Branch: + if (target_ptr) { + c.B((void*)target_ptr); + } else { + c.NOP(); + } + break; + case BlockRelocationType::MoveToScratch1: + if (target_ptr) { + c.ADRL(Xscratch1, (void*)target_ptr); + } else { + c.ADRL(Xscratch1, prelude_info.return_to_dispatcher); + } + break; + default: + ASSERT_FALSE("Invalid BlockRelocationType"); + } } } @@ -293,7 +295,7 @@ void AddressSpace::RelinkForDescriptor(IR::LocationDescriptor target_descriptor, const EmittedBlockInfo& block_info = block_iter->second; if (auto relocation_iter = block_info.block_relocations.find(target_descriptor); relocation_iter != block_info.block_relocations.end()) { - LinkBlockLinks(block_info.entry_point, target_ptr, relocation_iter->second, prelude_info.return_to_dispatcher); + LinkBlockLinks(block_info.entry_point, target_ptr, relocation_iter->second); } mem.invalidate(reinterpret_cast(block_info.entry_point), block_info.size); diff --git a/src/dynarmic/backend/arm64/address_space.h b/src/dynarmic/backend/arm64/address_space.h index 54a0f91f..a5fe7513 100644 --- a/src/dynarmic/backend/arm64/address_space.h +++ b/src/dynarmic/backend/arm64/address_space.h @@ -47,9 +47,22 @@ protected: virtual EmitConfig GetEmitConfig() = 0; virtual void RegisterNewBasicBlock(const IR::Block& block, const EmittedBlockInfo& block_info) = 0; + void ProtectCodeMemory() { +#if defined(DYNARMIC_ENABLE_NO_EXECUTE_SUPPORT) || defined(__APPLE__) || defined(__OpenBSD__) + mem.protect(); +#endif + } + + void UnprotectCodeMemory() { +#if defined(DYNARMIC_ENABLE_NO_EXECUTE_SUPPORT) || defined(__APPLE__) || defined(__OpenBSD__) + mem.unprotect(); +#endif + } + size_t GetRemainingSize(); EmittedBlockInfo Emit(IR::Block ir_block); void Link(EmittedBlockInfo& block); + void LinkBlockLinks(const CodePtr entry_point, const CodePtr target_ptr, const std::vector& block_relocations_list); void RelinkForDescriptor(IR::LocationDescriptor target_descriptor, CodePtr target_ptr); FakeCall FastmemCallback(u64 host_pc); @@ -69,7 +82,7 @@ protected: FastmemManager fastmem_manager; struct PreludeInfo { - u32* end_of_prelude; + std::ptrdiff_t end_of_prelude; using RunCodeFuncType = HaltReason (*)(CodePtr entry_point, void* jit_state, volatile u32* halt_reason); RunCodeFuncType run_code; diff --git a/src/dynarmic/backend/arm64/emit_arm64.cpp b/src/dynarmic/backend/arm64/emit_arm64.cpp index cc55b26a..1ecb5424 100644 --- a/src/dynarmic/backend/arm64/emit_arm64.cpp +++ b/src/dynarmic/backend/arm64/emit_arm64.cpp @@ -202,7 +202,7 @@ EmittedBlockInfo EmitArm64(oaknut::CodeGenerator& code, IR::Block block, const E RegAlloc reg_alloc{code, fpsr_manager, GPR_ORDER, FPR_ORDER}; EmitContext ctx{block, reg_alloc, conf, ebi, fpsr_manager, fastmem_manager, {}}; - ebi.entry_point = code.ptr(); + ebi.entry_point = code.xptr(); if (ctx.block.GetCondition() == IR::Cond::AL) { ASSERT(!ctx.block.HasConditionFailedLocation()); @@ -263,17 +263,17 @@ EmittedBlockInfo EmitArm64(oaknut::CodeGenerator& code, IR::Block block, const E } code.BRK(0); - ebi.size = code.ptr() - ebi.entry_point; + ebi.size = code.xptr() - ebi.entry_point; return ebi; } void EmitRelocation(oaknut::CodeGenerator& code, EmitContext& ctx, LinkTarget link_target) { - ctx.ebi.relocations.emplace_back(Relocation{code.ptr() - ctx.ebi.entry_point, link_target}); + ctx.ebi.relocations.emplace_back(Relocation{code.xptr() - ctx.ebi.entry_point, link_target}); code.NOP(); } void EmitBlockLinkRelocation(oaknut::CodeGenerator& code, EmitContext& ctx, const IR::LocationDescriptor& descriptor, BlockRelocationType type) { - ctx.ebi.block_relocations[descriptor].emplace_back(BlockRelocation{code.ptr() - ctx.ebi.entry_point, type}); + ctx.ebi.block_relocations[descriptor].emplace_back(BlockRelocation{code.xptr() - ctx.ebi.entry_point, type}); switch (type) { case BlockRelocationType::Branch: code.NOP(); diff --git a/src/dynarmic/backend/arm64/emit_arm64_memory.cpp b/src/dynarmic/backend/arm64/emit_arm64_memory.cpp index 8d2e09de..339e2c59 100644 --- a/src/dynarmic/backend/arm64/emit_arm64_memory.cpp +++ b/src/dynarmic/backend/arm64/emit_arm64_memory.cpp @@ -287,12 +287,12 @@ CodePtr EmitMemoryLdr(oaknut::CodeGenerator& code, int value_idx, oaknut::XReg X const auto add_ext = extend32 ? oaknut::AddSubExt::UXTW : oaknut::AddSubExt::LSL; const auto Roffset = extend32 ? oaknut::RReg{Xoffset.toW()} : oaknut::RReg{Xoffset}; - CodePtr fastmem_location = code.ptr(); + CodePtr fastmem_location = code.xptr(); if (ordered) { code.ADD(Xscratch0, Xbase, Roffset, add_ext); - fastmem_location = code.ptr(); + fastmem_location = code.xptr(); switch (bitsize) { case 8: @@ -315,7 +315,7 @@ CodePtr EmitMemoryLdr(oaknut::CodeGenerator& code, int value_idx, oaknut::XReg X ASSERT_FALSE("Invalid bitsize"); } } else { - fastmem_location = code.ptr(); + fastmem_location = code.xptr(); switch (bitsize) { case 8: @@ -352,7 +352,7 @@ CodePtr EmitMemoryStr(oaknut::CodeGenerator& code, int value_idx, oaknut::XReg X if (ordered) { code.ADD(Xscratch0, Xbase, Roffset, add_ext); - fastmem_location = code.ptr(); + fastmem_location = code.xptr(); switch (bitsize) { case 8: @@ -376,7 +376,7 @@ CodePtr EmitMemoryStr(oaknut::CodeGenerator& code, int value_idx, oaknut::XReg X ASSERT_FALSE("Invalid bitsize"); } } else { - fastmem_location = code.ptr(); + fastmem_location = code.xptr(); switch (bitsize) { case 8: @@ -548,7 +548,7 @@ void FastmemEmitReadMemory(oaknut::CodeGenerator& code, EmitContext& ctx, IR::In FastmemPatchInfo{ .marker = marker, .fc = FakeCall{ - .call_pc = mcl::bit_cast(code.ptr()), + .call_pc = mcl::bit_cast(code.xptr()), }, .recompile = ctx.conf.recompile_on_fastmem_failure, }); @@ -598,7 +598,7 @@ void FastmemEmitWriteMemory(oaknut::CodeGenerator& code, EmitContext& ctx, IR::I FastmemPatchInfo{ .marker = marker, .fc = FakeCall{ - .call_pc = mcl::bit_cast(code.ptr()), + .call_pc = mcl::bit_cast(code.xptr()), }, .recompile = ctx.conf.recompile_on_fastmem_failure, }); diff --git a/src/dynarmic/common/spin_lock_arm64.cpp b/src/dynarmic/common/spin_lock_arm64.cpp index 65b11d2d..ccf807e2 100644 --- a/src/dynarmic/common/spin_lock_arm64.cpp +++ b/src/dynarmic/common/spin_lock_arm64.cpp @@ -54,16 +54,16 @@ SpinLockImpl impl; SpinLockImpl::SpinLockImpl() : mem{4096} - , code{mem.ptr()} {} + , code{mem.ptr(), mem.ptr()} {} void SpinLockImpl::Initialize() { mem.unprotect(); - lock = code.ptr(); + lock = code.xptr(); EmitSpinLockLock(code, X0); code.RET(); - unlock = code.ptr(); + unlock = code.xptr(); EmitSpinLockUnlock(code, X0); code.RET(); diff --git a/tests/A64/fibonacci.cpp b/tests/A64/fibonacci.cpp index b5b10ec4..29dcbdcd 100644 --- a/tests/A64/fibonacci.cpp +++ b/tests/A64/fibonacci.cpp @@ -103,7 +103,7 @@ TEST_CASE("A64: fibonacci", "[a64]") { env.cpu = &cpu; std::vector instructions(1024); - oaknut::CodeGenerator code{instructions.data()}; + oaknut::CodeGenerator code{instructions.data(), nullptr}; using namespace oaknut::util;