emit_arm64_a32: Implement barriers

This commit is contained in:
Merry 2022-07-26 09:30:35 +01:00 committed by merry
parent a7f675864b
commit 8a0359ec52
6 changed files with 24 additions and 20 deletions

View file

@ -111,6 +111,7 @@ void A32AddressSpace::EmitPrelude() {
prelude_info.write_memory_16 = EmitCallTrampoline<&A32::UserCallbacks::MemoryWrite16>(code, conf.callbacks); 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_32 = EmitCallTrampoline<&A32::UserCallbacks::MemoryWrite32>(code, conf.callbacks);
prelude_info.write_memory_64 = EmitCallTrampoline<&A32::UserCallbacks::MemoryWrite64>(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<u32*>(); prelude_info.end_of_prelude = code.ptr<u32*>();
@ -129,6 +130,7 @@ EmittedBlockInfo A32AddressSpace::Emit(IR::Block block) {
mem.unprotect(); mem.unprotect();
EmittedBlockInfo block_info = EmitArm64(code, std::move(block), { EmittedBlockInfo block_info = EmitArm64(code, std::move(block), {
.hook_isb = conf.hook_isb,
.enable_cycle_counting = conf.enable_cycle_counting, .enable_cycle_counting = conf.enable_cycle_counting,
.always_little_endian = conf.always_little_endian, .always_little_endian = conf.always_little_endian,
}); });
@ -176,6 +178,9 @@ void A32AddressSpace::Link(EmittedBlockInfo& block_info) {
case LinkTarget::WriteMemory64: case LinkTarget::WriteMemory64:
c.BL(prelude_info.write_memory_64); c.BL(prelude_info.write_memory_64);
break; break;
case LinkTarget::InstructionSynchronizationBarrierRaised:
c.BL(prelude_info.isb_raised);
break;
default: default:
ASSERT_FALSE("Invalid relocation target"); ASSERT_FALSE("Invalid relocation target");
} }

View file

@ -64,6 +64,7 @@ private:
void* write_memory_16; void* write_memory_16;
void* write_memory_32; void* write_memory_32;
void* write_memory_64; void* write_memory_64;
void* isb_raised;
} prelude_info; } prelude_info;
}; };

View file

@ -117,11 +117,11 @@ void EmitIR<IR::Opcode::NZCVFromPackedFlags>(oaknut::CodeGenerator&, EmitContext
ctx.reg_alloc.DefineAsExisting(inst, args[0]); 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; EmittedBlockInfo ebi;
RegAlloc reg_alloc{code, GPR_ORDER, FPR_ORDER}; 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<CodePtr>(); ebi.entry_point = code.ptr<CodePtr>();
@ -155,7 +155,7 @@ EmittedBlockInfo EmitArm64(oaknut::CodeGenerator& code, IR::Block block, const E
reg_alloc.AssertNoMoreUses(); reg_alloc.AssertNoMoreUses();
if (emit_conf.enable_cycle_counting) { if (ctx.conf.enable_cycle_counting) {
const size_t cycles_to_add = block.CycleCount(); const size_t cycles_to_add = block.CycleCount();
code.LDR(Xscratch0, SP, offsetof(StackLayout, cycles_remaining)); code.LDR(Xscratch0, SP, offsetof(StackLayout, cycles_remaining));
if (oaknut::AddSubImm::is_valid(cycles_to_add)) { if (oaknut::AddSubImm::is_valid(cycles_to_add)) {

View file

@ -39,6 +39,7 @@ enum class LinkTarget {
WriteMemory16, WriteMemory16,
WriteMemory32, WriteMemory32,
WriteMemory64, WriteMemory64,
InstructionSynchronizationBarrierRaised,
}; };
struct Relocation { struct Relocation {
@ -53,6 +54,7 @@ struct EmittedBlockInfo {
}; };
struct EmitConfig { struct EmitConfig {
bool hook_isb;
bool enable_cycle_counting; bool enable_cycle_counting;
bool always_little_endian; bool always_little_endian;
}; };

View file

@ -47,7 +47,7 @@ void EmitSetUpperLocationDescriptor(oaknut::CodeGenerator& code, EmitContext& ct
const u32 old_upper = get_upper(old_location); const u32 old_upper = get_upper(old_location);
const u32 new_upper = [&] { 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; return get_upper(new_location) & mask;
}(); }();
@ -396,27 +396,23 @@ void EmitIR<IR::Opcode::A32ExceptionRaised>(oaknut::CodeGenerator& code, EmitCon
} }
template<> template<>
void EmitIR<IR::Opcode::A32DataSynchronizationBarrier>(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) { void EmitIR<IR::Opcode::A32DataSynchronizationBarrier>(oaknut::CodeGenerator& code, EmitContext&, IR::Inst*) {
(void)code; code.DSB(oaknut::BarrierOp::SY);
(void)ctx;
(void)inst;
ASSERT_FALSE("Unimplemented");
} }
template<> template<>
void EmitIR<IR::Opcode::A32DataMemoryBarrier>(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) { void EmitIR<IR::Opcode::A32DataMemoryBarrier>(oaknut::CodeGenerator& code, EmitContext&, IR::Inst*) {
(void)code; code.DMB(oaknut::BarrierOp::SY);
(void)ctx;
(void)inst;
ASSERT_FALSE("Unimplemented");
} }
template<> template<>
void EmitIR<IR::Opcode::A32InstructionSynchronizationBarrier>(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) { void EmitIR<IR::Opcode::A32InstructionSynchronizationBarrier>(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst*) {
(void)code; if (!ctx.conf.hook_isb) {
(void)ctx; return;
(void)inst; }
ASSERT_FALSE("Unimplemented");
ctx.reg_alloc.PrepareForCall(nullptr);
EmitRelocation(code, ctx, LinkTarget::InstructionSynchronizationBarrierRaised);
} }
template<> template<>

View file

@ -24,7 +24,7 @@ struct FpsrManager {
struct EmitContext { struct EmitContext {
IR::Block& block; IR::Block& block;
RegAlloc& reg_alloc; RegAlloc& reg_alloc;
const EmitConfig& emit_conf; const EmitConfig& conf;
EmittedBlockInfo& ebi; EmittedBlockInfo& ebi;
FpsrManager fpsr; FpsrManager fpsr;
}; };