emit_arm64: Handle cond prologue
This commit is contained in:
parent
aa6b31f2b8
commit
2ac12562ab
3 changed files with 31 additions and 9 deletions
|
@ -133,6 +133,17 @@ void EmitIR<IR::Opcode::NZCVFromPackedFlags>(oaknut::CodeGenerator&, EmitContext
|
|||
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 ebi;
|
||||
|
||||
|
@ -141,6 +152,19 @@ EmittedBlockInfo EmitArm64(oaknut::CodeGenerator& code, IR::Block block, const E
|
|||
|
||||
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) {
|
||||
IR::Inst* inst = &*iter;
|
||||
|
||||
|
@ -172,15 +196,7 @@ EmittedBlockInfo EmitArm64(oaknut::CodeGenerator& code, IR::Block block, const E
|
|||
reg_alloc.AssertNoMoreUses();
|
||||
|
||||
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)) {
|
||||
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));
|
||||
EmitAddCycles(code, ctx, block.CycleCount());
|
||||
}
|
||||
|
||||
EmitA32Terminal(code, ctx);
|
||||
|
|
|
@ -68,5 +68,6 @@ void EmitIR(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst);
|
|||
void EmitRelocation(oaknut::CodeGenerator& code, EmitContext& ctx, LinkTarget link_target);
|
||||
oaknut::Label EmitA32Cond(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Cond cond);
|
||||
void EmitA32Terminal(oaknut::CodeGenerator& code, EmitContext& ctx);
|
||||
void EmitA32ConditionFailedTerminal(oaknut::CodeGenerator& code, EmitContext& ctx);
|
||||
|
||||
} // namespace Dynarmic::Backend::Arm64
|
||||
|
|
|
@ -123,6 +123,11 @@ void EmitA32Terminal(oaknut::CodeGenerator& code, EmitContext& ctx) {
|
|||
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<>
|
||||
void EmitIR<IR::Opcode::A32SetCheckBit>(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) {
|
||||
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
|
||||
|
|
Loading…
Reference in a new issue