From 00e4fe3f69e36a98241a14524ee984cb50b4084b Mon Sep 17 00:00:00 2001 From: Alyssa Rosenzweig Date: Wed, 28 Aug 2024 13:06:48 -0400 Subject: [PATCH] IR: push down AXFLAG lowering so we can get the new axflag optimizations on billy's x13s. Signed-off-by: Alyssa Rosenzweig --- .../Interface/Core/JIT/Arm64/ALUOps.cpp | 19 +++++++++++++++-- .../Source/Interface/Core/OpcodeDispatcher.h | 21 ++++--------------- FEXCore/Source/Interface/IR/IR.json | 5 +++-- 3 files changed, 24 insertions(+), 21 deletions(-) diff --git a/FEXCore/Source/Interface/Core/JIT/Arm64/ALUOps.cpp b/FEXCore/Source/Interface/Core/JIT/Arm64/ALUOps.cpp index d1283b1460..d47501756f 100644 --- a/FEXCore/Source/Interface/Core/JIT/Arm64/ALUOps.cpp +++ b/FEXCore/Source/Interface/Core/JIT/Arm64/ALUOps.cpp @@ -5,6 +5,7 @@ tags: backend|arm64 $end_info$ */ +#include "CodeEmitter/Emitter.h" #include "FEXCore/IR/IR.h" #include "Interface/Context/Context.h" #include "Interface/Core/JIT/Arm64/JITClass.h" @@ -296,8 +297,22 @@ DEF_OP(SetSmallNZV) { } DEF_OP(AXFlag) { - LOGMAN_THROW_A_FMT(CTX->HostFeatures.SupportsFlagM2, "Unsupported flagm2 op"); - axflag(); + if (CTX->HostFeatures.SupportsFlagM2) { + axflag(); + } else { + // AXFLAG is defined in the Arm spec as + // + // gt: nzCv -> nzCv + // lt: Nzcv -> nzcv <==> 1 + 0 + // eq: nZCv -> nZCv <==> 1 + (~0) + // un: nzCV -> nZcv <==> 0 + 0 + // + // For the latter 3 cases, we therefore get the right NZCV by adding V_inv + // to (eq ? ~0 : 0). The remaining case is forced with ccmn. + auto V_inv = GetReg(IROp->Args[0].ID()); + csetm(ARMEmitter::Size::i64Bit, TMP1, ARMEmitter::Condition::CC_EQ); + ccmn(ARMEmitter::Size::i64Bit, V_inv, TMP1, ARMEmitter::StatusFlags {0x2} /* nzCv */, ARMEmitter::Condition::CC_LE); + } } DEF_OP(CondAddNZCV) { diff --git a/FEXCore/Source/Interface/Core/OpcodeDispatcher.h b/FEXCore/Source/Interface/Core/OpcodeDispatcher.h index d6dfdc0409..d9f19da1bf 100644 --- a/FEXCore/Source/Interface/Core/OpcodeDispatcher.h +++ b/FEXCore/Source/Interface/Core/OpcodeDispatcher.h @@ -2102,22 +2102,9 @@ class OpDispatchBuilder final : public IREmitter { // Convert NZCV from the Arm representation to an eXternal representation // that's totally not a euphemism for x86, nuh-uh. But maps to exactly we // need, what a coincidence! - if (CTX->HostFeatures.SupportsFlagM2) { - _AXFlag(); - } else { - // AXFLAG is defined in the Arm spec as - // - // gt: nzCv -> nzCv - // lt: Nzcv -> nzcv <==> 1 + 0 - // eq: nZCv -> nZCv <==> 1 + (~0) - // un: nzCV -> nZcv <==> 0 + 0 - // - // For the latter 3 cases, we therefore get the right NZCV by adding V_inv - // to (eq ? ~0 : 0). The remaining case is forced with ccmn. - Ref Eq = NZCVSelect(OpSize::i64Bit, {COND_EQ}, _Constant(~0ull), _Constant(0)); - _CondAddNZCV(OpSize::i64Bit, V_inv, Eq, {COND_FLEU}, 0x2 /* nzCv */); - } - + // + // Our AXFlag emulation on FlagM2-less systems needs V_inv passed. + _AXFlag(CTX->HostFeatures.SupportsFlagM2 ? Invalid() : V_inv); PossiblySetNZCVBits = ~0; CFInverted = true; } @@ -2131,7 +2118,7 @@ class OpDispatchBuilder final : public IREmitter { LOGMAN_THROW_A_FMT(!NZCVDirty, "only expected after fcmp"); // Convert to x86 flags, saves us from or'ing after. - _AXFlag(); + _AXFlag(Invalid()); PossiblySetNZCVBits = ~0; CFInverted = true; diff --git a/FEXCore/Source/Interface/IR/IR.json b/FEXCore/Source/Interface/IR/IR.json index f6c567f80f..590c64bbf0 100644 --- a/FEXCore/Source/Interface/IR/IR.json +++ b/FEXCore/Source/Interface/IR/IR.json @@ -1139,8 +1139,9 @@ "Desc": ["Invert carry flag in NZCV"], "HasSideEffects": true }, - "AXFlag": { - "Desc": ["After an FCmp, converts NZCV flags from the Arm format to a mysterious eXternal format"], + "AXFlag GPR:$V_inv": { + "Desc": ["After an FCmp, converts NZCV flags from the Arm format to a mysterious eXternal format", + "On FlagM2-less platforms, takes the inverted 1/0 overflow flag"], "HasSideEffects": true }, "RmifNZCV GPR:$Src, u8:$Rotate, u8:$Mask": {