From b02af9562921e869dc447324d0d76b3a23b0143d Mon Sep 17 00:00:00 2001 From: Lioncache Date: Fri, 10 Feb 2023 22:27:57 -0500 Subject: [PATCH 1/6] ARMEmitter: Handle SVE2 complex add category --- .../Core/ArchHelpers/CodeEmitter/SVEOps.inl | 25 ++++++++++++++++++- .../FEXCore/unittests/Emitter/SVE_Tests.cpp | 20 ++++++++++++++- 2 files changed, 43 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 ee940957f..8f83b60de 100644 --- a/External/FEXCore/Source/Interface/Core/ArchHelpers/CodeEmitter/SVEOps.inl +++ b/External/FEXCore/Source/Interface/Core/ArchHelpers/CodeEmitter/SVEOps.inl @@ -1966,7 +1966,13 @@ 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: // SVE2 integer add/subtract long with carry @@ -3649,6 +3655,23 @@ 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); + } + // 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..92aafa6f6 100644 --- a/External/FEXCore/unittests/Emitter/SVE_Tests.cpp +++ b/External/FEXCore/unittests/Emitter/SVE_Tests.cpp @@ -1857,7 +1857,25 @@ 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. From fdd950e1d122626f80054df71008485c9369c49e Mon Sep 17 00:00:00 2001 From: Lioncache Date: Fri, 10 Feb 2023 22:44:05 -0500 Subject: [PATCH 2/6] ARMEmitter: Handle SVE2 integer absolute difference and accumulate long category --- .../Core/ArchHelpers/CodeEmitter/SVEOps.inl | 27 ++++++++++++++++++- .../FEXCore/unittests/Emitter/SVE_Tests.cpp | 16 ++++++++++- 2 files changed, 41 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 8f83b60de..b219d3b34 100644 --- a/External/FEXCore/Source/Interface/Core/ArchHelpers/CodeEmitter/SVEOps.inl +++ b/External/FEXCore/Source/Interface/Core/ArchHelpers/CodeEmitter/SVEOps.inl @@ -1974,7 +1974,19 @@ public: } // 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: // SVE2 bitwise shift right and accumulate @@ -3672,6 +3684,19 @@ private: 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 92aafa6f6..e0edae989 100644 --- a/External/FEXCore/unittests/Emitter/SVE_Tests.cpp +++ b/External/FEXCore/unittests/Emitter/SVE_Tests.cpp @@ -1878,7 +1878,21 @@ TEST_CASE_METHOD(TestDisassembler, "Emitter: SVE: SVE2 complex integer add") { 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. From feacd897fc63d36977727cd04a9d9116410b9656 Mon Sep 17 00:00:00 2001 From: Lioncache Date: Fri, 10 Feb 2023 23:04:34 -0500 Subject: [PATCH 3/6] ARMEmitter: Handle SVE2 integer add/sub long with carry category --- .../Core/ArchHelpers/CodeEmitter/SVEOps.inl | 30 ++++++++++++++++++- .../FEXCore/unittests/Emitter/SVE_Tests.cpp | 12 +++++++- 2 files changed, 40 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 b219d3b34..a5c6cb0a9 100644 --- a/External/FEXCore/Source/Interface/Core/ArchHelpers/CodeEmitter/SVEOps.inl +++ b/External/FEXCore/Source/Interface/Core/ArchHelpers/CodeEmitter/SVEOps.inl @@ -1988,7 +1988,19 @@ public: } // 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: // SVE2 bitwise shift and insert @@ -3643,6 +3655,22 @@ private: 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 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"); diff --git a/External/FEXCore/unittests/Emitter/SVE_Tests.cpp b/External/FEXCore/unittests/Emitter/SVE_Tests.cpp index e0edae989..97068524a 100644 --- a/External/FEXCore/unittests/Emitter/SVE_Tests.cpp +++ b/External/FEXCore/unittests/Emitter/SVE_Tests.cpp @@ -1895,7 +1895,17 @@ TEST_CASE_METHOD(TestDisassembler, "Emitter: SVE: SVE2 integer absolute differen 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. From 880cc72842431c4aaa7b9c68c574e868887401b0 Mon Sep 17 00:00:00 2001 From: Lioncache Date: Fri, 10 Feb 2023 23:27:15 -0500 Subject: [PATCH 4/6] ARMEmitter: Handle SVE2 bitwise shift right and accumulate --- .../Core/ArchHelpers/CodeEmitter/SVEOps.inl | 56 ++++++++++++++++++- .../FEXCore/unittests/Emitter/SVE_Tests.cpp | 36 +++++++++++- 2 files changed, 90 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 a5c6cb0a9..c0ae0fe65 100644 --- a/External/FEXCore/Source/Interface/Core/ArchHelpers/CodeEmitter/SVEOps.inl +++ b/External/FEXCore/Source/Interface/Core/ArchHelpers/CodeEmitter/SVEOps.inl @@ -2002,7 +2002,19 @@ public: } // 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: // SVE2 integer absolute difference and accumulate @@ -3671,6 +3683,48 @@ private: 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 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"); diff --git a/External/FEXCore/unittests/Emitter/SVE_Tests.cpp b/External/FEXCore/unittests/Emitter/SVE_Tests.cpp index 97068524a..4b6cf08d7 100644 --- a/External/FEXCore/unittests/Emitter/SVE_Tests.cpp +++ b/External/FEXCore/unittests/Emitter/SVE_Tests.cpp @@ -1908,7 +1908,41 @@ TEST_CASE_METHOD(TestDisassembler, "Emitter: SVE: SVE2 integer add/subtract long 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. From 62e2f1b45d758ada665491dd5193cf5d568b422d Mon Sep 17 00:00:00 2001 From: Lioncache Date: Fri, 10 Feb 2023 23:44:42 -0500 Subject: [PATCH 5/6] ARMEmitter: Handle SVE2 bitwise shift and insert category --- .../Core/ArchHelpers/CodeEmitter/SVEOps.inl | 56 ++++++++++++++++++- .../FEXCore/unittests/Emitter/SVE_Tests.cpp | 26 ++++++++- 2 files changed, 80 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 c0ae0fe65..a56efc504 100644 --- a/External/FEXCore/Source/Interface/Core/ArchHelpers/CodeEmitter/SVEOps.inl +++ b/External/FEXCore/Source/Interface/Core/ArchHelpers/CodeEmitter/SVEOps.inl @@ -2016,7 +2016,14 @@ public: } // 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: // @@ -3725,6 +3732,53 @@ private: 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"); diff --git a/External/FEXCore/unittests/Emitter/SVE_Tests.cpp b/External/FEXCore/unittests/Emitter/SVE_Tests.cpp index 4b6cf08d7..2bb1bf96b 100644 --- a/External/FEXCore/unittests/Emitter/SVE_Tests.cpp +++ b/External/FEXCore/unittests/Emitter/SVE_Tests.cpp @@ -1945,7 +1945,31 @@ TEST_CASE_METHOD(TestDisassembler, "Emitter: SVE: SVE2 bitwise shift right and a 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. From 504be62a92341fe5a514f579ce42c5d452438ea4 Mon Sep 17 00:00:00 2001 From: Lioncache Date: Sat, 11 Feb 2023 00:02:06 -0500 Subject: [PATCH 6/6] ARMEmitter: Handle SVE2 integer absolute difference and accumulate --- .../Core/ArchHelpers/CodeEmitter/SVEOps.inl | 21 +++++++++++++++++-- .../FEXCore/unittests/Emitter/SVE_Tests.cpp | 10 ++++++++- 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/External/FEXCore/Source/Interface/Core/ArchHelpers/CodeEmitter/SVEOps.inl b/External/FEXCore/Source/Interface/Core/ArchHelpers/CodeEmitter/SVEOps.inl index a56efc504..d80abef9c 100644 --- a/External/FEXCore/Source/Interface/Core/ArchHelpers/CodeEmitter/SVEOps.inl +++ b/External/FEXCore/Source/Interface/Core/ArchHelpers/CodeEmitter/SVEOps.inl @@ -2025,8 +2025,13 @@ public: // 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) { @@ -3674,6 +3679,18 @@ 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"); diff --git a/External/FEXCore/unittests/Emitter/SVE_Tests.cpp b/External/FEXCore/unittests/Emitter/SVE_Tests.cpp index 2bb1bf96b..c8a72fb9c 100644 --- a/External/FEXCore/unittests/Emitter/SVE_Tests.cpp +++ b/External/FEXCore/unittests/Emitter/SVE_Tests.cpp @@ -1972,7 +1972,15 @@ TEST_CASE_METHOD(TestDisassembler, "Emitter: SVE: SVE2 bitwise shift and insert" 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");