diff --git a/External/FEXCore/Source/Interface/Core/ArchHelpers/CodeEmitter/SVEOps.inl b/External/FEXCore/Source/Interface/Core/ArchHelpers/CodeEmitter/SVEOps.inl index cdfcdbe87..128bba1eb 100644 --- a/External/FEXCore/Source/Interface/Core/ArchHelpers/CodeEmitter/SVEOps.inl +++ b/External/FEXCore/Source/Interface/Core/ArchHelpers/CodeEmitter/SVEOps.inl @@ -661,9 +661,45 @@ public: } // SVE integer multiply vectors (predicated) - // XXX: + void mul(SubRegSize size, ZRegister zd, PRegisterMerge pg, ZRegister zn, ZRegister zm) { + constexpr uint32_t Op = 0b0000'0100'0001'0000'0000'0000'0000'0000; + SVEIntegerMulDivVectorsPredicated(Op, 0b00, size, zd, pg, zn, zm); + } + void smulh(SubRegSize size, ZRegister zd, PRegisterMerge pg, ZRegister zn, ZRegister zm) { + constexpr uint32_t Op = 0b0000'0100'0001'0000'0000'0000'0000'0000; + SVEIntegerMulDivVectorsPredicated(Op, 0b10, size, zd, pg, zn, zm); + } + void umulh(SubRegSize size, ZRegister zd, PRegisterMerge pg, ZRegister zn, ZRegister zm) { + constexpr uint32_t Op = 0b0000'0100'0001'0000'0000'0000'0000'0000; + SVEIntegerMulDivVectorsPredicated(Op, 0b11, size, zd, pg, zn, zm); + } + // SVE integer divide vectors (predicated) - // XXX: + void sdiv(SubRegSize size, ZRegister zd, PRegisterMerge pg, ZRegister zn, ZRegister zm) { + LOGMAN_THROW_AA_FMT(size == SubRegSize::i32Bit || size == SubRegSize::i64Bit, + "Predicated divide only handles 32-bit or 64-bit elements"); + constexpr uint32_t Op = 0b0000'0100'0001'0100'0000'0000'0000'0000; + SVEIntegerMulDivVectorsPredicated(Op, 0b00, size, zd, pg, zn, zm); + } + void udiv(SubRegSize size, ZRegister zd, PRegisterMerge pg, ZRegister zn, ZRegister zm) { + LOGMAN_THROW_AA_FMT(size == SubRegSize::i32Bit || size == SubRegSize::i64Bit, + "Predicated divide only handles 32-bit or 64-bit elements"); + constexpr uint32_t Op = 0b0000'0100'0001'0100'0000'0000'0000'0000; + SVEIntegerMulDivVectorsPredicated(Op, 0b01, size, zd, pg, zn, zm); + } + void sdivr(SubRegSize size, ZRegister zd, PRegisterMerge pg, ZRegister zn, ZRegister zm) { + LOGMAN_THROW_AA_FMT(size == SubRegSize::i32Bit || size == SubRegSize::i64Bit, + "Predicated divide only handles 32-bit or 64-bit elements"); + constexpr uint32_t Op = 0b0000'0100'0001'0100'0000'0000'0000'0000; + SVEIntegerMulDivVectorsPredicated(Op, 0b10, size, zd, pg, zn, zm); + } + void udivr(SubRegSize size, ZRegister zd, PRegisterMerge pg, ZRegister zn, ZRegister zm) { + LOGMAN_THROW_AA_FMT(size == SubRegSize::i32Bit || size == SubRegSize::i64Bit, + "Predicated divide only handles 32-bit or 64-bit elements"); + constexpr uint32_t Op = 0b0000'0100'0001'0100'0000'0000'0000'0000; + SVEIntegerMulDivVectorsPredicated(Op, 0b11, size, zd, pg, zn, zm); + } + // SVE bitwise logical operations (predicated) void orr(FEXCore::ARMEmitter::SubRegSize size, FEXCore::ARMEmitter::ZRegister zd, FEXCore::ARMEmitter::PRegisterMerge pg, FEXCore::ARMEmitter::ZRegister zdn, FEXCore::ARMEmitter::ZRegister zm) { LOGMAN_THROW_AA_FMT(size != FEXCore::ARMEmitter::SubRegSize::i128Bit, "Can't use 128-bit size"); @@ -692,27 +728,35 @@ public: // SVE Integer Reduction // SVE integer add reduction (predicated) - // XXX: + void saddv(SubRegSize size, DRegister vd, PRegister pg, ZRegister zn) { + LOGMAN_THROW_A_FMT(size == SubRegSize::i8Bit || size == SubRegSize::i16Bit || size == SubRegSize::i32Bit, + "saddv may only use 8-bit, 16-bit, or 32-bit elements."); + constexpr uint32_t Op = 0b0000'0100'0000'0000'0010'0000'0000'0000; + SVEIntegerReductionOperation(Op, 0b00, size, vd, pg, zn); + } + void uaddv(SubRegSize size, DRegister vd, PRegister pg, ZRegister zn) { + LOGMAN_THROW_A_FMT(size == SubRegSize::i8Bit || size == SubRegSize::i16Bit || size == SubRegSize::i32Bit, + "uaddv may only use 8-bit, 16-bit, or 32-bit elements."); + constexpr uint32_t Op = 0b0000'0100'0000'0000'0010'0000'0000'0000; + SVEIntegerReductionOperation(Op, 0b01, size, vd, pg, zn); + } + // SVE integer min/max reduction (predicated) - void smaxv(FEXCore::ARMEmitter::SubRegSize size, FEXCore::ARMEmitter::ZRegister zd, FEXCore::ARMEmitter::PRegister pg, FEXCore::ARMEmitter::ZRegister zn) { - LOGMAN_THROW_A_FMT(size == FEXCore::ARMEmitter::SubRegSize::i8Bit || size == FEXCore::ARMEmitter::SubRegSize::i16Bit || size == FEXCore::ARMEmitter::SubRegSize::i32Bit, "Invalid subregsize size"); + void smaxv(SubRegSize size, VRegister vd, PRegister pg, ZRegister zn) { constexpr uint32_t Op = 0b0000'0100'0000'1000'001 << 13; - SVEIntegerMinMaxReduction(Op, 0, 0, size, pg, zn, zd); + SVEIntegerReductionOperation(Op, 0b00, size, vd, pg, zn); } - void umaxv(FEXCore::ARMEmitter::SubRegSize size, FEXCore::ARMEmitter::ZRegister zd, FEXCore::ARMEmitter::PRegister pg, FEXCore::ARMEmitter::ZRegister zn) { - LOGMAN_THROW_A_FMT(size == FEXCore::ARMEmitter::SubRegSize::i8Bit || size == FEXCore::ARMEmitter::SubRegSize::i16Bit || size == FEXCore::ARMEmitter::SubRegSize::i32Bit, "Invalid subregsize size"); + void umaxv(SubRegSize size, VRegister vd, PRegister pg, ZRegister zn) { constexpr uint32_t Op = 0b0000'0100'0000'1000'001 << 13; - SVEIntegerMinMaxReduction(Op, 0, 1, size, pg, zn, zd); + SVEIntegerReductionOperation(Op, 0b01, size, vd, pg, zn); } - void sminv(FEXCore::ARMEmitter::SubRegSize size, FEXCore::ARMEmitter::ZRegister zd, FEXCore::ARMEmitter::PRegister pg, FEXCore::ARMEmitter::ZRegister zn) { - LOGMAN_THROW_A_FMT(size == FEXCore::ARMEmitter::SubRegSize::i8Bit || size == FEXCore::ARMEmitter::SubRegSize::i16Bit || size == FEXCore::ARMEmitter::SubRegSize::i32Bit, "Invalid subregsize size"); + void sminv(SubRegSize size, VRegister vd, PRegister pg, ZRegister zn) { constexpr uint32_t Op = 0b0000'0100'0000'1000'001 << 13; - SVEIntegerMinMaxReduction(Op, 1, 0, size, pg, zn, zd); + SVEIntegerReductionOperation(Op, 0b10, size, vd, pg, zn); } - void uminv(FEXCore::ARMEmitter::SubRegSize size, FEXCore::ARMEmitter::ZRegister zd, FEXCore::ARMEmitter::PRegister pg, FEXCore::ARMEmitter::ZRegister zn) { - LOGMAN_THROW_A_FMT(size == FEXCore::ARMEmitter::SubRegSize::i8Bit || size == FEXCore::ARMEmitter::SubRegSize::i16Bit || size == FEXCore::ARMEmitter::SubRegSize::i32Bit, "Invalid subregsize size"); + void uminv(SubRegSize size, VRegister vd, PRegister pg, ZRegister zn) { constexpr uint32_t Op = 0b0000'0100'0000'1000'001 << 13; - SVEIntegerMinMaxReduction(Op, 1, 1, size, pg, zn, zd); + SVEIntegerReductionOperation(Op, 0b11, size, vd, pg, zn); } // SVE constructive prefix (predicated) @@ -726,7 +770,18 @@ public: } // SVE bitwise logical reduction (predicated) - // XXX + void orv(SubRegSize size, VRegister vd, PRegister pg, ZRegister zn) { + constexpr uint32_t Op = 0b0000'0100'0001'1000'0010'0000'0000'0000; + SVEIntegerReductionOperation(Op, 0b00, size, vd, pg, zn); + } + void eorv(SubRegSize size, VRegister vd, PRegister pg, ZRegister zn) { + constexpr uint32_t Op = 0b0000'0100'0001'1000'0010'0000'0000'0000; + SVEIntegerReductionOperation(Op, 0b01, size, vd, pg, zn); + } + void andv(SubRegSize size, VRegister vd, PRegister pg, ZRegister zn) { + constexpr uint32_t Op = 0b0000'0100'0001'1000'0010'0000'0000'0000; + SVEIntegerReductionOperation(Op, 0b10, size, vd, pg, zn); + } // SVE Bitwise Shift - Predicated // SVE bitwise shift by immediate (predicated) @@ -3809,19 +3864,6 @@ private: dc32(Instr); } - // SVE integer min/max reduction (predicated) - void SVEIntegerMinMaxReduction(uint32_t Op, uint32_t op, uint32_t U, FEXCore::ARMEmitter::SubRegSize size, FEXCore::ARMEmitter::PRegister pg, FEXCore::ARMEmitter::ZRegister zn, FEXCore::ARMEmitter::ZRegister zd) { - uint32_t Instr = Op; - - Instr |= FEXCore::ToUnderlying(size) << 22; - Instr |= op << 17; - Instr |= U << 16; - Instr |= pg.Idx() << 10; - Instr |= Encode_rn(zn); - Instr |= Encode_rd(zd); - dc32(Instr); - } - // SVE constructive prefix (predicated) void SVEConstructivePrefixPredicated(uint32_t Op, uint32_t opc, uint32_t M, FEXCore::ARMEmitter::SubRegSize size, FEXCore::ARMEmitter::PRegister pg, FEXCore::ARMEmitter::ZRegister zn, FEXCore::ARMEmitter::ZRegister zd) { uint32_t Instr = Op; @@ -3987,6 +4029,32 @@ private: dc32(Instr); } + void SVEIntegerMulDivVectorsPredicated(uint32_t op, uint32_t opc, SubRegSize size, ZRegister zd, PRegisterMerge pg, ZRegister zn, ZRegister zm) { + LOGMAN_THROW_AA_FMT(zd.Idx() == zn.Idx(), "zd and zn must be the same register"); + LOGMAN_THROW_AA_FMT(pg <= PReg::p7, "Mul/Div 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 |= zm.Idx() << 5; + Instr |= zd.Idx(); + dc32(Instr); + } + + void SVEIntegerReductionOperation(uint32_t op, uint32_t opc, SubRegSize size, VRegister vd, PRegister pg, ZRegister zn) { + LOGMAN_THROW_AA_FMT(size != SubRegSize::i128Bit, "Can't use 128-bit element size for reduction operation"); + LOGMAN_THROW_AA_FMT(pg <= PReg::p7, "Integer 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/Source/Interface/Core/JIT/Arm64/VectorOps.cpp b/External/FEXCore/Source/Interface/Core/JIT/Arm64/VectorOps.cpp index af0c2b171..932ee64ae 100644 --- a/External/FEXCore/Source/Interface/Core/JIT/Arm64/VectorOps.cpp +++ b/External/FEXCore/Source/Interface/Core/JIT/Arm64/VectorOps.cpp @@ -423,7 +423,7 @@ DEF_OP(VUMinV) { const auto Pred = OpSize == 16 ? PRED_TMP_16B : PRED_TMP_32B; - uminv(SubRegSize, Dst.Z(), Pred, Vector.Z()); + uminv(SubRegSize, Dst, Pred, Vector.Z()); } else { // Vector uminv(SubRegSize, Dst.Q(), Vector.Q()); diff --git a/External/FEXCore/unittests/Emitter/SVE_Tests.cpp b/External/FEXCore/unittests/Emitter/SVE_Tests.cpp index 9dde27cb3..49ca57f56 100644 --- a/External/FEXCore/unittests/Emitter/SVE_Tests.cpp +++ b/External/FEXCore/unittests/Emitter/SVE_Tests.cpp @@ -512,11 +512,54 @@ TEST_CASE_METHOD(TestDisassembler, "Emitter: SVE: SVE integer min/max/difference } TEST_CASE_METHOD(TestDisassembler, "Emitter: SVE: SVE integer multiply vectors (predicated)") { - // TODO: Implement in emitter. + TEST_SINGLE(mul(SubRegSize::i8Bit, ZReg::z30, PReg::p7.Merging(), ZReg::z30, ZReg::z29), + "mul z30.b, p7/m, z30.b, z29.b"); + TEST_SINGLE(mul(SubRegSize::i16Bit, ZReg::z30, PReg::p7.Merging(), ZReg::z30, ZReg::z29), + "mul z30.h, p7/m, z30.h, z29.h"); + TEST_SINGLE(mul(SubRegSize::i32Bit, ZReg::z30, PReg::p7.Merging(), ZReg::z30, ZReg::z29), + "mul z30.s, p7/m, z30.s, z29.s"); + TEST_SINGLE(mul(SubRegSize::i64Bit, ZReg::z30, PReg::p7.Merging(), ZReg::z30, ZReg::z29), + "mul z30.d, p7/m, z30.d, z29.d"); + + TEST_SINGLE(smulh(SubRegSize::i8Bit, ZReg::z30, PReg::p7.Merging(), ZReg::z30, ZReg::z29), + "smulh z30.b, p7/m, z30.b, z29.b"); + TEST_SINGLE(smulh(SubRegSize::i16Bit, ZReg::z30, PReg::p7.Merging(), ZReg::z30, ZReg::z29), + "smulh z30.h, p7/m, z30.h, z29.h"); + TEST_SINGLE(smulh(SubRegSize::i32Bit, ZReg::z30, PReg::p7.Merging(), ZReg::z30, ZReg::z29), + "smulh z30.s, p7/m, z30.s, z29.s"); + TEST_SINGLE(smulh(SubRegSize::i64Bit, ZReg::z30, PReg::p7.Merging(), ZReg::z30, ZReg::z29), + "smulh z30.d, p7/m, z30.d, z29.d"); + + TEST_SINGLE(umulh(SubRegSize::i8Bit, ZReg::z30, PReg::p7.Merging(), ZReg::z30, ZReg::z29), + "umulh z30.b, p7/m, z30.b, z29.b"); + TEST_SINGLE(umulh(SubRegSize::i16Bit, ZReg::z30, PReg::p7.Merging(), ZReg::z30, ZReg::z29), + "umulh z30.h, p7/m, z30.h, z29.h"); + TEST_SINGLE(umulh(SubRegSize::i32Bit, ZReg::z30, PReg::p7.Merging(), ZReg::z30, ZReg::z29), + "umulh z30.s, p7/m, z30.s, z29.s"); + TEST_SINGLE(umulh(SubRegSize::i64Bit, ZReg::z30, PReg::p7.Merging(), ZReg::z30, ZReg::z29), + "umulh z30.d, p7/m, z30.d, z29.d"); } TEST_CASE_METHOD(TestDisassembler, "Emitter: SVE: SVE integer divide vectors (predicated)") { - // TODO: Implement in emitter. + TEST_SINGLE(sdiv(SubRegSize::i32Bit, ZReg::z30, PReg::p7.Merging(), ZReg::z30, ZReg::z29), + "sdiv z30.s, p7/m, z30.s, z29.s"); + TEST_SINGLE(sdiv(SubRegSize::i64Bit, ZReg::z30, PReg::p7.Merging(), ZReg::z30, ZReg::z29), + "sdiv z30.d, p7/m, z30.d, z29.d"); + + TEST_SINGLE(udiv(SubRegSize::i32Bit, ZReg::z30, PReg::p7.Merging(), ZReg::z30, ZReg::z29), + "udiv z30.s, p7/m, z30.s, z29.s"); + TEST_SINGLE(udiv(SubRegSize::i64Bit, ZReg::z30, PReg::p7.Merging(), ZReg::z30, ZReg::z29), + "udiv z30.d, p7/m, z30.d, z29.d"); + + TEST_SINGLE(sdivr(SubRegSize::i32Bit, ZReg::z30, PReg::p7.Merging(), ZReg::z30, ZReg::z29), + "sdivr z30.s, p7/m, z30.s, z29.s"); + TEST_SINGLE(sdivr(SubRegSize::i64Bit, ZReg::z30, PReg::p7.Merging(), ZReg::z30, ZReg::z29), + "sdivr z30.d, p7/m, z30.d, z29.d"); + + TEST_SINGLE(udivr(SubRegSize::i32Bit, ZReg::z30, PReg::p7.Merging(), ZReg::z30, ZReg::z29), + "udivr z30.s, p7/m, z30.s, z29.s"); + TEST_SINGLE(udivr(SubRegSize::i64Bit, ZReg::z30, PReg::p7.Merging(), ZReg::z30, ZReg::z29), + "udivr z30.d, p7/m, z30.d, z29.d"); } TEST_CASE_METHOD(TestDisassembler, "Emitter: SVE: SVE bitwise logical operations (predicated)") { @@ -546,32 +589,34 @@ TEST_CASE_METHOD(TestDisassembler, "Emitter: SVE: SVE bitwise logical operations } TEST_CASE_METHOD(TestDisassembler, "Emitter: SVE: SVE integer add reduction (predicated)") { - // TODO: Implement in emitter. + TEST_SINGLE(saddv(SubRegSize::i8Bit, DReg::d30, PReg::p7, ZReg::z29), "saddv d30, p7, z29.b"); + TEST_SINGLE(saddv(SubRegSize::i16Bit, DReg::d30, PReg::p7, ZReg::z29), "saddv d30, p7, z29.h"); + TEST_SINGLE(saddv(SubRegSize::i32Bit, DReg::d30, PReg::p7, ZReg::z29), "saddv d30, p7, z29.s"); + + TEST_SINGLE(uaddv(SubRegSize::i8Bit, DReg::d30, PReg::p7, ZReg::z29), "uaddv d30, p7, z29.b"); + TEST_SINGLE(uaddv(SubRegSize::i16Bit, DReg::d30, PReg::p7, ZReg::z29), "uaddv d30, p7, z29.h"); + TEST_SINGLE(uaddv(SubRegSize::i32Bit, DReg::d30, PReg::p7, ZReg::z29), "uaddv d30, p7, z29.s"); } TEST_CASE_METHOD(TestDisassembler, "Emitter: SVE: SVE integer min/max reduction (predicated)") { - TEST_SINGLE(smaxv(SubRegSize::i8Bit, ZReg::z30, PReg::p6, ZReg::z29), "smaxv b30, p6, z29.b"); - TEST_SINGLE(smaxv(SubRegSize::i16Bit, ZReg::z30, PReg::p6, ZReg::z29), "smaxv h30, p6, z29.h"); - TEST_SINGLE(smaxv(SubRegSize::i32Bit, ZReg::z30, PReg::p6, ZReg::z29), "smaxv s30, p6, z29.s"); - //TEST_SINGLE(smaxv(SubRegSize::i64Bit, ZReg::z30, PReg::p6, ZReg::z29), "smaxv d30, p6, z29.d"); - //TEST_SINGLE(smaxv(SubRegSize::i128Bit, ZReg::z30, PReg::p6, ZReg::z29), "smaxv q30, p6, z29.q"); + TEST_SINGLE(smaxv(SubRegSize::i8Bit, VReg::v30, PReg::p6, ZReg::z29), "smaxv b30, p6, z29.b"); + TEST_SINGLE(smaxv(SubRegSize::i16Bit, VReg::v30, PReg::p6, ZReg::z29), "smaxv h30, p6, z29.h"); + TEST_SINGLE(smaxv(SubRegSize::i32Bit, VReg::v30, PReg::p6, ZReg::z29), "smaxv s30, p6, z29.s"); + TEST_SINGLE(smaxv(SubRegSize::i64Bit, VReg::v30, PReg::p6, ZReg::z29), "smaxv d30, p6, z29.d"); - TEST_SINGLE(umaxv(SubRegSize::i8Bit, ZReg::z30, PReg::p6, ZReg::z29), "umaxv b30, p6, z29.b"); - TEST_SINGLE(umaxv(SubRegSize::i16Bit, ZReg::z30, PReg::p6, ZReg::z29), "umaxv h30, p6, z29.h"); - TEST_SINGLE(umaxv(SubRegSize::i32Bit, ZReg::z30, PReg::p6, ZReg::z29), "umaxv s30, p6, z29.s"); - //TEST_SINGLE(umaxv(SubRegSize::i64Bit, ZReg::z30, PReg::p6, ZReg::z29), "umaxv d30, p6, z29.d"); - //TEST_SINGLE(umaxv(SubRegSize::i128Bit, ZReg::z30, PReg::p6, ZReg::z29), "umaxv q30, p6, z29.q"); + TEST_SINGLE(umaxv(SubRegSize::i8Bit, VReg::v30, PReg::p6, ZReg::z29), "umaxv b30, p6, z29.b"); + TEST_SINGLE(umaxv(SubRegSize::i16Bit, VReg::v30, PReg::p6, ZReg::z29), "umaxv h30, p6, z29.h"); + TEST_SINGLE(umaxv(SubRegSize::i32Bit, VReg::v30, PReg::p6, ZReg::z29), "umaxv s30, p6, z29.s"); + TEST_SINGLE(umaxv(SubRegSize::i64Bit, VReg::v30, PReg::p6, ZReg::z29), "umaxv d30, p6, z29.d"); - TEST_SINGLE(sminv(SubRegSize::i8Bit, ZReg::z30, PReg::p6, ZReg::z29), "sminv b30, p6, z29.b"); - TEST_SINGLE(sminv(SubRegSize::i16Bit, ZReg::z30, PReg::p6, ZReg::z29), "sminv h30, p6, z29.h"); - TEST_SINGLE(sminv(SubRegSize::i32Bit, ZReg::z30, PReg::p6, ZReg::z29), "sminv s30, p6, z29.s"); - //TEST_SINGLE(sminv(SubRegSize::i64Bit, ZReg::z30, PReg::p6, ZReg::z29), "sminv d30, p6, z29.d"); - //TEST_SINGLE(sminv(SubRegSize::i128Bit, ZReg::z30, PReg::p6, ZReg::z29), "sminv q30, p6, z29.q"); + TEST_SINGLE(sminv(SubRegSize::i8Bit, VReg::v30, PReg::p6, ZReg::z29), "sminv b30, p6, z29.b"); + TEST_SINGLE(sminv(SubRegSize::i16Bit, VReg::v30, PReg::p6, ZReg::z29), "sminv h30, p6, z29.h"); + TEST_SINGLE(sminv(SubRegSize::i32Bit, VReg::v30, PReg::p6, ZReg::z29), "sminv s30, p6, z29.s"); + TEST_SINGLE(sminv(SubRegSize::i64Bit, VReg::v30, PReg::p6, ZReg::z29), "sminv d30, p6, z29.d"); - TEST_SINGLE(uminv(SubRegSize::i8Bit, ZReg::z30, PReg::p6, ZReg::z29), "uminv b30, p6, z29.b"); - TEST_SINGLE(uminv(SubRegSize::i16Bit, ZReg::z30, PReg::p6, ZReg::z29), "uminv h30, p6, z29.h"); - TEST_SINGLE(uminv(SubRegSize::i32Bit, ZReg::z30, PReg::p6, ZReg::z29), "uminv s30, p6, z29.s"); - //TEST_SINGLE(uminv(SubRegSize::i64Bit, ZReg::z30, PReg::p6, ZReg::z29), "uminv d30, p6, z29.d"); - //TEST_SINGLE(uminv(SubRegSize::i128Bit, ZReg::z30, PReg::p6, ZReg::z29), "uminv q30, p6, z29.q"); + TEST_SINGLE(uminv(SubRegSize::i8Bit, VReg::v30, PReg::p6, ZReg::z29), "uminv b30, p6, z29.b"); + TEST_SINGLE(uminv(SubRegSize::i16Bit, VReg::v30, PReg::p6, ZReg::z29), "uminv h30, p6, z29.h"); + TEST_SINGLE(uminv(SubRegSize::i32Bit, VReg::v30, PReg::p6, ZReg::z29), "uminv s30, p6, z29.s"); + TEST_SINGLE(uminv(SubRegSize::i64Bit, VReg::v30, PReg::p6, ZReg::z29), "uminv d30, p6, z29.d"); } TEST_CASE_METHOD(TestDisassembler, "Emitter: SVE: SVE constructive prefix (predicated)") { TEST_SINGLE(movprfx(SubRegSize::i8Bit, ZReg::z30, PReg::p6.Merging(), ZReg::z29), "movprfx z30.b, p6/m, z29.b"); @@ -586,7 +631,20 @@ TEST_CASE_METHOD(TestDisassembler, "Emitter: SVE: SVE constructive prefix (predi //TEST_SINGLE(movprfx(SubRegSize::i128Bit, ZReg::z30, PReg::p6.Zeroing(), ZReg::z29), "movprfx z30.q, p6/z, z29.q"); } TEST_CASE_METHOD(TestDisassembler, "Emitter: SVE: SVE bitwise logical reduction (predicated)") { - // TODO: Implement in emitter. + TEST_SINGLE(orv(SubRegSize::i8Bit, VReg::v30, PReg::p7, ZReg::z29), "orv b30, p7, z29.b"); + TEST_SINGLE(orv(SubRegSize::i16Bit, VReg::v30, PReg::p7, ZReg::z29), "orv h30, p7, z29.h"); + TEST_SINGLE(orv(SubRegSize::i32Bit, VReg::v30, PReg::p7, ZReg::z29), "orv s30, p7, z29.s"); + TEST_SINGLE(orv(SubRegSize::i64Bit, VReg::v30, PReg::p7, ZReg::z29), "orv d30, p7, z29.d"); + + TEST_SINGLE(eorv(SubRegSize::i8Bit, VReg::v30, PReg::p7, ZReg::z29), "eorv b30, p7, z29.b"); + TEST_SINGLE(eorv(SubRegSize::i16Bit, VReg::v30, PReg::p7, ZReg::z29), "eorv h30, p7, z29.h"); + TEST_SINGLE(eorv(SubRegSize::i32Bit, VReg::v30, PReg::p7, ZReg::z29), "eorv s30, p7, z29.s"); + TEST_SINGLE(eorv(SubRegSize::i64Bit, VReg::v30, PReg::p7, ZReg::z29), "eorv d30, p7, z29.d"); + + TEST_SINGLE(andv(SubRegSize::i8Bit, VReg::v30, PReg::p7, ZReg::z29), "andv b30, p7, z29.b"); + TEST_SINGLE(andv(SubRegSize::i16Bit, VReg::v30, PReg::p7, ZReg::z29), "andv h30, p7, z29.h"); + TEST_SINGLE(andv(SubRegSize::i32Bit, VReg::v30, PReg::p7, ZReg::z29), "andv s30, p7, z29.s"); + TEST_SINGLE(andv(SubRegSize::i64Bit, VReg::v30, PReg::p7, ZReg::z29), "andv d30, p7, z29.d"); } TEST_CASE_METHOD(TestDisassembler, "Emitter: SVE: SVE bitwise shift by immediate (predicated)") { TEST_SINGLE(asr(SubRegSize::i8Bit, ZReg::z30, PReg::p6.Merging(), ZReg::z30, 1), "asr z30.b, p6/m, z30.b, #1");