From 437ea926b45bb14e5a176b8f3deba3ca7388c8bf Mon Sep 17 00:00:00 2001 From: Lioncache Date: Tue, 21 Mar 2023 12:41:21 -0400 Subject: [PATCH] ARMEmitter: Handle SVE saturating inc/dec register by element count --- .../Core/ArchHelpers/CodeEmitter/SVEOps.inl | 100 +++++++++++++- .../FEXCore/unittests/Emitter/SVE_Tests.cpp | 128 +++++++++++++++++- 2 files changed, 226 insertions(+), 2 deletions(-) diff --git a/External/FEXCore/Source/Interface/Core/ArchHelpers/CodeEmitter/SVEOps.inl b/External/FEXCore/Source/Interface/Core/ArchHelpers/CodeEmitter/SVEOps.inl index f666843ef..d520f52cd 100644 --- a/External/FEXCore/Source/Interface/Core/ArchHelpers/CodeEmitter/SVEOps.inl +++ b/External/FEXCore/Source/Interface/Core/ArchHelpers/CodeEmitter/SVEOps.inl @@ -1118,7 +1118,105 @@ public: } // SVE saturating inc/dec register by element count - // XXX: + void sqincb(XRegister rdn, PredicatePattern pattern, uint32_t imm) { + SVEElementCount(1, 0b1100, SubRegSize::i8Bit, ZRegister{rdn.Idx()}, pattern, imm); + } + void sqincb(WRegister rdn, PredicatePattern pattern, uint32_t imm) { + SVEElementCount(0, 0b1100, SubRegSize::i8Bit, ZRegister{rdn.Idx()}, pattern, imm); + } + void uqincb(XRegister rdn, PredicatePattern pattern, uint32_t imm) { + SVEElementCount(1, 0b1101, SubRegSize::i8Bit, ZRegister{rdn.Idx()}, pattern, imm); + } + void uqincb(WRegister rdn, PredicatePattern pattern, uint32_t imm) { + SVEElementCount(0, 0b1101, SubRegSize::i8Bit, ZRegister{rdn.Idx()}, pattern, imm); + } + void sqdecb(XRegister rdn, PredicatePattern pattern, uint32_t imm) { + SVEElementCount(1, 0b1110, SubRegSize::i8Bit, ZRegister{rdn.Idx()}, pattern, imm); + } + void sqdecb(WRegister rdn, PredicatePattern pattern, uint32_t imm) { + SVEElementCount(0, 0b1110, SubRegSize::i8Bit, ZRegister{rdn.Idx()}, pattern, imm); + } + void uqdecb(XRegister rdn, PredicatePattern pattern, uint32_t imm) { + SVEElementCount(1, 0b1111, SubRegSize::i8Bit, ZRegister{rdn.Idx()}, pattern, imm); + } + void uqdecb(WRegister rdn, PredicatePattern pattern, uint32_t imm) { + SVEElementCount(0, 0b1111, SubRegSize::i8Bit, ZRegister{rdn.Idx()}, pattern, imm); + } + + void sqinch(XRegister rdn, PredicatePattern pattern, uint32_t imm) { + SVEElementCount(1, 0b1100, SubRegSize::i16Bit, ZRegister{rdn.Idx()}, pattern, imm); + } + void sqinch(WRegister rdn, PredicatePattern pattern, uint32_t imm) { + SVEElementCount(0, 0b1100, SubRegSize::i16Bit, ZRegister{rdn.Idx()}, pattern, imm); + } + void uqinch(XRegister rdn, PredicatePattern pattern, uint32_t imm) { + SVEElementCount(1, 0b1101, SubRegSize::i16Bit, ZRegister{rdn.Idx()}, pattern, imm); + } + void uqinch(WRegister rdn, PredicatePattern pattern, uint32_t imm) { + SVEElementCount(0, 0b1101, SubRegSize::i16Bit, ZRegister{rdn.Idx()}, pattern, imm); + } + void sqdech(XRegister rdn, PredicatePattern pattern, uint32_t imm) { + SVEElementCount(1, 0b1110, SubRegSize::i16Bit, ZRegister{rdn.Idx()}, pattern, imm); + } + void sqdech(WRegister rdn, PredicatePattern pattern, uint32_t imm) { + SVEElementCount(0, 0b1110, SubRegSize::i16Bit, ZRegister{rdn.Idx()}, pattern, imm); + } + void uqdech(XRegister rdn, PredicatePattern pattern, uint32_t imm) { + SVEElementCount(1, 0b1111, SubRegSize::i16Bit, ZRegister{rdn.Idx()}, pattern, imm); + } + void uqdech(WRegister rdn, PredicatePattern pattern, uint32_t imm) { + SVEElementCount(0, 0b1111, SubRegSize::i16Bit, ZRegister{rdn.Idx()}, pattern, imm); + } + + void sqincw(XRegister rdn, PredicatePattern pattern, uint32_t imm) { + SVEElementCount(1, 0b1100, SubRegSize::i32Bit, ZRegister{rdn.Idx()}, pattern, imm); + } + void sqincw(WRegister rdn, PredicatePattern pattern, uint32_t imm) { + SVEElementCount(0, 0b1100, SubRegSize::i32Bit, ZRegister{rdn.Idx()}, pattern, imm); + } + void uqincw(XRegister rdn, PredicatePattern pattern, uint32_t imm) { + SVEElementCount(1, 0b1101, SubRegSize::i32Bit, ZRegister{rdn.Idx()}, pattern, imm); + } + void uqincw(WRegister rdn, PredicatePattern pattern, uint32_t imm) { + SVEElementCount(0, 0b1101, SubRegSize::i32Bit, ZRegister{rdn.Idx()}, pattern, imm); + } + void sqdecw(XRegister rdn, PredicatePattern pattern, uint32_t imm) { + SVEElementCount(1, 0b1110, SubRegSize::i32Bit, ZRegister{rdn.Idx()}, pattern, imm); + } + void sqdecw(WRegister rdn, PredicatePattern pattern, uint32_t imm) { + SVEElementCount(0, 0b1110, SubRegSize::i32Bit, ZRegister{rdn.Idx()}, pattern, imm); + } + void uqdecw(XRegister rdn, PredicatePattern pattern, uint32_t imm) { + SVEElementCount(1, 0b1111, SubRegSize::i32Bit, ZRegister{rdn.Idx()}, pattern, imm); + } + void uqdecw(WRegister rdn, PredicatePattern pattern, uint32_t imm) { + SVEElementCount(0, 0b1111, SubRegSize::i32Bit, ZRegister{rdn.Idx()}, pattern, imm); + } + + void sqincd(XRegister rdn, PredicatePattern pattern, uint32_t imm) { + SVEElementCount(1, 0b1100, SubRegSize::i64Bit, ZRegister{rdn.Idx()}, pattern, imm); + } + void sqincd(WRegister rdn, PredicatePattern pattern, uint32_t imm) { + SVEElementCount(0, 0b1100, SubRegSize::i64Bit, ZRegister{rdn.Idx()}, pattern, imm); + } + void uqincd(XRegister rdn, PredicatePattern pattern, uint32_t imm) { + SVEElementCount(1, 0b1101, SubRegSize::i64Bit, ZRegister{rdn.Idx()}, pattern, imm); + } + void uqincd(WRegister rdn, PredicatePattern pattern, uint32_t imm) { + SVEElementCount(0, 0b1101, SubRegSize::i64Bit, ZRegister{rdn.Idx()}, pattern, imm); + } + void sqdecd(XRegister rdn, PredicatePattern pattern, uint32_t imm) { + SVEElementCount(1, 0b1110, SubRegSize::i64Bit, ZRegister{rdn.Idx()}, pattern, imm); + } + void sqdecd(WRegister rdn, PredicatePattern pattern, uint32_t imm) { + SVEElementCount(0, 0b1110, SubRegSize::i64Bit, ZRegister{rdn.Idx()}, pattern, imm); + } + void uqdecd(XRegister rdn, PredicatePattern pattern, uint32_t imm) { + SVEElementCount(1, 0b1111, SubRegSize::i64Bit, ZRegister{rdn.Idx()}, pattern, imm); + } + void uqdecd(WRegister rdn, PredicatePattern pattern, uint32_t imm) { + SVEElementCount(0, 0b1111, SubRegSize::i64Bit, ZRegister{rdn.Idx()}, pattern, imm); + } // SVE Bitwise Immediate // XXX: DUPM diff --git a/External/FEXCore/unittests/Emitter/SVE_Tests.cpp b/External/FEXCore/unittests/Emitter/SVE_Tests.cpp index 23fb8bbc7..c6906072c 100644 --- a/External/FEXCore/unittests/Emitter/SVE_Tests.cpp +++ b/External/FEXCore/unittests/Emitter/SVE_Tests.cpp @@ -1195,7 +1195,133 @@ TEST_CASE_METHOD(TestDisassembler, "Emitter: SVE: SVE inc/dec register by elemen } TEST_CASE_METHOD(TestDisassembler, "Emitter: SVE: SVE saturating inc/dec register by element count") { - // TODO: Implement in emitter. + TEST_SINGLE(sqincb(XReg::x30, PredicatePattern::SVE_POW2 , 1), "sqincb x30, pow2"); + TEST_SINGLE(sqincb(XReg::x30, PredicatePattern::SVE_VL256, 7), "sqincb x30, vl256, mul #7"); + TEST_SINGLE(sqincb(XReg::x30, PredicatePattern::SVE_ALL , 16), "sqincb x30, all, mul #16"); + + TEST_SINGLE(sqincb(WReg::w30, PredicatePattern::SVE_POW2 , 1), "sqincb x30, w30, pow2"); + TEST_SINGLE(sqincb(WReg::w30, PredicatePattern::SVE_VL256, 7), "sqincb x30, w30, vl256, mul #7"); + TEST_SINGLE(sqincb(WReg::w30, PredicatePattern::SVE_ALL , 16), "sqincb x30, w30, all, mul #16"); + + TEST_SINGLE(uqincb(XReg::x30, PredicatePattern::SVE_POW2 , 1), "uqincb x30, pow2"); + TEST_SINGLE(uqincb(XReg::x30, PredicatePattern::SVE_VL256, 7), "uqincb x30, vl256, mul #7"); + TEST_SINGLE(uqincb(XReg::x30, PredicatePattern::SVE_ALL , 16), "uqincb x30, all, mul #16"); + + TEST_SINGLE(uqincb(WReg::w30, PredicatePattern::SVE_POW2 , 1), "uqincb w30, pow2"); + TEST_SINGLE(uqincb(WReg::w30, PredicatePattern::SVE_VL256, 7), "uqincb w30, vl256, mul #7"); + TEST_SINGLE(uqincb(WReg::w30, PredicatePattern::SVE_ALL , 16), "uqincb w30, all, mul #16"); + + TEST_SINGLE(sqdecb(XReg::x30, PredicatePattern::SVE_POW2 , 1), "sqdecb x30, pow2"); + TEST_SINGLE(sqdecb(XReg::x30, PredicatePattern::SVE_VL256, 7), "sqdecb x30, vl256, mul #7"); + TEST_SINGLE(sqdecb(XReg::x30, PredicatePattern::SVE_ALL , 16), "sqdecb x30, all, mul #16"); + + TEST_SINGLE(sqdecb(WReg::w30, PredicatePattern::SVE_POW2 , 1), "sqdecb x30, w30, pow2"); + TEST_SINGLE(sqdecb(WReg::w30, PredicatePattern::SVE_VL256, 7), "sqdecb x30, w30, vl256, mul #7"); + TEST_SINGLE(sqdecb(WReg::w30, PredicatePattern::SVE_ALL , 16), "sqdecb x30, w30, all, mul #16"); + + TEST_SINGLE(uqdecb(XReg::x30, PredicatePattern::SVE_POW2 , 1), "uqdecb x30, pow2"); + TEST_SINGLE(uqdecb(XReg::x30, PredicatePattern::SVE_VL256, 7), "uqdecb x30, vl256, mul #7"); + TEST_SINGLE(uqdecb(XReg::x30, PredicatePattern::SVE_ALL , 16), "uqdecb x30, all, mul #16"); + + TEST_SINGLE(uqdecb(WReg::w30, PredicatePattern::SVE_POW2 , 1), "uqdecb w30, pow2"); + TEST_SINGLE(uqdecb(WReg::w30, PredicatePattern::SVE_VL256, 7), "uqdecb w30, vl256, mul #7"); + TEST_SINGLE(uqdecb(WReg::w30, PredicatePattern::SVE_ALL , 16), "uqdecb w30, all, mul #16"); + + TEST_SINGLE(sqinch(XReg::x30, PredicatePattern::SVE_POW2 , 1), "sqinch x30, pow2"); + TEST_SINGLE(sqinch(XReg::x30, PredicatePattern::SVE_VL256, 7), "sqinch x30, vl256, mul #7"); + TEST_SINGLE(sqinch(XReg::x30, PredicatePattern::SVE_ALL , 16), "sqinch x30, all, mul #16"); + + TEST_SINGLE(sqinch(WReg::w30, PredicatePattern::SVE_POW2 , 1), "sqinch x30, w30, pow2"); + TEST_SINGLE(sqinch(WReg::w30, PredicatePattern::SVE_VL256, 7), "sqinch x30, w30, vl256, mul #7"); + TEST_SINGLE(sqinch(WReg::w30, PredicatePattern::SVE_ALL , 16), "sqinch x30, w30, all, mul #16"); + + TEST_SINGLE(uqinch(XReg::x30, PredicatePattern::SVE_POW2 , 1), "uqinch x30, pow2"); + TEST_SINGLE(uqinch(XReg::x30, PredicatePattern::SVE_VL256, 7), "uqinch x30, vl256, mul #7"); + TEST_SINGLE(uqinch(XReg::x30, PredicatePattern::SVE_ALL , 16), "uqinch x30, all, mul #16"); + + TEST_SINGLE(uqinch(WReg::w30, PredicatePattern::SVE_POW2 , 1), "uqinch w30, pow2"); + TEST_SINGLE(uqinch(WReg::w30, PredicatePattern::SVE_VL256, 7), "uqinch w30, vl256, mul #7"); + TEST_SINGLE(uqinch(WReg::w30, PredicatePattern::SVE_ALL , 16), "uqinch w30, all, mul #16"); + + TEST_SINGLE(sqdech(XReg::x30, PredicatePattern::SVE_POW2 , 1), "sqdech x30, pow2"); + TEST_SINGLE(sqdech(XReg::x30, PredicatePattern::SVE_VL256, 7), "sqdech x30, vl256, mul #7"); + TEST_SINGLE(sqdech(XReg::x30, PredicatePattern::SVE_ALL , 16), "sqdech x30, all, mul #16"); + + TEST_SINGLE(sqdech(WReg::w30, PredicatePattern::SVE_POW2 , 1), "sqdech x30, w30, pow2"); + TEST_SINGLE(sqdech(WReg::w30, PredicatePattern::SVE_VL256, 7), "sqdech x30, w30, vl256, mul #7"); + TEST_SINGLE(sqdech(WReg::w30, PredicatePattern::SVE_ALL , 16), "sqdech x30, w30, all, mul #16"); + + TEST_SINGLE(uqdech(XReg::x30, PredicatePattern::SVE_POW2 , 1), "uqdech x30, pow2"); + TEST_SINGLE(uqdech(XReg::x30, PredicatePattern::SVE_VL256, 7), "uqdech x30, vl256, mul #7"); + TEST_SINGLE(uqdech(XReg::x30, PredicatePattern::SVE_ALL , 16), "uqdech x30, all, mul #16"); + + TEST_SINGLE(uqdech(WReg::w30, PredicatePattern::SVE_POW2 , 1), "uqdech w30, pow2"); + TEST_SINGLE(uqdech(WReg::w30, PredicatePattern::SVE_VL256, 7), "uqdech w30, vl256, mul #7"); + TEST_SINGLE(uqdech(WReg::w30, PredicatePattern::SVE_ALL , 16), "uqdech w30, all, mul #16"); + + TEST_SINGLE(sqincw(XReg::x30, PredicatePattern::SVE_POW2 , 1), "sqincw x30, pow2"); + TEST_SINGLE(sqincw(XReg::x30, PredicatePattern::SVE_VL256, 7), "sqincw x30, vl256, mul #7"); + TEST_SINGLE(sqincw(XReg::x30, PredicatePattern::SVE_ALL , 16), "sqincw x30, all, mul #16"); + + TEST_SINGLE(sqincw(WReg::w30, PredicatePattern::SVE_POW2 , 1), "sqincw x30, w30, pow2"); + TEST_SINGLE(sqincw(WReg::w30, PredicatePattern::SVE_VL256, 7), "sqincw x30, w30, vl256, mul #7"); + TEST_SINGLE(sqincw(WReg::w30, PredicatePattern::SVE_ALL , 16), "sqincw x30, w30, all, mul #16"); + + TEST_SINGLE(uqincw(XReg::x30, PredicatePattern::SVE_POW2 , 1), "uqincw x30, pow2"); + TEST_SINGLE(uqincw(XReg::x30, PredicatePattern::SVE_VL256, 7), "uqincw x30, vl256, mul #7"); + TEST_SINGLE(uqincw(XReg::x30, PredicatePattern::SVE_ALL , 16), "uqincw x30, all, mul #16"); + + TEST_SINGLE(uqincw(WReg::w30, PredicatePattern::SVE_POW2 , 1), "uqincw w30, pow2"); + TEST_SINGLE(uqincw(WReg::w30, PredicatePattern::SVE_VL256, 7), "uqincw w30, vl256, mul #7"); + TEST_SINGLE(uqincw(WReg::w30, PredicatePattern::SVE_ALL , 16), "uqincw w30, all, mul #16"); + + TEST_SINGLE(sqdecw(XReg::x30, PredicatePattern::SVE_POW2 , 1), "sqdecw x30, pow2"); + TEST_SINGLE(sqdecw(XReg::x30, PredicatePattern::SVE_VL256, 7), "sqdecw x30, vl256, mul #7"); + TEST_SINGLE(sqdecw(XReg::x30, PredicatePattern::SVE_ALL , 16), "sqdecw x30, all, mul #16"); + + TEST_SINGLE(sqdecw(WReg::w30, PredicatePattern::SVE_POW2 , 1), "sqdecw x30, w30, pow2"); + TEST_SINGLE(sqdecw(WReg::w30, PredicatePattern::SVE_VL256, 7), "sqdecw x30, w30, vl256, mul #7"); + TEST_SINGLE(sqdecw(WReg::w30, PredicatePattern::SVE_ALL , 16), "sqdecw x30, w30, all, mul #16"); + + TEST_SINGLE(uqdecw(XReg::x30, PredicatePattern::SVE_POW2 , 1), "uqdecw x30, pow2"); + TEST_SINGLE(uqdecw(XReg::x30, PredicatePattern::SVE_VL256, 7), "uqdecw x30, vl256, mul #7"); + TEST_SINGLE(uqdecw(XReg::x30, PredicatePattern::SVE_ALL , 16), "uqdecw x30, all, mul #16"); + + TEST_SINGLE(uqdecw(WReg::w30, PredicatePattern::SVE_POW2 , 1), "uqdecw w30, pow2"); + TEST_SINGLE(uqdecw(WReg::w30, PredicatePattern::SVE_VL256, 7), "uqdecw w30, vl256, mul #7"); + TEST_SINGLE(uqdecw(WReg::w30, PredicatePattern::SVE_ALL , 16), "uqdecw w30, all, mul #16"); + + TEST_SINGLE(sqincd(XReg::x30, PredicatePattern::SVE_POW2 , 1), "sqincd x30, pow2"); + TEST_SINGLE(sqincd(XReg::x30, PredicatePattern::SVE_VL256, 7), "sqincd x30, vl256, mul #7"); + TEST_SINGLE(sqincd(XReg::x30, PredicatePattern::SVE_ALL , 16), "sqincd x30, all, mul #16"); + + TEST_SINGLE(sqincd(WReg::w30, PredicatePattern::SVE_POW2 , 1), "sqincd x30, w30, pow2"); + TEST_SINGLE(sqincd(WReg::w30, PredicatePattern::SVE_VL256, 7), "sqincd x30, w30, vl256, mul #7"); + TEST_SINGLE(sqincd(WReg::w30, PredicatePattern::SVE_ALL , 16), "sqincd x30, w30, all, mul #16"); + + TEST_SINGLE(uqincd(XReg::x30, PredicatePattern::SVE_POW2 , 1), "uqincd x30, pow2"); + TEST_SINGLE(uqincd(XReg::x30, PredicatePattern::SVE_VL256, 7), "uqincd x30, vl256, mul #7"); + TEST_SINGLE(uqincd(XReg::x30, PredicatePattern::SVE_ALL , 16), "uqincd x30, all, mul #16"); + + TEST_SINGLE(uqincd(WReg::w30, PredicatePattern::SVE_POW2 , 1), "uqincd w30, pow2"); + TEST_SINGLE(uqincd(WReg::w30, PredicatePattern::SVE_VL256, 7), "uqincd w30, vl256, mul #7"); + TEST_SINGLE(uqincd(WReg::w30, PredicatePattern::SVE_ALL , 16), "uqincd w30, all, mul #16"); + + TEST_SINGLE(sqdecd(XReg::x30, PredicatePattern::SVE_POW2 , 1), "sqdecd x30, pow2"); + TEST_SINGLE(sqdecd(XReg::x30, PredicatePattern::SVE_VL256, 7), "sqdecd x30, vl256, mul #7"); + TEST_SINGLE(sqdecd(XReg::x30, PredicatePattern::SVE_ALL , 16), "sqdecd x30, all, mul #16"); + + TEST_SINGLE(sqdecd(WReg::w30, PredicatePattern::SVE_POW2 , 1), "sqdecd x30, w30, pow2"); + TEST_SINGLE(sqdecd(WReg::w30, PredicatePattern::SVE_VL256, 7), "sqdecd x30, w30, vl256, mul #7"); + TEST_SINGLE(sqdecd(WReg::w30, PredicatePattern::SVE_ALL , 16), "sqdecd x30, w30, all, mul #16"); + + TEST_SINGLE(uqdecd(XReg::x30, PredicatePattern::SVE_POW2 , 1), "uqdecd x30, pow2"); + TEST_SINGLE(uqdecd(XReg::x30, PredicatePattern::SVE_VL256, 7), "uqdecd x30, vl256, mul #7"); + TEST_SINGLE(uqdecd(XReg::x30, PredicatePattern::SVE_ALL , 16), "uqdecd x30, all, mul #16"); + + TEST_SINGLE(uqdecd(WReg::w30, PredicatePattern::SVE_POW2 , 1), "uqdecd w30, pow2"); + TEST_SINGLE(uqdecd(WReg::w30, PredicatePattern::SVE_VL256, 7), "uqdecd w30, vl256, mul #7"); + TEST_SINGLE(uqdecd(WReg::w30, PredicatePattern::SVE_ALL , 16), "uqdecd w30, all, mul #16"); } TEST_CASE_METHOD(TestDisassembler, "Emitter: SVE: SVE Bitwise Immediate") {