From ac0a20795aec323c2d8a325e083b89d888cf3ada Mon Sep 17 00:00:00 2001 From: merry Date: Tue, 6 Dec 2022 15:04:26 +0000 Subject: [PATCH] emit_arm64_memory: Simplify interface to just require a bitsize --- .../backend/arm64/emit_arm64_a32_memory.cpp | 32 ++-- .../backend/arm64/emit_arm64_a64_memory.cpp | 40 ++--- .../backend/arm64/emit_arm64_memory.cpp | 165 ++++++++++++++---- .../backend/arm64/emit_arm64_memory.h | 17 +- 4 files changed, 177 insertions(+), 77 deletions(-) diff --git a/src/dynarmic/backend/arm64/emit_arm64_a32_memory.cpp b/src/dynarmic/backend/arm64/emit_arm64_a32_memory.cpp index 4fffa996..9e8426e2 100644 --- a/src/dynarmic/backend/arm64/emit_arm64_a32_memory.cpp +++ b/src/dynarmic/backend/arm64/emit_arm64_a32_memory.cpp @@ -26,82 +26,82 @@ void EmitIR(oaknut::CodeGenerator& code, EmitCont template<> void EmitIR(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) { - EmitReadMemory(code, ctx, inst, LinkTarget::ReadMemory8); + EmitReadMemory<8>(code, ctx, inst); } template<> void EmitIR(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) { - EmitReadMemory(code, ctx, inst, LinkTarget::ReadMemory16); + EmitReadMemory<16>(code, ctx, inst); } template<> void EmitIR(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) { - EmitReadMemory(code, ctx, inst, LinkTarget::ReadMemory32); + EmitReadMemory<32>(code, ctx, inst); } template<> void EmitIR(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) { - EmitReadMemory(code, ctx, inst, LinkTarget::ReadMemory64); + EmitReadMemory<64>(code, ctx, inst); } template<> void EmitIR(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) { - EmitExclusiveReadMemory(code, ctx, inst, LinkTarget::ExclusiveReadMemory8); + EmitExclusiveReadMemory<8>(code, ctx, inst); } template<> void EmitIR(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) { - EmitExclusiveReadMemory(code, ctx, inst, LinkTarget::ExclusiveReadMemory16); + EmitExclusiveReadMemory<16>(code, ctx, inst); } template<> void EmitIR(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) { - EmitExclusiveReadMemory(code, ctx, inst, LinkTarget::ExclusiveReadMemory32); + EmitExclusiveReadMemory<32>(code, ctx, inst); } template<> void EmitIR(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) { - EmitExclusiveReadMemory(code, ctx, inst, LinkTarget::ExclusiveReadMemory64); + EmitExclusiveReadMemory<64>(code, ctx, inst); } template<> void EmitIR(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) { - EmitWriteMemory(code, ctx, inst, LinkTarget::WriteMemory8); + EmitWriteMemory<8>(code, ctx, inst); } template<> void EmitIR(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) { - EmitWriteMemory(code, ctx, inst, LinkTarget::WriteMemory16); + EmitWriteMemory<16>(code, ctx, inst); } template<> void EmitIR(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) { - EmitWriteMemory(code, ctx, inst, LinkTarget::WriteMemory32); + EmitWriteMemory<32>(code, ctx, inst); } template<> void EmitIR(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) { - EmitWriteMemory(code, ctx, inst, LinkTarget::WriteMemory64); + EmitWriteMemory<64>(code, ctx, inst); } template<> void EmitIR(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) { - EmitExclusiveWriteMemory(code, ctx, inst, LinkTarget::ExclusiveWriteMemory8); + EmitExclusiveWriteMemory<8>(code, ctx, inst); } template<> void EmitIR(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) { - EmitExclusiveWriteMemory(code, ctx, inst, LinkTarget::ExclusiveWriteMemory16); + EmitExclusiveWriteMemory<16>(code, ctx, inst); } template<> void EmitIR(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) { - EmitExclusiveWriteMemory(code, ctx, inst, LinkTarget::ExclusiveWriteMemory32); + EmitExclusiveWriteMemory<32>(code, ctx, inst); } template<> void EmitIR(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) { - EmitExclusiveWriteMemory(code, ctx, inst, LinkTarget::ExclusiveWriteMemory64); + EmitExclusiveWriteMemory<64>(code, ctx, inst); } } // namespace Dynarmic::Backend::Arm64 diff --git a/src/dynarmic/backend/arm64/emit_arm64_a64_memory.cpp b/src/dynarmic/backend/arm64/emit_arm64_a64_memory.cpp index 43f0ea4d..099c81a4 100644 --- a/src/dynarmic/backend/arm64/emit_arm64_a64_memory.cpp +++ b/src/dynarmic/backend/arm64/emit_arm64_a64_memory.cpp @@ -27,102 +27,102 @@ void EmitIR(oaknut::CodeGenerator& code, EmitCont template<> void EmitIR(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) { - EmitReadMemory(code, ctx, inst, LinkTarget::ReadMemory8); + EmitReadMemory<8>(code, ctx, inst); } template<> void EmitIR(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) { - EmitReadMemory(code, ctx, inst, LinkTarget::ReadMemory16); + EmitReadMemory<16>(code, ctx, inst); } template<> void EmitIR(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) { - EmitReadMemory(code, ctx, inst, LinkTarget::ReadMemory32); + EmitReadMemory<32>(code, ctx, inst); } template<> void EmitIR(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) { - EmitReadMemory(code, ctx, inst, LinkTarget::ReadMemory64); + EmitReadMemory<64>(code, ctx, inst); } template<> void EmitIR(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) { - EmitReadMemory128(code, ctx, inst, LinkTarget::ReadMemory128); + EmitReadMemory<128>(code, ctx, inst); } template<> void EmitIR(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) { - EmitExclusiveReadMemory(code, ctx, inst, LinkTarget::ExclusiveReadMemory8); + EmitExclusiveReadMemory<8>(code, ctx, inst); } template<> void EmitIR(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) { - EmitExclusiveReadMemory(code, ctx, inst, LinkTarget::ExclusiveReadMemory16); + EmitExclusiveReadMemory<16>(code, ctx, inst); } template<> void EmitIR(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) { - EmitExclusiveReadMemory(code, ctx, inst, LinkTarget::ExclusiveReadMemory32); + EmitExclusiveReadMemory<32>(code, ctx, inst); } template<> void EmitIR(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) { - EmitExclusiveReadMemory(code, ctx, inst, LinkTarget::ExclusiveReadMemory64); + EmitExclusiveReadMemory<64>(code, ctx, inst); } template<> void EmitIR(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) { - EmitExclusiveReadMemory128(code, ctx, inst, LinkTarget::ExclusiveReadMemory128); + EmitExclusiveReadMemory<128>(code, ctx, inst); } template<> void EmitIR(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) { - EmitWriteMemory(code, ctx, inst, LinkTarget::WriteMemory8); + EmitWriteMemory<8>(code, ctx, inst); } template<> void EmitIR(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) { - EmitWriteMemory(code, ctx, inst, LinkTarget::WriteMemory16); + EmitWriteMemory<16>(code, ctx, inst); } template<> void EmitIR(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) { - EmitWriteMemory(code, ctx, inst, LinkTarget::WriteMemory32); + EmitWriteMemory<32>(code, ctx, inst); } template<> void EmitIR(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) { - EmitWriteMemory(code, ctx, inst, LinkTarget::WriteMemory64); + EmitWriteMemory<64>(code, ctx, inst); } template<> void EmitIR(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) { - EmitWriteMemory(code, ctx, inst, LinkTarget::WriteMemory128); + EmitWriteMemory<128>(code, ctx, inst); } template<> void EmitIR(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) { - EmitExclusiveWriteMemory(code, ctx, inst, LinkTarget::ExclusiveWriteMemory8); + EmitExclusiveWriteMemory<8>(code, ctx, inst); } template<> void EmitIR(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) { - EmitExclusiveWriteMemory(code, ctx, inst, LinkTarget::ExclusiveWriteMemory16); + EmitExclusiveWriteMemory<16>(code, ctx, inst); } template<> void EmitIR(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) { - EmitExclusiveWriteMemory(code, ctx, inst, LinkTarget::ExclusiveWriteMemory32); + EmitExclusiveWriteMemory<32>(code, ctx, inst); } template<> void EmitIR(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) { - EmitExclusiveWriteMemory(code, ctx, inst, LinkTarget::ExclusiveWriteMemory64); + EmitExclusiveWriteMemory<64>(code, ctx, inst); } template<> void EmitIR(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) { - EmitExclusiveWriteMemory(code, ctx, inst, LinkTarget::ExclusiveWriteMemory128); + EmitExclusiveWriteMemory<128>(code, ctx, inst); } } // namespace Dynarmic::Backend::Arm64 diff --git a/src/dynarmic/backend/arm64/emit_arm64_memory.cpp b/src/dynarmic/backend/arm64/emit_arm64_memory.cpp index cdc078a7..f51fd016 100644 --- a/src/dynarmic/backend/arm64/emit_arm64_memory.cpp +++ b/src/dynarmic/backend/arm64/emit_arm64_memory.cpp @@ -20,65 +20,118 @@ namespace Dynarmic::Backend::Arm64 { using namespace oaknut::util; +namespace { + bool IsOrdered(IR::AccType acctype) { return acctype == IR::AccType::ORDERED || acctype == IR::AccType::ORDEREDRW || acctype == IR::AccType::LIMITEDORDERED; } -void EmitReadMemory(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst, LinkTarget fn) { +LinkTarget ReadMemoryLinkTarget(size_t bitsize) { + switch (bitsize) { + case 8: + return LinkTarget::ReadMemory8; + case 16: + return LinkTarget::ReadMemory16; + case 32: + return LinkTarget::ReadMemory32; + case 64: + return LinkTarget::ReadMemory64; + case 128: + return LinkTarget::ReadMemory128; + } + UNREACHABLE(); +} + +LinkTarget WriteMemoryLinkTarget(size_t bitsize) { + switch (bitsize) { + case 8: + return LinkTarget::WriteMemory8; + case 16: + return LinkTarget::WriteMemory16; + case 32: + return LinkTarget::WriteMemory32; + case 64: + return LinkTarget::WriteMemory64; + case 128: + return LinkTarget::WriteMemory128; + } + UNREACHABLE(); +} + +LinkTarget ExclusiveReadMemoryLinkTarget(size_t bitsize) { + switch (bitsize) { + case 8: + return LinkTarget::ExclusiveReadMemory8; + case 16: + return LinkTarget::ExclusiveReadMemory16; + case 32: + return LinkTarget::ExclusiveReadMemory32; + case 64: + return LinkTarget::ExclusiveReadMemory64; + case 128: + return LinkTarget::ExclusiveReadMemory128; + } + UNREACHABLE(); +} + +LinkTarget ExclusiveWriteMemoryLinkTarget(size_t bitsize) { + switch (bitsize) { + case 8: + return LinkTarget::ExclusiveWriteMemory8; + case 16: + return LinkTarget::ExclusiveWriteMemory16; + case 32: + return LinkTarget::ExclusiveWriteMemory32; + case 64: + return LinkTarget::ExclusiveWriteMemory64; + case 128: + return LinkTarget::ExclusiveWriteMemory128; + } + UNREACHABLE(); +} + +template +void CallbackOnlyEmitReadMemory(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) { auto args = ctx.reg_alloc.GetArgumentInfo(inst); ctx.reg_alloc.PrepareForCall({}, args[1]); const bool ordered = IsOrdered(args[2].GetImmediateAccType()); - EmitRelocation(code, ctx, fn); + EmitRelocation(code, ctx, ReadMemoryLinkTarget(bitsize)); if (ordered) { code.DMB(oaknut::BarrierOp::ISH); } - ctx.reg_alloc.DefineAsRegister(inst, X0); -} -void EmitReadMemory128(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst, LinkTarget fn) { - auto args = ctx.reg_alloc.GetArgumentInfo(inst); - ctx.reg_alloc.PrepareForCall({}, args[1]); - const bool ordered = IsOrdered(args[2].GetImmediateAccType()); - - EmitRelocation(code, ctx, fn); - if (ordered) { - code.DMB(oaknut::BarrierOp::ISH); + if constexpr (bitsize == 128) { + code.MOV(Q8.B16(), Q0.B16()); + ctx.reg_alloc.DefineAsRegister(inst, Q8); + } else { + ctx.reg_alloc.DefineAsRegister(inst, X0); } - code.MOV(Q8.B16(), Q0.B16()); - ctx.reg_alloc.DefineAsRegister(inst, Q8); } -void EmitExclusiveReadMemory(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst, LinkTarget fn) { +template +void CallbackOnlyEmitExclusiveReadMemory(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) { auto args = ctx.reg_alloc.GetArgumentInfo(inst); ctx.reg_alloc.PrepareForCall({}, args[1]); const bool ordered = IsOrdered(args[2].GetImmediateAccType()); code.MOV(Wscratch0, 1); code.STRB(Wscratch0, Xstate, ctx.conf.state_exclusive_state_offset); - EmitRelocation(code, ctx, fn); + EmitRelocation(code, ctx, ExclusiveReadMemoryLinkTarget(bitsize)); if (ordered) { code.DMB(oaknut::BarrierOp::ISH); } - ctx.reg_alloc.DefineAsRegister(inst, X0); -} -void EmitExclusiveReadMemory128(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst, LinkTarget fn) { - auto args = ctx.reg_alloc.GetArgumentInfo(inst); - ctx.reg_alloc.PrepareForCall({}, args[1]); - const bool ordered = IsOrdered(args[2].GetImmediateAccType()); - - code.MOV(Wscratch0, 1); - code.STRB(Wscratch0, Xstate, ctx.conf.state_exclusive_state_offset); - EmitRelocation(code, ctx, fn); - if (ordered) { - code.DMB(oaknut::BarrierOp::ISH); + if constexpr (bitsize == 128) { + code.MOV(Q8.B16(), Q0.B16()); + ctx.reg_alloc.DefineAsRegister(inst, Q8); + } else { + ctx.reg_alloc.DefineAsRegister(inst, X0); } - code.MOV(Q8.B16(), Q0.B16()); - ctx.reg_alloc.DefineAsRegister(inst, Q8); } -void EmitWriteMemory(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst, LinkTarget fn) { +template +void CallbackOnlyEmitWriteMemory(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) { auto args = ctx.reg_alloc.GetArgumentInfo(inst); ctx.reg_alloc.PrepareForCall({}, args[1], args[2]); const bool ordered = IsOrdered(args[3].GetImmediateAccType()); @@ -86,13 +139,14 @@ void EmitWriteMemory(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* in if (ordered) { code.DMB(oaknut::BarrierOp::ISH); } - EmitRelocation(code, ctx, fn); + EmitRelocation(code, ctx, WriteMemoryLinkTarget(bitsize)); if (ordered) { code.DMB(oaknut::BarrierOp::ISH); } } -void EmitExclusiveWriteMemory(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst, LinkTarget fn) { +template +void CallbackOnlyEmitExclusiveWriteMemory(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) { auto args = ctx.reg_alloc.GetArgumentInfo(inst); ctx.reg_alloc.PrepareForCall({}, args[1], args[2]); const bool ordered = IsOrdered(args[3].GetImmediateAccType()); @@ -106,7 +160,7 @@ void EmitExclusiveWriteMemory(oaknut::CodeGenerator& code, EmitContext& ctx, IR: code.LDRB(Wscratch0, Xstate, ctx.conf.state_exclusive_state_offset); code.CBZ(Wscratch0, end); code.STRB(WZR, Xstate, ctx.conf.state_exclusive_state_offset); - EmitRelocation(code, ctx, fn); + EmitRelocation(code, ctx, ExclusiveWriteMemoryLinkTarget(bitsize)); if (ordered) { code.DMB(oaknut::BarrierOp::ISH); } @@ -114,4 +168,47 @@ void EmitExclusiveWriteMemory(oaknut::CodeGenerator& code, EmitContext& ctx, IR: ctx.reg_alloc.DefineAsRegister(inst, X0); } +} // namespace + +template +void EmitReadMemory(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) { + CallbackOnlyEmitReadMemory(code, ctx, inst); +} + +template +void EmitExclusiveReadMemory(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) { + CallbackOnlyEmitExclusiveReadMemory(code, ctx, inst); +} + +template +void EmitWriteMemory(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) { + CallbackOnlyEmitWriteMemory(code, ctx, inst); +} + +template +void EmitExclusiveWriteMemory(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) { + CallbackOnlyEmitExclusiveWriteMemory(code, ctx, inst); +} + +template void EmitReadMemory<8>(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst); +template void EmitReadMemory<16>(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst); +template void EmitReadMemory<32>(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst); +template void EmitReadMemory<64>(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst); +template void EmitReadMemory<128>(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst); +template void EmitExclusiveReadMemory<8>(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst); +template void EmitExclusiveReadMemory<16>(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst); +template void EmitExclusiveReadMemory<32>(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst); +template void EmitExclusiveReadMemory<64>(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst); +template void EmitExclusiveReadMemory<128>(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst); +template void EmitWriteMemory<8>(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst); +template void EmitWriteMemory<16>(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst); +template void EmitWriteMemory<32>(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst); +template void EmitWriteMemory<64>(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst); +template void EmitWriteMemory<128>(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst); +template void EmitExclusiveWriteMemory<8>(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst); +template void EmitExclusiveWriteMemory<16>(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst); +template void EmitExclusiveWriteMemory<32>(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst); +template void EmitExclusiveWriteMemory<64>(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst); +template void EmitExclusiveWriteMemory<128>(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst); + } // namespace Dynarmic::Backend::Arm64 diff --git a/src/dynarmic/backend/arm64/emit_arm64_memory.h b/src/dynarmic/backend/arm64/emit_arm64_memory.h index ae7ec4c3..fb2f5780 100644 --- a/src/dynarmic/backend/arm64/emit_arm64_memory.h +++ b/src/dynarmic/backend/arm64/emit_arm64_memory.h @@ -3,6 +3,8 @@ * SPDX-License-Identifier: 0BSD */ +#include + namespace oaknut { struct PointerCodeGeneratorPolicy; template @@ -21,12 +23,13 @@ namespace Dynarmic::Backend::Arm64 { struct EmitContext; enum class LinkTarget; -bool IsOrdered(IR::AccType acctype); -void EmitReadMemory(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst, LinkTarget fn); -void EmitReadMemory128(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst, LinkTarget fn); -void EmitExclusiveReadMemory(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst, LinkTarget fn); -void EmitExclusiveReadMemory128(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst, LinkTarget fn); -void EmitWriteMemory(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst, LinkTarget fn); -void EmitExclusiveWriteMemory(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst, LinkTarget fn); +template +void EmitReadMemory(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst); +template +void EmitExclusiveReadMemory(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst); +template +void EmitWriteMemory(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst); +template +void EmitExclusiveWriteMemory(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst); } // namespace Dynarmic::Backend::Arm64