emit_arm64_memory: Simplify interface to just require a bitsize

This commit is contained in:
merry 2022-12-06 15:04:26 +00:00
parent f8d8618af1
commit ac0a20795a
4 changed files with 177 additions and 77 deletions

View file

@ -26,82 +26,82 @@ void EmitIR<IR::Opcode::A32ClearExclusive>(oaknut::CodeGenerator& code, EmitCont
template<> template<>
void EmitIR<IR::Opcode::A32ReadMemory8>(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) { void EmitIR<IR::Opcode::A32ReadMemory8>(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) {
EmitReadMemory(code, ctx, inst, LinkTarget::ReadMemory8); EmitReadMemory<8>(code, ctx, inst);
} }
template<> template<>
void EmitIR<IR::Opcode::A32ReadMemory16>(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) { void EmitIR<IR::Opcode::A32ReadMemory16>(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) {
EmitReadMemory(code, ctx, inst, LinkTarget::ReadMemory16); EmitReadMemory<16>(code, ctx, inst);
} }
template<> template<>
void EmitIR<IR::Opcode::A32ReadMemory32>(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) { void EmitIR<IR::Opcode::A32ReadMemory32>(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) {
EmitReadMemory(code, ctx, inst, LinkTarget::ReadMemory32); EmitReadMemory<32>(code, ctx, inst);
} }
template<> template<>
void EmitIR<IR::Opcode::A32ReadMemory64>(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) { void EmitIR<IR::Opcode::A32ReadMemory64>(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) {
EmitReadMemory(code, ctx, inst, LinkTarget::ReadMemory64); EmitReadMemory<64>(code, ctx, inst);
} }
template<> template<>
void EmitIR<IR::Opcode::A32ExclusiveReadMemory8>(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) { void EmitIR<IR::Opcode::A32ExclusiveReadMemory8>(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) {
EmitExclusiveReadMemory(code, ctx, inst, LinkTarget::ExclusiveReadMemory8); EmitExclusiveReadMemory<8>(code, ctx, inst);
} }
template<> template<>
void EmitIR<IR::Opcode::A32ExclusiveReadMemory16>(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) { void EmitIR<IR::Opcode::A32ExclusiveReadMemory16>(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) {
EmitExclusiveReadMemory(code, ctx, inst, LinkTarget::ExclusiveReadMemory16); EmitExclusiveReadMemory<16>(code, ctx, inst);
} }
template<> template<>
void EmitIR<IR::Opcode::A32ExclusiveReadMemory32>(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) { void EmitIR<IR::Opcode::A32ExclusiveReadMemory32>(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) {
EmitExclusiveReadMemory(code, ctx, inst, LinkTarget::ExclusiveReadMemory32); EmitExclusiveReadMemory<32>(code, ctx, inst);
} }
template<> template<>
void EmitIR<IR::Opcode::A32ExclusiveReadMemory64>(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) { void EmitIR<IR::Opcode::A32ExclusiveReadMemory64>(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) {
EmitExclusiveReadMemory(code, ctx, inst, LinkTarget::ExclusiveReadMemory64); EmitExclusiveReadMemory<64>(code, ctx, inst);
} }
template<> template<>
void EmitIR<IR::Opcode::A32WriteMemory8>(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) { void EmitIR<IR::Opcode::A32WriteMemory8>(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) {
EmitWriteMemory(code, ctx, inst, LinkTarget::WriteMemory8); EmitWriteMemory<8>(code, ctx, inst);
} }
template<> template<>
void EmitIR<IR::Opcode::A32WriteMemory16>(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) { void EmitIR<IR::Opcode::A32WriteMemory16>(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) {
EmitWriteMemory(code, ctx, inst, LinkTarget::WriteMemory16); EmitWriteMemory<16>(code, ctx, inst);
} }
template<> template<>
void EmitIR<IR::Opcode::A32WriteMemory32>(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) { void EmitIR<IR::Opcode::A32WriteMemory32>(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) {
EmitWriteMemory(code, ctx, inst, LinkTarget::WriteMemory32); EmitWriteMemory<32>(code, ctx, inst);
} }
template<> template<>
void EmitIR<IR::Opcode::A32WriteMemory64>(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) { void EmitIR<IR::Opcode::A32WriteMemory64>(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) {
EmitWriteMemory(code, ctx, inst, LinkTarget::WriteMemory64); EmitWriteMemory<64>(code, ctx, inst);
} }
template<> template<>
void EmitIR<IR::Opcode::A32ExclusiveWriteMemory8>(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) { void EmitIR<IR::Opcode::A32ExclusiveWriteMemory8>(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) {
EmitExclusiveWriteMemory(code, ctx, inst, LinkTarget::ExclusiveWriteMemory8); EmitExclusiveWriteMemory<8>(code, ctx, inst);
} }
template<> template<>
void EmitIR<IR::Opcode::A32ExclusiveWriteMemory16>(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) { void EmitIR<IR::Opcode::A32ExclusiveWriteMemory16>(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) {
EmitExclusiveWriteMemory(code, ctx, inst, LinkTarget::ExclusiveWriteMemory16); EmitExclusiveWriteMemory<16>(code, ctx, inst);
} }
template<> template<>
void EmitIR<IR::Opcode::A32ExclusiveWriteMemory32>(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) { void EmitIR<IR::Opcode::A32ExclusiveWriteMemory32>(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) {
EmitExclusiveWriteMemory(code, ctx, inst, LinkTarget::ExclusiveWriteMemory32); EmitExclusiveWriteMemory<32>(code, ctx, inst);
} }
template<> template<>
void EmitIR<IR::Opcode::A32ExclusiveWriteMemory64>(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) { void EmitIR<IR::Opcode::A32ExclusiveWriteMemory64>(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) {
EmitExclusiveWriteMemory(code, ctx, inst, LinkTarget::ExclusiveWriteMemory64); EmitExclusiveWriteMemory<64>(code, ctx, inst);
} }
} // namespace Dynarmic::Backend::Arm64 } // namespace Dynarmic::Backend::Arm64

