| 724 | } |
| 725 | |
| 726 | void OpDispatchBuilder::MOVMSKOp(OpcodeArgs, IR::OpSize ElementSize) { |
| 727 | const auto Size = OpSizeFromSrc(Op); |
| 728 | const auto NumElements = IR::NumElements(Size, ElementSize); |
| 729 | |
| 730 | Ref Src = LoadSource(FPRClass, Op, Op->Src[0], Op->Flags); |
| 731 | |
| 732 | if (Size == OpSize::i128Bit && ElementSize == OpSize::i64Bit) { |
| 733 | // UnZip2 the 64-bit elements as 32-bit to get the sign bits closer. |
| 734 | // Sign bits are now in bit positions 31 and 63 after this. |
| 735 | Src = _VUnZip2(Size, OpSize::i32Bit, Src, Src); |
| 736 | |
| 737 | // Extract the low 64-bits to GPR in one move. |
| 738 | Ref GPR = _VExtractToGPR(Size, OpSize::i64Bit, Src, 0); |
| 739 | // BFI the sign bit in 31 in to 62. |
| 740 | // Inserting the full lower 32-bits offset 31 so the sign bit ends up at offset 63. |
| 741 | GPR = _Bfi(OpSize::i64Bit, 32, 31, GPR, GPR); |
| 742 | // Shift right to only get the two sign bits we care about. |
| 743 | GPR = _Lshr(OpSize::i64Bit, GPR, Constant(62)); |
| 744 | StoreResult_WithOpSize(GPRClass, Op, Op->Dest, GPR, GetGPROpSize(), OpSize::iInvalid); |
| 745 | } else if (Size == OpSize::i128Bit && ElementSize == OpSize::i32Bit) { |
| 746 | // Shift all the sign bits to the bottom of their respective elements. |
| 747 | Src = _VUShrI(Size, OpSize::i32Bit, Src, 31); |
| 748 | // Load the specific 128-bit movmskps shift elements operator. |
| 749 | auto ConstantUSHL = LoadAndCacheNamedVectorConstant(Size, NAMED_VECTOR_MOVMSKPS_SHIFT); |
| 750 | // Shift the sign bits in to specific locations. |
| 751 | Src = _VUShl(Size, OpSize::i32Bit, Src, ConstantUSHL, false); |
| 752 | // Add across the vector so the sign bits will end up in bits [3:0] |
| 753 | Src = _VAddV(Size, OpSize::i32Bit, Src); |
| 754 | // Extract to a GPR. |
| 755 | Ref GPR = _VExtractToGPR(Size, OpSize::i32Bit, Src, 0); |
| 756 | StoreResult_WithOpSize(GPRClass, Op, Op->Dest, GPR, GetGPROpSize(), OpSize::iInvalid); |
| 757 | } else { |
| 758 | Ref CurrentVal = Constant(0); |
| 759 | |
| 760 | for (unsigned i = 0; i < NumElements; ++i) { |
| 761 | // Extract the top bit of the element |
| 762 | Ref Tmp = _VExtractToGPR(Size, ElementSize, Src, i); |
| 763 | Tmp = _Bfe(ElementSize, 1, IR::OpSizeAsBits(ElementSize) - 1, Tmp); |
| 764 | |
| 765 | // Shift it to the correct location and or it with the current value |
| 766 | if (i != 0) { |
| 767 | CurrentVal = _Orlshl(OpSize::i64Bit, CurrentVal, Tmp, i); |
| 768 | } else { |
| 769 | CurrentVal = Tmp; |
| 770 | } |
| 771 | } |
| 772 | StoreResult(GPRClass, Op, CurrentVal, OpSize::iInvalid); |
| 773 | } |
| 774 | } |
| 775 | |
| 776 | void OpDispatchBuilder::MOVMSKOpOne(OpcodeArgs) { |
| 777 | const auto SrcSize = OpSizeFromSrc(Op); |
nothing calls this directly
no test coverage detected