From c6ba51ee357cb489589fd265630dc1636e44d896 Mon Sep 17 00:00:00 2001 From: Lioncache Date: Thu, 9 Mar 2023 01:00:23 -0500 Subject: [PATCH] ARMEmitter: Handle SVE floating-point compare with zero group --- .../Core/ArchHelpers/CodeEmitter/SVEOps.inl | 34 ++++++++++++++++++- .../FEXCore/unittests/Emitter/SVE_Tests.cpp | 26 ++++++++++++++ 2 files changed, 59 insertions(+), 1 deletion(-) diff --git a/External/FEXCore/Source/Interface/Core/ArchHelpers/CodeEmitter/SVEOps.inl b/External/FEXCore/Source/Interface/Core/ArchHelpers/CodeEmitter/SVEOps.inl index a08acc96e..426454dd7 100644 --- a/External/FEXCore/Source/Interface/Core/ArchHelpers/CodeEmitter/SVEOps.inl +++ b/External/FEXCore/Source/Interface/Core/ArchHelpers/CodeEmitter/SVEOps.inl @@ -2231,7 +2231,24 @@ public: // SVE Floating Point Compare - with Zero // SVE floating-point compare with zero - // XXX: + void fcmge(SubRegSize size, PRegister pd, PRegisterZero pg, ZRegister zn) { + SVEFPCompareWithZero(0b00, 0, size, pd, pg, zn); + } + void fcmgt(SubRegSize size, PRegister pd, PRegisterZero pg, ZRegister zn) { + SVEFPCompareWithZero(0b00, 1, size, pd, pg, zn); + } + void fcmlt(SubRegSize size, PRegister pd, PRegisterZero pg, ZRegister zn) { + SVEFPCompareWithZero(0b01, 0, size, pd, pg, zn); + } + void fcmle(SubRegSize size, PRegister pd, PRegisterZero pg, ZRegister zn) { + SVEFPCompareWithZero(0b01, 1, size, pd, pg, zn); + } + void fcmeq(SubRegSize size, PRegister pd, PRegisterZero pg, ZRegister zn) { + SVEFPCompareWithZero(0b10, 0, size, pd, pg, zn); + } + void fcmne(SubRegSize size, PRegister pd, PRegisterZero pg, ZRegister zn) { + SVEFPCompareWithZero(0b11, 0, size, pd, pg, zn); + } // SVE Floating Point Accumulating Reduction // SVE floating-point serial reduction (predicated) @@ -4086,3 +4103,18 @@ private: Instr |= vd.Idx(); dc32(Instr); } + + void SVEFPCompareWithZero(uint32_t eqlt, uint32_t ne, SubRegSize size, PRegister pd, PRegister pg, ZRegister zn) { + LOGMAN_THROW_AA_FMT(size == SubRegSize::i16Bit || size == SubRegSize::i32Bit || size == SubRegSize::i64Bit, + "SubRegSize must be 16-bit, 32-bit, or 64-bit"); + LOGMAN_THROW_A_FMT(pg <= PReg::p7, "Can only use p0-p7 as a governing predicate"); + + uint32_t Instr = 0b0110'0101'0001'0000'0010'0000'0000'0000; + Instr |= FEXCore::ToUnderlying(size) << 22; + Instr |= eqlt << 16; + Instr |= pg.Idx() << 10; + Instr |= zn.Idx() << 5; + Instr |= ne << 4; + Instr |= pd.Idx(); + dc32(Instr); + } diff --git a/External/FEXCore/unittests/Emitter/SVE_Tests.cpp b/External/FEXCore/unittests/Emitter/SVE_Tests.cpp index 68f91f915..0e6148153 100644 --- a/External/FEXCore/unittests/Emitter/SVE_Tests.cpp +++ b/External/FEXCore/unittests/Emitter/SVE_Tests.cpp @@ -2856,6 +2856,32 @@ TEST_CASE_METHOD(TestDisassembler, "Emitter: SVE: SVE floating-point serial redu TEST_SINGLE(fadda(SubRegSize::i64Bit, VReg::v30, PReg::p7, VReg::v30, ZReg::z29), "fadda d30, p7, d30, z29.d"); } +TEST_CASE_METHOD(TestDisassembler, "Emitter: SVE: SVE floating-point compare with zero") { + TEST_SINGLE(fcmge(SubRegSize::i16Bit, PReg::p15, PReg::p7.Zeroing(), ZReg::z30), "fcmge p15.h, p7/z, z30.h, #0.0"); + TEST_SINGLE(fcmge(SubRegSize::i32Bit, PReg::p15, PReg::p7.Zeroing(), ZReg::z30), "fcmge p15.s, p7/z, z30.s, #0.0"); + TEST_SINGLE(fcmge(SubRegSize::i64Bit, PReg::p15, PReg::p7.Zeroing(), ZReg::z30), "fcmge p15.d, p7/z, z30.d, #0.0"); + + TEST_SINGLE(fcmgt(SubRegSize::i16Bit, PReg::p15, PReg::p7.Zeroing(), ZReg::z30), "fcmgt p15.h, p7/z, z30.h, #0.0"); + TEST_SINGLE(fcmgt(SubRegSize::i32Bit, PReg::p15, PReg::p7.Zeroing(), ZReg::z30), "fcmgt p15.s, p7/z, z30.s, #0.0"); + TEST_SINGLE(fcmgt(SubRegSize::i64Bit, PReg::p15, PReg::p7.Zeroing(), ZReg::z30), "fcmgt p15.d, p7/z, z30.d, #0.0"); + + TEST_SINGLE(fcmlt(SubRegSize::i16Bit, PReg::p15, PReg::p7.Zeroing(), ZReg::z30), "fcmlt p15.h, p7/z, z30.h, #0.0"); + TEST_SINGLE(fcmlt(SubRegSize::i32Bit, PReg::p15, PReg::p7.Zeroing(), ZReg::z30), "fcmlt p15.s, p7/z, z30.s, #0.0"); + TEST_SINGLE(fcmlt(SubRegSize::i64Bit, PReg::p15, PReg::p7.Zeroing(), ZReg::z30), "fcmlt p15.d, p7/z, z30.d, #0.0"); + + TEST_SINGLE(fcmle(SubRegSize::i16Bit, PReg::p15, PReg::p7.Zeroing(), ZReg::z30), "fcmle p15.h, p7/z, z30.h, #0.0"); + TEST_SINGLE(fcmle(SubRegSize::i32Bit, PReg::p15, PReg::p7.Zeroing(), ZReg::z30), "fcmle p15.s, p7/z, z30.s, #0.0"); + TEST_SINGLE(fcmle(SubRegSize::i64Bit, PReg::p15, PReg::p7.Zeroing(), ZReg::z30), "fcmle p15.d, p7/z, z30.d, #0.0"); + + TEST_SINGLE(fcmeq(SubRegSize::i16Bit, PReg::p15, PReg::p7.Zeroing(), ZReg::z30), "fcmeq p15.h, p7/z, z30.h, #0.0"); + TEST_SINGLE(fcmeq(SubRegSize::i32Bit, PReg::p15, PReg::p7.Zeroing(), ZReg::z30), "fcmeq p15.s, p7/z, z30.s, #0.0"); + TEST_SINGLE(fcmeq(SubRegSize::i64Bit, PReg::p15, PReg::p7.Zeroing(), ZReg::z30), "fcmeq p15.d, p7/z, z30.d, #0.0"); + + TEST_SINGLE(fcmne(SubRegSize::i16Bit, PReg::p15, PReg::p7.Zeroing(), ZReg::z30), "fcmne p15.h, p7/z, z30.h, #0.0"); + TEST_SINGLE(fcmne(SubRegSize::i32Bit, PReg::p15, PReg::p7.Zeroing(), ZReg::z30), "fcmne p15.s, p7/z, z30.s, #0.0"); + TEST_SINGLE(fcmne(SubRegSize::i64Bit, PReg::p15, PReg::p7.Zeroing(), ZReg::z30), "fcmne p15.d, p7/z, z30.d, #0.0"); +} + TEST_CASE_METHOD(TestDisassembler, "Emitter: SVE: SVE store multiple structures (scalar plus immediate)") { TEST_SINGLE(st2b(ZReg::z31, ZReg::z0, PReg::p6, Reg::r29, 0), "st2b {z31.b, z0.b}, p6, [x29]"); TEST_SINGLE(st2b(ZReg::z26, ZReg::z27, PReg::p6, Reg::r29, 0), "st2b {z26.b, z27.b}, p6, [x29]");