View file

@ -27,102 +27,102 @@ void EmitIR<IR::Opcode::A64ClearExclusive>(oaknut::CodeGenerator& code, EmitCont
template<> template<>
void EmitIR<IR::Opcode::A64ReadMemory8>(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) { void EmitIR<IR::Opcode::A64ReadMemory8>(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) {
EmitReadMemory(code, ctx, inst, LinkTarget::ReadMemory8); EmitReadMemory<8>(code, ctx, inst);
} }
template<> template<>
void EmitIR<IR::Opcode::A64ReadMemory16>(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) { void EmitIR<IR::Opcode::A64ReadMemory16>(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) {
EmitReadMemory(code, ctx, inst, LinkTarget::ReadMemory16); EmitReadMemory<16>(code, ctx, inst);
} }
template<> template<>
void EmitIR<IR::Opcode::A64ReadMemory32>(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) { void EmitIR<IR::Opcode::A64ReadMemory32>(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) {
EmitReadMemory(code, ctx, inst, LinkTarget::ReadMemory32); EmitReadMemory<32>(code, ctx, inst);
} }
template<> template<>
void EmitIR<IR::Opcode::A64ReadMemory64>(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) { void EmitIR<IR::Opcode::A64ReadMemory64>(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) {
EmitReadMemory(code, ctx, inst, LinkTarget::ReadMemory64); EmitReadMemory<64>(code, ctx, inst);
} }
template<> template<>
void EmitIR<IR::Opcode::A64ReadMemory128>(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) { void EmitIR<IR::Opcode::A64ReadMemory128>(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) {
EmitReadMemory128(code, ctx, inst, LinkTarget::ReadMemory128); EmitReadMemory<128>(code, ctx, inst);
} }
template<> template<>
void EmitIR<IR::Opcode::A64ExclusiveReadMemory8>(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) { void EmitIR<IR::Opcode::A64ExclusiveReadMemory8>(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) {
EmitExclusiveReadMemory(code, ctx, inst, LinkTarget::ExclusiveReadMemory8); EmitExclusiveReadMemory<8>(code, ctx, inst);
} }
template<> template<>
void EmitIR<IR::Opcode::A64ExclusiveReadMemory16>(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) { void EmitIR<IR::Opcode::A64ExclusiveReadMemory16>(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) {
EmitExclusiveReadMemory(code, ctx, inst, LinkTarget::ExclusiveReadMemory16); EmitExclusiveReadMemory<16>(code, ctx, inst);
} }
template<> template<>
void EmitIR<IR::Opcode::A64ExclusiveReadMemory32>(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) { void EmitIR<IR::Opcode::A64ExclusiveReadMemory32>(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) {
EmitExclusiveReadMemory(code, ctx, inst, LinkTarget::ExclusiveReadMemory32); EmitExclusiveReadMemory<32>(code, ctx, inst);
} }
template<> template<>
void EmitIR<IR::Opcode::A64ExclusiveReadMemory64>(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) { void EmitIR<IR::Opcode::A64ExclusiveReadMemory64>(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) {
EmitExclusiveReadMemory(code, ctx, inst, LinkTarget::ExclusiveReadMemory64); EmitExclusiveReadMemory<64>(code, ctx, inst);
} }
template<> template<>
void EmitIR<IR::Opcode::A64ExclusiveReadMemory128>(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) { void EmitIR<IR::Opcode::A64ExclusiveReadMemory128>(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) {
EmitExclusiveReadMemory128(code, ctx, inst, LinkTarget::ExclusiveReadMemory128); EmitExclusiveReadMemory<128>(code, ctx, inst);
} }
template<> template<>
void EmitIR<IR::Opcode::A64WriteMemory8>(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) { void EmitIR<IR::Opcode::A64WriteMemory8>(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) {
EmitWriteMemory(code, ctx, inst, LinkTarget::WriteMemory8); EmitWriteMemory<8>(code, ctx, inst);
} }
template<> template<>
void EmitIR<IR::Opcode::A64WriteMemory16>(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) { void EmitIR<IR::Opcode::A64WriteMemory16>(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) {
EmitWriteMemory(code, ctx, inst, LinkTarget::WriteMemory16); EmitWriteMemory<16>(code, ctx, inst);
} }
template<> template<>
void EmitIR<IR::Opcode::A64WriteMemory32>(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) { void EmitIR<IR::Opcode::A64WriteMemory32>(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) {
EmitWriteMemory(code, ctx, inst, LinkTarget::WriteMemory32); EmitWriteMemory<32>(code, ctx, inst);
} }
template<> template<>
void EmitIR<IR::Opcode::A64WriteMemory64>(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) { void EmitIR<IR::Opcode::A64WriteMemory64>(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) {
EmitWriteMemory(code, ctx, inst, LinkTarget::WriteMemory64); EmitWriteMemory<64>(code, ctx, inst);
} }
template<> template<>
void EmitIR<IR::Opcode::A64WriteMemory128>(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) { void EmitIR<IR::Opcode::A64WriteMemory128>(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) {
EmitWriteMemory(code, ctx, inst, LinkTarget::WriteMemory128); EmitWriteMemory<128>(code, ctx, inst);
} }
template<> template<>
void EmitIR<IR::Opcode::A64ExclusiveWriteMemory8>(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) { void EmitIR<IR::Opcode::A64ExclusiveWriteMemory8>(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) {
EmitExclusiveWriteMemory(code, ctx, inst, LinkTarget::ExclusiveWriteMemory8); EmitExclusiveWriteMemory<8>(code, ctx, inst);
} }
template<> template<>
void EmitIR<IR::Opcode::A64ExclusiveWriteMemory16>(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) { void EmitIR<IR::Opcode::A64ExclusiveWriteMemory16>(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) {
EmitExclusiveWriteMemory(code, ctx, inst, LinkTarget::ExclusiveWriteMemory16); EmitExclusiveWriteMemory<16>(code, ctx, inst);
} }
template<> template<>
void EmitIR<IR::Opcode::A64ExclusiveWriteMemory32>(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) { void EmitIR<IR::Opcode::A64ExclusiveWriteMemory32>(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) {
EmitExclusiveWriteMemory(code, ctx, inst, LinkTarget::ExclusiveWriteMemory32); EmitExclusiveWriteMemory<32>(code, ctx, inst);
} }
template<> template<>
void EmitIR<IR::Opcode::A64ExclusiveWriteMemory64>(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) { void EmitIR<IR::Opcode::A64ExclusiveWriteMemory64>(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) {
EmitExclusiveWriteMemory(code, ctx, inst, LinkTarget::ExclusiveWriteMemory64); EmitExclusiveWriteMemory<64>(code, ctx, inst);
} }
template<> template<>
void EmitIR<IR::Opcode::A64ExclusiveWriteMemory128>(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) { void EmitIR<IR::Opcode::A64ExclusiveWriteMemory128>(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) {
EmitExclusiveWriteMemory(code, ctx, inst, LinkTarget::ExclusiveWriteMemory128); EmitExclusiveWriteMemory<128>(code, ctx, inst);
} }
} // namespace Dynarmic::Backend::Arm64 } // namespace Dynarmic::Backend::Arm64

