From 708ea9d50a056313b4936ea110080aa671a0dad2 Mon Sep 17 00:00:00 2001 From: Lioncache Date: Wed, 16 Jul 2025 17:05:48 -0400 Subject: [PATCH 1/2] ASIMDOps: Merge half-float 3-reg same with single/double variants --- CodeEmitter/CodeEmitter/ASIMDOps.inl | 577 ++++++++++------------ FEXCore/unittests/Emitter/ASIMD_Tests.cpp | 48 +- 2 files changed, 278 insertions(+), 347 deletions(-) diff --git a/CodeEmitter/CodeEmitter/ASIMDOps.inl b/CodeEmitter/CodeEmitter/ASIMDOps.inl index 413fe3edf..9e0d2827a 100644 --- a/CodeEmitter/CodeEmitter/ASIMDOps.inl +++ b/CodeEmitter/CodeEmitter/ASIMDOps.inl @@ -444,133 +444,6 @@ public: ASIMDScalarCopy(Op, 1, imm5, imm4, rd, rn); } - // Advanced SIMD three same (FP16) - template - requires (size == ARMEmitter::SubRegSize::i16Bit) - void fmaxnm(T rd, T rn, T rm) { - ASIMDThreeSameFP16(0, 0, 0b000, rm, rn, rd); - } - - template - requires (size == ARMEmitter::SubRegSize::i16Bit) - void fmla(T rd, T rn, T rm) { - ASIMDThreeSameFP16(0, 0, 0b001, rm, rn, rd); - } - - template - requires (size == ARMEmitter::SubRegSize::i16Bit) - void fadd(T rd, T rn, T rm) { - ASIMDThreeSameFP16(0, 0, 0b010, rm, rn, rd); - } - - template - requires (size == ARMEmitter::SubRegSize::i16Bit) - void fmulx(T rd, T rn, T rm) { - ASIMDThreeSameFP16(0, 0, 0b011, rm, rn, rd); - } - - template - requires (size == ARMEmitter::SubRegSize::i16Bit) - void fcmeq(T rd, T rn, T rm) { - ASIMDThreeSameFP16(0, 0, 0b100, rm, rn, rd); - } - - template - requires (size == ARMEmitter::SubRegSize::i16Bit) - void fmax(T rd, T rn, T rm) { - ASIMDThreeSameFP16(0, 0, 0b110, rm, rn, rd); - } - template - requires (size == ARMEmitter::SubRegSize::i16Bit) - void frecps(T rd, T rn, T rm) { - ASIMDThreeSameFP16(0, 0, 0b111, rm, rn, rd); - } - template - requires (size == ARMEmitter::SubRegSize::i16Bit) - void fminnm(T rd, T rn, T rm) { - ASIMDThreeSameFP16(0, 1, 0b000, rm, rn, rd); - } - template - requires (size == ARMEmitter::SubRegSize::i16Bit) - void fmls(T rd, T rn, T rm) { - ASIMDThreeSameFP16(0, 1, 0b001, rm, rn, rd); - } - template - requires (size == ARMEmitter::SubRegSize::i16Bit) - void fsub(T rd, T rn, T rm) { - ASIMDThreeSameFP16(0, 1, 0b010, rm, rn, rd); - } - template - requires (size == ARMEmitter::SubRegSize::i16Bit) - void fmin(T rd, T rn, T rm) { - ASIMDThreeSameFP16(0, 1, 0b110, rm, rn, rd); - } - template - requires (size == ARMEmitter::SubRegSize::i16Bit) - void frsqrts(T rd, T rn, T rm) { - ASIMDThreeSameFP16(0, 1, 0b111, rm, rn, rd); - } - template - requires (size == ARMEmitter::SubRegSize::i16Bit) - void fmaxnmp(T rd, T rn, T rm) { - ASIMDThreeSameFP16(1, 0, 0b000, rm, rn, rd); - } - template - requires (size == ARMEmitter::SubRegSize::i16Bit) - void faddp(T rd, T rn, T rm) { - ASIMDThreeSameFP16(1, 0, 0b010, rm, rn, rd); - } - template - requires (size == ARMEmitter::SubRegSize::i16Bit) - void fmul(T rd, T rn, T rm) { - ASIMDThreeSameFP16(1, 0, 0b011, rm, rn, rd); - } - template - requires (size == ARMEmitter::SubRegSize::i16Bit) - void fcmge(T rd, T rn, T rm) { - ASIMDThreeSameFP16(1, 0, 0b100, rm, rn, rd); - } - template - requires (size == ARMEmitter::SubRegSize::i16Bit) - void facge(T rd, T rn, T rm) { - ASIMDThreeSameFP16(1, 0, 0b101, rm, rn, rd); - } - template - requires (size == ARMEmitter::SubRegSize::i16Bit) - void fmaxp(T rd, T rn, T rm) { - ASIMDThreeSameFP16(1, 0, 0b110, rm, rn, rd); - } - template - requires (size == ARMEmitter::SubRegSize::i16Bit) - void fdiv(T rd, T rn, T rm) { - ASIMDThreeSameFP16(1, 0, 0b111, rm, rn, rd); - } - template - requires (size == ARMEmitter::SubRegSize::i16Bit) - void fminnmp(T rd, T rn, T rm) { - ASIMDThreeSameFP16(1, 1, 0b000, rm, rn, rd); - } - template - requires (size == ARMEmitter::SubRegSize::i16Bit) - void fabd(T rd, T rn, T rm) { - ASIMDThreeSameFP16(1, 1, 0b010, rm, rn, rd); - } - template - requires (size == ARMEmitter::SubRegSize::i16Bit) - void fcmgt(T rd, T rn, T rm) { - ASIMDThreeSameFP16(1, 1, 0b100, rm, rn, rd); - } - template - requires (size == ARMEmitter::SubRegSize::i16Bit) - void facgt(T rd, T rn, T rm) { - ASIMDThreeSameFP16(1, 1, 0b101, rm, rn, rd); - } - template - requires (size == ARMEmitter::SubRegSize::i16Bit) - void fminp(T rd, T rn, T rm) { - ASIMDThreeSameFP16(1, 1, 0b110, rm, rn, rd); - } - // Advanced SIMD three-register extension template void sdot(ARMEmitter::SubRegSize size, T rd, T rn, T rm) { @@ -2241,102 +2114,116 @@ public: ASIMD3Same(Op, 0, size, 0b10111, rd, rn, rm); } template - void fmaxnm(ARMEmitter::SubRegSize size, T rd, T rn, T rm) { - if constexpr (std::is_same_v) { - LOGMAN_THROW_A_FMT(size != ARMEmitter::SubRegSize::i64Bit, "Invalid element size with 64-bit {}", __func__); + void fmaxnm(SubRegSize size, T rd, T rn, T rm) { + if constexpr (std::is_same_v) { + LOGMAN_THROW_A_FMT(size != SubRegSize::i64Bit, "Invalid element size with 64-bit {}", __func__); } - LOGMAN_THROW_A_FMT(size == ARMEmitter::SubRegSize::i64Bit || size == ARMEmitter::SubRegSize::i32Bit, "Only 32-bit and 64-bit " - "subregsize supported"); + LOGMAN_THROW_A_FMT(IsStandardFloatSize(size), "Only 16/32/64-bit subregsize supported"); - constexpr uint32_t Op = 0b0000'1110'0010'0000'0000'01 << 10; - const ARMEmitter::SubRegSize ConvertedSize = - size == ARMEmitter::SubRegSize::i64Bit ? ARMEmitter::SubRegSize::i16Bit : ARMEmitter::SubRegSize::i8Bit; + if (size == SubRegSize::i16Bit) { + ASIMDThreeSameFP16(0, 0, 0b000, rm, rn, rd); + } else { + constexpr uint32_t Op = 0b0000'1110'0010'0000'0000'01 << 10; + const auto ConvertedSize = size == SubRegSize::i64Bit ? SubRegSize::i16Bit : SubRegSize::i8Bit; - ASIMD3Same(Op, 0, ConvertedSize, 0b11000, rd, rn, rm); + ASIMD3Same(Op, 0, ConvertedSize, 0b11000, rd, rn, rm); + } } template - void fmla(ARMEmitter::SubRegSize size, T rd, T rn, T rm) { - if constexpr (std::is_same_v) { - LOGMAN_THROW_A_FMT(size != ARMEmitter::SubRegSize::i64Bit, "Invalid element size with 64-bit {}", __func__); + void fmla(SubRegSize size, T rd, T rn, T rm) { + if constexpr (std::is_same_v) { + LOGMAN_THROW_A_FMT(size != SubRegSize::i64Bit, "Invalid element size with 64-bit {}", __func__); } - LOGMAN_THROW_A_FMT(size == ARMEmitter::SubRegSize::i64Bit || size == ARMEmitter::SubRegSize::i32Bit, "Only 32-bit and 64-bit " - "subregsize supported"); + LOGMAN_THROW_A_FMT(IsStandardFloatSize(size), "Only 16/32/64-bit subregsize supported"); - constexpr uint32_t Op = 0b0000'1110'0010'0000'0000'01 << 10; - const ARMEmitter::SubRegSize ConvertedSize = - size == ARMEmitter::SubRegSize::i64Bit ? ARMEmitter::SubRegSize::i16Bit : ARMEmitter::SubRegSize::i8Bit; + if (size == SubRegSize::i16Bit) { + ASIMDThreeSameFP16(0, 0, 0b001, rm, rn, rd); + } else { + constexpr uint32_t Op = 0b0000'1110'0010'0000'0000'01 << 10; + const auto ConvertedSize = size == SubRegSize::i64Bit ? SubRegSize::i16Bit : SubRegSize::i8Bit; - ASIMD3Same(Op, 0, ConvertedSize, 0b11001, rd, rn, rm); + ASIMD3Same(Op, 0, ConvertedSize, 0b11001, rd, rn, rm); + } } template - void fadd(ARMEmitter::SubRegSize size, T rd, T rn, T rm) { - if constexpr (std::is_same_v) { - LOGMAN_THROW_A_FMT(size != ARMEmitter::SubRegSize::i64Bit, "Invalid element size with 64-bit {}", __func__); + void fadd(SubRegSize size, T rd, T rn, T rm) { + if constexpr (std::is_same_v) { + LOGMAN_THROW_A_FMT(size != SubRegSize::i64Bit, "Invalid element size with 64-bit {}", __func__); } - LOGMAN_THROW_A_FMT(size == ARMEmitter::SubRegSize::i64Bit || size == ARMEmitter::SubRegSize::i32Bit, "Only 32-bit and 64-bit " - "subregsize supported"); + LOGMAN_THROW_A_FMT(IsStandardFloatSize(size), "Only 16/32/64-bit subregsize supported"); - constexpr uint32_t Op = 0b0000'1110'0010'0000'0000'01 << 10; - const ARMEmitter::SubRegSize ConvertedSize = - size == ARMEmitter::SubRegSize::i64Bit ? ARMEmitter::SubRegSize::i16Bit : ARMEmitter::SubRegSize::i8Bit; + if (size == SubRegSize::i16Bit) { + ASIMDThreeSameFP16(0, 0, 0b010, rm, rn, rd); + } else { + constexpr uint32_t Op = 0b0000'1110'0010'0000'0000'01 << 10; + const auto ConvertedSize = size == SubRegSize::i64Bit ? SubRegSize::i16Bit : SubRegSize::i8Bit; - ASIMD3Same(Op, 0, ConvertedSize, 0b11010, rd, rn, rm); + ASIMD3Same(Op, 0, ConvertedSize, 0b11010, rd, rn, rm); + } } template - void fmulx(ARMEmitter::SubRegSize size, T rd, T rn, T rm) { - if constexpr (std::is_same_v) { - LOGMAN_THROW_A_FMT(size != ARMEmitter::SubRegSize::i64Bit, "Invalid element size with 64-bit {}", __func__); + void fmulx(SubRegSize size, T rd, T rn, T rm) { + if constexpr (std::is_same_v) { + LOGMAN_THROW_A_FMT(size != SubRegSize::i64Bit, "Invalid element size with 64-bit {}", __func__); } - LOGMAN_THROW_A_FMT(size == ARMEmitter::SubRegSize::i64Bit || size == ARMEmitter::SubRegSize::i32Bit, "Only 32-bit and 64-bit " - "subregsize supported"); + LOGMAN_THROW_A_FMT(IsStandardFloatSize(size), "Only 16/32/64-bit subregsize supported"); - constexpr uint32_t Op = 0b0000'1110'0010'0000'0000'01 << 10; - const ARMEmitter::SubRegSize ConvertedSize = - size == ARMEmitter::SubRegSize::i64Bit ? ARMEmitter::SubRegSize::i16Bit : ARMEmitter::SubRegSize::i8Bit; + if (size == SubRegSize::i16Bit) { + ASIMDThreeSameFP16(0, 0, 0b011, rm, rn, rd); + } else { + constexpr uint32_t Op = 0b0000'1110'0010'0000'0000'01 << 10; + const auto ConvertedSize = size == SubRegSize::i64Bit ? SubRegSize::i16Bit : SubRegSize::i8Bit; - ASIMD3Same(Op, 0, ConvertedSize, 0b11011, rd, rn, rm); + ASIMD3Same(Op, 0, ConvertedSize, 0b11011, rd, rn, rm); + } } template - void fcmeq(ARMEmitter::SubRegSize size, T rd, T rn, T rm) { - if constexpr (std::is_same_v) { - LOGMAN_THROW_A_FMT(size != ARMEmitter::SubRegSize::i64Bit, "Invalid element size with 64-bit {}", __func__); + void fcmeq(SubRegSize size, T rd, T rn, T rm) { + if constexpr (std::is_same_v) { + LOGMAN_THROW_A_FMT(size != SubRegSize::i64Bit, "Invalid element size with 64-bit {}", __func__); } - LOGMAN_THROW_A_FMT(size == ARMEmitter::SubRegSize::i64Bit || size == ARMEmitter::SubRegSize::i32Bit, "Only 32-bit and 64-bit " - "subregsize supported"); + LOGMAN_THROW_A_FMT(IsStandardFloatSize(size), "Only 16/32/64-bit subregsize supported"); - constexpr uint32_t Op = 0b0000'1110'0010'0000'0000'01 << 10; - const ARMEmitter::SubRegSize ConvertedSize = - size == ARMEmitter::SubRegSize::i64Bit ? ARMEmitter::SubRegSize::i16Bit : ARMEmitter::SubRegSize::i8Bit; + if (size == SubRegSize::i16Bit) { + ASIMDThreeSameFP16(0, 0, 0b100, rm, rn, rd); + } else { + constexpr uint32_t Op = 0b0000'1110'0010'0000'0000'01 << 10; + const auto ConvertedSize = size == SubRegSize::i64Bit ? SubRegSize::i16Bit : SubRegSize::i8Bit; - ASIMD3Same(Op, 0, ConvertedSize, 0b11100, rd, rn, rm); + ASIMD3Same(Op, 0, ConvertedSize, 0b11100, rd, rn, rm); + } } template - void fmax(ARMEmitter::SubRegSize size, T rd, T rn, T rm) { - if constexpr (std::is_same_v) { - LOGMAN_THROW_A_FMT(size != ARMEmitter::SubRegSize::i64Bit, "Invalid element size with 64-bit {}", __func__); + void fmax(SubRegSize size, T rd, T rn, T rm) { + if constexpr (std::is_same_v) { + LOGMAN_THROW_A_FMT(size != SubRegSize::i64Bit, "Invalid element size with 64-bit {}", __func__); } - LOGMAN_THROW_A_FMT(size == ARMEmitter::SubRegSize::i64Bit || size == ARMEmitter::SubRegSize::i32Bit, "Only 32-bit and 64-bit " - "subregsize supported"); + LOGMAN_THROW_A_FMT(IsStandardFloatSize(size), "Only 16/32/64-bit subregsize supported"); - constexpr uint32_t Op = 0b0000'1110'0010'0000'0000'01 << 10; - const ARMEmitter::SubRegSize ConvertedSize = - size == ARMEmitter::SubRegSize::i64Bit ? ARMEmitter::SubRegSize::i16Bit : ARMEmitter::SubRegSize::i8Bit; + if (size == SubRegSize::i16Bit) { + ASIMDThreeSameFP16(0, 0, 0b110, rm, rn, rd); + } else { + constexpr uint32_t Op = 0b0000'1110'0010'0000'0000'01 << 10; + const auto ConvertedSize = size == SubRegSize::i64Bit ? SubRegSize::i16Bit : SubRegSize::i8Bit; - ASIMD3Same(Op, 0, ConvertedSize, 0b11110, rd, rn, rm); + ASIMD3Same(Op, 0, ConvertedSize, 0b11110, rd, rn, rm); + } } template - void frecps(ARMEmitter::SubRegSize size, T rd, T rn, T rm) { - if constexpr (std::is_same_v) { - LOGMAN_THROW_A_FMT(size != ARMEmitter::SubRegSize::i64Bit, "Invalid element size with 64-bit {}", __func__); + void frecps(SubRegSize size, T rd, T rn, T rm) { + if constexpr (std::is_same_v) { + LOGMAN_THROW_A_FMT(size != SubRegSize::i64Bit, "Invalid element size with 64-bit {}", __func__); } - LOGMAN_THROW_A_FMT(size == ARMEmitter::SubRegSize::i64Bit || size == ARMEmitter::SubRegSize::i32Bit, "Only 32-bit and 64-bit " - "subregsize supported"); + LOGMAN_THROW_A_FMT(IsStandardFloatSize(size), "Only 16/32/64-bit subregsize supported"); - constexpr uint32_t Op = 0b0000'1110'0010'0000'0000'01 << 10; - const ARMEmitter::SubRegSize ConvertedSize = - size == ARMEmitter::SubRegSize::i64Bit ? ARMEmitter::SubRegSize::i16Bit : ARMEmitter::SubRegSize::i8Bit; + if (size == SubRegSize::i16Bit) { + ASIMDThreeSameFP16(0, 0, 0b111, rm, rn, rd); + } else { + constexpr uint32_t Op = 0b0000'1110'0010'0000'0000'01 << 10; + const auto ConvertedSize = size == SubRegSize::i64Bit ? SubRegSize::i16Bit : SubRegSize::i8Bit; - ASIMD3Same(Op, 0, ConvertedSize, 0b11111, rd, rn, rm); + ASIMD3Same(Op, 0, ConvertedSize, 0b11111, rd, rn, rm); + } } template void and_(T rd, T rn, T rm) { @@ -2359,59 +2246,74 @@ public: ASIMD3Same(Op, 0, ARMEmitter::SubRegSize::i16Bit, 0b00011, rd, rn, rm); } template - void fminnm(ARMEmitter::SubRegSize size, T rd, T rn, T rm) { - if constexpr (std::is_same_v) { - LOGMAN_THROW_A_FMT(size != ARMEmitter::SubRegSize::i64Bit, "Invalid element size with 64-bit {}", __func__); + void fminnm(SubRegSize size, T rd, T rn, T rm) { + if constexpr (std::is_same_v) { + LOGMAN_THROW_A_FMT(size != SubRegSize::i64Bit, "Invalid element size with 64-bit {}", __func__); } - LOGMAN_THROW_A_FMT(size == ARMEmitter::SubRegSize::i64Bit || size == ARMEmitter::SubRegSize::i32Bit, "Only 32-bit and 64-bit " - "subregsize supported"); + LOGMAN_THROW_A_FMT(IsStandardFloatSize(size), "Only 16/32/64-bit subregsize supported"); - constexpr uint32_t Op = 0b0000'1110'0010'0000'0000'01 << 10; - ASIMD3Same(Op, 0, size, 0b11000, rd, rn, rm); + if (size == SubRegSize::i16Bit) { + ASIMDThreeSameFP16(0, 1, 0b000, rm, rn, rd); + } else { + constexpr uint32_t Op = 0b0000'1110'0010'0000'0000'01 << 10; + ASIMD3Same(Op, 0, size, 0b11000, rd, rn, rm); + } } template - void fmls(ARMEmitter::SubRegSize size, T rd, T rn, T rm) { - if constexpr (std::is_same_v) { - LOGMAN_THROW_A_FMT(size != ARMEmitter::SubRegSize::i64Bit, "Invalid element size with 64-bit {}", __func__); + void fmls(SubRegSize size, T rd, T rn, T rm) { + if constexpr (std::is_same_v) { + LOGMAN_THROW_A_FMT(size != SubRegSize::i64Bit, "Invalid element size with 64-bit {}", __func__); } - LOGMAN_THROW_A_FMT(size == ARMEmitter::SubRegSize::i64Bit || size == ARMEmitter::SubRegSize::i32Bit, "Only 32-bit and 64-bit " - "subregsize supported"); + LOGMAN_THROW_A_FMT(IsStandardFloatSize(size), "Only 16/32/64-bit subregsize supported"); - constexpr uint32_t Op = 0b0000'1110'0010'0000'0000'01 << 10; - ASIMD3Same(Op, 0, size, 0b11001, rd, rn, rm); + if (size == SubRegSize::i16Bit) { + ASIMDThreeSameFP16(0, 1, 0b001, rm, rn, rd); + } else { + constexpr uint32_t Op = 0b0000'1110'0010'0000'0000'01 << 10; + ASIMD3Same(Op, 0, size, 0b11001, rd, rn, rm); + } } template - void fsub(ARMEmitter::SubRegSize size, T rd, T rn, T rm) { - if constexpr (std::is_same_v) { - LOGMAN_THROW_A_FMT(size != ARMEmitter::SubRegSize::i64Bit, "Invalid element size with 64-bit {}", __func__); + void fsub(SubRegSize size, T rd, T rn, T rm) { + if constexpr (std::is_same_v) { + LOGMAN_THROW_A_FMT(size != SubRegSize::i64Bit, "Invalid element size with 64-bit {}", __func__); } - LOGMAN_THROW_A_FMT(size == ARMEmitter::SubRegSize::i64Bit || size == ARMEmitter::SubRegSize::i32Bit, "Only 32-bit and 64-bit " - "subregsize supported"); + LOGMAN_THROW_A_FMT(IsStandardFloatSize(size), "Only 16/32/64-bit subregsize supported"); - constexpr uint32_t Op = 0b0000'1110'0010'0000'0000'01 << 10; - ASIMD3Same(Op, 0, size, 0b11010, rd, rn, rm); + if (size == SubRegSize::i16Bit) { + ASIMDThreeSameFP16(0, 1, 0b010, rm, rn, rd); + } else { + constexpr uint32_t Op = 0b0000'1110'0010'0000'0000'01 << 10; + ASIMD3Same(Op, 0, size, 0b11010, rd, rn, rm); + } } template - void fmin(ARMEmitter::SubRegSize size, T rd, T rn, T rm) { - if constexpr (std::is_same_v) { - LOGMAN_THROW_A_FMT(size != ARMEmitter::SubRegSize::i64Bit, "Invalid element size with 64-bit {}", __func__); + void fmin(SubRegSize size, T rd, T rn, T rm) { + if constexpr (std::is_same_v) { + LOGMAN_THROW_A_FMT(size != SubRegSize::i64Bit, "Invalid element size with 64-bit {}", __func__); } - LOGMAN_THROW_A_FMT(size == ARMEmitter::SubRegSize::i64Bit || size == ARMEmitter::SubRegSize::i32Bit, "Only 32-bit and 64-bit " - "subregsize supported"); + LOGMAN_THROW_A_FMT(IsStandardFloatSize(size), "Only 16/32/64-bit subregsize supported"); - constexpr uint32_t Op = 0b0000'1110'0010'0000'0000'01 << 10; - ASIMD3Same(Op, 0, size, 0b11110, rd, rn, rm); + if (size == SubRegSize::i16Bit) { + ASIMDThreeSameFP16(0, 1, 0b110, rm, rn, rd); + } else { + constexpr uint32_t Op = 0b0000'1110'0010'0000'0000'01 << 10; + ASIMD3Same(Op, 0, size, 0b11110, rd, rn, rm); + } } template - void frsqrts(ARMEmitter::SubRegSize size, T rd, T rn, T rm) { - if constexpr (std::is_same_v) { - LOGMAN_THROW_A_FMT(size != ARMEmitter::SubRegSize::i64Bit, "Invalid element size with 64-bit {}", __func__); + void frsqrts(SubRegSize size, T rd, T rn, T rm) { + if constexpr (std::is_same_v) { + LOGMAN_THROW_A_FMT(size != SubRegSize::i64Bit, "Invalid element size with 64-bit {}", __func__); } - LOGMAN_THROW_A_FMT(size == ARMEmitter::SubRegSize::i64Bit || size == ARMEmitter::SubRegSize::i32Bit, "Only 32-bit and 64-bit " - "subregsize supported"); + LOGMAN_THROW_A_FMT(IsStandardFloatSize(size), "Only 16/32/64-bit subregsize supported"); - constexpr uint32_t Op = 0b0000'1110'0010'0000'0000'01 << 10; - ASIMD3Same(Op, 0, size, 0b11111, rd, rn, rm); + if (size == SubRegSize::i16Bit) { + ASIMDThreeSameFP16(0, 1, 0b111, rm, rn, rd); + } else { + constexpr uint32_t Op = 0b0000'1110'0010'0000'0000'01 << 10; + ASIMD3Same(Op, 0, size, 0b11111, rd, rn, rm); + } } template void orr(T rd, T rn, T rm) { @@ -2582,102 +2484,116 @@ public: ASIMD3Same(Op, 1, size, 0b10110, rd, rn, rm); } template - void fmaxnmp(ARMEmitter::SubRegSize size, T rd, T rn, T rm) { - if constexpr (std::is_same_v) { - LOGMAN_THROW_A_FMT(size != ARMEmitter::SubRegSize::i64Bit, "Invalid element size with 64-bit {}", __func__); + void fmaxnmp(SubRegSize size, T rd, T rn, T rm) { + if constexpr (std::is_same_v) { + LOGMAN_THROW_A_FMT(size != SubRegSize::i64Bit, "Invalid element size with 64-bit {}", __func__); } - LOGMAN_THROW_A_FMT(size == ARMEmitter::SubRegSize::i64Bit || size == ARMEmitter::SubRegSize::i32Bit, "Only 32-bit and 64-bit " - "subregsize supported"); + LOGMAN_THROW_A_FMT(IsStandardFloatSize(size), "Only 16/32/64-bit subregsize supported"); - constexpr uint32_t Op = 0b0000'1110'0010'0000'0000'01 << 10; - const ARMEmitter::SubRegSize ConvertedSize = - size == ARMEmitter::SubRegSize::i64Bit ? ARMEmitter::SubRegSize::i16Bit : ARMEmitter::SubRegSize::i8Bit; + if (size == SubRegSize::i16Bit) { + ASIMDThreeSameFP16(1, 0, 0b000, rm, rn, rd); + } else { + constexpr uint32_t Op = 0b0000'1110'0010'0000'0000'01 << 10; + const auto ConvertedSize = size == SubRegSize::i64Bit ? SubRegSize::i16Bit : SubRegSize::i8Bit; - ASIMD3Same(Op, 1, ConvertedSize, 0b11000, rd, rn, rm); + ASIMD3Same(Op, 1, ConvertedSize, 0b11000, rd, rn, rm); + } } template - void faddp(ARMEmitter::SubRegSize size, T rd, T rn, T rm) { - if constexpr (std::is_same_v) { - LOGMAN_THROW_A_FMT(size != ARMEmitter::SubRegSize::i64Bit, "Invalid element size with 64-bit {}", __func__); + void faddp(SubRegSize size, T rd, T rn, T rm) { + if constexpr (std::is_same_v) { + LOGMAN_THROW_A_FMT(size != SubRegSize::i64Bit, "Invalid element size with 64-bit {}", __func__); } - LOGMAN_THROW_A_FMT(size == ARMEmitter::SubRegSize::i64Bit || size == ARMEmitter::SubRegSize::i32Bit, "Only 32-bit and 64-bit " - "subregsize supported"); + LOGMAN_THROW_A_FMT(IsStandardFloatSize(size), "Only 16/32/64-bit subregsize supported"); - constexpr uint32_t Op = 0b0000'1110'0010'0000'0000'01 << 10; - const ARMEmitter::SubRegSize ConvertedSize = - size == ARMEmitter::SubRegSize::i64Bit ? ARMEmitter::SubRegSize::i16Bit : ARMEmitter::SubRegSize::i8Bit; + if (size == SubRegSize::i16Bit) { + ASIMDThreeSameFP16(1, 0, 0b010, rm, rn, rd); + } else { + constexpr uint32_t Op = 0b0000'1110'0010'0000'0000'01 << 10; + const auto ConvertedSize = size == SubRegSize::i64Bit ? SubRegSize::i16Bit : SubRegSize::i8Bit; - ASIMD3Same(Op, 1, ConvertedSize, 0b11010, rd, rn, rm); + ASIMD3Same(Op, 1, ConvertedSize, 0b11010, rd, rn, rm); + } } template - void fmul(ARMEmitter::SubRegSize size, T rd, T rn, T rm) { - if constexpr (std::is_same_v) { - LOGMAN_THROW_A_FMT(size != ARMEmitter::SubRegSize::i64Bit, "Invalid element size with 64-bit {}", __func__); + void fmul(SubRegSize size, T rd, T rn, T rm) { + if constexpr (std::is_same_v) { + LOGMAN_THROW_A_FMT(size != SubRegSize::i64Bit, "Invalid element size with 64-bit {}", __func__); } - LOGMAN_THROW_A_FMT(size == ARMEmitter::SubRegSize::i64Bit || size == ARMEmitter::SubRegSize::i32Bit, "Only 32-bit and 64-bit " - "subregsize supported"); + LOGMAN_THROW_A_FMT(IsStandardFloatSize(size), "Only 16/32/64-bit subregsize supported"); - constexpr uint32_t Op = 0b0000'1110'0010'0000'0000'01 << 10; - const ARMEmitter::SubRegSize ConvertedSize = - size == ARMEmitter::SubRegSize::i64Bit ? ARMEmitter::SubRegSize::i16Bit : ARMEmitter::SubRegSize::i8Bit; + if (size == SubRegSize::i16Bit) { + ASIMDThreeSameFP16(1, 0, 0b011, rm, rn, rd); + } else { + constexpr uint32_t Op = 0b0000'1110'0010'0000'0000'01 << 10; + const auto ConvertedSize = size == SubRegSize::i64Bit ? SubRegSize::i16Bit : SubRegSize::i8Bit; - ASIMD3Same(Op, 1, ConvertedSize, 0b11011, rd, rn, rm); + ASIMD3Same(Op, 1, ConvertedSize, 0b11011, rd, rn, rm); + } } template - void fcmge(ARMEmitter::SubRegSize size, T rd, T rn, T rm) { - if constexpr (std::is_same_v) { - LOGMAN_THROW_A_FMT(size != ARMEmitter::SubRegSize::i64Bit, "Invalid element size with 64-bit {}", __func__); + void fcmge(SubRegSize size, T rd, T rn, T rm) { + if constexpr (std::is_same_v) { + LOGMAN_THROW_A_FMT(size != SubRegSize::i64Bit, "Invalid element size with 64-bit {}", __func__); } - LOGMAN_THROW_A_FMT(size == ARMEmitter::SubRegSize::i64Bit || size == ARMEmitter::SubRegSize::i32Bit, "Only 32-bit and 64-bit " - "subregsize supported"); + LOGMAN_THROW_A_FMT(IsStandardFloatSize(size), "Only 16/32/64-bit subregsize supported"); - constexpr uint32_t Op = 0b0000'1110'0010'0000'0000'01 << 10; - const ARMEmitter::SubRegSize ConvertedSize = - size == ARMEmitter::SubRegSize::i64Bit ? ARMEmitter::SubRegSize::i16Bit : ARMEmitter::SubRegSize::i8Bit; + if (size == SubRegSize::i16Bit) { + ASIMDThreeSameFP16(1, 0, 0b100, rm, rn, rd); + } else { + constexpr uint32_t Op = 0b0000'1110'0010'0000'0000'01 << 10; + const auto ConvertedSize = size == SubRegSize::i64Bit ? SubRegSize::i16Bit : SubRegSize::i8Bit; - ASIMD3Same(Op, 1, ConvertedSize, 0b11100, rd, rn, rm); + ASIMD3Same(Op, 1, ConvertedSize, 0b11100, rd, rn, rm); + } } template - void facge(ARMEmitter::SubRegSize size, T rd, T rn, T rm) { - if constexpr (std::is_same_v) { - LOGMAN_THROW_A_FMT(size != ARMEmitter::SubRegSize::i64Bit, "Invalid element size with 64-bit {}", __func__); + void facge(SubRegSize size, T rd, T rn, T rm) { + if constexpr (std::is_same_v) { + LOGMAN_THROW_A_FMT(size != SubRegSize::i64Bit, "Invalid element size with 64-bit {}", __func__); } - LOGMAN_THROW_A_FMT(size == ARMEmitter::SubRegSize::i64Bit || size == ARMEmitter::SubRegSize::i32Bit, "Only 32-bit and 64-bit " - "subregsize supported"); + LOGMAN_THROW_A_FMT(IsStandardFloatSize(size), "Only 16/32/64-bit subregsize supported"); - constexpr uint32_t Op = 0b0000'1110'0010'0000'0000'01 << 10; - const ARMEmitter::SubRegSize ConvertedSize = - size == ARMEmitter::SubRegSize::i64Bit ? ARMEmitter::SubRegSize::i16Bit : ARMEmitter::SubRegSize::i8Bit; + if (size == SubRegSize::i16Bit) { + ASIMDThreeSameFP16(1, 0, 0b101, rm, rn, rd); + } else { + constexpr uint32_t Op = 0b0000'1110'0010'0000'0000'01 << 10; + const auto ConvertedSize = size == SubRegSize::i64Bit ? SubRegSize::i16Bit : SubRegSize::i8Bit; - ASIMD3Same(Op, 1, ConvertedSize, 0b11101, rd, rn, rm); + ASIMD3Same(Op, 1, ConvertedSize, 0b11101, rd, rn, rm); + } } template - void fmaxp(ARMEmitter::SubRegSize size, T rd, T rn, T rm) { - if constexpr (std::is_same_v) { - LOGMAN_THROW_A_FMT(size != ARMEmitter::SubRegSize::i64Bit, "Invalid element size with 64-bit {}", __func__); + void fmaxp(SubRegSize size, T rd, T rn, T rm) { + if constexpr (std::is_same_v) { + LOGMAN_THROW_A_FMT(size != SubRegSize::i64Bit, "Invalid element size with 64-bit {}", __func__); } - LOGMAN_THROW_A_FMT(size == ARMEmitter::SubRegSize::i64Bit || size == ARMEmitter::SubRegSize::i32Bit, "Only 32-bit and 64-bit " - "subregsize supported"); + LOGMAN_THROW_A_FMT(IsStandardFloatSize(size), "Only 16/32/64-bit subregsize supported"); - constexpr uint32_t Op = 0b0000'1110'0010'0000'0000'01 << 10; - const ARMEmitter::SubRegSize ConvertedSize = - size == ARMEmitter::SubRegSize::i64Bit ? ARMEmitter::SubRegSize::i16Bit : ARMEmitter::SubRegSize::i8Bit; + if (size == SubRegSize::i16Bit) { + ASIMDThreeSameFP16(1, 0, 0b110, rm, rn, rd); + } else { + constexpr uint32_t Op = 0b0000'1110'0010'0000'0000'01 << 10; + const auto ConvertedSize = size == SubRegSize::i64Bit ? SubRegSize::i16Bit : SubRegSize::i8Bit; - ASIMD3Same(Op, 1, ConvertedSize, 0b11110, rd, rn, rm); + ASIMD3Same(Op, 1, ConvertedSize, 0b11110, rd, rn, rm); + } } template - void fdiv(ARMEmitter::SubRegSize size, T rd, T rn, T rm) { - if constexpr (std::is_same_v) { - LOGMAN_THROW_A_FMT(size != ARMEmitter::SubRegSize::i64Bit, "Invalid element size with 64-bit {}", __func__); + void fdiv(SubRegSize size, T rd, T rn, T rm) { + if constexpr (std::is_same_v) { + LOGMAN_THROW_A_FMT(size != SubRegSize::i64Bit, "Invalid element size with 64-bit {}", __func__); } - LOGMAN_THROW_A_FMT(size == ARMEmitter::SubRegSize::i64Bit || size == ARMEmitter::SubRegSize::i32Bit, "Only 32-bit and 64-bit " - "subregsize supported"); + LOGMAN_THROW_A_FMT(IsStandardFloatSize(size), "Only 16/32/64-bit subregsize supported"); - constexpr uint32_t Op = 0b0000'1110'0010'0000'0000'01 << 10; - const ARMEmitter::SubRegSize ConvertedSize = - size == ARMEmitter::SubRegSize::i64Bit ? ARMEmitter::SubRegSize::i16Bit : ARMEmitter::SubRegSize::i8Bit; + if (size == SubRegSize::i16Bit) { + ASIMDThreeSameFP16(1, 0, 0b111, rm, rn, rd); + } else { + constexpr uint32_t Op = 0b0000'1110'0010'0000'0000'01 << 10; + const auto ConvertedSize = size == SubRegSize::i64Bit ? SubRegSize::i16Bit : SubRegSize::i8Bit; - ASIMD3Same(Op, 1, ConvertedSize, 0b11111, rd, rn, rm); + ASIMD3Same(Op, 1, ConvertedSize, 0b11111, rd, rn, rm); + } } template void eor(T rd, T rn, T rm) { @@ -2690,59 +2606,74 @@ public: ASIMD3Same(Op, 1, ARMEmitter::SubRegSize::i16Bit, 0b00011, rd, rn, rm); } template - void fminnmp(ARMEmitter::SubRegSize size, T rd, T rn, T rm) { - if constexpr (std::is_same_v) { - LOGMAN_THROW_A_FMT(size != ARMEmitter::SubRegSize::i64Bit, "Invalid element size with 64-bit {}", __func__); + void fminnmp(SubRegSize size, T rd, T rn, T rm) { + if constexpr (std::is_same_v) { + LOGMAN_THROW_A_FMT(size != SubRegSize::i64Bit, "Invalid element size with 64-bit {}", __func__); } - LOGMAN_THROW_A_FMT(size == ARMEmitter::SubRegSize::i64Bit || size == ARMEmitter::SubRegSize::i32Bit, "Only 32-bit and 64-bit " - "subregsize supported"); + LOGMAN_THROW_A_FMT(IsStandardFloatSize(size), "Only 16/32/64-bit subregsize supported"); - constexpr uint32_t Op = 0b0000'1110'0010'0000'0000'01 << 10; - ASIMD3Same(Op, 1, size, 0b11000, rd, rn, rm); + if (size == SubRegSize::i16Bit) { + ASIMDThreeSameFP16(1, 1, 0b000, rm, rn, rd); + } else { + constexpr uint32_t Op = 0b0000'1110'0010'0000'0000'01 << 10; + ASIMD3Same(Op, 1, size, 0b11000, rd, rn, rm); + } } template - void fabd(ARMEmitter::SubRegSize size, T rd, T rn, T rm) { - if constexpr (std::is_same_v) { - LOGMAN_THROW_A_FMT(size != ARMEmitter::SubRegSize::i64Bit, "Invalid element size with 64-bit {}", __func__); + void fabd(SubRegSize size, T rd, T rn, T rm) { + if constexpr (std::is_same_v) { + LOGMAN_THROW_A_FMT(size != SubRegSize::i64Bit, "Invalid element size with 64-bit {}", __func__); } - LOGMAN_THROW_A_FMT(size == ARMEmitter::SubRegSize::i64Bit || size == ARMEmitter::SubRegSize::i32Bit, "Only 32-bit and 64-bit " - "subregsize supported"); + LOGMAN_THROW_A_FMT(IsStandardFloatSize(size), "Only 16/32/64-bit subregsize supported"); - constexpr uint32_t Op = 0b0000'1110'0010'0000'0000'01 << 10; - ASIMD3Same(Op, 1, size, 0b11010, rd, rn, rm); + if (size == SubRegSize::i16Bit) { + ASIMDThreeSameFP16(1, 1, 0b010, rm, rn, rd); + } else { + constexpr uint32_t Op = 0b0000'1110'0010'0000'0000'01 << 10; + ASIMD3Same(Op, 1, size, 0b11010, rd, rn, rm); + } } template - void fcmgt(ARMEmitter::SubRegSize size, T rd, T rn, T rm) { - if constexpr (std::is_same_v) { - LOGMAN_THROW_A_FMT(size != ARMEmitter::SubRegSize::i64Bit, "Invalid element size with 64-bit {}", __func__); + void fcmgt(SubRegSize size, T rd, T rn, T rm) { + if constexpr (std::is_same_v) { + LOGMAN_THROW_A_FMT(size != SubRegSize::i64Bit, "Invalid element size with 64-bit {}", __func__); } - LOGMAN_THROW_A_FMT(size == ARMEmitter::SubRegSize::i64Bit || size == ARMEmitter::SubRegSize::i32Bit, "Only 32-bit and 64-bit " - "subregsize supported"); + LOGMAN_THROW_A_FMT(IsStandardFloatSize(size), "Only 16/32/64-bit subregsize supported"); - constexpr uint32_t Op = 0b0000'1110'0010'0000'0000'01 << 10; - ASIMD3Same(Op, 1, size, 0b11100, rd, rn, rm); + if (size == SubRegSize::i16Bit) { + ASIMDThreeSameFP16(1, 1, 0b100, rm, rn, rd); + } else { + constexpr uint32_t Op = 0b0000'1110'0010'0000'0000'01 << 10; + ASIMD3Same(Op, 1, size, 0b11100, rd, rn, rm); + } } template - void facgt(ARMEmitter::SubRegSize size, T rd, T rn, T rm) { - if constexpr (std::is_same_v) { - LOGMAN_THROW_A_FMT(size != ARMEmitter::SubRegSize::i64Bit, "Invalid element size with 64-bit {}", __func__); + void facgt(SubRegSize size, T rd, T rn, T rm) { + if constexpr (std::is_same_v) { + LOGMAN_THROW_A_FMT(size != SubRegSize::i64Bit, "Invalid element size with 64-bit {}", __func__); } - LOGMAN_THROW_A_FMT(size == ARMEmitter::SubRegSize::i64Bit || size == ARMEmitter::SubRegSize::i32Bit, "Only 32-bit and 64-bit " - "subregsize supported"); + LOGMAN_THROW_A_FMT(IsStandardFloatSize(size), "Only 16/32/64-bit subregsize supported"); - constexpr uint32_t Op = 0b0000'1110'0010'0000'0000'01 << 10; - ASIMD3Same(Op, 1, size, 0b11101, rd, rn, rm); + if (size == SubRegSize::i16Bit) { + ASIMDThreeSameFP16(1, 1, 0b101, rm, rn, rd); + } else { + constexpr uint32_t Op = 0b0000'1110'0010'0000'0000'01 << 10; + ASIMD3Same(Op, 1, size, 0b11101, rd, rn, rm); + } } template - void fminp(ARMEmitter::SubRegSize size, T rd, T rn, T rm) { - if constexpr (std::is_same_v) { - LOGMAN_THROW_A_FMT(size != ARMEmitter::SubRegSize::i64Bit, "Invalid element size with 64-bit {}", __func__); + void fminp(SubRegSize size, T rd, T rn, T rm) { + if constexpr (std::is_same_v) { + LOGMAN_THROW_A_FMT(size != SubRegSize::i64Bit, "Invalid element size with 64-bit {}", __func__); } - LOGMAN_THROW_A_FMT(size == ARMEmitter::SubRegSize::i64Bit || size == ARMEmitter::SubRegSize::i32Bit, "Only 32-bit and 64-bit " - "subregsize supported"); + LOGMAN_THROW_A_FMT(IsStandardFloatSize(size), "Only 16/32/64-bit subregsize supported"); - constexpr uint32_t Op = 0b0000'1110'0010'0000'0000'01 << 10; - ASIMD3Same(Op, 1, size, 0b11110, rd, rn, rm); + if (size == SubRegSize::i16Bit) { + ASIMDThreeSameFP16(1, 1, 0b110, rm, rn, rd); + } else { + constexpr uint32_t Op = 0b0000'1110'0010'0000'0000'01 << 10; + ASIMD3Same(Op, 1, size, 0b11110, rd, rn, rm); + } } template void bit(T rd, T rn, T rm) { diff --git a/FEXCore/unittests/Emitter/ASIMD_Tests.cpp b/FEXCore/unittests/Emitter/ASIMD_Tests.cpp index e43a93ad9..0ff45ca9e 100644 --- a/FEXCore/unittests/Emitter/ASIMD_Tests.cpp +++ b/FEXCore/unittests/Emitter/ASIMD_Tests.cpp @@ -262,30 +262,30 @@ TEST_CASE_METHOD(TestDisassembler, "Emitter: ASIMD: Advanced SIMD copy") { TEST_SINGLE(ins(SubRegSize::i64Bit, VReg::v30, 1, VReg::v29, 0), "mov v30.d[1], v29.d[0]"); } TEST_CASE_METHOD(TestDisassembler, "Emitter: ASIMD: Advanced SIMD three same (FP16)") { - TEST_SINGLE(fmaxnm(QReg::q30, QReg::q29, QReg::q28), "fmaxnm v30.8h, v29.8h, v28.8h"); - TEST_SINGLE(fmla(QReg::q30, QReg::q29, QReg::q28), "fmla v30.8h, v29.8h, v28.8h"); - TEST_SINGLE(fadd(QReg::q30, QReg::q29, QReg::q28), "fadd v30.8h, v29.8h, v28.8h"); - TEST_SINGLE(fmulx(QReg::q30, QReg::q29, QReg::q28), "fmulx v30.8h, v29.8h, v28.8h"); - TEST_SINGLE(fcmeq(QReg::q30, QReg::q29, QReg::q28), "fcmeq v30.8h, v29.8h, v28.8h"); - TEST_SINGLE(fmax(QReg::q30, QReg::q29, QReg::q28), "fmax v30.8h, v29.8h, v28.8h"); - TEST_SINGLE(frecps(QReg::q30, QReg::q29, QReg::q28), "frecps v30.8h, v29.8h, v28.8h"); - TEST_SINGLE(fminnm(QReg::q30, QReg::q29, QReg::q28), "fminnm v30.8h, v29.8h, v28.8h"); - TEST_SINGLE(fmls(QReg::q30, QReg::q29, QReg::q28), "fmls v30.8h, v29.8h, v28.8h"); - TEST_SINGLE(fsub(QReg::q30, QReg::q29, QReg::q28), "fsub v30.8h, v29.8h, v28.8h"); - TEST_SINGLE(fmin(QReg::q30, QReg::q29, QReg::q28), "fmin v30.8h, v29.8h, v28.8h"); - TEST_SINGLE(frsqrts(QReg::q30, QReg::q29, QReg::q28), "frsqrts v30.8h, v29.8h, v28.8h"); - TEST_SINGLE(fmaxnmp(QReg::q30, QReg::q29, QReg::q28), "fmaxnmp v30.8h, v29.8h, v28.8h"); - TEST_SINGLE(faddp(QReg::q30, QReg::q29, QReg::q28), "faddp v30.8h, v29.8h, v28.8h"); - TEST_SINGLE(fmul(QReg::q30, QReg::q29, QReg::q28), "fmul v30.8h, v29.8h, v28.8h"); - TEST_SINGLE(fcmge(QReg::q30, QReg::q29, QReg::q28), "fcmge v30.8h, v29.8h, v28.8h"); - TEST_SINGLE(facge(QReg::q30, QReg::q29, QReg::q28), "facge v30.8h, v29.8h, v28.8h"); - TEST_SINGLE(fmaxp(QReg::q30, QReg::q29, QReg::q28), "fmaxp v30.8h, v29.8h, v28.8h"); - TEST_SINGLE(fdiv(QReg::q30, QReg::q29, QReg::q28), "fdiv v30.8h, v29.8h, v28.8h"); - TEST_SINGLE(fminnmp(QReg::q30, QReg::q29, QReg::q28), "fminnmp v30.8h, v29.8h, v28.8h"); - TEST_SINGLE(fabd(QReg::q30, QReg::q29, QReg::q28), "fabd v30.8h, v29.8h, v28.8h"); - TEST_SINGLE(fcmgt(QReg::q30, QReg::q29, QReg::q28), "fcmgt v30.8h, v29.8h, v28.8h"); - TEST_SINGLE(facgt(QReg::q30, QReg::q29, QReg::q28), "facgt v30.8h, v29.8h, v28.8h"); - TEST_SINGLE(fminp(QReg::q30, QReg::q29, QReg::q28), "fminp v30.8h, v29.8h, v28.8h"); + TEST_SINGLE(fmaxnm(SubRegSize::i16Bit, QReg::q30, QReg::q29, QReg::q28), "fmaxnm v30.8h, v29.8h, v28.8h"); + TEST_SINGLE(fmla(SubRegSize::i16Bit, QReg::q30, QReg::q29, QReg::q28), "fmla v30.8h, v29.8h, v28.8h"); + TEST_SINGLE(fadd(SubRegSize::i16Bit, QReg::q30, QReg::q29, QReg::q28), "fadd v30.8h, v29.8h, v28.8h"); + TEST_SINGLE(fmulx(SubRegSize::i16Bit, QReg::q30, QReg::q29, QReg::q28), "fmulx v30.8h, v29.8h, v28.8h"); + TEST_SINGLE(fcmeq(SubRegSize::i16Bit, QReg::q30, QReg::q29, QReg::q28), "fcmeq v30.8h, v29.8h, v28.8h"); + TEST_SINGLE(fmax(SubRegSize::i16Bit, QReg::q30, QReg::q29, QReg::q28), "fmax v30.8h, v29.8h, v28.8h"); + TEST_SINGLE(frecps(SubRegSize::i16Bit, QReg::q30, QReg::q29, QReg::q28), "frecps v30.8h, v29.8h, v28.8h"); + TEST_SINGLE(fminnm(SubRegSize::i16Bit, QReg::q30, QReg::q29, QReg::q28), "fminnm v30.8h, v29.8h, v28.8h"); + TEST_SINGLE(fmls(SubRegSize::i16Bit, QReg::q30, QReg::q29, QReg::q28), "fmls v30.8h, v29.8h, v28.8h"); + TEST_SINGLE(fsub(SubRegSize::i16Bit, QReg::q30, QReg::q29, QReg::q28), "fsub v30.8h, v29.8h, v28.8h"); + TEST_SINGLE(fmin(SubRegSize::i16Bit, QReg::q30, QReg::q29, QReg::q28), "fmin v30.8h, v29.8h, v28.8h"); + TEST_SINGLE(frsqrts(SubRegSize::i16Bit, QReg::q30, QReg::q29, QReg::q28), "frsqrts v30.8h, v29.8h, v28.8h"); + TEST_SINGLE(fmaxnmp(SubRegSize::i16Bit, QReg::q30, QReg::q29, QReg::q28), "fmaxnmp v30.8h, v29.8h, v28.8h"); + TEST_SINGLE(faddp(SubRegSize::i16Bit, QReg::q30, QReg::q29, QReg::q28), "faddp v30.8h, v29.8h, v28.8h"); + TEST_SINGLE(fmul(SubRegSize::i16Bit, QReg::q30, QReg::q29, QReg::q28), "fmul v30.8h, v29.8h, v28.8h"); + TEST_SINGLE(fcmge(SubRegSize::i16Bit, QReg::q30, QReg::q29, QReg::q28), "fcmge v30.8h, v29.8h, v28.8h"); + TEST_SINGLE(facge(SubRegSize::i16Bit, QReg::q30, QReg::q29, QReg::q28), "facge v30.8h, v29.8h, v28.8h"); + TEST_SINGLE(fmaxp(SubRegSize::i16Bit, QReg::q30, QReg::q29, QReg::q28), "fmaxp v30.8h, v29.8h, v28.8h"); + TEST_SINGLE(fdiv(SubRegSize::i16Bit, QReg::q30, QReg::q29, QReg::q28), "fdiv v30.8h, v29.8h, v28.8h"); + TEST_SINGLE(fminnmp(SubRegSize::i16Bit, QReg::q30, QReg::q29, QReg::q28), "fminnmp v30.8h, v29.8h, v28.8h"); + TEST_SINGLE(fabd(SubRegSize::i16Bit, QReg::q30, QReg::q29, QReg::q28), "fabd v30.8h, v29.8h, v28.8h"); + TEST_SINGLE(fcmgt(SubRegSize::i16Bit, QReg::q30, QReg::q29, QReg::q28), "fcmgt v30.8h, v29.8h, v28.8h"); + TEST_SINGLE(facgt(SubRegSize::i16Bit, QReg::q30, QReg::q29, QReg::q28), "facgt v30.8h, v29.8h, v28.8h"); + TEST_SINGLE(fminp(SubRegSize::i16Bit, 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(SubRegSize::i16Bit, QReg::q30, QReg::q29), "frintn v30.8h, v29.8h"); From a615f8970ae63de2459c1885c89463d378e445d6 Mon Sep 17 00:00:00 2001 From: Lioncache Date: Wed, 16 Jul 2025 17:46:25 -0400 Subject: [PATCH 2/2] ASIMDOps: Constrain 3-reg same float arguments with IsQOrDRegister These are only intended to be used with QRegisters or DRegisters, so we can constrain these so that the proper types are enforced at compile-time. --- CodeEmitter/CodeEmitter/ASIMDOps.inl | 48 ++++++++++++++-------------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/CodeEmitter/CodeEmitter/ASIMDOps.inl b/CodeEmitter/CodeEmitter/ASIMDOps.inl index 9e0d2827a..ae19dee56 100644 --- a/CodeEmitter/CodeEmitter/ASIMDOps.inl +++ b/CodeEmitter/CodeEmitter/ASIMDOps.inl @@ -2113,7 +2113,7 @@ public: constexpr uint32_t Op = 0b0000'1110'0010'0000'0000'01 << 10; ASIMD3Same(Op, 0, size, 0b10111, rd, rn, rm); } - template + template void fmaxnm(SubRegSize size, T rd, T rn, T rm) { if constexpr (std::is_same_v) { LOGMAN_THROW_A_FMT(size != SubRegSize::i64Bit, "Invalid element size with 64-bit {}", __func__); @@ -2129,7 +2129,7 @@ public: ASIMD3Same(Op, 0, ConvertedSize, 0b11000, rd, rn, rm); } } - template + template void fmla(SubRegSize size, T rd, T rn, T rm) { if constexpr (std::is_same_v) { LOGMAN_THROW_A_FMT(size != SubRegSize::i64Bit, "Invalid element size with 64-bit {}", __func__); @@ -2145,7 +2145,7 @@ public: ASIMD3Same(Op, 0, ConvertedSize, 0b11001, rd, rn, rm); } } - template + template void fadd(SubRegSize size, T rd, T rn, T rm) { if constexpr (std::is_same_v) { LOGMAN_THROW_A_FMT(size != SubRegSize::i64Bit, "Invalid element size with 64-bit {}", __func__); @@ -2161,7 +2161,7 @@ public: ASIMD3Same(Op, 0, ConvertedSize, 0b11010, rd, rn, rm); } } - template + template void fmulx(SubRegSize size, T rd, T rn, T rm) { if constexpr (std::is_same_v) { LOGMAN_THROW_A_FMT(size != SubRegSize::i64Bit, "Invalid element size with 64-bit {}", __func__); @@ -2177,7 +2177,7 @@ public: ASIMD3Same(Op, 0, ConvertedSize, 0b11011, rd, rn, rm); } } - template + template void fcmeq(SubRegSize size, T rd, T rn, T rm) { if constexpr (std::is_same_v) { LOGMAN_THROW_A_FMT(size != SubRegSize::i64Bit, "Invalid element size with 64-bit {}", __func__); @@ -2193,7 +2193,7 @@ public: ASIMD3Same(Op, 0, ConvertedSize, 0b11100, rd, rn, rm); } } - template + template void fmax(SubRegSize size, T rd, T rn, T rm) { if constexpr (std::is_same_v) { LOGMAN_THROW_A_FMT(size != SubRegSize::i64Bit, "Invalid element size with 64-bit {}", __func__); @@ -2209,7 +2209,7 @@ public: ASIMD3Same(Op, 0, ConvertedSize, 0b11110, rd, rn, rm); } } - template + template void frecps(SubRegSize size, T rd, T rn, T rm) { if constexpr (std::is_same_v) { LOGMAN_THROW_A_FMT(size != SubRegSize::i64Bit, "Invalid element size with 64-bit {}", __func__); @@ -2245,7 +2245,7 @@ public: constexpr uint32_t Op = 0b0000'1110'0010'0000'0000'01 << 10; ASIMD3Same(Op, 0, ARMEmitter::SubRegSize::i16Bit, 0b00011, rd, rn, rm); } - template + template void fminnm(SubRegSize size, T rd, T rn, T rm) { if constexpr (std::is_same_v) { LOGMAN_THROW_A_FMT(size != SubRegSize::i64Bit, "Invalid element size with 64-bit {}", __func__); @@ -2259,7 +2259,7 @@ public: ASIMD3Same(Op, 0, size, 0b11000, rd, rn, rm); } } - template + template void fmls(SubRegSize size, T rd, T rn, T rm) { if constexpr (std::is_same_v) { LOGMAN_THROW_A_FMT(size != SubRegSize::i64Bit, "Invalid element size with 64-bit {}", __func__); @@ -2273,7 +2273,7 @@ public: ASIMD3Same(Op, 0, size, 0b11001, rd, rn, rm); } } - template + template void fsub(SubRegSize size, T rd, T rn, T rm) { if constexpr (std::is_same_v) { LOGMAN_THROW_A_FMT(size != SubRegSize::i64Bit, "Invalid element size with 64-bit {}", __func__); @@ -2287,7 +2287,7 @@ public: ASIMD3Same(Op, 0, size, 0b11010, rd, rn, rm); } } - template + template void fmin(SubRegSize size, T rd, T rn, T rm) { if constexpr (std::is_same_v) { LOGMAN_THROW_A_FMT(size != SubRegSize::i64Bit, "Invalid element size with 64-bit {}", __func__); @@ -2301,7 +2301,7 @@ public: ASIMD3Same(Op, 0, size, 0b11110, rd, rn, rm); } } - template + template void frsqrts(SubRegSize size, T rd, T rn, T rm) { if constexpr (std::is_same_v) { LOGMAN_THROW_A_FMT(size != SubRegSize::i64Bit, "Invalid element size with 64-bit {}", __func__); @@ -2483,7 +2483,7 @@ public: constexpr uint32_t Op = 0b0000'1110'0010'0000'0000'01 << 10; ASIMD3Same(Op, 1, size, 0b10110, rd, rn, rm); } - template + template void fmaxnmp(SubRegSize size, T rd, T rn, T rm) { if constexpr (std::is_same_v) { LOGMAN_THROW_A_FMT(size != SubRegSize::i64Bit, "Invalid element size with 64-bit {}", __func__); @@ -2499,7 +2499,7 @@ public: ASIMD3Same(Op, 1, ConvertedSize, 0b11000, rd, rn, rm); } } - template + template void faddp(SubRegSize size, T rd, T rn, T rm) { if constexpr (std::is_same_v) { LOGMAN_THROW_A_FMT(size != SubRegSize::i64Bit, "Invalid element size with 64-bit {}", __func__); @@ -2515,7 +2515,7 @@ public: ASIMD3Same(Op, 1, ConvertedSize, 0b11010, rd, rn, rm); } } - template + template void fmul(SubRegSize size, T rd, T rn, T rm) { if constexpr (std::is_same_v) { LOGMAN_THROW_A_FMT(size != SubRegSize::i64Bit, "Invalid element size with 64-bit {}", __func__); @@ -2531,7 +2531,7 @@ public: ASIMD3Same(Op, 1, ConvertedSize, 0b11011, rd, rn, rm); } } - template + template void fcmge(SubRegSize size, T rd, T rn, T rm) { if constexpr (std::is_same_v) { LOGMAN_THROW_A_FMT(size != SubRegSize::i64Bit, "Invalid element size with 64-bit {}", __func__); @@ -2547,7 +2547,7 @@ public: ASIMD3Same(Op, 1, ConvertedSize, 0b11100, rd, rn, rm); } } - template + template void facge(SubRegSize size, T rd, T rn, T rm) { if constexpr (std::is_same_v) { LOGMAN_THROW_A_FMT(size != SubRegSize::i64Bit, "Invalid element size with 64-bit {}", __func__); @@ -2563,7 +2563,7 @@ public: ASIMD3Same(Op, 1, ConvertedSize, 0b11101, rd, rn, rm); } } - template + template void fmaxp(SubRegSize size, T rd, T rn, T rm) { if constexpr (std::is_same_v) { LOGMAN_THROW_A_FMT(size != SubRegSize::i64Bit, "Invalid element size with 64-bit {}", __func__); @@ -2579,7 +2579,7 @@ public: ASIMD3Same(Op, 1, ConvertedSize, 0b11110, rd, rn, rm); } } - template + template void fdiv(SubRegSize size, T rd, T rn, T rm) { if constexpr (std::is_same_v) { LOGMAN_THROW_A_FMT(size != SubRegSize::i64Bit, "Invalid element size with 64-bit {}", __func__); @@ -2605,7 +2605,7 @@ public: constexpr uint32_t Op = 0b0000'1110'0010'0000'0000'01 << 10; ASIMD3Same(Op, 1, ARMEmitter::SubRegSize::i16Bit, 0b00011, rd, rn, rm); } - template + template void fminnmp(SubRegSize size, T rd, T rn, T rm) { if constexpr (std::is_same_v) { LOGMAN_THROW_A_FMT(size != SubRegSize::i64Bit, "Invalid element size with 64-bit {}", __func__); @@ -2619,7 +2619,7 @@ public: ASIMD3Same(Op, 1, size, 0b11000, rd, rn, rm); } } - template + template void fabd(SubRegSize size, T rd, T rn, T rm) { if constexpr (std::is_same_v) { LOGMAN_THROW_A_FMT(size != SubRegSize::i64Bit, "Invalid element size with 64-bit {}", __func__); @@ -2633,7 +2633,7 @@ public: ASIMD3Same(Op, 1, size, 0b11010, rd, rn, rm); } } - template + template void fcmgt(SubRegSize size, T rd, T rn, T rm) { if constexpr (std::is_same_v) { LOGMAN_THROW_A_FMT(size != SubRegSize::i64Bit, "Invalid element size with 64-bit {}", __func__); @@ -2647,7 +2647,7 @@ public: ASIMD3Same(Op, 1, size, 0b11100, rd, rn, rm); } } - template + template void facgt(SubRegSize size, T rd, T rn, T rm) { if constexpr (std::is_same_v) { LOGMAN_THROW_A_FMT(size != SubRegSize::i64Bit, "Invalid element size with 64-bit {}", __func__); @@ -2661,7 +2661,7 @@ public: ASIMD3Same(Op, 1, size, 0b11101, rd, rn, rm); } } - template + template void fminp(SubRegSize size, T rd, T rn, T rm) { if constexpr (std::is_same_v) { LOGMAN_THROW_A_FMT(size != SubRegSize::i64Bit, "Invalid element size with 64-bit {}", __func__);