From ff34f4c6ae9671b293712b0d64fe5b165e379475 Mon Sep 17 00:00:00 2001 From: Merry Date: Tue, 26 Jul 2022 21:46:08 +0100 Subject: [PATCH] emit_arm64_data_processing: Fix flag reading in AddSub Also improve codegen for ZR case. --- .../backend/arm64/emit_arm64_data_processing.cpp | 16 ++++++++++++++-- src/dynarmic/backend/arm64/reg_alloc.cpp | 15 +++++++++------ src/dynarmic/backend/arm64/reg_alloc.h | 4 +--- 3 files changed, 24 insertions(+), 11 deletions(-) diff --git a/src/dynarmic/backend/arm64/emit_arm64_data_processing.cpp b/src/dynarmic/backend/arm64/emit_arm64_data_processing.cpp index 23347eea..2398bc0f 100644 --- a/src/dynarmic/backend/arm64/emit_arm64_data_processing.cpp +++ b/src/dynarmic/backend/arm64/emit_arm64_data_processing.cpp @@ -758,8 +758,18 @@ static void EmitAddSub(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* MaybeAddSubImm(code, sub ? ~imm : imm, [&](const auto b) { code.ADD(Rresult, *Ra, b); }); } } else { - code.MOV(Rscratch0(), imm); - sub ? code.SBC(Rresult, Ra, Rscratch0()) : code.ADC(Rresult, Ra, Rscratch0()); + ctx.reg_alloc.ReadWriteFlags(args[2], nullptr); + + if (imm == 0) { + if constexpr (bitsize == 32) { + sub ? code.SBC(Rresult, Ra, WZR) : code.ADC(Rresult, Ra, WZR); + } else { + sub ? code.SBC(Rresult, Ra, XZR) : code.ADC(Rresult, Ra, XZR); + } + } else { + code.MOV(Rscratch0(), imm); + sub ? code.SBC(Rresult, Ra, Rscratch0()) : code.ADC(Rresult, Ra, Rscratch0()); + } } } else { auto Rb = ctx.reg_alloc.ReadReg(args[1]); @@ -783,6 +793,8 @@ static void EmitAddSub(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* } } } else { + ctx.reg_alloc.ReadWriteFlags(args[2], nullptr); + sub ? code.SBC(Rresult, Ra, Rb) : code.ADC(Rresult, Ra, Rb); } } diff --git a/src/dynarmic/backend/arm64/reg_alloc.cpp b/src/dynarmic/backend/arm64/reg_alloc.cpp index c54c3d10..e1776033 100644 --- a/src/dynarmic/backend/arm64/reg_alloc.cpp +++ b/src/dynarmic/backend/arm64/reg_alloc.cpp @@ -274,7 +274,7 @@ int RegAlloc::RealizeReadImpl(const IR::Value& value) { // ASSERT size fits break; case HostLoc::Kind::Spill: - code.LDR(oaknut::XReg{new_location_index}, SP, spill_offset + new_location_index * spill_slot_size); + code.LDR(oaknut::XReg{new_location_index}, SP, spill_offset + current_location->index * spill_slot_size); break; case HostLoc::Kind::Flags: code.MRS(oaknut::XReg{new_location_index}, oaknut::SystemReg::NZCV); @@ -296,7 +296,7 @@ int RegAlloc::RealizeReadImpl(const IR::Value& value) { ASSERT_FALSE("Logic error"); break; case HostLoc::Kind::Spill: - code.LDR(oaknut::QReg{new_location_index}, SP, spill_offset + new_location_index * spill_slot_size); + code.LDR(oaknut::QReg{new_location_index}, SP, spill_offset + current_location->index * spill_slot_size); break; case HostLoc::Kind::Flags: ASSERT_FALSE("Moving from flags into fprs is not currently supported"); @@ -307,7 +307,7 @@ int RegAlloc::RealizeReadImpl(const IR::Value& value) { fprs[new_location_index].realized = true; return new_location_index; } else if constexpr (required_kind == HostLoc::Kind::Flags) { - ASSERT_FALSE("Loading flags back into NZCV is not currently supported"); + ASSERT_FALSE("A simple read from flags is likely a logic error."); } else { static_assert(required_kind == HostLoc::Kind::Fpr || required_kind == HostLoc::Kind::Gpr || required_kind == HostLoc::Kind::Flags); } @@ -399,9 +399,12 @@ void RegAlloc::ReadWriteFlags(Argument& read, IR::Inst* write) { } else { ASSERT_FALSE("Invalid current location for flags"); } - flags.SetupLocation(write); - flags.locked--; - flags.realized = false; + + if (write) { + flags.SetupLocation(write); + flags.locked--; + flags.realized = false; + } } void RegAlloc::SpillFlags() { diff --git a/src/dynarmic/backend/arm64/reg_alloc.h b/src/dynarmic/backend/arm64/reg_alloc.h index 151ffa2b..aa77e9ed 100644 --- a/src/dynarmic/backend/arm64/reg_alloc.h +++ b/src/dynarmic/backend/arm64/reg_alloc.h @@ -153,8 +153,6 @@ public: auto ReadH(Argument& arg) { return RAReg{*this, false, arg.value}; } auto ReadB(Argument& arg) { return RAReg{*this, false, arg.value}; } - auto ReadFlags(Argument& arg) { return RAReg{*this, false, arg.value}; } - template auto ReadReg(Argument& arg) { if constexpr (size == 64) { @@ -300,7 +298,7 @@ RAReg::~RAReg() { HostLocInfo& info = reg_alloc.ValueInfo(value.GetInst()); info.locked--; if (reg) { - info.realized = false; + reg_alloc.ValueInfo(HostLoc{kind, reg->index()}).realized = false; } } }