View file

@ -20,65 +20,118 @@ namespace Dynarmic::Backend::Arm64 {
using namespace oaknut::util; using namespace oaknut::util;
namespace {
bool IsOrdered(IR::AccType acctype) { bool IsOrdered(IR::AccType acctype) {
return acctype == IR::AccType::ORDERED || acctype == IR::AccType::ORDEREDRW || acctype == IR::AccType::LIMITEDORDERED; 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) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst); switch (bitsize) {
ctx.reg_alloc.PrepareForCall({}, args[1]); case 8:
const bool ordered = IsOrdered(args[2].GetImmediateAccType()); return LinkTarget::ReadMemory8;
case 16:
EmitRelocation(code, ctx, fn); return LinkTarget::ReadMemory16;
if (ordered) { case 32:
code.DMB(oaknut::BarrierOp::ISH); return LinkTarget::ReadMemory32;
case 64:
return LinkTarget::ReadMemory64;
case 128:
return LinkTarget::ReadMemory128;
} }
ctx.reg_alloc.DefineAsRegister(inst, X0); UNREACHABLE();
} }
void EmitReadMemory128(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst, LinkTarget fn) { 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<size_t bitsize>
void CallbackOnlyEmitReadMemory(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto args = ctx.reg_alloc.GetArgumentInfo(inst);
ctx.reg_alloc.PrepareForCall({}, args[1]); ctx.reg_alloc.PrepareForCall({}, args[1]);
const bool ordered = IsOrdered(args[2].GetImmediateAccType()); const bool ordered = IsOrdered(args[2].GetImmediateAccType());
EmitRelocation(code, ctx, fn); EmitRelocation(code, ctx, ReadMemoryLinkTarget(bitsize));
if (ordered) { if (ordered) {
code.DMB(oaknut::BarrierOp::ISH); code.DMB(oaknut::BarrierOp::ISH);
} }
if constexpr (bitsize == 128) {
code.MOV(Q8.B16(), Q0.B16()); code.MOV(Q8.B16(), Q0.B16());
ctx.reg_alloc.DefineAsRegister(inst, Q8); ctx.reg_alloc.DefineAsRegister(inst, Q8);
} else {
ctx.reg_alloc.DefineAsRegister(inst, X0);
}
} }
void EmitExclusiveReadMemory(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst, LinkTarget fn) { template<size_t bitsize>
void CallbackOnlyEmitExclusiveReadMemory(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto args = ctx.reg_alloc.GetArgumentInfo(inst);
ctx.reg_alloc.PrepareForCall({}, args[1]); ctx.reg_alloc.PrepareForCall({}, args[1]);
const bool ordered = IsOrdered(args[2].GetImmediateAccType()); const bool ordered = IsOrdered(args[2].GetImmediateAccType());
code.MOV(Wscratch0, 1); code.MOV(Wscratch0, 1);
code.STRB(Wscratch0, Xstate, ctx.conf.state_exclusive_state_offset); code.STRB(Wscratch0, Xstate, ctx.conf.state_exclusive_state_offset);
EmitRelocation(code, ctx, fn); EmitRelocation(code, ctx, ExclusiveReadMemoryLinkTarget(bitsize));
if (ordered) { if (ordered) {
code.DMB(oaknut::BarrierOp::ISH); code.DMB(oaknut::BarrierOp::ISH);
} }
ctx.reg_alloc.DefineAsRegister(inst, X0);
}
void EmitExclusiveReadMemory128(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst, LinkTarget fn) { if constexpr (bitsize == 128) {
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);
}
code.MOV(Q8.B16(), Q0.B16()); code.MOV(Q8.B16(), Q0.B16());
ctx.reg_alloc.DefineAsRegister(inst, Q8); ctx.reg_alloc.DefineAsRegister(inst, Q8);
} else {
ctx.reg_alloc.DefineAsRegister(inst, X0);
}
} }
void EmitWriteMemory(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst, LinkTarget fn) { template<size_t bitsize>
void CallbackOnlyEmitWriteMemory(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto args = ctx.reg_alloc.GetArgumentInfo(inst);
ctx.reg_alloc.PrepareForCall({}, args[1], args[2]); ctx.reg_alloc.PrepareForCall({}, args[1], args[2]);
const bool ordered = IsOrdered(args[3].GetImmediateAccType()); const bool ordered = IsOrdered(args[3].GetImmediateAccType());
@ -86,13 +139,14 @@ void EmitWriteMemory(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* in
if (ordered) { if (ordered) {
code.DMB(oaknut::BarrierOp::ISH); code.DMB(oaknut::BarrierOp::ISH);
} }
EmitRelocation(code, ctx, fn); EmitRelocation(code, ctx, WriteMemoryLinkTarget(bitsize));
if (ordered) { if (ordered) {
code.DMB(oaknut::BarrierOp::ISH); code.DMB(oaknut::BarrierOp::ISH);
} }
} }
void EmitExclusiveWriteMemory(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst, LinkTarget fn) { template<size_t bitsize>
void CallbackOnlyEmitExclusiveWriteMemory(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto args = ctx.reg_alloc.GetArgumentInfo(inst);
ctx.reg_alloc.PrepareForCall({}, args[1], args[2]); ctx.reg_alloc.PrepareForCall({}, args[1], args[2]);
const bool ordered = IsOrdered(args[3].GetImmediateAccType()); 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.LDRB(Wscratch0, Xstate, ctx.conf.state_exclusive_state_offset);
code.CBZ(Wscratch0, end); code.CBZ(Wscratch0, end);
code.STRB(WZR, Xstate, ctx.conf.state_exclusive_state_offset); code.STRB(WZR, Xstate, ctx.conf.state_exclusive_state_offset);
EmitRelocation(code, ctx, fn); EmitRelocation(code, ctx, ExclusiveWriteMemoryLinkTarget(bitsize));
if (ordered) { if (ordered) {
code.DMB(oaknut::BarrierOp::ISH); code.DMB(oaknut::BarrierOp::ISH);
} }
@ -114,4 +168,47 @@ void EmitExclusiveWriteMemory(oaknut::CodeGenerator& code, EmitContext& ctx, IR:
ctx.reg_alloc.DefineAsRegister(inst, X0); ctx.reg_alloc.DefineAsRegister(inst, X0);
} }
} // namespace
template<size_t bitsize>
void EmitReadMemory(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) {
CallbackOnlyEmitReadMemory<bitsize>(code, ctx, inst);
}
template<size_t bitsize>
void EmitExclusiveReadMemory(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) {
CallbackOnlyEmitExclusiveReadMemory<bitsize>(code, ctx, inst);
}
template<size_t bitsize>
void EmitWriteMemory(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) {
CallbackOnlyEmitWriteMemory<bitsize>(code, ctx, inst);
}
template<size_t bitsize>
void EmitExclusiveWriteMemory(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) {
CallbackOnlyEmitExclusiveWriteMemory<bitsize>(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 } // namespace Dynarmic::Backend::Arm64

View file

@ -3,6 +3,8 @@
* SPDX-License-Identifier: 0BSD * SPDX-License-Identifier: 0BSD
*/ */
#include <mcl/stdint.hpp>
namespace oaknut { namespace oaknut {
struct PointerCodeGeneratorPolicy; struct PointerCodeGeneratorPolicy;
template<typename> template<typename>
@ -21,12 +23,13 @@ namespace Dynarmic::Backend::Arm64 {
struct EmitContext; struct EmitContext;
enum class LinkTarget; enum class LinkTarget;
bool IsOrdered(IR::AccType acctype); template<size_t bitsize>
void EmitReadMemory(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst, LinkTarget fn); void EmitReadMemory(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst);
void EmitReadMemory128(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst, LinkTarget fn); template<size_t bitsize>
void EmitExclusiveReadMemory(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst, LinkTarget fn); void EmitExclusiveReadMemory(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst);
void EmitExclusiveReadMemory128(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst, LinkTarget fn); template<size_t bitsize>
void EmitWriteMemory(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst, LinkTarget fn); void EmitWriteMemory(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst);
void EmitExclusiveWriteMemory(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst, LinkTarget fn); template<size_t bitsize>
void EmitExclusiveWriteMemory(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst);
} // namespace Dynarmic::Backend::Arm64 } // namespace Dynarmic::Backend::Arm64