diff --git a/FEXCore/Source/Interface/Core/OpcodeDispatcher/Vector.cpp b/FEXCore/Source/Interface/Core/OpcodeDispatcher/Vector.cpp index b1cdd4d4f..a2fbf8114 100644 --- a/FEXCore/Source/Interface/Core/OpcodeDispatcher/Vector.cpp +++ b/FEXCore/Source/Interface/Core/OpcodeDispatcher/Vector.cpp @@ -732,11 +732,9 @@ void OpDispatchBuilder::MOVQMMXOp(OpcodeArgs) { void OpDispatchBuilder::MOVMSKOp(OpcodeArgs, IR::OpSize ElementSize) { const auto Size = OpSizeFromSrc(Op); - const auto NumElements = IR::NumElements(Size, ElementSize); - Ref Src = LoadSourceFPR(Op, Op->Src[0], Op->Flags); - const auto F32Handler = [this](Ref Input, IR::OpSize VecSize) { + const auto F32Handler = [this](Ref Input, OpSize VecSize) { // Shift all the sign bits to the bottom of their respective elements. Input = _VUShrI(VecSize, OpSize::i32Bit, Input, 31); // Load the specific 128-bit movmskps shift elements operator. @@ -749,45 +747,36 @@ void OpDispatchBuilder::MOVMSKOp(OpcodeArgs, IR::OpSize ElementSize) { return _VExtractToGPR(VecSize, OpSize::i32Bit, Input, 0); }; - if (Size == OpSize::i128Bit && ElementSize == OpSize::i64Bit) { + const auto F64Handler = [this](Ref Input, OpSize VecSize) { // UnZip2 the 64-bit elements as 32-bit to get the sign bits closer. // Sign bits are now in bit positions 31 and 63 after this. - Src = _VUnZip2(Size, OpSize::i32Bit, Src, Src); - + Input = _VUnZip2(VecSize, OpSize::i32Bit, Input, Input); // Extract the low 64-bits to GPR in one move. - Ref GPR = _VExtractToGPR(Size, OpSize::i64Bit, Src, 0); + Ref GPR = _VExtractToGPR(VecSize, OpSize::i64Bit, Input, 0); // BFI the sign bit in 31 in to 62. // Inserting the full lower 32-bits offset 31 so the sign bit ends up at offset 63. GPR = _Bfi(OpSize::i64Bit, 32, 31, GPR, GPR); // Shift right to only get the two sign bits we care about. - GPR = _Lshr(OpSize::i64Bit, GPR, Constant(62)); - StoreResultGPR_WithOpSize(Op, Op->Dest, GPR, GetGPROpSize()); - } else if (Size == OpSize::i128Bit && ElementSize == OpSize::i32Bit) { - Ref GPR = F32Handler(Src, Size); - StoreResultGPR_WithOpSize(Op, Op->Dest, GPR, GetGPROpSize()); - } else if (Size == OpSize::i256Bit && ElementSize == OpSize::i32Bit) { - Ref UpperLane = _VDupElement(Size, OpSize::i128Bit, Src, 1); + return _Lshr(OpSize::i64Bit, GPR, Constant(62)); + }; - Ref Lower = F32Handler(Src, OpSize::i128Bit); - Ref Upper = F32Handler(UpperLane, OpSize::i128Bit); - Ref Result = _Orlshl(OpSize::i64Bit, Lower, Upper, 4); - StoreResultGPR_WithOpSize(Op, Op->Dest, Result, GetGPROpSize()); + if (Size == OpSize::i128Bit) { + Ref GPR = ElementSize == OpSize::i32Bit ? F32Handler(Src, Size) : F64Handler(Src, Size); + StoreResultGPR_WithOpSize(Op, Op->Dest, GPR, GetGPROpSize()); } else { - Ref CurrentVal = Constant(0); + Ref UpperLane = _VDupElement(Size, OpSize::i128Bit, Src, 1); + Ref Result {}; - for (unsigned i = 0; i < NumElements; ++i) { - // Extract the top bit of the element - Ref Tmp = _VExtractToGPR(Size, ElementSize, Src, i); - Tmp = _Bfe(ElementSize, 1, IR::OpSizeAsBits(ElementSize) - 1, Tmp); - - // Shift it to the correct location and or it with the current value - if (i != 0) { - CurrentVal = _Orlshl(OpSize::i64Bit, CurrentVal, Tmp, i); - } else { - CurrentVal = Tmp; - } + if (ElementSize == OpSize::i32Bit) { + Ref Lower = F32Handler(Src, OpSize::i128Bit); + Ref Upper = F32Handler(UpperLane, OpSize::i128Bit); + Result = _Orlshl(OpSize::i64Bit, Lower, Upper, 4); + } else { + Ref Lower = F64Handler(Src, OpSize::i128Bit); + Ref Upper = F64Handler(UpperLane, OpSize::i128Bit); + Result = _Orlshl(OpSize::i64Bit, Lower, Upper, 2); } - StoreResultGPR(Op, CurrentVal); + StoreResultGPR_WithOpSize(Op, Op->Dest, Result, GetGPROpSize()); } } diff --git a/unittests/InstructionCountCI/VEX_map1.json b/unittests/InstructionCountCI/VEX_map1.json index c17b479ef..7d1dd37cf 100644 --- a/unittests/InstructionCountCI/VEX_map1.json +++ b/unittests/InstructionCountCI/VEX_map1.json @@ -516,27 +516,21 @@ ] }, "vmovmskpd rax, ymm0": { - "ExpectedInstructionCount": 16, + "ExpectedInstructionCount": 10, "Comment": [ "Map 1 0b01 0x50 256-bit" ], "ExpectedArm64ASM": [ - "mov x20, v16.d[0]", - "lsr x20, x20, #63", - "mov x21, v16.d[1]", - "lsr x21, x21, #63", - "orr x20, x20, x21, lsl #1", - "not p0.b, p7/z, p6.b", - "compact z0.d, p0, z16.d", - "mov x21, v16.d[0]", - "lsr x21, x21, #63", - "orr x20, x20, x21, lsl #2", - "not p0.b, p7/z, p6.b", - "compact z0.d, p0, z16.d", - "mov x21, v16.d[1]", - "lsr x21, x21, #63", - "orr x20, x20, x21, lsl #3", - "mov w4, w20" + "mov z2.q, z16.q[1]", + "uzp2 v3.4s, v16.4s, v16.4s", + "mov x20, v3.d[0]", + "bfi x20, x20, #31, #32", + "lsr x20, x20, #62", + "uzp2 v2.4s, v2.4s, v2.4s", + "mov x21, v2.d[0]", + "bfi x21, x21, #31, #32", + "lsr x21, x21, #62", + "orr x4, x20, x21, lsl #2" ] }, "vsqrtps xmm0, xmm1": {