From 9d6758b4ae4a9b6fa6346f4f8b8c75de5e4c8727 Mon Sep 17 00:00:00 2001 From: Merry Date: Fri, 11 Nov 2022 23:56:52 +0000 Subject: [PATCH] emit_arm64: Fix 1MB block link limit --- .../backend/arm64/a32_address_space.cpp | 30 ++++--------------- src/dynarmic/backend/arm64/emit_arm64.cpp | 4 +-- src/dynarmic/backend/arm64/emit_arm64.h | 9 +----- src/dynarmic/backend/arm64/emit_arm64_a32.cpp | 11 +++++-- 4 files changed, 16 insertions(+), 38 deletions(-) diff --git a/src/dynarmic/backend/arm64/a32_address_space.cpp b/src/dynarmic/backend/arm64/a32_address_space.cpp index 00a0a894..01b78938 100644 --- a/src/dynarmic/backend/arm64/a32_address_space.cpp +++ b/src/dynarmic/backend/arm64/a32_address_space.cpp @@ -329,33 +329,13 @@ static void LinkBlockLinks(const CodePtr entry_point, const CodePtr target_ptr, using namespace oaknut; using namespace oaknut::util; - for (auto [ptr_offset, type] : block_relocations_list) { + for (auto [ptr_offset] : block_relocations_list) { CodeGenerator c{reinterpret_cast(entry_point + ptr_offset)}; - switch (type) { - case BlockLinkType::LinkBlockUnconditionally: - if (target_ptr) { - c.B((void*)target_ptr); - } else { - c.NOP(); - } - break; - case BlockLinkType::LinkBlockIfGreater: - if (target_ptr) { - c.B(GE, (void*)target_ptr); - } else { - c.NOP(); - } - break; - case BlockLinkType::LinkBlockIfWscratch0IsZero: - if (target_ptr) { - c.CBZ(Wscratch0, (void*)target_ptr); - } else { - c.NOP(); - } - break; - default: - ASSERT_FALSE("Invalid block relocation type"); + if (target_ptr) { + c.B((void*)target_ptr); + } else { + c.NOP(); } } } diff --git a/src/dynarmic/backend/arm64/emit_arm64.cpp b/src/dynarmic/backend/arm64/emit_arm64.cpp index bd864dca..104d173d 100644 --- a/src/dynarmic/backend/arm64/emit_arm64.cpp +++ b/src/dynarmic/backend/arm64/emit_arm64.cpp @@ -216,8 +216,8 @@ void EmitRelocation(oaknut::CodeGenerator& code, EmitContext& ctx, LinkTarget li code.NOP(); } -void EmitRelocation(oaknut::CodeGenerator& code, EmitContext& ctx, BlockLinkType link_type, const IR::LocationDescriptor& descriptor) { - ctx.ebi.block_relocations[descriptor].emplace_back(BlockRelocation{code.ptr() - ctx.ebi.entry_point, link_type}); +void EmitBlockLinkRelocation(oaknut::CodeGenerator& code, EmitContext& ctx, const IR::LocationDescriptor& descriptor) { + ctx.ebi.block_relocations[descriptor].emplace_back(BlockRelocation{code.ptr() - ctx.ebi.entry_point}); code.NOP(); } diff --git a/src/dynarmic/backend/arm64/emit_arm64.h b/src/dynarmic/backend/arm64/emit_arm64.h index 9f6767f4..1c5adf3f 100644 --- a/src/dynarmic/backend/arm64/emit_arm64.h +++ b/src/dynarmic/backend/arm64/emit_arm64.h @@ -66,12 +66,6 @@ enum class LinkTarget { GetTicksRemaining, }; -enum class BlockLinkType { - LinkBlockUnconditionally, - LinkBlockIfGreater, - LinkBlockIfWscratch0IsZero, -}; - struct Relocation { std::ptrdiff_t code_offset; LinkTarget target; @@ -79,7 +73,6 @@ struct Relocation { struct BlockRelocation { std::ptrdiff_t code_offset; - BlockLinkType type; }; struct EmittedBlockInfo { @@ -113,7 +106,7 @@ EmittedBlockInfo EmitArm64(oaknut::CodeGenerator& code, IR::Block block, const E template void EmitIR(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst); void EmitRelocation(oaknut::CodeGenerator& code, EmitContext& ctx, LinkTarget link_target); -void EmitRelocation(oaknut::CodeGenerator& code, EmitContext& ctx, BlockLinkType type, const IR::LocationDescriptor& descriptor); +void EmitBlockLinkRelocation(oaknut::CodeGenerator& code, EmitContext& ctx, const IR::LocationDescriptor& descriptor); oaknut::Label EmitA32Cond(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Cond cond); void EmitA32Terminal(oaknut::CodeGenerator& code, EmitContext& ctx); void EmitA32ConditionFailedTerminal(oaknut::CodeGenerator& code, EmitContext& ctx); diff --git a/src/dynarmic/backend/arm64/emit_arm64_a32.cpp b/src/dynarmic/backend/arm64/emit_arm64_a32.cpp index 9d9db953..bd8bda45 100644 --- a/src/dynarmic/backend/arm64/emit_arm64_a32.cpp +++ b/src/dynarmic/backend/arm64/emit_arm64_a32.cpp @@ -61,16 +61,21 @@ void EmitSetUpperLocationDescriptor(oaknut::CodeGenerator& code, EmitContext& ct void EmitA32Terminal(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Term::LinkBlock terminal, IR::LocationDescriptor initial_location, bool is_single_step) { EmitSetUpperLocationDescriptor(code, ctx, terminal.next, initial_location); + oaknut::Label fail; + if (ctx.conf.HasOptimization(OptimizationFlag::BlockLinking) && !is_single_step) { if (ctx.conf.enable_cycle_counting) { code.CMP(Xticks, 0); - EmitRelocation(code, ctx, BlockLinkType::LinkBlockIfGreater, terminal.next); + code.B(LE, fail); + EmitBlockLinkRelocation(code, ctx, terminal.next); } else { code.LDAR(Wscratch0, Xhalt); - EmitRelocation(code, ctx, BlockLinkType::LinkBlockIfWscratch0IsZero, terminal.next); + code.CBNZ(Wscratch0, fail); + EmitBlockLinkRelocation(code, ctx, terminal.next); } } + code.l(fail); code.MOV(Wscratch0, A32::LocationDescriptor{terminal.next}.PC()); code.STR(Wscratch0, Xstate, offsetof(A32JitState, regs) + sizeof(u32) * 15); EmitRelocation(code, ctx, LinkTarget::ReturnToDispatcher); @@ -80,7 +85,7 @@ void EmitA32Terminal(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Term::Li EmitSetUpperLocationDescriptor(code, ctx, terminal.next, initial_location); if (ctx.conf.HasOptimization(OptimizationFlag::BlockLinking) && !is_single_step) { - EmitRelocation(code, ctx, BlockLinkType::LinkBlockUnconditionally, terminal.next); + EmitBlockLinkRelocation(code, ctx, terminal.next); } code.MOV(Wscratch0, A32::LocationDescriptor{terminal.next}.PC());