diff --git a/src/dynarmic/backend/arm64/a32_address_space.cpp b/src/dynarmic/backend/arm64/a32_address_space.cpp index c0cf9d5b..3bd5b54a 100644 --- a/src/dynarmic/backend/arm64/a32_address_space.cpp +++ b/src/dynarmic/backend/arm64/a32_address_space.cpp @@ -111,6 +111,7 @@ void A32AddressSpace::EmitPrelude() { prelude_info.write_memory_16 = EmitCallTrampoline<&A32::UserCallbacks::MemoryWrite16>(code, conf.callbacks); prelude_info.write_memory_32 = EmitCallTrampoline<&A32::UserCallbacks::MemoryWrite32>(code, conf.callbacks); prelude_info.write_memory_64 = EmitCallTrampoline<&A32::UserCallbacks::MemoryWrite64>(code, conf.callbacks); + prelude_info.isb_raised = EmitCallTrampoline<&A32::UserCallbacks::InstructionSynchronizationBarrierRaised>(code, conf.callbacks); prelude_info.end_of_prelude = code.ptr(); @@ -129,6 +130,7 @@ EmittedBlockInfo A32AddressSpace::Emit(IR::Block block) { mem.unprotect(); EmittedBlockInfo block_info = EmitArm64(code, std::move(block), { + .hook_isb = conf.hook_isb, .enable_cycle_counting = conf.enable_cycle_counting, .always_little_endian = conf.always_little_endian, }); @@ -176,6 +178,9 @@ void A32AddressSpace::Link(EmittedBlockInfo& block_info) { case LinkTarget::WriteMemory64: c.BL(prelude_info.write_memory_64); break; + case LinkTarget::InstructionSynchronizationBarrierRaised: + c.BL(prelude_info.isb_raised); + break; default: ASSERT_FALSE("Invalid relocation target"); } diff --git a/src/dynarmic/backend/arm64/a32_address_space.h b/src/dynarmic/backend/arm64/a32_address_space.h index d14ddfc7..4243290f 100644 --- a/src/dynarmic/backend/arm64/a32_address_space.h +++ b/src/dynarmic/backend/arm64/a32_address_space.h @@ -64,6 +64,7 @@ private: void* write_memory_16; void* write_memory_32; void* write_memory_64; + void* isb_raised; } prelude_info; }; diff --git a/src/dynarmic/backend/arm64/emit_arm64.cpp b/src/dynarmic/backend/arm64/emit_arm64.cpp index 8139efef..d12e4d19 100644 --- a/src/dynarmic/backend/arm64/emit_arm64.cpp +++ b/src/dynarmic/backend/arm64/emit_arm64.cpp @@ -117,11 +117,11 @@ void EmitIR(oaknut::CodeGenerator&, EmitContext ctx.reg_alloc.DefineAsExisting(inst, args[0]); } -EmittedBlockInfo EmitArm64(oaknut::CodeGenerator& code, IR::Block block, const EmitConfig& emit_conf) { +EmittedBlockInfo EmitArm64(oaknut::CodeGenerator& code, IR::Block block, const EmitConfig& conf) { EmittedBlockInfo ebi; RegAlloc reg_alloc{code, GPR_ORDER, FPR_ORDER}; - EmitContext ctx{block, reg_alloc, emit_conf, ebi, {}}; + EmitContext ctx{block, reg_alloc, conf, ebi, {}}; ebi.entry_point = code.ptr(); @@ -155,7 +155,7 @@ EmittedBlockInfo EmitArm64(oaknut::CodeGenerator& code, IR::Block block, const E reg_alloc.AssertNoMoreUses(); - if (emit_conf.enable_cycle_counting) { + if (ctx.conf.enable_cycle_counting) { const size_t cycles_to_add = block.CycleCount(); code.LDR(Xscratch0, SP, offsetof(StackLayout, cycles_remaining)); if (oaknut::AddSubImm::is_valid(cycles_to_add)) { diff --git a/src/dynarmic/backend/arm64/emit_arm64.h b/src/dynarmic/backend/arm64/emit_arm64.h index ddb7ac16..652f19cd 100644 --- a/src/dynarmic/backend/arm64/emit_arm64.h +++ b/src/dynarmic/backend/arm64/emit_arm64.h @@ -39,6 +39,7 @@ enum class LinkTarget { WriteMemory16, WriteMemory32, WriteMemory64, + InstructionSynchronizationBarrierRaised, }; struct Relocation { @@ -53,6 +54,7 @@ struct EmittedBlockInfo { }; struct EmitConfig { + bool hook_isb; bool enable_cycle_counting; bool always_little_endian; }; diff --git a/src/dynarmic/backend/arm64/emit_arm64_a32.cpp b/src/dynarmic/backend/arm64/emit_arm64_a32.cpp index dbb8daca..cc928c30 100644 --- a/src/dynarmic/backend/arm64/emit_arm64_a32.cpp +++ b/src/dynarmic/backend/arm64/emit_arm64_a32.cpp @@ -47,7 +47,7 @@ void EmitSetUpperLocationDescriptor(oaknut::CodeGenerator& code, EmitContext& ct const u32 old_upper = get_upper(old_location); const u32 new_upper = [&] { - const u32 mask = ~u32(ctx.emit_conf.always_little_endian ? 0x2 : 0); + const u32 mask = ~u32(ctx.conf.always_little_endian ? 0x2 : 0); return get_upper(new_location) & mask; }(); @@ -396,27 +396,23 @@ void EmitIR(oaknut::CodeGenerator& code, EmitCon } template<> -void EmitIR(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) { - (void)code; - (void)ctx; - (void)inst; - ASSERT_FALSE("Unimplemented"); +void EmitIR(oaknut::CodeGenerator& code, EmitContext&, IR::Inst*) { + code.DSB(oaknut::BarrierOp::SY); } template<> -void EmitIR(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) { - (void)code; - (void)ctx; - (void)inst; - ASSERT_FALSE("Unimplemented"); +void EmitIR(oaknut::CodeGenerator& code, EmitContext&, IR::Inst*) { + code.DMB(oaknut::BarrierOp::SY); } template<> -void EmitIR(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) { - (void)code; - (void)ctx; - (void)inst; - ASSERT_FALSE("Unimplemented"); +void EmitIR(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst*) { + if (!ctx.conf.hook_isb) { + return; + } + + ctx.reg_alloc.PrepareForCall(nullptr); + EmitRelocation(code, ctx, LinkTarget::InstructionSynchronizationBarrierRaised); } template<> diff --git a/src/dynarmic/backend/arm64/emit_context.h b/src/dynarmic/backend/arm64/emit_context.h index 5ae3efc5..9fd232c5 100644 --- a/src/dynarmic/backend/arm64/emit_context.h +++ b/src/dynarmic/backend/arm64/emit_context.h @@ -24,7 +24,7 @@ struct FpsrManager { struct EmitContext { IR::Block& block; RegAlloc& reg_alloc; - const EmitConfig& emit_conf; + const EmitConfig& conf; EmittedBlockInfo& ebi; FpsrManager fpsr; };