diff --git a/External/FEXCore/Source/Interface/Core/ArchHelpers/CodeEmitter/SVEOps.inl b/External/FEXCore/Source/Interface/Core/ArchHelpers/CodeEmitter/SVEOps.inl index 12ba2a204..a3fbec28f 100644 --- a/External/FEXCore/Source/Interface/Core/ArchHelpers/CodeEmitter/SVEOps.inl +++ b/External/FEXCore/Source/Interface/Core/ArchHelpers/CodeEmitter/SVEOps.inl @@ -573,7 +573,26 @@ public: } // SVE floating-point recursive reduction - // XXX: + void faddv(SubRegSize size, VRegister vd, PRegister pg, ZRegister zn) { + constexpr uint32_t Op = 0b0110'0101'0000'0000'0010'0000'0000'0000; + SVEFPRecursiveReduction(Op, 0b000, size, vd, pg, zn); + } + void fmaxnmv(SubRegSize size, VRegister vd, PRegister pg, ZRegister zn) { + constexpr uint32_t Op = 0b0110'0101'0000'0000'0010'0000'0000'0000; + SVEFPRecursiveReduction(Op, 0b100, size, vd, pg, zn); + } + void fminnmv(SubRegSize size, VRegister vd, PRegister pg, ZRegister zn) { + constexpr uint32_t Op = 0b0110'0101'0000'0000'0010'0000'0000'0000; + SVEFPRecursiveReduction(Op, 0b101, size, vd, pg, zn); + } + void fmaxv(SubRegSize size, VRegister vd, PRegister pg, ZRegister zn) { + constexpr uint32_t Op = 0b0110'0101'0000'0000'0010'0000'0000'0000; + SVEFPRecursiveReduction(Op, 0b110, size, vd, pg, zn); + } + void fminv(SubRegSize size, VRegister vd, PRegister pg, ZRegister zn) { + constexpr uint32_t Op = 0b0110'0101'0000'0000'0010'0000'0000'0000; + SVEFPRecursiveReduction(Op, 0b111, size, vd, pg, zn); + } // SVE integer Multiply-Add - Predicated // SVE integer multiply-accumulate writing addend (predicated) @@ -3929,6 +3948,20 @@ private: dc32(Instr); } + void SVEFPRecursiveReduction(uint32_t op, uint32_t opc, SubRegSize size, VRegister vd, PRegister pg, ZRegister zn) { + LOGMAN_THROW_AA_FMT(size == SubRegSize::i16Bit || size == SubRegSize::i32Bit || size == SubRegSize::i64Bit, + "FP reduction operation can only use 16-bit, 32-bit, or 64-bit element sizes"); + LOGMAN_THROW_AA_FMT(pg <= PReg::p7, "FP reduction operation can only use p0-p7 as a governing predicate"); + + uint32_t Instr = op; + Instr |= FEXCore::ToUnderlying(size) << 22; + Instr |= opc << 16; + Instr |= pg.Idx() << 10; + Instr |= zn.Idx() << 5; + Instr |= vd.Idx(); + dc32(Instr); + } + // SVE floating-point round to integral value void frintX(uint32_t opc, FEXCore::ARMEmitter::SubRegSize size, FEXCore::ARMEmitter::ZRegister zd, FEXCore::ARMEmitter::PRegister pg, FEXCore::ARMEmitter::ZRegister zn) { // opc = round mode diff --git a/External/FEXCore/unittests/Emitter/SVE_Tests.cpp b/External/FEXCore/unittests/Emitter/SVE_Tests.cpp index 3115e212f..57f0ebaf6 100644 --- a/External/FEXCore/unittests/Emitter/SVE_Tests.cpp +++ b/External/FEXCore/unittests/Emitter/SVE_Tests.cpp @@ -433,7 +433,25 @@ TEST_CASE_METHOD(TestDisassembler, "Emitter: SVE: SVE floating-point arithmetic //TEST_SINGLE(frsqrts(SubRegSize::i128Bit, ZReg::z30, ZReg::z29, ZReg::z28), "frsqrts z30.q, z29.q, z28.q"); } TEST_CASE_METHOD(TestDisassembler, "Emitter: SVE: SVE floating-point recursive reduction") { - // TODO: Implement in emitter. + TEST_SINGLE(faddv(SubRegSize::i16Bit, VReg::v30, PReg::p7, ZReg::z28), "faddv h30, p7, z28.h"); + TEST_SINGLE(faddv(SubRegSize::i32Bit, VReg::v30, PReg::p7, ZReg::z28), "faddv s30, p7, z28.s"); + TEST_SINGLE(faddv(SubRegSize::i64Bit, VReg::v30, PReg::p7, ZReg::z28), "faddv d30, p7, z28.d"); + + TEST_SINGLE(fmaxnmv(SubRegSize::i16Bit, VReg::v30, PReg::p7, ZReg::z28), "fmaxnmv h30, p7, z28.h"); + TEST_SINGLE(fmaxnmv(SubRegSize::i32Bit, VReg::v30, PReg::p7, ZReg::z28), "fmaxnmv s30, p7, z28.s"); + TEST_SINGLE(fmaxnmv(SubRegSize::i64Bit, VReg::v30, PReg::p7, ZReg::z28), "fmaxnmv d30, p7, z28.d"); + + TEST_SINGLE(fminnmv(SubRegSize::i16Bit, VReg::v30, PReg::p7, ZReg::z28), "fminnmv h30, p7, z28.h"); + TEST_SINGLE(fminnmv(SubRegSize::i32Bit, VReg::v30, PReg::p7, ZReg::z28), "fminnmv s30, p7, z28.s"); + TEST_SINGLE(fminnmv(SubRegSize::i64Bit, VReg::v30, PReg::p7, ZReg::z28), "fminnmv d30, p7, z28.d"); + + TEST_SINGLE(fmaxv(SubRegSize::i16Bit, VReg::v30, PReg::p7, ZReg::z28), "fmaxv h30, p7, z28.h"); + TEST_SINGLE(fmaxv(SubRegSize::i32Bit, VReg::v30, PReg::p7, ZReg::z28), "fmaxv s30, p7, z28.s"); + TEST_SINGLE(fmaxv(SubRegSize::i64Bit, VReg::v30, PReg::p7, ZReg::z28), "fmaxv d30, p7, z28.d"); + + TEST_SINGLE(fminv(SubRegSize::i16Bit, VReg::v30, PReg::p7, ZReg::z28), "fminv h30, p7, z28.h"); + TEST_SINGLE(fminv(SubRegSize::i32Bit, VReg::v30, PReg::p7, ZReg::z28), "fminv s30, p7, z28.s"); + TEST_SINGLE(fminv(SubRegSize::i64Bit, VReg::v30, PReg::p7, ZReg::z28), "fminv d30, p7, z28.d"); } TEST_CASE_METHOD(TestDisassembler, "Emitter: SVE: SVE integer multiply-accumulate writing addend (predicated)") {