emit_arm64: Handle cond prologue

This commit is contained in:
Merry 2022-07-31 09:07:43 +01:00 committed by merry
parent aa6b31f2b8
commit 2ac12562ab
3 changed files with 31 additions and 9 deletions

View file

@ -133,6 +133,17 @@ void EmitIR<IR::Opcode::NZCVFromPackedFlags>(oaknut::CodeGenerator&, EmitContext
ctx.reg_alloc.DefineAsExisting(inst, args[0]); ctx.reg_alloc.DefineAsExisting(inst, args[0]);
} }
static void EmitAddCycles(oaknut::CodeGenerator& code, EmitContext&, size_t cycles_to_add) {
code.LDR(Xscratch0, SP, offsetof(StackLayout, cycles_remaining));
if (oaknut::AddSubImm::is_valid(cycles_to_add)) {
code.SUBS(Xscratch0, Xscratch0, cycles_to_add);
} else {
code.MOV(Xscratch1, cycles_to_add);
code.SUBS(Xscratch0, Xscratch0, Xscratch1);
}
code.STR(Xscratch0, SP, offsetof(StackLayout, cycles_remaining));
}
EmittedBlockInfo EmitArm64(oaknut::CodeGenerator& code, IR::Block block, const EmitConfig& conf) { EmittedBlockInfo EmitArm64(oaknut::CodeGenerator& code, IR::Block block, const EmitConfig& conf) {
EmittedBlockInfo ebi; EmittedBlockInfo ebi;
@ -141,6 +152,19 @@ EmittedBlockInfo EmitArm64(oaknut::CodeGenerator& code, IR::Block block, const E
ebi.entry_point = code.ptr<CodePtr>(); ebi.entry_point = code.ptr<CodePtr>();
if (ctx.block.GetCondition() == IR::Cond::AL) {
ASSERT(!ctx.block.HasConditionFailedLocation());
} else {
ASSERT(ctx.block.HasConditionFailedLocation());
oaknut::Label pass = EmitA32Cond(code, ctx, ctx.block.GetCondition());
if (conf.enable_cycle_counting) {
EmitAddCycles(code, ctx, ctx.block.ConditionFailedCycleCount());
}
EmitA32ConditionFailedTerminal(code, ctx);
code.l(pass);
}
for (auto iter = block.begin(); iter != block.end(); ++iter) { for (auto iter = block.begin(); iter != block.end(); ++iter) {
IR::Inst* inst = &*iter; IR::Inst* inst = &*iter;
@ -172,15 +196,7 @@ EmittedBlockInfo EmitArm64(oaknut::CodeGenerator& code, IR::Block block, const E
reg_alloc.AssertNoMoreUses(); reg_alloc.AssertNoMoreUses();
if (ctx.conf.enable_cycle_counting) { if (ctx.conf.enable_cycle_counting) {
const size_t cycles_to_add = block.CycleCount(); EmitAddCycles(code, ctx, block.CycleCount());
code.LDR(Xscratch0, SP, offsetof(StackLayout, cycles_remaining));
if (oaknut::AddSubImm::is_valid(cycles_to_add)) {
code.SUBS(Xscratch0, Xscratch0, cycles_to_add);
} else {
code.MOV(Xscratch1, cycles_to_add);
code.SUBS(Xscratch0, Xscratch0, Xscratch1);
}
code.STR(Xscratch0, SP, offsetof(StackLayout, cycles_remaining));
} }
EmitA32Terminal(code, ctx); EmitA32Terminal(code, ctx);

View file

@ -68,5 +68,6 @@ 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, LinkTarget link_target);
oaknut::Label EmitA32Cond(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Cond cond); oaknut::Label EmitA32Cond(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Cond cond);
void EmitA32Terminal(oaknut::CodeGenerator& code, EmitContext& ctx); void EmitA32Terminal(oaknut::CodeGenerator& code, EmitContext& ctx);
void EmitA32ConditionFailedTerminal(oaknut::CodeGenerator& code, EmitContext& ctx);
} // namespace Dynarmic::Backend::Arm64 } // namespace Dynarmic::Backend::Arm64

View file

@ -123,6 +123,11 @@ void EmitA32Terminal(oaknut::CodeGenerator& code, EmitContext& ctx) {
EmitA32Terminal(code, ctx, ctx.block.GetTerminal(), location.SetSingleStepping(false), location.SingleStepping()); EmitA32Terminal(code, ctx, ctx.block.GetTerminal(), location.SetSingleStepping(false), location.SingleStepping());
} }
void EmitA32ConditionFailedTerminal(oaknut::CodeGenerator& code, EmitContext& ctx) {
const A32::LocationDescriptor location{ctx.block.Location()};
EmitA32Terminal(code, ctx, IR::Term::LinkBlock{ctx.block.ConditionFailedLocation()}, location.SetSingleStepping(false), location.SingleStepping());
}
template<> template<>
void EmitIR<IR::Opcode::A32SetCheckBit>(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) { void EmitIR<IR::Opcode::A32SetCheckBit>(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto args = ctx.reg_alloc.GetArgumentInfo(inst);