diff --git a/External/FEXCore/Source/Interface/Core/ArchHelpers/CodeEmitter/SVEOps.inl b/External/FEXCore/Source/Interface/Core/ArchHelpers/CodeEmitter/SVEOps.inl index f22cd1726..f3635bfdb 100644 --- a/External/FEXCore/Source/Interface/Core/ArchHelpers/CodeEmitter/SVEOps.inl +++ b/External/FEXCore/Source/Interface/Core/ArchHelpers/CodeEmitter/SVEOps.inl @@ -1911,8 +1911,17 @@ public: // SVE Misc // SVE2 bitwise shift left long // XXX: + // SVE2 integer add/subtract interleaved long - // XXX: + void saddlbt(SubRegSize size, ZRegister zd, ZRegister zn, ZRegister zm) { + SVE2IntegerAddSubInterleavedLong(size, 0b00, zd, zn, zm); + } + void ssublbt(SubRegSize size, ZRegister zd, ZRegister zn, ZRegister zm) { + SVE2IntegerAddSubInterleavedLong(size, 0b10, zd, zn, zm); + } + void ssubltb(SubRegSize size, ZRegister zd, ZRegister zn, ZRegister zm) { + SVE2IntegerAddSubInterleavedLong(size, 0b11, zd, zn, zm); + } // SVE2 bitwise exclusive-or interleaved void eorbt(SubRegSize size, ZRegister zd, ZRegister zn, ZRegister zm) { @@ -3592,6 +3601,19 @@ private: dc32(Instr); } + void SVE2IntegerAddSubInterleavedLong(SubRegSize size, uint32_t opc, ZRegister zd, ZRegister zn, ZRegister zm) { + LOGMAN_THROW_A_FMT(size != SubRegSize::i8Bit && size != SubRegSize::i128Bit, + "Can't use 8-bit or 128-bit element size"); + + uint32_t Instr = 0b0100'0101'0000'0000'1000'0000'0000'0000; + Instr |= FEXCore::ToUnderlying(size) << 22; + Instr |= zm.Idx() << 16; + Instr |= opc << 10; + Instr |= zn.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 40b94a9e9..2257d6258 100644 --- a/External/FEXCore/unittests/Emitter/SVE_Tests.cpp +++ b/External/FEXCore/unittests/Emitter/SVE_Tests.cpp @@ -1786,7 +1786,17 @@ TEST_CASE_METHOD(TestDisassembler, "Emitter: SVE: SVE2 bitwise shift left long") // TODO: Implement in emitter. } TEST_CASE_METHOD(TestDisassembler, "Emitter: SVE: SVE2 integer add/subtract interleaved long") { - // TODO: Implement in emitter. + TEST_SINGLE(saddlbt(SubRegSize::i16Bit, ZReg::z30, ZReg::z29, ZReg::z28), "saddlbt z30.h, z29.b, z28.b"); + TEST_SINGLE(saddlbt(SubRegSize::i32Bit, ZReg::z30, ZReg::z29, ZReg::z28), "saddlbt z30.s, z29.h, z28.h"); + TEST_SINGLE(saddlbt(SubRegSize::i64Bit, ZReg::z30, ZReg::z29, ZReg::z28), "saddlbt z30.d, z29.s, z28.s"); + + TEST_SINGLE(ssublbt(SubRegSize::i16Bit, ZReg::z30, ZReg::z29, ZReg::z28), "ssublbt z30.h, z29.b, z28.b"); + TEST_SINGLE(ssublbt(SubRegSize::i32Bit, ZReg::z30, ZReg::z29, ZReg::z28), "ssublbt z30.s, z29.h, z28.h"); + TEST_SINGLE(ssublbt(SubRegSize::i64Bit, ZReg::z30, ZReg::z29, ZReg::z28), "ssublbt z30.d, z29.s, z28.s"); + + TEST_SINGLE(ssubltb(SubRegSize::i16Bit, ZReg::z30, ZReg::z29, ZReg::z28), "ssubltb z30.h, z29.b, z28.b"); + TEST_SINGLE(ssubltb(SubRegSize::i32Bit, ZReg::z30, ZReg::z29, ZReg::z28), "ssubltb z30.s, z29.h, z28.h"); + TEST_SINGLE(ssubltb(SubRegSize::i64Bit, ZReg::z30, ZReg::z29, ZReg::z28), "ssubltb z30.d, z29.s, z28.s"); } TEST_CASE_METHOD(TestDisassembler, "Emitter: SVE: SVE2 bitwise exclusive-or interleaved") { TEST_SINGLE(eorbt(SubRegSize::i8Bit, ZReg::z30, ZReg::z29, ZReg::z28), "eorbt z30.b, z29.b, z28.b");