diff --git a/External/FEXCore/Source/Interface/Core/ArchHelpers/CodeEmitter/SVEOps.inl b/External/FEXCore/Source/Interface/Core/ArchHelpers/CodeEmitter/SVEOps.inl index ee940957f..d80abef9c 100644 --- a/External/FEXCore/Source/Interface/Core/ArchHelpers/CodeEmitter/SVEOps.inl +++ b/External/FEXCore/Source/Interface/Core/ArchHelpers/CodeEmitter/SVEOps.inl @@ -1966,18 +1966,72 @@ public: // SVE2 Accumulate // SVE2 complex integer add - // XXX: + void cadd(SubRegSize size, ZRegister zd, ZRegister zn, ZRegister zm, Rotation rot) { + SVE2ComplexIntAdd(size, 0b0, rot, zd, zn, zm); + } + void sqcadd(SubRegSize size, ZRegister zd, ZRegister zn, ZRegister zm, Rotation rot) { + SVE2ComplexIntAdd(size, 0b1, rot, zd, zn, zm); + } + // SVE2 integer absolute difference and accumulate long - // XXX: + void sabalb(SubRegSize size, ZRegister zda, ZRegister zn, ZRegister zm) { + SVE2IntegerAddSubInterleavedLong(size, 0b10000, zda, zn, zm); + } + void sabalt(SubRegSize size, ZRegister zda, ZRegister zn, ZRegister zm) { + SVE2IntegerAddSubInterleavedLong(size, 0b10001, zda, zn, zm); + } + void uabalb(SubRegSize size, ZRegister zda, ZRegister zn, ZRegister zm) { + SVE2IntegerAddSubInterleavedLong(size, 0b10010, zda, zn, zm); + } + void uabalt(SubRegSize size, ZRegister zda, ZRegister zn, ZRegister zm) { + SVE2IntegerAddSubInterleavedLong(size, 0b10011, zda, zn, zm); + } + // SVE2 integer add/subtract long with carry - // XXX: + void adclb(SubRegSize size, ZRegister zda, ZRegister zn, ZRegister zm) { + SVE2IntegerAddSubLongWithCarry(size, 0, 0, zda, zn, zm); + } + void adclt(SubRegSize size, ZRegister zda, ZRegister zn, ZRegister zm) { + SVE2IntegerAddSubLongWithCarry(size, 0, 1, zda, zn, zm); + } + void sbclb(SubRegSize size, ZRegister zda, ZRegister zn, ZRegister zm) { + SVE2IntegerAddSubLongWithCarry(size, 1, 0, zda, zn, zm); + } + void sbclt(SubRegSize size, ZRegister zda, ZRegister zn, ZRegister zm) { + SVE2IntegerAddSubLongWithCarry(size, 1, 1, zda, zn, zm); + } + // SVE2 bitwise shift right and accumulate - // XXX: + void ssra(SubRegSize size, ZRegister zda, ZRegister zn, uint32_t shift) { + SVE2BitwiseShiftRightAndAccumulate(size, 0b00, zda, zn, shift); + } + void usra(SubRegSize size, ZRegister zda, ZRegister zn, uint32_t shift) { + SVE2BitwiseShiftRightAndAccumulate(size, 0b01, zda, zn, shift); + } + void srsra(SubRegSize size, ZRegister zda, ZRegister zn, uint32_t shift) { + SVE2BitwiseShiftRightAndAccumulate(size, 0b10, zda, zn, shift); + } + void ursra(SubRegSize size, ZRegister zda, ZRegister zn, uint32_t shift) { + SVE2BitwiseShiftRightAndAccumulate(size, 0b11, zda, zn, shift); + } + // SVE2 bitwise shift and insert - // XXX: + void sri(SubRegSize size, ZRegister zda, ZRegister zn, uint32_t shift) { + SVE2BitwiseShiftAndInsert(size, 0b0, zda, zn, shift); + } + void sli(SubRegSize size, ZRegister zda, ZRegister zn, uint32_t shift) { + SVE2BitwiseShiftAndInsert(size, 0b1, zda, zn, shift); + } + + // SVE2 integer absolute difference and accumulate - // XXX: - // + void saba(SubRegSize size, ZRegister zda, ZRegister zn, ZRegister zm) { + SVE2IntegerAbsDiffAndAccumulate(size, 0b0, zda, zn, zm); + } + void uaba(SubRegSize size, ZRegister zda, ZRegister zn, ZRegister zm) { + SVE2IntegerAbsDiffAndAccumulate(size, 0b1, zda, zn, zm); + } + // SVE2 Narrowing // SVE2 saturating extract narrow void sqxtnb(SubRegSize size, ZRegister zd, ZRegister zn) { @@ -3625,6 +3679,123 @@ private: dc32(Instr); } + void SVE2IntegerAbsDiffAndAccumulate(SubRegSize size, uint32_t opc, ZRegister zda, ZRegister zn, ZRegister zm) { + LOGMAN_THROW_A_FMT(size != SubRegSize::i128Bit, "Can't use 128-bit element size"); + + uint32_t Instr = 0b0100'0101'0000'0000'1111'1000'0000'0000; + Instr |= FEXCore::ToUnderlying(size) << 22; + Instr |= zm.Idx() << 16; + Instr |= opc << 10; + Instr |= zn.Idx() << 5; + Instr |= zda.Idx(); + dc32(Instr); + } + + void SVE2IntegerAddSubLongWithCarry(SubRegSize size, uint32_t sizep1, uint32_t T, ZRegister zda, ZRegister zn, ZRegister zm) { + LOGMAN_THROW_A_FMT(size == SubRegSize::i32Bit || size == SubRegSize::i64Bit, + "Element size must be 32-bit or 64-bit"); + + const uint32_t NewSize = size == SubRegSize::i32Bit ? 0 : 1; + + uint32_t Instr = 0b0100'0101'0000'0000'1101'0000'0000'0000; + Instr |= sizep1 << 23; + Instr |= NewSize << 22; + Instr |= zm.Idx() << 16; + Instr |= T << 10; + Instr |= zn.Idx() << 5; + Instr |= zda.Idx(); + dc32(Instr); + } + + void SVE2BitwiseShiftRightAndAccumulate(SubRegSize size, uint32_t opc, ZRegister zda, ZRegister zn, uint32_t shift) { + LOGMAN_THROW_A_FMT(size != SubRegSize::i128Bit, "Element size cannot be 128-bit"); + + const auto ElementSize = SubRegSizeInBits(size); + + LOGMAN_THROW_A_FMT(shift > 0 && shift <= ElementSize, "Incorrect right shift: {}", shift); + + uint32_t tszh = 0; + uint32_t tszl = 0; + uint32_t imm3 = 0; + const uint32_t InverseShift = (2 * ElementSize) - shift; + + if (size == SubRegSize::i8Bit) { + tszh = 0b00; + tszl = 0b01; + imm3 = InverseShift & 0b111; + } else if (size == SubRegSize::i16Bit) { + tszh = 0b00; + tszl = 0b10 | ((InverseShift >> 3) & 0b1); + imm3 = InverseShift & 0b111; + } else if (size == SubRegSize::i32Bit) { + tszh = 0b01; + tszl = (InverseShift >> 3) & 0b11; + imm3 = InverseShift & 0b111; + } else if (size == SubRegSize::i64Bit) { + tszh = 0b10 | ((InverseShift >> 5) & 1); + tszl = (InverseShift >> 3) & 0b11; + imm3 = InverseShift & 0b111; + } else { + FEX_UNREACHABLE; + } + + uint32_t Instr = 0b0100'0101'0000'0000'1110'0000'0000'0000; + Instr |= tszh << 22; + Instr |= tszl << 19; + Instr |= imm3 << 16; + Instr |= opc << 10; + Instr |= zn.Idx() << 5; + Instr |= zda.Idx(); + dc32(Instr); + } + + void SVE2BitwiseShiftAndInsert(SubRegSize size, uint32_t opc, ZRegister zd, ZRegister zn, uint32_t shift) { + LOGMAN_THROW_A_FMT(size != SubRegSize::i128Bit, "Element size cannot be 128-bit"); + + const auto ElementSize = SubRegSizeInBits(size); + const bool IsLeftShift = opc != 0; + if (IsLeftShift) { + LOGMAN_THROW_A_FMT(shift >= 0 && shift < ElementSize, "Incorrect left shift: {}", shift); + } else { + LOGMAN_THROW_A_FMT(shift > 0 && shift <= ElementSize, "Incorrect right shift: {}", shift); + } + + uint32_t tszh = 0; + uint32_t tszl = 0; + uint32_t imm3 = 0; + const uint32_t InverseShift = IsLeftShift ? shift + :(2 * ElementSize) - shift; + + if (size == SubRegSize::i8Bit) { + tszh = 0b00; + tszl = 0b01; + imm3 = InverseShift & 0b111; + } else if (size == SubRegSize::i16Bit) { + tszh = 0b00; + tszl = 0b10 | ((InverseShift >> 3) & 0b1); + imm3 = InverseShift & 0b111; + } else if (size == SubRegSize::i32Bit) { + tszh = 0b01; + tszl = (InverseShift >> 3) & 0b11; + imm3 = InverseShift & 0b111; + } else if (size == SubRegSize::i64Bit) { + tszh = 0b10 | ((InverseShift >> 5) & 1); + tszl = (InverseShift >> 3) & 0b11; + imm3 = InverseShift & 0b111; + } else { + FEX_UNREACHABLE; + } + + uint32_t Instr = 0b0100'0101'0000'0000'1111'0000'0000'0000; + Instr |= tszh << 22; + Instr |= tszl << 19; + Instr |= imm3 << 16; + Instr |= opc << 10; + Instr |= zn.Idx() << 5; + Instr |= zd.Idx(); + dc32(Instr); + } + void SVE2BitwiseShiftLeftLong(SubRegSize size, uint32_t opc, ZRegister zd, ZRegister zn, uint32_t shift) { LOGMAN_THROW_A_FMT(size != SubRegSize::i8Bit && size != SubRegSize::i128Bit, "Can't use 8-bit or 128-bit element size"); @@ -3649,6 +3820,36 @@ private: dc32(Instr); } + void SVE2ComplexIntAdd(SubRegSize size, uint32_t opc, Rotation rot, ZRegister zd, ZRegister zn, ZRegister zm) { + LOGMAN_THROW_A_FMT(size != SubRegSize::i128Bit, "Complex add cannot use 128-bit element size"); + LOGMAN_THROW_A_FMT(zd.Idx() == zn.Idx(), "zd and zn must be the same register"); + LOGMAN_THROW_A_FMT(rot == Rotation::ROTATE_90 || rot == Rotation::ROTATE_270, + "Rotation must be 90 or 270 degrees"); + + const uint32_t SanitizedRot = rot == Rotation::ROTATE_90 ? 0 : 1; + + uint32_t Instr = 0b0100'0101'0000'0000'1101'1000'0000'0000; + Instr |= FEXCore::ToUnderlying(size) << 22; + Instr |= opc << 16; + Instr |= SanitizedRot << 10; + Instr |= zm.Idx() << 5; + Instr |= zd.Idx(); + dc32(Instr); + } + + void SVE2AbsDiffAccLong(SubRegSize size, uint32_t opc, ZRegister zda, ZRegister zn, ZRegister zm) { + LOGMAN_THROW_A_FMT(size != SubRegSize::i8Bit && size != SubRegSize::i128Bit, + "Cannot use 8-bit or 128-bit element size"); + + uint32_t Instr = 0b0100'0101'0000'0000'1100'0000'0000'0000; + Instr |= FEXCore::ToUnderlying(size) << 22; + Instr |= zm.Idx() << 16; + Instr |= opc << 10; + Instr |= zn.Idx() << 5; + Instr |= zda.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 c91c1b834..c8a72fb9c 100644 --- a/External/FEXCore/unittests/Emitter/SVE_Tests.cpp +++ b/External/FEXCore/unittests/Emitter/SVE_Tests.cpp @@ -1857,22 +1857,130 @@ TEST_CASE_METHOD(TestDisassembler, "Emitter: SVE: SVE2 bitwise permute") { TEST_SINGLE(bgrp(SubRegSize::i64Bit, ZReg::z30, ZReg::z29, ZReg::z28), "bgrp z30.d, z29.d, z28.d"); } TEST_CASE_METHOD(TestDisassembler, "Emitter: SVE: SVE2 complex integer add") { - // TODO: Implement in emitter. + TEST_SINGLE(cadd(SubRegSize::i8Bit, ZReg::z30, ZReg::z30, ZReg::z29, Rotation::ROTATE_90), "cadd z30.b, z30.b, z29.b, #90"); + TEST_SINGLE(cadd(SubRegSize::i16Bit, ZReg::z30, ZReg::z30, ZReg::z29, Rotation::ROTATE_90), "cadd z30.h, z30.h, z29.h, #90"); + TEST_SINGLE(cadd(SubRegSize::i32Bit, ZReg::z30, ZReg::z30, ZReg::z29, Rotation::ROTATE_90), "cadd z30.s, z30.s, z29.s, #90"); + TEST_SINGLE(cadd(SubRegSize::i64Bit, ZReg::z30, ZReg::z30, ZReg::z29, Rotation::ROTATE_90), "cadd z30.d, z30.d, z29.d, #90"); + + TEST_SINGLE(cadd(SubRegSize::i8Bit, ZReg::z30, ZReg::z30, ZReg::z29, Rotation::ROTATE_270), "cadd z30.b, z30.b, z29.b, #270"); + TEST_SINGLE(cadd(SubRegSize::i16Bit, ZReg::z30, ZReg::z30, ZReg::z29, Rotation::ROTATE_270), "cadd z30.h, z30.h, z29.h, #270"); + TEST_SINGLE(cadd(SubRegSize::i32Bit, ZReg::z30, ZReg::z30, ZReg::z29, Rotation::ROTATE_270), "cadd z30.s, z30.s, z29.s, #270"); + TEST_SINGLE(cadd(SubRegSize::i64Bit, ZReg::z30, ZReg::z30, ZReg::z29, Rotation::ROTATE_270), "cadd z30.d, z30.d, z29.d, #270"); + + TEST_SINGLE(sqcadd(SubRegSize::i8Bit, ZReg::z30, ZReg::z30, ZReg::z29, Rotation::ROTATE_90), "sqcadd z30.b, z30.b, z29.b, #90"); + TEST_SINGLE(sqcadd(SubRegSize::i16Bit, ZReg::z30, ZReg::z30, ZReg::z29, Rotation::ROTATE_90), "sqcadd z30.h, z30.h, z29.h, #90"); + TEST_SINGLE(sqcadd(SubRegSize::i32Bit, ZReg::z30, ZReg::z30, ZReg::z29, Rotation::ROTATE_90), "sqcadd z30.s, z30.s, z29.s, #90"); + TEST_SINGLE(sqcadd(SubRegSize::i64Bit, ZReg::z30, ZReg::z30, ZReg::z29, Rotation::ROTATE_90), "sqcadd z30.d, z30.d, z29.d, #90"); + + TEST_SINGLE(sqcadd(SubRegSize::i8Bit, ZReg::z30, ZReg::z30, ZReg::z29, Rotation::ROTATE_270), "sqcadd z30.b, z30.b, z29.b, #270"); + TEST_SINGLE(sqcadd(SubRegSize::i16Bit, ZReg::z30, ZReg::z30, ZReg::z29, Rotation::ROTATE_270), "sqcadd z30.h, z30.h, z29.h, #270"); + TEST_SINGLE(sqcadd(SubRegSize::i32Bit, ZReg::z30, ZReg::z30, ZReg::z29, Rotation::ROTATE_270), "sqcadd z30.s, z30.s, z29.s, #270"); + TEST_SINGLE(sqcadd(SubRegSize::i64Bit, ZReg::z30, ZReg::z30, ZReg::z29, Rotation::ROTATE_270), "sqcadd z30.d, z30.d, z29.d, #270"); } TEST_CASE_METHOD(TestDisassembler, "Emitter: SVE: SVE2 integer absolute difference and accumulate long") { - // TODO: Implement in emitter. + TEST_SINGLE(sabalb(SubRegSize::i16Bit, ZReg::z28, ZReg::z29, ZReg::z30), "sabalb z28.h, z29.b, z30.b"); + TEST_SINGLE(sabalb(SubRegSize::i32Bit, ZReg::z28, ZReg::z29, ZReg::z30), "sabalb z28.s, z29.h, z30.h"); + TEST_SINGLE(sabalb(SubRegSize::i64Bit, ZReg::z28, ZReg::z29, ZReg::z30), "sabalb z28.d, z29.s, z30.s"); + + TEST_SINGLE(sabalt(SubRegSize::i16Bit, ZReg::z28, ZReg::z29, ZReg::z30), "sabalt z28.h, z29.b, z30.b"); + TEST_SINGLE(sabalt(SubRegSize::i32Bit, ZReg::z28, ZReg::z29, ZReg::z30), "sabalt z28.s, z29.h, z30.h"); + TEST_SINGLE(sabalt(SubRegSize::i64Bit, ZReg::z28, ZReg::z29, ZReg::z30), "sabalt z28.d, z29.s, z30.s"); + + TEST_SINGLE(uabalb(SubRegSize::i16Bit, ZReg::z28, ZReg::z29, ZReg::z30), "uabalb z28.h, z29.b, z30.b"); + TEST_SINGLE(uabalb(SubRegSize::i32Bit, ZReg::z28, ZReg::z29, ZReg::z30), "uabalb z28.s, z29.h, z30.h"); + TEST_SINGLE(uabalb(SubRegSize::i64Bit, ZReg::z28, ZReg::z29, ZReg::z30), "uabalb z28.d, z29.s, z30.s"); + + TEST_SINGLE(uabalt(SubRegSize::i16Bit, ZReg::z28, ZReg::z29, ZReg::z30), "uabalt z28.h, z29.b, z30.b"); + TEST_SINGLE(uabalt(SubRegSize::i32Bit, ZReg::z28, ZReg::z29, ZReg::z30), "uabalt z28.s, z29.h, z30.h"); + TEST_SINGLE(uabalt(SubRegSize::i64Bit, ZReg::z28, ZReg::z29, ZReg::z30), "uabalt z28.d, z29.s, z30.s"); } TEST_CASE_METHOD(TestDisassembler, "Emitter: SVE: SVE2 integer add/subtract long with carry") { - // TODO: Implement in emitter. + TEST_SINGLE(adclb(SubRegSize::i32Bit, ZReg::z28, ZReg::z29, ZReg::z30), "adclb z28.s, z29.s, z30.s"); + TEST_SINGLE(adclb(SubRegSize::i64Bit, ZReg::z28, ZReg::z29, ZReg::z30), "adclb z28.d, z29.d, z30.d"); + + TEST_SINGLE(adclt(SubRegSize::i32Bit, ZReg::z28, ZReg::z29, ZReg::z30), "adclt z28.s, z29.s, z30.s"); + TEST_SINGLE(adclt(SubRegSize::i64Bit, ZReg::z28, ZReg::z29, ZReg::z30), "adclt z28.d, z29.d, z30.d"); + + TEST_SINGLE(sbclb(SubRegSize::i32Bit, ZReg::z28, ZReg::z29, ZReg::z30), "sbclb z28.s, z29.s, z30.s"); + TEST_SINGLE(sbclb(SubRegSize::i64Bit, ZReg::z28, ZReg::z29, ZReg::z30), "sbclb z28.d, z29.d, z30.d"); + + TEST_SINGLE(sbclt(SubRegSize::i32Bit, ZReg::z28, ZReg::z29, ZReg::z30), "sbclt z28.s, z29.s, z30.s"); + TEST_SINGLE(sbclt(SubRegSize::i64Bit, ZReg::z28, ZReg::z29, ZReg::z30), "sbclt z28.d, z29.d, z30.d"); } TEST_CASE_METHOD(TestDisassembler, "Emitter: SVE: SVE2 bitwise shift right and accumulate") { - // TODO: Implement in emitter. + TEST_SINGLE(ssra(SubRegSize::i8Bit, ZReg::z30, ZReg::z29, 1), "ssra z30.b, z29.b, #1"); + TEST_SINGLE(ssra(SubRegSize::i8Bit, ZReg::z30, ZReg::z29, 8), "ssra z30.b, z29.b, #8"); + TEST_SINGLE(ssra(SubRegSize::i16Bit, ZReg::z30, ZReg::z29, 1), "ssra z30.h, z29.h, #1"); + TEST_SINGLE(ssra(SubRegSize::i16Bit, ZReg::z30, ZReg::z29, 16), "ssra z30.h, z29.h, #16"); + TEST_SINGLE(ssra(SubRegSize::i32Bit, ZReg::z30, ZReg::z29, 1), "ssra z30.s, z29.s, #1"); + TEST_SINGLE(ssra(SubRegSize::i32Bit, ZReg::z30, ZReg::z29, 32), "ssra z30.s, z29.s, #32"); + TEST_SINGLE(ssra(SubRegSize::i64Bit, ZReg::z30, ZReg::z29, 1), "ssra z30.d, z29.d, #1"); + TEST_SINGLE(ssra(SubRegSize::i64Bit, ZReg::z30, ZReg::z29, 64), "ssra z30.d, z29.d, #64"); + + TEST_SINGLE(usra(SubRegSize::i8Bit, ZReg::z30, ZReg::z29, 1), "usra z30.b, z29.b, #1"); + TEST_SINGLE(usra(SubRegSize::i8Bit, ZReg::z30, ZReg::z29, 8), "usra z30.b, z29.b, #8"); + TEST_SINGLE(usra(SubRegSize::i16Bit, ZReg::z30, ZReg::z29, 1), "usra z30.h, z29.h, #1"); + TEST_SINGLE(usra(SubRegSize::i16Bit, ZReg::z30, ZReg::z29, 16), "usra z30.h, z29.h, #16"); + TEST_SINGLE(usra(SubRegSize::i32Bit, ZReg::z30, ZReg::z29, 1), "usra z30.s, z29.s, #1"); + TEST_SINGLE(usra(SubRegSize::i32Bit, ZReg::z30, ZReg::z29, 32), "usra z30.s, z29.s, #32"); + TEST_SINGLE(usra(SubRegSize::i64Bit, ZReg::z30, ZReg::z29, 1), "usra z30.d, z29.d, #1"); + TEST_SINGLE(usra(SubRegSize::i64Bit, ZReg::z30, ZReg::z29, 64), "usra z30.d, z29.d, #64"); + + TEST_SINGLE(srsra(SubRegSize::i8Bit, ZReg::z30, ZReg::z29, 1), "srsra z30.b, z29.b, #1"); + TEST_SINGLE(srsra(SubRegSize::i8Bit, ZReg::z30, ZReg::z29, 8), "srsra z30.b, z29.b, #8"); + TEST_SINGLE(srsra(SubRegSize::i16Bit, ZReg::z30, ZReg::z29, 1), "srsra z30.h, z29.h, #1"); + TEST_SINGLE(srsra(SubRegSize::i16Bit, ZReg::z30, ZReg::z29, 16), "srsra z30.h, z29.h, #16"); + TEST_SINGLE(srsra(SubRegSize::i32Bit, ZReg::z30, ZReg::z29, 1), "srsra z30.s, z29.s, #1"); + TEST_SINGLE(srsra(SubRegSize::i32Bit, ZReg::z30, ZReg::z29, 32), "srsra z30.s, z29.s, #32"); + TEST_SINGLE(srsra(SubRegSize::i64Bit, ZReg::z30, ZReg::z29, 1), "srsra z30.d, z29.d, #1"); + TEST_SINGLE(srsra(SubRegSize::i64Bit, ZReg::z30, ZReg::z29, 64), "srsra z30.d, z29.d, #64"); + + TEST_SINGLE(ursra(SubRegSize::i8Bit, ZReg::z30, ZReg::z29, 1), "ursra z30.b, z29.b, #1"); + TEST_SINGLE(ursra(SubRegSize::i8Bit, ZReg::z30, ZReg::z29, 8), "ursra z30.b, z29.b, #8"); + TEST_SINGLE(ursra(SubRegSize::i16Bit, ZReg::z30, ZReg::z29, 1), "ursra z30.h, z29.h, #1"); + TEST_SINGLE(ursra(SubRegSize::i16Bit, ZReg::z30, ZReg::z29, 16), "ursra z30.h, z29.h, #16"); + TEST_SINGLE(ursra(SubRegSize::i32Bit, ZReg::z30, ZReg::z29, 1), "ursra z30.s, z29.s, #1"); + TEST_SINGLE(ursra(SubRegSize::i32Bit, ZReg::z30, ZReg::z29, 32), "ursra z30.s, z29.s, #32"); + TEST_SINGLE(ursra(SubRegSize::i64Bit, ZReg::z30, ZReg::z29, 1), "ursra z30.d, z29.d, #1"); + TEST_SINGLE(ursra(SubRegSize::i64Bit, ZReg::z30, ZReg::z29, 64), "ursra z30.d, z29.d, #64"); } TEST_CASE_METHOD(TestDisassembler, "Emitter: SVE: SVE2 bitwise shift and insert") { - // TODO: Implement in emitter. + TEST_SINGLE(sri(SubRegSize::i8Bit, ZReg::z30, ZReg::z29, 1), "sri z30.b, z29.b, #1");\ + TEST_SINGLE(sri(SubRegSize::i8Bit, ZReg::z30, ZReg::z29, 4), "sri z30.b, z29.b, #4"); + TEST_SINGLE(sri(SubRegSize::i8Bit, ZReg::z30, ZReg::z29, 8), "sri z30.b, z29.b, #8"); + TEST_SINGLE(sri(SubRegSize::i16Bit, ZReg::z30, ZReg::z29, 1), "sri z30.h, z29.h, #1"); + TEST_SINGLE(sri(SubRegSize::i16Bit, ZReg::z30, ZReg::z29, 15), "sri z30.h, z29.h, #15"); + TEST_SINGLE(sri(SubRegSize::i16Bit, ZReg::z30, ZReg::z29, 16), "sri z30.h, z29.h, #16"); + TEST_SINGLE(sri(SubRegSize::i32Bit, ZReg::z30, ZReg::z29, 1), "sri z30.s, z29.s, #1"); + TEST_SINGLE(sri(SubRegSize::i32Bit, ZReg::z30, ZReg::z29, 15), "sri z30.s, z29.s, #15"); + TEST_SINGLE(sri(SubRegSize::i32Bit, ZReg::z30, ZReg::z29, 32), "sri z30.s, z29.s, #32"); + TEST_SINGLE(sri(SubRegSize::i64Bit, ZReg::z30, ZReg::z29, 1), "sri z30.d, z29.d, #1"); + TEST_SINGLE(sri(SubRegSize::i64Bit, ZReg::z30, ZReg::z29, 31), "sri z30.d, z29.d, #31"); + TEST_SINGLE(sri(SubRegSize::i64Bit, ZReg::z30, ZReg::z29, 64), "sri z30.d, z29.d, #64"); + + TEST_SINGLE(sli(SubRegSize::i8Bit, ZReg::z30, ZReg::z29, 0), "sli z30.b, z29.b, #0"); + TEST_SINGLE(sli(SubRegSize::i8Bit, ZReg::z30, ZReg::z29, 4), "sli z30.b, z29.b, #4"); + TEST_SINGLE(sli(SubRegSize::i8Bit, ZReg::z30, ZReg::z29, 7), "sli z30.b, z29.b, #7"); + TEST_SINGLE(sli(SubRegSize::i16Bit, ZReg::z30, ZReg::z29, 0), "sli z30.h, z29.h, #0"); + TEST_SINGLE(sli(SubRegSize::i16Bit, ZReg::z30, ZReg::z29, 7), "sli z30.h, z29.h, #7"); + TEST_SINGLE(sli(SubRegSize::i16Bit, ZReg::z30, ZReg::z29, 15), "sli z30.h, z29.h, #15"); + TEST_SINGLE(sli(SubRegSize::i32Bit, ZReg::z30, ZReg::z29, 0), "sli z30.s, z29.s, #0"); + TEST_SINGLE(sli(SubRegSize::i32Bit, ZReg::z30, ZReg::z29, 15), "sli z30.s, z29.s, #15"); + TEST_SINGLE(sli(SubRegSize::i32Bit, ZReg::z30, ZReg::z29, 31), "sli z30.s, z29.s, #31"); + TEST_SINGLE(sli(SubRegSize::i64Bit, ZReg::z30, ZReg::z29, 0), "sli z30.d, z29.d, #0"); + TEST_SINGLE(sli(SubRegSize::i64Bit, ZReg::z30, ZReg::z29, 31), "sli z30.d, z29.d, #31"); + TEST_SINGLE(sli(SubRegSize::i64Bit, ZReg::z30, ZReg::z29, 63), "sli z30.d, z29.d, #63"); } TEST_CASE_METHOD(TestDisassembler, "Emitter: SVE: SVE2 integer absolute difference and accumulate") { - // TODO: Implement in emitter. + TEST_SINGLE(saba(SubRegSize::i8Bit, ZReg::z28, ZReg::z29, ZReg::z30), "saba z28.b, z29.b, z30.b"); + TEST_SINGLE(saba(SubRegSize::i16Bit, ZReg::z28, ZReg::z29, ZReg::z30), "saba z28.h, z29.h, z30.h"); + TEST_SINGLE(saba(SubRegSize::i32Bit, ZReg::z28, ZReg::z29, ZReg::z30), "saba z28.s, z29.s, z30.s"); + TEST_SINGLE(saba(SubRegSize::i64Bit, ZReg::z28, ZReg::z29, ZReg::z30), "saba z28.d, z29.d, z30.d"); + + TEST_SINGLE(uaba(SubRegSize::i8Bit, ZReg::z28, ZReg::z29, ZReg::z30), "uaba z28.b, z29.b, z30.b"); + TEST_SINGLE(uaba(SubRegSize::i16Bit, ZReg::z28, ZReg::z29, ZReg::z30), "uaba z28.h, z29.h, z30.h"); + TEST_SINGLE(uaba(SubRegSize::i32Bit, ZReg::z28, ZReg::z29, ZReg::z30), "uaba z28.s, z29.s, z30.s"); + TEST_SINGLE(uaba(SubRegSize::i64Bit, ZReg::z28, ZReg::z29, ZReg::z30), "uaba z28.d, z29.d, z30.d"); } TEST_CASE_METHOD(TestDisassembler, "Emitter: SVE: SVE2 saturating extract narrow") { TEST_SINGLE(sqxtnb(SubRegSize::i8Bit, ZReg::z30, ZReg::z29), "sqxtnb z30.b, z29.h");