diff --git a/CodeEmitter/CodeEmitter/ASIMDOps.inl b/CodeEmitter/CodeEmitter/ASIMDOps.inl index 9f58407ba..413fe3edf 100644 --- a/CodeEmitter/CodeEmitter/ASIMDOps.inl +++ b/CodeEmitter/CodeEmitter/ASIMDOps.inl @@ -571,153 +571,6 @@ public: ASIMDThreeSameFP16(1, 1, 0b110, rm, rn, rd); } - // Advanced SIMD two-register miscellaneous (FP16) - template - requires (size == ARMEmitter::SubRegSize::i16Bit) - void frintn(T rd, T rn) { - ASIMDTwoRegMiscFP16(0, 0, 0b11000, rn, rd); - } - template - requires (size == ARMEmitter::SubRegSize::i16Bit) - void frintm(T rd, T rn) { - ASIMDTwoRegMiscFP16(0, 0, 0b11001, rn, rd); - } - template - requires (size == ARMEmitter::SubRegSize::i16Bit) - void fcvtns(T rd, T rn) { - ASIMDTwoRegMiscFP16(0, 0, 0b11010, rn, rd); - } - template - requires (size == ARMEmitter::SubRegSize::i16Bit) - void fcvtms(T rd, T rn) { - ASIMDTwoRegMiscFP16(0, 0, 0b11011, rn, rd); - } - template - requires (size == ARMEmitter::SubRegSize::i16Bit) - void fcvtas(T rd, T rn) { - ASIMDTwoRegMiscFP16(0, 0, 0b11100, rn, rd); - } - template - requires (size == ARMEmitter::SubRegSize::i16Bit) - void scvtf(T rd, T rn) { - ASIMDTwoRegMiscFP16(0, 0, 0b11101, rn, rd); - } - template - requires (size == ARMEmitter::SubRegSize::i16Bit) - void fcmgt(T rd, T rn) { - ASIMDTwoRegMiscFP16(0, 1, 0b01100, rn, rd); - } - template - requires (size == ARMEmitter::SubRegSize::i16Bit) - void fcmeq(T rd, T rn) { - ASIMDTwoRegMiscFP16(0, 1, 0b01101, rn, rd); - } - template - requires (size == ARMEmitter::SubRegSize::i16Bit) - void fcmlt(T rd, T rn) { - ASIMDTwoRegMiscFP16(0, 1, 0b01110, rn, rd); - } - template - requires (size == ARMEmitter::SubRegSize::i16Bit) - void fabs(T rd, T rn) { - ASIMDTwoRegMiscFP16(0, 1, 0b01111, rn, rd); - } - template - requires (size == ARMEmitter::SubRegSize::i16Bit) - void frintp(T rd, T rn) { - ASIMDTwoRegMiscFP16(0, 1, 0b11000, rn, rd); - } - template - requires (size == ARMEmitter::SubRegSize::i16Bit) - void frintz(T rd, T rn) { - ASIMDTwoRegMiscFP16(0, 1, 0b11001, rn, rd); - } - template - requires (size == ARMEmitter::SubRegSize::i16Bit) - void fcvtps(T rd, T rn) { - ASIMDTwoRegMiscFP16(0, 1, 0b11010, rn, rd); - } - template - requires (size == ARMEmitter::SubRegSize::i16Bit) - void fcvtzs(T rd, T rn) { - ASIMDTwoRegMiscFP16(0, 1, 0b11011, rn, rd); - } - template - requires (size == ARMEmitter::SubRegSize::i16Bit) - void frecpe(T rd, T rn) { - ASIMDTwoRegMiscFP16(0, 1, 0b11101, rn, rd); - } - template - requires (size == ARMEmitter::SubRegSize::i16Bit) - void frinta(T rd, T rn) { - ASIMDTwoRegMiscFP16(1, 0, 0b11000, rn, rd); - } - template - requires (size == ARMEmitter::SubRegSize::i16Bit) - void frintx(T rd, T rn) { - ASIMDTwoRegMiscFP16(1, 0, 0b11001, rn, rd); - } - template - requires (size == ARMEmitter::SubRegSize::i16Bit) - void fcvtnu(T rd, T rn) { - ASIMDTwoRegMiscFP16(1, 0, 0b11010, rn, rd); - } - template - requires (size == ARMEmitter::SubRegSize::i16Bit) - void fcvtmu(T rd, T rn) { - ASIMDTwoRegMiscFP16(1, 0, 0b11011, rn, rd); - } - template - requires (size == ARMEmitter::SubRegSize::i16Bit) - void fcvtau(T rd, T rn) { - ASIMDTwoRegMiscFP16(1, 0, 0b11100, rn, rd); - } - template - requires (size == ARMEmitter::SubRegSize::i16Bit) - void ucvtf(T rd, T rn) { - ASIMDTwoRegMiscFP16(1, 0, 0b11101, rn, rd); - } - template - requires (size == ARMEmitter::SubRegSize::i16Bit) - void fcmge(T rd, T rn) { - ASIMDTwoRegMiscFP16(1, 1, 0b01100, rn, rd); - } - template - requires (size == ARMEmitter::SubRegSize::i16Bit) - void fcmle(T rd, T rn) { - ASIMDTwoRegMiscFP16(1, 1, 0b01101, rn, rd); - } - template - requires (size == ARMEmitter::SubRegSize::i16Bit) - void fneg(T rd, T rn) { - ASIMDTwoRegMiscFP16(1, 1, 0b01111, rn, rd); - } - template - requires (size == ARMEmitter::SubRegSize::i16Bit) - void frinti(T rd, T rn) { - ASIMDTwoRegMiscFP16(1, 1, 0b11001, rn, rd); - } - template - requires (size == ARMEmitter::SubRegSize::i16Bit) - void fcvtpu(T rd, T rn) { - ASIMDTwoRegMiscFP16(1, 1, 0b11010, rn, rd); - } - template - requires (size == ARMEmitter::SubRegSize::i16Bit) - void fcvtzu(T rd, T rn) { - ASIMDTwoRegMiscFP16(1, 1, 0b11011, rn, rd); - } - template - requires (size == ARMEmitter::SubRegSize::i16Bit) - void frsqrte(T rd, T rn) { - ASIMDTwoRegMiscFP16(1, 1, 0b11101, rn, rd); - } - template - requires (size == ARMEmitter::SubRegSize::i16Bit) - void fsqrt(T rd, T rn) { - ASIMDTwoRegMiscFP16(1, 1, 0b11111, rn, rd); - } - // Advanced SIMD three-register extension template void sdot(ARMEmitter::SubRegSize size, T rd, T rn, T rm) { @@ -977,77 +830,101 @@ public: } template - void frintn(ARMEmitter::SubRegSize size, T rd, T rn) { - if constexpr (std::is_same_v) { - LOGMAN_THROW_A_FMT(size != ARMEmitter::SubRegSize::i64Bit, "64-bit subregsize not supported"); + void frintn(SubRegSize size, T rd, T rn) { + if constexpr (std::is_same_v) { + LOGMAN_THROW_A_FMT(size != SubRegSize::i64Bit, "64-bit subregsize not supported"); } - LOGMAN_THROW_A_FMT(size == ARMEmitter::SubRegSize::i64Bit || size == ARMEmitter::SubRegSize::i32Bit, "Only 32-bit & 64-bit subregsize " - "supported"); - constexpr uint32_t Op = 0b0000'1110'0010'0000'0000'10 << 10; - const auto ConvertedSize = size == ARMEmitter::SubRegSize::i64Bit ? ARMEmitter::SubRegSize::i16Bit : ARMEmitter::SubRegSize::i8Bit; + LOGMAN_THROW_A_FMT(IsStandardFloatSize(size), "Only 16/32/64-bit subregsize supported"); - ASIMD2RegMisc(Op, 0, ConvertedSize, 0b11000, rd, rn); + if (size == SubRegSize::i16Bit) { + ASIMDTwoRegMiscFP16(0, 0, 0b11000, rn, rd); + } else { + constexpr uint32_t Op = 0b0000'1110'0010'0000'0000'10 << 10; + const auto ConvertedSize = size == SubRegSize::i64Bit ? SubRegSize::i16Bit : SubRegSize::i8Bit; + + ASIMD2RegMisc(Op, 0, ConvertedSize, 0b11000, rd, rn); + } } template - void frintm(ARMEmitter::SubRegSize size, T rd, T rn) { - if constexpr (std::is_same_v) { - LOGMAN_THROW_A_FMT(size != ARMEmitter::SubRegSize::i64Bit, "64-bit subregsize not supported"); + void frintm(SubRegSize size, T rd, T rn) { + if constexpr (std::is_same_v) { + LOGMAN_THROW_A_FMT(size != SubRegSize::i64Bit, "64-bit subregsize not supported"); } - LOGMAN_THROW_A_FMT(size == ARMEmitter::SubRegSize::i64Bit || size == ARMEmitter::SubRegSize::i32Bit, "Only 32-bit & 64-bit subregsize " - "supported"); - constexpr uint32_t Op = 0b0000'1110'0010'0000'0000'10 << 10; - const auto ConvertedSize = size == ARMEmitter::SubRegSize::i64Bit ? ARMEmitter::SubRegSize::i16Bit : ARMEmitter::SubRegSize::i8Bit; + LOGMAN_THROW_A_FMT(IsStandardFloatSize(size), "Only 16/32/64-bit subregsize supported"); - ASIMD2RegMisc(Op, 0, ConvertedSize, 0b11001, rd, rn); + if (size == SubRegSize::i16Bit) { + ASIMDTwoRegMiscFP16(0, 0, 0b11001, rn, rd); + } else { + constexpr uint32_t Op = 0b0000'1110'0010'0000'0000'10 << 10; + const auto ConvertedSize = size == SubRegSize::i64Bit ? SubRegSize::i16Bit : SubRegSize::i8Bit; + + ASIMD2RegMisc(Op, 0, ConvertedSize, 0b11001, rd, rn); + } } template - void fcvtns(ARMEmitter::SubRegSize size, T rd, T rn) { - if constexpr (std::is_same_v) { - LOGMAN_THROW_A_FMT(size != ARMEmitter::SubRegSize::i64Bit, "64-bit subregsize not supported"); + void fcvtns(SubRegSize size, T rd, T rn) { + if constexpr (std::is_same_v) { + LOGMAN_THROW_A_FMT(size != SubRegSize::i64Bit, "64-bit subregsize not supported"); } - LOGMAN_THROW_A_FMT(size == ARMEmitter::SubRegSize::i64Bit || size == ARMEmitter::SubRegSize::i32Bit, "Only 32-bit & 64-bit subregsize " - "supported"); - constexpr uint32_t Op = 0b0000'1110'0010'0000'0000'10 << 10; - const auto ConvertedSize = size == ARMEmitter::SubRegSize::i64Bit ? ARMEmitter::SubRegSize::i16Bit : ARMEmitter::SubRegSize::i8Bit; + LOGMAN_THROW_A_FMT(IsStandardFloatSize(size), "Only 16/32/64-bit subregsize supported"); - ASIMD2RegMisc(Op, 0, ConvertedSize, 0b11010, rd, rn); + if (size == SubRegSize::i16Bit) { + ASIMDTwoRegMiscFP16(0, 0, 0b11010, rn, rd); + } else { + constexpr uint32_t Op = 0b0000'1110'0010'0000'0000'10 << 10; + const auto ConvertedSize = size == SubRegSize::i64Bit ? SubRegSize::i16Bit : SubRegSize::i8Bit; + + ASIMD2RegMisc(Op, 0, ConvertedSize, 0b11010, rd, rn); + } } template - void fcvtms(ARMEmitter::SubRegSize size, T rd, T rn) { - if constexpr (std::is_same_v) { - LOGMAN_THROW_A_FMT(size != ARMEmitter::SubRegSize::i64Bit, "64-bit subregsize not supported"); + void fcvtms(SubRegSize size, T rd, T rn) { + if constexpr (std::is_same_v) { + LOGMAN_THROW_A_FMT(size != SubRegSize::i64Bit, "64-bit subregsize not supported"); } - LOGMAN_THROW_A_FMT(size == ARMEmitter::SubRegSize::i64Bit || size == ARMEmitter::SubRegSize::i32Bit, "Only 32-bit & 64-bit subregsize " - "supported"); - constexpr uint32_t Op = 0b0000'1110'0010'0000'0000'10 << 10; - const auto ConvertedSize = size == ARMEmitter::SubRegSize::i64Bit ? ARMEmitter::SubRegSize::i16Bit : ARMEmitter::SubRegSize::i8Bit; + LOGMAN_THROW_A_FMT(IsStandardFloatSize(size), "Only 16/32/64-bit subregsize supported"); - ASIMD2RegMisc(Op, 0, ConvertedSize, 0b11011, rd, rn); + if (size == SubRegSize::i16Bit) { + ASIMDTwoRegMiscFP16(0, 0, 0b11011, rn, rd); + } else { + constexpr uint32_t Op = 0b0000'1110'0010'0000'0000'10 << 10; + const auto ConvertedSize = size == SubRegSize::i64Bit ? SubRegSize::i16Bit : SubRegSize::i8Bit; + + ASIMD2RegMisc(Op, 0, ConvertedSize, 0b11011, rd, rn); + } } template - void fcvtas(ARMEmitter::SubRegSize size, T rd, T rn) { - if constexpr (std::is_same_v) { - LOGMAN_THROW_A_FMT(size != ARMEmitter::SubRegSize::i64Bit, "64-bit subregsize not supported"); + void fcvtas(SubRegSize size, T rd, T rn) { + if constexpr (std::is_same_v) { + LOGMAN_THROW_A_FMT(size != SubRegSize::i64Bit, "64-bit subregsize not supported"); } - LOGMAN_THROW_A_FMT(size == ARMEmitter::SubRegSize::i64Bit || size == ARMEmitter::SubRegSize::i32Bit, "Only 32-bit & 64-bit subregsize " - "supported"); - constexpr uint32_t Op = 0b0000'1110'0010'0000'0000'10 << 10; - const auto ConvertedSize = size == ARMEmitter::SubRegSize::i64Bit ? ARMEmitter::SubRegSize::i16Bit : ARMEmitter::SubRegSize::i8Bit; + LOGMAN_THROW_A_FMT(IsStandardFloatSize(size), "Only 16/32/64-bit subregsize supported"); - ASIMD2RegMisc(Op, 0, ConvertedSize, 0b11100, rd, rn); + if (size == SubRegSize::i16Bit) { + ASIMDTwoRegMiscFP16(0, 0, 0b11100, rn, rd); + } else { + constexpr uint32_t Op = 0b0000'1110'0010'0000'0000'10 << 10; + const auto ConvertedSize = size == SubRegSize::i64Bit ? SubRegSize::i16Bit : SubRegSize::i8Bit; + + ASIMD2RegMisc(Op, 0, ConvertedSize, 0b11100, rd, rn); + } } template - void scvtf(ARMEmitter::SubRegSize size, T rd, T rn) { - if constexpr (std::is_same_v) { - LOGMAN_THROW_A_FMT(size != ARMEmitter::SubRegSize::i64Bit, "64-bit subregsize not supported"); + void scvtf(SubRegSize size, T rd, T rn) { + if constexpr (std::is_same_v) { + LOGMAN_THROW_A_FMT(size != SubRegSize::i64Bit, "64-bit subregsize not supported"); } - LOGMAN_THROW_A_FMT(size == ARMEmitter::SubRegSize::i64Bit || size == ARMEmitter::SubRegSize::i32Bit, "Only 32-bit & 64-bit subregsize " - "supported"); - constexpr uint32_t Op = 0b0000'1110'0010'0000'0000'10 << 10; - const auto ConvertedSize = size == ARMEmitter::SubRegSize::i64Bit ? ARMEmitter::SubRegSize::i16Bit : ARMEmitter::SubRegSize::i8Bit; + LOGMAN_THROW_A_FMT(IsStandardFloatSize(size), "Only 16/32/64-bit subregsize supported"); - ASIMD2RegMisc(Op, 0, ConvertedSize, 0b11101, rd, rn); + if (size == SubRegSize::i16Bit) { + ASIMDTwoRegMiscFP16(0, 0, 0b11101, rn, rd); + } else { + constexpr uint32_t Op = 0b0000'1110'0010'0000'0000'10 << 10; + const auto ConvertedSize = size == SubRegSize::i64Bit ? SubRegSize::i16Bit : SubRegSize::i8Bit; + + ASIMD2RegMisc(Op, 0, ConvertedSize, 0b11101, rd, rn); + } } template void frint32z(ARMEmitter::SubRegSize size, T rd, T rn) { @@ -1075,91 +952,123 @@ public: } template - void fcmgt(ARMEmitter::SubRegSize size, T rd, T rn) { - if constexpr (std::is_same_v) { - LOGMAN_THROW_A_FMT(size != ARMEmitter::SubRegSize::i64Bit, "64-bit subregsize not supported"); + void fcmgt(SubRegSize size, T rd, T rn) { + if constexpr (std::is_same_v) { + LOGMAN_THROW_A_FMT(size != SubRegSize::i64Bit, "64-bit subregsize not supported"); + } + LOGMAN_THROW_A_FMT(IsStandardFloatSize(size), "Only 16/32/64-bit subregsize supported"); + + if (size == SubRegSize::i16Bit) { + ASIMDTwoRegMiscFP16(0, 1, 0b01100, rn, rd); + } else { + constexpr uint32_t Op = 0b0000'1110'0010'0000'0000'10 << 10; + ASIMD2RegMisc(Op, 0, size, 0b01100, rd, rn); } - LOGMAN_THROW_A_FMT(size == ARMEmitter::SubRegSize::i64Bit || size == ARMEmitter::SubRegSize::i32Bit, "Only 32-bit & 64-bit subregsize " - "supported"); - constexpr uint32_t Op = 0b0000'1110'0010'0000'0000'10 << 10; - ASIMD2RegMisc(Op, 0, size, 0b01100, rd, rn); } template - void fcmeq(ARMEmitter::SubRegSize size, T rd, T rn) { - if constexpr (std::is_same_v) { - LOGMAN_THROW_A_FMT(size != ARMEmitter::SubRegSize::i64Bit, "64-bit subregsize not supported"); + void fcmeq(SubRegSize size, T rd, T rn) { + if constexpr (std::is_same_v) { + LOGMAN_THROW_A_FMT(size != SubRegSize::i64Bit, "64-bit subregsize not supported"); + } + LOGMAN_THROW_A_FMT(IsStandardFloatSize(size), "Only 16/32/64-bit subregsize supported"); + + if (size == SubRegSize::i16Bit) { + ASIMDTwoRegMiscFP16(0, 1, 0b01101, rn, rd); + } else { + constexpr uint32_t Op = 0b0000'1110'0010'0000'0000'10 << 10; + ASIMD2RegMisc(Op, 0, size, 0b01101, rd, rn); } - LOGMAN_THROW_A_FMT(size == ARMEmitter::SubRegSize::i64Bit || size == ARMEmitter::SubRegSize::i32Bit, "Only 32-bit & 64-bit subregsize " - "supported"); - constexpr uint32_t Op = 0b0000'1110'0010'0000'0000'10 << 10; - ASIMD2RegMisc(Op, 0, size, 0b01101, rd, rn); } template - void fcmlt(ARMEmitter::SubRegSize size, T rd, T rn) { - if constexpr (std::is_same_v) { - LOGMAN_THROW_A_FMT(size != ARMEmitter::SubRegSize::i64Bit, "64-bit subregsize not supported"); + void fcmlt(SubRegSize size, T rd, T rn) { + if constexpr (std::is_same_v) { + LOGMAN_THROW_A_FMT(size != SubRegSize::i64Bit, "64-bit subregsize not supported"); + } + LOGMAN_THROW_A_FMT(IsStandardFloatSize(size), "Only 16/32/64-bit subregsize supported"); + + if (size == SubRegSize::i16Bit) { + ASIMDTwoRegMiscFP16(0, 1, 0b01110, rn, rd); + } else { + constexpr uint32_t Op = 0b0000'1110'0010'0000'0000'10 << 10; + ASIMD2RegMisc(Op, 0, size, 0b01110, rd, rn); } - LOGMAN_THROW_A_FMT(size == ARMEmitter::SubRegSize::i64Bit || size == ARMEmitter::SubRegSize::i32Bit, "Only 32-bit & 64-bit subregsize " - "supported"); - constexpr uint32_t Op = 0b0000'1110'0010'0000'0000'10 << 10; - ASIMD2RegMisc(Op, 0, size, 0b01110, rd, rn); } template - void fabs(ARMEmitter::SubRegSize size, T rd, T rn) { - if constexpr (std::is_same_v) { - LOGMAN_THROW_A_FMT(size != ARMEmitter::SubRegSize::i64Bit, "64-bit subregsize not supported"); + void fabs(SubRegSize size, T rd, T rn) { + if constexpr (std::is_same_v) { + LOGMAN_THROW_A_FMT(size != SubRegSize::i64Bit, "64-bit subregsize not supported"); + } + LOGMAN_THROW_A_FMT(IsStandardFloatSize(size), "Only 16/32/64-bit subregsize supported"); + + if (size == SubRegSize::i16Bit) { + ASIMDTwoRegMiscFP16(0, 1, 0b01111, rn, rd); + } else { + constexpr uint32_t Op = 0b0000'1110'0010'0000'0000'10 << 10; + ASIMD2RegMisc(Op, 0, size, 0b01111, rd, rn); } - LOGMAN_THROW_A_FMT(size == ARMEmitter::SubRegSize::i64Bit || size == ARMEmitter::SubRegSize::i32Bit, "Only 32-bit & 64-bit subregsize " - "supported"); - constexpr uint32_t Op = 0b0000'1110'0010'0000'0000'10 << 10; - ASIMD2RegMisc(Op, 0, size, 0b01111, rd, rn); } template - void frintp(ARMEmitter::SubRegSize size, T rd, T rn) { - if constexpr (std::is_same_v) { - LOGMAN_THROW_A_FMT(size != ARMEmitter::SubRegSize::i64Bit, "64-bit subregsize not supported"); + void frintp(SubRegSize size, T rd, T rn) { + if constexpr (std::is_same_v) { + LOGMAN_THROW_A_FMT(size != SubRegSize::i64Bit, "64-bit subregsize not supported"); + } + LOGMAN_THROW_A_FMT(IsStandardFloatSize(size), "Only 16/32/64-bit subregsize supported"); + + if (size == SubRegSize::i16Bit) { + ASIMDTwoRegMiscFP16(0, 1, 0b11000, rn, rd); + } else { + constexpr uint32_t Op = 0b0000'1110'0010'0000'0000'10 << 10; + ASIMD2RegMisc(Op, 0, size, 0b11000, rd, rn); } - LOGMAN_THROW_A_FMT(size == ARMEmitter::SubRegSize::i64Bit || size == ARMEmitter::SubRegSize::i32Bit, "Only 32-bit & 64-bit subregsize " - "supported"); - constexpr uint32_t Op = 0b0000'1110'0010'0000'0000'10 << 10; - ASIMD2RegMisc(Op, 0, size, 0b11000, rd, rn); } template - void frintz(ARMEmitter::SubRegSize size, T rd, T rn) { - if constexpr (std::is_same_v) { - LOGMAN_THROW_A_FMT(size != ARMEmitter::SubRegSize::i64Bit, "64-bit subregsize not supported"); + void frintz(SubRegSize size, T rd, T rn) { + if constexpr (std::is_same_v) { + LOGMAN_THROW_A_FMT(size != SubRegSize::i64Bit, "64-bit subregsize not supported"); + } + LOGMAN_THROW_A_FMT(IsStandardFloatSize(size), "Only 16/32/64-bit subregsize supported"); + + if (size == SubRegSize::i16Bit) { + ASIMDTwoRegMiscFP16(0, 1, 0b11001, rn, rd); + } else { + constexpr uint32_t Op = 0b0000'1110'0010'0000'0000'10 << 10; + ASIMD2RegMisc(Op, 0, size, 0b11001, rd, rn); } - LOGMAN_THROW_A_FMT(size == ARMEmitter::SubRegSize::i64Bit || size == ARMEmitter::SubRegSize::i32Bit, "Only 32-bit & 64-bit subregsize " - "supported"); - constexpr uint32_t Op = 0b0000'1110'0010'0000'0000'10 << 10; - ASIMD2RegMisc(Op, 0, size, 0b11001, rd, rn); } template - void fcvtps(ARMEmitter::SubRegSize size, T rd, T rn) { - if constexpr (std::is_same_v) { - LOGMAN_THROW_A_FMT(size != ARMEmitter::SubRegSize::i64Bit, "64-bit subregsize not supported"); + void fcvtps(SubRegSize size, T rd, T rn) { + if constexpr (std::is_same_v) { + LOGMAN_THROW_A_FMT(size != SubRegSize::i64Bit, "64-bit subregsize not supported"); + } + LOGMAN_THROW_A_FMT(IsStandardFloatSize(size), "Only 16/32/64-bit subregsize supported"); + + if (size == SubRegSize::i16Bit) { + ASIMDTwoRegMiscFP16(0, 1, 0b11010, rn, rd); + } else { + constexpr uint32_t Op = 0b0000'1110'0010'0000'0000'10 << 10; + ASIMD2RegMisc(Op, 0, size, 0b11010, rd, rn); } - LOGMAN_THROW_A_FMT(size == ARMEmitter::SubRegSize::i64Bit || size == ARMEmitter::SubRegSize::i32Bit, "Only 32-bit & 64-bit subregsize " - "supported"); - constexpr uint32_t Op = 0b0000'1110'0010'0000'0000'10 << 10; - ASIMD2RegMisc(Op, 0, size, 0b11010, rd, rn); } template - void fcvtzs(ARMEmitter::SubRegSize size, T rd, T rn) { - if constexpr (std::is_same_v) { - LOGMAN_THROW_A_FMT(size != ARMEmitter::SubRegSize::i64Bit, "64-bit subregsize not supported"); + void fcvtzs(SubRegSize size, T rd, T rn) { + if constexpr (std::is_same_v) { + LOGMAN_THROW_A_FMT(size != SubRegSize::i64Bit, "64-bit subregsize not supported"); + } + LOGMAN_THROW_A_FMT(IsStandardFloatSize(size), "Only 16/32/64-bit subregsize supported"); + + if (size == SubRegSize::i16Bit) { + ASIMDTwoRegMiscFP16(0, 1, 0b11011, rn, rd); + } else { + constexpr uint32_t Op = 0b0000'1110'0010'0000'0000'10 << 10; + ASIMD2RegMisc(Op, 0, size, 0b11011, rd, rn); } - LOGMAN_THROW_A_FMT(size == ARMEmitter::SubRegSize::i64Bit || size == ARMEmitter::SubRegSize::i32Bit, "Only 32-bit & 64-bit subregsize " - "supported"); - constexpr uint32_t Op = 0b0000'1110'0010'0000'0000'10 << 10; - ASIMD2RegMisc(Op, 0, size, 0b11011, rd, rn); } template @@ -1170,11 +1079,15 @@ public: } template - void frecpe(ARMEmitter::SubRegSize size, T rd, T rn) { - LOGMAN_THROW_A_FMT(size == ARMEmitter::SubRegSize::i64Bit || size == ARMEmitter::SubRegSize::i32Bit, "Only 32-bit & 64-bit subregsize " - "supported"); - constexpr uint32_t Op = 0b0000'1110'0010'0000'0000'10 << 10; - ASIMD2RegMisc(Op, 0, size, 0b11101, rd, rn); + void frecpe(SubRegSize size, T rd, T rn) { + LOGMAN_THROW_A_FMT(IsStandardFloatSize(size), "Only 16/32/64-bit subregsize supported"); + + if (size == SubRegSize::i16Bit) { + ASIMDTwoRegMiscFP16(0, 1, 0b11101, rn, rd); + } else { + constexpr uint32_t Op = 0b0000'1110'0010'0000'0000'10 << 10; + ASIMD2RegMisc(Op, 0, size, 0b11101, rd, rn); + } } template @@ -1332,59 +1245,83 @@ public: ASIMD2RegMisc(Op, 1, ConvertedSize, 0b10110, rd.Q(), rn.Q()); } template - void frinta(ARMEmitter::SubRegSize size, T rd, T rn) { - LOGMAN_THROW_A_FMT(size == ARMEmitter::SubRegSize::i64Bit || size == ARMEmitter::SubRegSize::i32Bit, "Only 32-bit & 64-bit subregsize " - "supported"); - constexpr uint32_t Op = 0b0000'1110'0010'0000'0000'10 << 10; - const auto ConvertedSize = size == ARMEmitter::SubRegSize::i64Bit ? ARMEmitter::SubRegSize::i16Bit : ARMEmitter::SubRegSize::i8Bit; + void frinta(SubRegSize size, T rd, T rn) { + LOGMAN_THROW_A_FMT(IsStandardFloatSize(size), "Only 16/32/64-bit subregsize supported"); - ASIMD2RegMisc(Op, 1, ConvertedSize, 0b11000, rd, rn); + if (size == SubRegSize::i16Bit) { + ASIMDTwoRegMiscFP16(1, 0, 0b11000, rn, rd); + } else { + constexpr uint32_t Op = 0b0000'1110'0010'0000'0000'10 << 10; + const auto ConvertedSize = size == SubRegSize::i64Bit ? SubRegSize::i16Bit : SubRegSize::i8Bit; + + ASIMD2RegMisc(Op, 1, ConvertedSize, 0b11000, rd, rn); + } } template - void frintx(ARMEmitter::SubRegSize size, T rd, T rn) { - LOGMAN_THROW_A_FMT(size == ARMEmitter::SubRegSize::i64Bit || size == ARMEmitter::SubRegSize::i32Bit, "Only 32-bit & 64-bit subregsize " - "supported"); - constexpr uint32_t Op = 0b0000'1110'0010'0000'0000'10 << 10; - const auto ConvertedSize = size == ARMEmitter::SubRegSize::i64Bit ? ARMEmitter::SubRegSize::i16Bit : ARMEmitter::SubRegSize::i8Bit; + void frintx(SubRegSize size, T rd, T rn) { + LOGMAN_THROW_A_FMT(IsStandardFloatSize(size), "Only 16/32/64-bit subregsize supported"); - ASIMD2RegMisc(Op, 1, ConvertedSize, 0b11001, rd, rn); + if (size == SubRegSize::i16Bit) { + ASIMDTwoRegMiscFP16(1, 0, 0b11001, rn, rd); + } else { + constexpr uint32_t Op = 0b0000'1110'0010'0000'0000'10 << 10; + const auto ConvertedSize = size == SubRegSize::i64Bit ? SubRegSize::i16Bit : SubRegSize::i8Bit; + + ASIMD2RegMisc(Op, 1, ConvertedSize, 0b11001, rd, rn); + } } template - void fcvtnu(ARMEmitter::SubRegSize size, T rd, T rn) { - LOGMAN_THROW_A_FMT(size == ARMEmitter::SubRegSize::i64Bit || size == ARMEmitter::SubRegSize::i32Bit, "Only 32-bit & 64-bit subregsize " - "supported"); - constexpr uint32_t Op = 0b0000'1110'0010'0000'0000'10 << 10; - const auto ConvertedSize = size == ARMEmitter::SubRegSize::i64Bit ? ARMEmitter::SubRegSize::i16Bit : ARMEmitter::SubRegSize::i8Bit; + void fcvtnu(SubRegSize size, T rd, T rn) { + LOGMAN_THROW_A_FMT(IsStandardFloatSize(size), "Only 16/32/64-bit subregsize supported"); - ASIMD2RegMisc(Op, 1, ConvertedSize, 0b11010, rd, rn); + if (size == SubRegSize::i16Bit) { + ASIMDTwoRegMiscFP16(1, 0, 0b11010, rn, rd); + } else { + constexpr uint32_t Op = 0b0000'1110'0010'0000'0000'10 << 10; + const auto ConvertedSize = size == SubRegSize::i64Bit ? SubRegSize::i16Bit : SubRegSize::i8Bit; + + ASIMD2RegMisc(Op, 1, ConvertedSize, 0b11010, rd, rn); + } } template - void fcvtmu(ARMEmitter::SubRegSize size, T rd, T rn) { - LOGMAN_THROW_A_FMT(size == ARMEmitter::SubRegSize::i64Bit || size == ARMEmitter::SubRegSize::i32Bit, "Only 32-bit & 64-bit subregsize " - "supported"); - constexpr uint32_t Op = 0b0000'1110'0010'0000'0000'10 << 10; - const auto ConvertedSize = size == ARMEmitter::SubRegSize::i64Bit ? ARMEmitter::SubRegSize::i16Bit : ARMEmitter::SubRegSize::i8Bit; + void fcvtmu(SubRegSize size, T rd, T rn) { + LOGMAN_THROW_A_FMT(IsStandardFloatSize(size), "Only 16/32/64-bit subregsize supported"); - ASIMD2RegMisc(Op, 1, ConvertedSize, 0b11011, rd, rn); + if (size == SubRegSize::i16Bit) { + ASIMDTwoRegMiscFP16(1, 0, 0b11011, rn, rd); + } else { + constexpr uint32_t Op = 0b0000'1110'0010'0000'0000'10 << 10; + const auto ConvertedSize = size == SubRegSize::i64Bit ? SubRegSize::i16Bit : SubRegSize::i8Bit; + + ASIMD2RegMisc(Op, 1, ConvertedSize, 0b11011, rd, rn); + } } template - void fcvtau(ARMEmitter::SubRegSize size, T rd, T rn) { - LOGMAN_THROW_A_FMT(size == ARMEmitter::SubRegSize::i64Bit || size == ARMEmitter::SubRegSize::i32Bit, "Only 32-bit & 64-bit subregsize " - "supported"); - constexpr uint32_t Op = 0b0000'1110'0010'0000'0000'10 << 10; - const auto ConvertedSize = size == ARMEmitter::SubRegSize::i64Bit ? ARMEmitter::SubRegSize::i16Bit : ARMEmitter::SubRegSize::i8Bit; + void fcvtau(SubRegSize size, T rd, T rn) { + LOGMAN_THROW_A_FMT(IsStandardFloatSize(size), "Only 16/32/64-bit subregsize supported"); - ASIMD2RegMisc(Op, 1, ConvertedSize, 0b11100, rd, rn); + if (size == SubRegSize::i16Bit) { + ASIMDTwoRegMiscFP16(1, 0, 0b11100, rn, rd); + } else { + constexpr uint32_t Op = 0b0000'1110'0010'0000'0000'10 << 10; + const auto ConvertedSize = size == SubRegSize::i64Bit ? SubRegSize::i16Bit : SubRegSize::i8Bit; + + ASIMD2RegMisc(Op, 1, ConvertedSize, 0b11100, rd, rn); + } } template - void ucvtf(ARMEmitter::SubRegSize size, T rd, T rn) { - LOGMAN_THROW_A_FMT(size == ARMEmitter::SubRegSize::i64Bit || size == ARMEmitter::SubRegSize::i32Bit, "Only 32-bit & 64-bit subregsize " - "supported"); - constexpr uint32_t Op = 0b0000'1110'0010'0000'0000'10 << 10; - const auto ConvertedSize = size == ARMEmitter::SubRegSize::i64Bit ? ARMEmitter::SubRegSize::i16Bit : ARMEmitter::SubRegSize::i8Bit; + void ucvtf(SubRegSize size, T rd, T rn) { + LOGMAN_THROW_A_FMT(IsStandardFloatSize(size), "Only 16/32/64-bit subregsize supported"); - ASIMD2RegMisc(Op, 1, ConvertedSize, 0b11101, rd, rn); + if (size == SubRegSize::i16Bit) { + ASIMDTwoRegMiscFP16(1, 0, 0b11101, rn, rd); + } else { + constexpr uint32_t Op = 0b0000'1110'0010'0000'0000'10 << 10; + const auto ConvertedSize = size == SubRegSize::i64Bit ? SubRegSize::i16Bit : SubRegSize::i8Bit; + + ASIMD2RegMisc(Op, 1, ConvertedSize, 0b11101, rd, rn); + } } template void frint32x(ARMEmitter::SubRegSize size, T rd, T rn) { @@ -1426,67 +1363,91 @@ public: } template - void fcmge(ARMEmitter::SubRegSize size, T rd, T rn) { - if constexpr (std::is_same_v) { - LOGMAN_THROW_A_FMT(size != ARMEmitter::SubRegSize::i64Bit, "64-bit subregsize not supported"); + void fcmge(SubRegSize size, T rd, T rn) { + if constexpr (std::is_same_v) { + LOGMAN_THROW_A_FMT(size != SubRegSize::i64Bit, "64-bit subregsize not supported"); + } + LOGMAN_THROW_A_FMT(IsStandardFloatSize(size), "Only 16/32/64-bit subregsize supported"); + + if (size == SubRegSize::i16Bit) { + ASIMDTwoRegMiscFP16(1, 1, 0b01100, rn, rd); + } else { + constexpr uint32_t Op = 0b0000'1110'0010'0000'0000'10 << 10; + ASIMD2RegMisc(Op, 1, size, 0b01100, rd, rn); } - LOGMAN_THROW_A_FMT(size == ARMEmitter::SubRegSize::i64Bit || size == ARMEmitter::SubRegSize::i32Bit, "Only 32-bit & 64-bit subregsize " - "supported"); - constexpr uint32_t Op = 0b0000'1110'0010'0000'0000'10 << 10; - ASIMD2RegMisc(Op, 1, size, 0b01100, rd, rn); } template - void fcmle(ARMEmitter::SubRegSize size, T rd, T rn) { - if constexpr (std::is_same_v) { - LOGMAN_THROW_A_FMT(size != ARMEmitter::SubRegSize::i64Bit, "64-bit subregsize not supported"); + void fcmle(SubRegSize size, T rd, T rn) { + if constexpr (std::is_same_v) { + LOGMAN_THROW_A_FMT(size != SubRegSize::i64Bit, "64-bit subregsize not supported"); + } + LOGMAN_THROW_A_FMT(IsStandardFloatSize(size), "Only 16/32/64-bit subregsize supported"); + + if (size == SubRegSize::i16Bit) { + ASIMDTwoRegMiscFP16(1, 1, 0b01101, rn, rd); + } else { + constexpr uint32_t Op = 0b0000'1110'0010'0000'0000'10 << 10; + ASIMD2RegMisc(Op, 1, size, 0b01101, rd, rn); } - LOGMAN_THROW_A_FMT(size == ARMEmitter::SubRegSize::i64Bit || size == ARMEmitter::SubRegSize::i32Bit, "Only 32-bit & 64-bit subregsize " - "supported"); - constexpr uint32_t Op = 0b0000'1110'0010'0000'0000'10 << 10; - ASIMD2RegMisc(Op, 1, size, 0b01101, rd, rn); } template - void fneg(ARMEmitter::SubRegSize size, T rd, T rn) { - if constexpr (std::is_same_v) { - LOGMAN_THROW_A_FMT(size != ARMEmitter::SubRegSize::i64Bit, "64-bit subregsize not supported"); + void fneg(SubRegSize size, T rd, T rn) { + if constexpr (std::is_same_v) { + LOGMAN_THROW_A_FMT(size != SubRegSize::i64Bit, "64-bit subregsize not supported"); + } + LOGMAN_THROW_A_FMT(IsStandardFloatSize(size), "Only 16/32/64-bit subregsize supported"); + + if (size == SubRegSize::i16Bit) { + ASIMDTwoRegMiscFP16(1, 1, 0b01111, rn, rd); + } else { + constexpr uint32_t Op = 0b0000'1110'0010'0000'0000'10 << 10; + ASIMD2RegMisc(Op, 1, size, 0b01111, rd, rn); } - LOGMAN_THROW_A_FMT(size == ARMEmitter::SubRegSize::i64Bit || size == ARMEmitter::SubRegSize::i32Bit, "Only 32-bit & 64-bit subregsize " - "supported"); - constexpr uint32_t Op = 0b0000'1110'0010'0000'0000'10 << 10; - ASIMD2RegMisc(Op, 1, size, 0b01111, rd, rn); } template - void frinti(ARMEmitter::SubRegSize size, T rd, T rn) { - if constexpr (std::is_same_v) { - LOGMAN_THROW_A_FMT(size != ARMEmitter::SubRegSize::i64Bit, "64-bit subregsize not supported"); + void frinti(SubRegSize size, T rd, T rn) { + if constexpr (std::is_same_v) { + LOGMAN_THROW_A_FMT(size != SubRegSize::i64Bit, "64-bit subregsize not supported"); + } + LOGMAN_THROW_A_FMT(IsStandardFloatSize(size), "Only 16/32/64-bit subregsize supported"); + + if (size == SubRegSize::i16Bit) { + ASIMDTwoRegMiscFP16(1, 1, 0b11001, rn, rd); + } else { + constexpr uint32_t Op = 0b0000'1110'0010'0000'0000'10 << 10; + ASIMD2RegMisc(Op, 1, size, 0b11001, rd, rn); } - LOGMAN_THROW_A_FMT(size == ARMEmitter::SubRegSize::i64Bit || size == ARMEmitter::SubRegSize::i32Bit, "Only 32-bit & 64-bit subregsize " - "supported"); - constexpr uint32_t Op = 0b0000'1110'0010'0000'0000'10 << 10; - ASIMD2RegMisc(Op, 1, size, 0b11001, rd, rn); } template - void fcvtpu(ARMEmitter::SubRegSize size, T rd, T rn) { - if constexpr (std::is_same_v) { - LOGMAN_THROW_A_FMT(size != ARMEmitter::SubRegSize::i64Bit, "64-bit subregsize not supported"); + void fcvtpu(SubRegSize size, T rd, T rn) { + if constexpr (std::is_same_v) { + LOGMAN_THROW_A_FMT(size != SubRegSize::i64Bit, "64-bit subregsize not supported"); + } + LOGMAN_THROW_A_FMT(IsStandardFloatSize(size), "Only 16/32/64-bit subregsize supported"); + + if (size == SubRegSize::i16Bit) { + ASIMDTwoRegMiscFP16(1, 1, 0b11010, rn, rd); + } else { + constexpr uint32_t Op = 0b0000'1110'0010'0000'0000'10 << 10; + ASIMD2RegMisc(Op, 1, size, 0b11010, rd, rn); } - LOGMAN_THROW_A_FMT(size == ARMEmitter::SubRegSize::i64Bit || size == ARMEmitter::SubRegSize::i32Bit, "Only 32-bit & 64-bit subregsize " - "supported"); - constexpr uint32_t Op = 0b0000'1110'0010'0000'0000'10 << 10; - ASIMD2RegMisc(Op, 1, size, 0b11010, rd, rn); } template - void fcvtzu(ARMEmitter::SubRegSize size, T rd, T rn) { - if constexpr (std::is_same_v) { - LOGMAN_THROW_A_FMT(size != ARMEmitter::SubRegSize::i64Bit, "64-bit subregsize not supported"); + void fcvtzu(SubRegSize size, T rd, T rn) { + if constexpr (std::is_same_v) { + LOGMAN_THROW_A_FMT(size != SubRegSize::i64Bit, "64-bit subregsize not supported"); + } + LOGMAN_THROW_A_FMT(IsStandardFloatSize(size), "Only 16/32/64-bit subregsize supported"); + + if (size == SubRegSize::i16Bit) { + ASIMDTwoRegMiscFP16(1, 1, 0b11011, rn, rd); + } else { + constexpr uint32_t Op = 0b0000'1110'0010'0000'0000'10 << 10; + ASIMD2RegMisc(Op, 1, size, 0b11011, rd, rn); } - LOGMAN_THROW_A_FMT(size == ARMEmitter::SubRegSize::i64Bit || size == ARMEmitter::SubRegSize::i32Bit, "Only 32-bit & 64-bit subregsize " - "supported"); - constexpr uint32_t Op = 0b0000'1110'0010'0000'0000'10 << 10; - ASIMD2RegMisc(Op, 1, size, 0b11011, rd, rn); } template @@ -1496,25 +1457,33 @@ public: ASIMD2RegMisc(Op, 1, size, 0b11100, rd, rn); } template - void frsqrte(ARMEmitter::SubRegSize size, T rd, T rn) { - if constexpr (std::is_same_v) { - LOGMAN_THROW_A_FMT(size != ARMEmitter::SubRegSize::i64Bit, "64-bit subregsize not supported"); + void frsqrte(SubRegSize size, T rd, T rn) { + if constexpr (std::is_same_v) { + LOGMAN_THROW_A_FMT(size != SubRegSize::i64Bit, "64-bit subregsize not supported"); + } + LOGMAN_THROW_A_FMT(IsStandardFloatSize(size), "Only 16/32/64-bit subregsize supported"); + + if (size == SubRegSize::i16Bit) { + ASIMDTwoRegMiscFP16(1, 1, 0b11101, rn, rd); + } else { + constexpr uint32_t Op = 0b0000'1110'0010'0000'0000'10 << 10; + ASIMD2RegMisc(Op, 1, size, 0b11101, rd, rn); } - LOGMAN_THROW_A_FMT(size == ARMEmitter::SubRegSize::i64Bit || size == ARMEmitter::SubRegSize::i32Bit, "Only 32-bit & 64-bit subregsize " - "supported"); - constexpr uint32_t Op = 0b0000'1110'0010'0000'0000'10 << 10; - ASIMD2RegMisc(Op, 1, size, 0b11101, rd, rn); } template - void fsqrt(ARMEmitter::SubRegSize size, T rd, T rn) { - if constexpr (std::is_same_v) { - LOGMAN_THROW_A_FMT(size != ARMEmitter::SubRegSize::i64Bit, "64-bit subregsize not supported"); + void fsqrt(SubRegSize size, T rd, T rn) { + if constexpr (std::is_same_v) { + LOGMAN_THROW_A_FMT(size != SubRegSize::i64Bit, "64-bit subregsize not supported"); + } + LOGMAN_THROW_A_FMT(IsStandardFloatSize(size), "Only 16/32/64-bit subregsize supported"); + + if (size == SubRegSize::i16Bit) { + ASIMDTwoRegMiscFP16(1, 1, 0b11111, rn, rd); + } else { + constexpr uint32_t Op = 0b0000'1110'0010'0000'0000'10 << 10; + ASIMD2RegMisc(Op, 1, size, 0b11111, rd, rn); } - LOGMAN_THROW_A_FMT(size == ARMEmitter::SubRegSize::i64Bit || size == ARMEmitter::SubRegSize::i32Bit, "Only 32-bit & 64-bit subregsize " - "supported"); - constexpr uint32_t Op = 0b0000'1110'0010'0000'0000'10 << 10; - ASIMD2RegMisc(Op, 1, size, 0b11111, rd, rn); } // Advanced SIMD across lanes diff --git a/CodeEmitter/CodeEmitter/Emitter.h b/CodeEmitter/CodeEmitter/Emitter.h index c48705f08..a5ba7cfe8 100644 --- a/CodeEmitter/CodeEmitter/Emitter.h +++ b/CodeEmitter/CodeEmitter/Emitter.h @@ -86,6 +86,14 @@ constexpr size_t SubRegSizeInBits(SubRegSize size) { return size_t {8} << FEXCore::ToUnderlying(size); } +// Many floating point operations constrain their element sizes to the +// main three float sizes half, single, and double precision. This just +// combines all the checks together for brevity. +[[nodiscard]] +constexpr bool IsStandardFloatSize(SubRegSize size) { + return size == SubRegSize::i16Bit || size == SubRegSize::i32Bit || size == SubRegSize::i64Bit; +} + /* This `ScalarRegSize` enum is used for most scalar float * operations. * diff --git a/FEXCore/unittests/Emitter/ASIMD_Tests.cpp b/FEXCore/unittests/Emitter/ASIMD_Tests.cpp index d1381bfe3..e43a93ad9 100644 --- a/FEXCore/unittests/Emitter/ASIMD_Tests.cpp +++ b/FEXCore/unittests/Emitter/ASIMD_Tests.cpp @@ -288,35 +288,35 @@ TEST_CASE_METHOD(TestDisassembler, "Emitter: ASIMD: Advanced SIMD three same (FP TEST_SINGLE(fminp(QReg::q30, QReg::q29, QReg::q28), "fminp v30.8h, v29.8h, v28.8h"); } TEST_CASE_METHOD(TestDisassembler, "Emitter: ASIMD: Advanced SIMD two-register miscellaneous (FP16)") { - TEST_SINGLE(frintn(QReg::q30, QReg::q29), "frintn v30.8h, v29.8h"); - TEST_SINGLE(frintm(QReg::q30, QReg::q29), "frintm v30.8h, v29.8h"); - TEST_SINGLE(fcvtns(QReg::q30, QReg::q29), "fcvtns v30.8h, v29.8h"); - TEST_SINGLE(fcvtms(QReg::q30, QReg::q29), "fcvtms v30.8h, v29.8h"); - TEST_SINGLE(fcvtas(QReg::q30, QReg::q29), "fcvtas v30.8h, v29.8h"); - TEST_SINGLE(scvtf(QReg::q30, QReg::q29), "scvtf v30.8h, v29.8h"); - TEST_SINGLE(fcmgt(QReg::q30, QReg::q29), "fcmgt v30.8h, v29.8h, #0.0"); - TEST_SINGLE(fcmeq(QReg::q30, QReg::q29), "fcmeq v30.8h, v29.8h, #0.0"); - TEST_SINGLE(fcmlt(QReg::q30, QReg::q29), "fcmlt v30.8h, v29.8h, #0.0"); - TEST_SINGLE(fabs(QReg::q30, QReg::q29), "fabs v30.8h, v29.8h"); - TEST_SINGLE(frintp(QReg::q30, QReg::q29), "frintp v30.8h, v29.8h"); - TEST_SINGLE(frintz(QReg::q30, QReg::q29), "frintz v30.8h, v29.8h"); - TEST_SINGLE(fcvtps(QReg::q30, QReg::q29), "fcvtps v30.8h, v29.8h"); - TEST_SINGLE(fcvtzs(QReg::q30, QReg::q29), "fcvtzs v30.8h, v29.8h"); - TEST_SINGLE(frecpe(QReg::q30, QReg::q29), "frecpe v30.8h, v29.8h"); - TEST_SINGLE(frinta(QReg::q30, QReg::q29), "frinta v30.8h, v29.8h"); - TEST_SINGLE(frintx(QReg::q30, QReg::q29), "frintx v30.8h, v29.8h"); - TEST_SINGLE(fcvtnu(QReg::q30, QReg::q29), "fcvtnu v30.8h, v29.8h"); - TEST_SINGLE(fcvtmu(QReg::q30, QReg::q29), "fcvtmu v30.8h, v29.8h"); - TEST_SINGLE(fcvtau(QReg::q30, QReg::q29), "fcvtau v30.8h, v29.8h"); - TEST_SINGLE(ucvtf(QReg::q30, QReg::q29), "ucvtf v30.8h, v29.8h"); - TEST_SINGLE(fcmge(QReg::q30, QReg::q29), "fcmge v30.8h, v29.8h, #0.0"); - TEST_SINGLE(fcmle(QReg::q30, QReg::q29), "fcmle v30.8h, v29.8h, #0.0"); - TEST_SINGLE(fneg(QReg::q30, QReg::q29), "fneg v30.8h, v29.8h"); - TEST_SINGLE(frinti(QReg::q30, QReg::q29), "frinti v30.8h, v29.8h"); - TEST_SINGLE(fcvtpu(QReg::q30, QReg::q29), "fcvtpu v30.8h, v29.8h"); - TEST_SINGLE(fcvtzu(QReg::q30, QReg::q29), "fcvtzu v30.8h, v29.8h"); - TEST_SINGLE(frsqrte(QReg::q30, QReg::q29), "frsqrte v30.8h, v29.8h"); - TEST_SINGLE(fsqrt(QReg::q30, QReg::q29), "fsqrt v30.8h, v29.8h"); + TEST_SINGLE(frintn(SubRegSize::i16Bit, QReg::q30, QReg::q29), "frintn v30.8h, v29.8h"); + TEST_SINGLE(frintm(SubRegSize::i16Bit, QReg::q30, QReg::q29), "frintm v30.8h, v29.8h"); + TEST_SINGLE(fcvtns(SubRegSize::i16Bit, QReg::q30, QReg::q29), "fcvtns v30.8h, v29.8h"); + TEST_SINGLE(fcvtms(SubRegSize::i16Bit, QReg::q30, QReg::q29), "fcvtms v30.8h, v29.8h"); + TEST_SINGLE(fcvtas(SubRegSize::i16Bit, QReg::q30, QReg::q29), "fcvtas v30.8h, v29.8h"); + TEST_SINGLE(scvtf(SubRegSize::i16Bit, QReg::q30, QReg::q29), "scvtf v30.8h, v29.8h"); + TEST_SINGLE(fcmgt(SubRegSize::i16Bit, QReg::q30, QReg::q29), "fcmgt v30.8h, v29.8h, #0.0"); + TEST_SINGLE(fcmeq(SubRegSize::i16Bit, QReg::q30, QReg::q29), "fcmeq v30.8h, v29.8h, #0.0"); + TEST_SINGLE(fcmlt(SubRegSize::i16Bit, QReg::q30, QReg::q29), "fcmlt v30.8h, v29.8h, #0.0"); + TEST_SINGLE(fabs(SubRegSize::i16Bit, QReg::q30, QReg::q29), "fabs v30.8h, v29.8h"); + TEST_SINGLE(frintp(SubRegSize::i16Bit, QReg::q30, QReg::q29), "frintp v30.8h, v29.8h"); + TEST_SINGLE(frintz(SubRegSize::i16Bit, QReg::q30, QReg::q29), "frintz v30.8h, v29.8h"); + TEST_SINGLE(fcvtps(SubRegSize::i16Bit, QReg::q30, QReg::q29), "fcvtps v30.8h, v29.8h"); + TEST_SINGLE(fcvtzs(SubRegSize::i16Bit, QReg::q30, QReg::q29), "fcvtzs v30.8h, v29.8h"); + TEST_SINGLE(frecpe(SubRegSize::i16Bit, QReg::q30, QReg::q29), "frecpe v30.8h, v29.8h"); + TEST_SINGLE(frinta(SubRegSize::i16Bit, QReg::q30, QReg::q29), "frinta v30.8h, v29.8h"); + TEST_SINGLE(frintx(SubRegSize::i16Bit, QReg::q30, QReg::q29), "frintx v30.8h, v29.8h"); + TEST_SINGLE(fcvtnu(SubRegSize::i16Bit, QReg::q30, QReg::q29), "fcvtnu v30.8h, v29.8h"); + TEST_SINGLE(fcvtmu(SubRegSize::i16Bit, QReg::q30, QReg::q29), "fcvtmu v30.8h, v29.8h"); + TEST_SINGLE(fcvtau(SubRegSize::i16Bit, QReg::q30, QReg::q29), "fcvtau v30.8h, v29.8h"); + TEST_SINGLE(ucvtf(SubRegSize::i16Bit, QReg::q30, QReg::q29), "ucvtf v30.8h, v29.8h"); + TEST_SINGLE(fcmge(SubRegSize::i16Bit, QReg::q30, QReg::q29), "fcmge v30.8h, v29.8h, #0.0"); + TEST_SINGLE(fcmle(SubRegSize::i16Bit, QReg::q30, QReg::q29), "fcmle v30.8h, v29.8h, #0.0"); + TEST_SINGLE(fneg(SubRegSize::i16Bit, QReg::q30, QReg::q29), "fneg v30.8h, v29.8h"); + TEST_SINGLE(frinti(SubRegSize::i16Bit, QReg::q30, QReg::q29), "frinti v30.8h, v29.8h"); + TEST_SINGLE(fcvtpu(SubRegSize::i16Bit, QReg::q30, QReg::q29), "fcvtpu v30.8h, v29.8h"); + TEST_SINGLE(fcvtzu(SubRegSize::i16Bit, QReg::q30, QReg::q29), "fcvtzu v30.8h, v29.8h"); + TEST_SINGLE(frsqrte(SubRegSize::i16Bit, QReg::q30, QReg::q29), "frsqrte v30.8h, v29.8h"); + TEST_SINGLE(fsqrt(SubRegSize::i16Bit, QReg::q30, QReg::q29), "fsqrt v30.8h, v29.8h"); } TEST_CASE_METHOD(TestDisassembler, "Emitter: ASIMD: Advanced SIMD three-register extension") { TEST_SINGLE(sdot(SubRegSize::i32Bit, QReg::q30, QReg::q29, QReg::q28), "sdot v30.4s, v29.16b, v28.16b");