diff --git a/External/FEXCore/Source/Interface/Core/ArchHelpers/CodeEmitter/SVEOps.inl b/External/FEXCore/Source/Interface/Core/ArchHelpers/CodeEmitter/SVEOps.inl index efee6ef4a..11d900d39 100644 --- a/External/FEXCore/Source/Interface/Core/ArchHelpers/CodeEmitter/SVEOps.inl +++ b/External/FEXCore/Source/Interface/Core/ArchHelpers/CodeEmitter/SVEOps.inl @@ -1372,54 +1372,49 @@ public: } // SVE Predicate Misc - // XXX: - // XXX: PNEXT + void pnext(SubRegSize size, PRegister pd, PRegister pv, PRegister pn) { + LOGMAN_THROW_A_FMT(pd == pn, "pd and pn need to be the same"); + SVEPredicateMisc(0b1001, 0b00010, pv.Idx(), size, pd); + } + // SVE predicate test - void ptest(FEXCore::ARMEmitter::PRegister pg, FEXCore::ARMEmitter::PRegister pn) { - constexpr uint32_t Op = 0b0010'0101'0001'0000'11 << 14; - SVEPredicateTest(Op, 0, 1, 0b0000, pg, pn); + void ptest(PRegister pg, PRegister pn) { + SVEPredicateMisc(0b0000, pg.Idx() << 1, pn.Idx(), SubRegSize::i16Bit, PReg::p0); } // SVE predicate first active - void pfirst(FEXCore::ARMEmitter::PRegister pd, FEXCore::ARMEmitter::PRegister pg, FEXCore::ARMEmitter::PRegister pn) { + void pfirst(PRegister pd, PRegister pg, PRegister pn) { LOGMAN_THROW_A_FMT(pd == pn, "pd and pn need to be the same"); - constexpr uint32_t Op = 0b0010'0101'0001'1000'1100 << 12; - SVEPredicateReadFFRPredicated(Op, 0, 1, pg, pd); + SVEPredicateMisc(0b1000, 0b00000, pg.Idx(), SubRegSize::i16Bit, pd); } // SVE predicate zero - void pfalse(FEXCore::ARMEmitter::PRegister pd) { - constexpr uint32_t Op = 0b0010'0101'0001'1000'1110'01 << 10; - SVEPredicateReadFFR(Op, 0, 0, pd); + void pfalse(PRegister pd) { + SVEPredicateMisc(0b1000, 0b10010, 0b0000, SubRegSize::i8Bit, pd); } // SVE predicate read from FFR (predicated) - void rdffr(FEXCore::ARMEmitter::PRegister pd, FEXCore::ARMEmitter::PRegister pg) { - constexpr uint32_t Op = 0b0010'0101'0001'1000'1111 << 12; - SVEPredicateReadFFRPredicated(Op, 0, 0, pg, pd); + void rdffr(PRegister pd, PRegisterZero pg) { + SVEPredicateMisc(0b1000, 0b11000, pg.Idx(), SubRegSize::i8Bit, pd); } - void rdffrs(FEXCore::ARMEmitter::PRegister pd, FEXCore::ARMEmitter::PRegister pg) { - constexpr uint32_t Op = 0b0010'0101'0001'1000'1111 << 12; - SVEPredicateReadFFRPredicated(Op, 0, 1, pg, pd); + void rdffrs(PRegister pd, PRegisterZero pg) { + SVEPredicateMisc(0b1000, 0b11000, pg.Idx(), SubRegSize::i16Bit, pd); } // SVE predicate read from FFR (unpredicated) - void rdffr(FEXCore::ARMEmitter::PRegister pd) { - constexpr uint32_t Op = 0b0010'0101'0001'1001'1111 << 12; - SVEPredicateReadFFR(Op, 0, 0, pd); + void rdffr(PRegister pd) { + SVEPredicateMisc(0b1001, 0b11000, 0b0000, SubRegSize::i8Bit, pd); } // SVE predicate initialize - template - void ptrue(FEXCore::ARMEmitter::PRegister pd, FEXCore::ARMEmitter::PredicatePattern pattern) { - constexpr uint32_t Op = 0b0010'0101'0001'1000'1110 << 12; - SVEPredicateInit(Op, size, 0, pattern, pd); + template + void ptrue(PRegister pd, PredicatePattern pattern) { + SVEPredicateMisc(0b1000, 0b10000, FEXCore::ToUnderlying(pattern), size, pd); } - template - void ptrues(FEXCore::ARMEmitter::PRegister pd, FEXCore::ARMEmitter::PredicatePattern pattern) { - constexpr uint32_t Op = 0b0010'0101'0001'1000'1110 << 12; - SVEPredicateInit(Op, size, 1, pattern, pd); + template + void ptrues(PRegister pd, PredicatePattern pattern) { + SVEPredicateMisc(0b1001, 0b10000, FEXCore::ToUnderlying(pattern), size, pd); } // SVE Integer Compare - Scalars @@ -3705,45 +3700,6 @@ private: Instr |= zt.Idx(); dc32(Instr); } - void SVEPredicateTest(uint32_t Op, uint32_t op, uint32_t S, uint32_t opc2, FEXCore::ARMEmitter::PRegister pg, FEXCore::ARMEmitter::PRegister pn) { - uint32_t Instr = Op; - - Instr |= op << 23; - Instr |= S << 22; - Instr |= pg.Idx() << 10; - Instr |= pn.Idx() << 5; - Instr |= opc2; - dc32(Instr); - } - - void SVEPredicateReadFFRPredicated(uint32_t Op, uint32_t op, uint32_t S, FEXCore::ARMEmitter::PRegister pg, FEXCore::ARMEmitter::PRegister pd) { - uint32_t Instr = Op; - - Instr |= op << 23; - Instr |= S << 22; - Instr |= pg.Idx() << 5; - Instr |= pd.Idx(); - dc32(Instr); - } - - void SVEPredicateReadFFR(uint32_t Op, uint32_t op, uint32_t S, FEXCore::ARMEmitter::PRegister pd) { - uint32_t Instr = Op; - - Instr |= op << 23; - Instr |= S << 16; - Instr |= pd.Idx(); - dc32(Instr); - } - - void SVEPredicateInit(uint32_t Op, FEXCore::ARMEmitter::SubRegSize size, uint32_t S, FEXCore::ARMEmitter::PredicatePattern pattern, FEXCore::ARMEmitter::PRegister pd) { - uint32_t Instr = Op; - - Instr |= FEXCore::ToUnderlying(size) << 22; - Instr |= S << 16; - Instr |= FEXCore::ToUnderlying(pattern) << 5; - Instr |= pd.Idx(); - dc32(Instr); - } void SVEIndexGeneration(uint32_t op, SubRegSize size, ZRegister zd, int32_t imm5, int32_t imm5b) { LOGMAN_THROW_A_FMT(size != SubRegSize::i128Bit, "INDEX cannot use 128-bit element sizes"); @@ -4112,3 +4068,16 @@ private: Instr |= pd.Idx(); dc32(Instr); } + + void SVEPredicateMisc(uint32_t op0, uint32_t op2, uint32_t op3, SubRegSize size, PRegister pd) { + // Note: op2 combines op1 like [op1:op2], since they're adjacent. + LOGMAN_THROW_A_FMT(size != SubRegSize::i128Bit, "Can't use 128-bit size"); + + uint32_t Instr = 0b0010'0101'0001'0000'1100'0000'0000'0000; + Instr |= FEXCore::ToUnderlying(size) << 22; + Instr |= op0 << 16; + Instr |= op2 << 9; + Instr |= op3 << 5; + Instr |= pd.Idx(); + dc32(Instr); + } diff --git a/External/FEXCore/unittests/Emitter/SVE_Tests.cpp b/External/FEXCore/unittests/Emitter/SVE_Tests.cpp index ad0fc8af9..db6ec649a 100644 --- a/External/FEXCore/unittests/Emitter/SVE_Tests.cpp +++ b/External/FEXCore/unittests/Emitter/SVE_Tests.cpp @@ -1395,28 +1395,37 @@ TEST_CASE_METHOD(TestDisassembler, "Emitter: SVE: SVE partition break condition" } TEST_CASE_METHOD(TestDisassembler, "Emitter: SVE: SVE Predicate Misc") { - // TODO: Implement in emitter. + TEST_SINGLE(pnext(SubRegSize::i8Bit, PReg::p15, PReg::p14, PReg::p15), "pnext p15.b, p14, p15.b"); + TEST_SINGLE(pnext(SubRegSize::i16Bit, PReg::p15, PReg::p14, PReg::p15), "pnext p15.h, p14, p15.h"); + TEST_SINGLE(pnext(SubRegSize::i32Bit, PReg::p15, PReg::p14, PReg::p15), "pnext p15.s, p14, p15.s"); + TEST_SINGLE(pnext(SubRegSize::i64Bit, PReg::p15, PReg::p14, PReg::p15), "pnext p15.d, p14, p15.d"); } TEST_CASE_METHOD(TestDisassembler, "Emitter: SVE: SVE predicate test") { - TEST_SINGLE(ptest(PReg::p6, PReg::p5), "ptest p6, p5.b"); + TEST_SINGLE(ptest(PReg::p6, PReg::p5), "ptest p6, p5.b"); + TEST_SINGLE(ptest(PReg::p15, PReg::p14), "ptest p15, p14.b"); } TEST_CASE_METHOD(TestDisassembler, "Emitter: SVE: SVE predicate first active") { - TEST_SINGLE(pfirst(PReg::p6, PReg::p5, PReg::p6), "pfirst p6.b, p5, p6.b"); + TEST_SINGLE(pfirst(PReg::p6, PReg::p5, PReg::p6), "pfirst p6.b, p5, p6.b"); + TEST_SINGLE(pfirst(PReg::p15, PReg::p14, PReg::p15), "pfirst p15.b, p14, p15.b"); } TEST_CASE_METHOD(TestDisassembler, "Emitter: SVE: SVE predicate zero") { - TEST_SINGLE(pfalse(PReg::p6), "pfalse p6.b"); + TEST_SINGLE(pfalse(PReg::p6), "pfalse p6.b"); + TEST_SINGLE(pfalse(PReg::p15), "pfalse p15.b"); } TEST_CASE_METHOD(TestDisassembler, "Emitter: SVE: SVE predicate read from FFR (predicated)") { - TEST_SINGLE(rdffr(PReg::p6, PReg::p5), "rdffr p6.b, p5/z"); - TEST_SINGLE(rdffrs(PReg::p6, PReg::p5), "rdffrs p6.b, p5/z"); + TEST_SINGLE(rdffr(PReg::p6, PReg::p5.Zeroing()), "rdffr p6.b, p5/z"); + TEST_SINGLE(rdffr(PReg::p15, PReg::p14.Zeroing()), "rdffr p15.b, p14/z"); + TEST_SINGLE(rdffrs(PReg::p6, PReg::p5.Zeroing()), "rdffrs p6.b, p5/z"); + TEST_SINGLE(rdffrs(PReg::p15, PReg::p14.Zeroing()), "rdffrs p15.b, p14/z"); } TEST_CASE_METHOD(TestDisassembler, "Emitter: SVE: SVE predicate read from FFR (unpredicated)") { - TEST_SINGLE(rdffr(PReg::p6), "rdffr p6.b"); + TEST_SINGLE(rdffr(PReg::p6), "rdffr p6.b"); + TEST_SINGLE(rdffr(PReg::p15), "rdffr p15.b"); } TEST_CASE_METHOD(TestDisassembler, "Emitter: SVE: SVE predicate initialize") {