MCPcopy Create free account
hub / github.com/FEX-Emu/FEX / MOVMSKOp

Method MOVMSKOp

FEXCore/Source/Interface/Core/OpcodeDispatcher/Vector.cpp:726–774  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

724}
725
726void 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
776void OpDispatchBuilder::MOVMSKOpOne(OpcodeArgs) {
777 const auto SrcSize = OpSizeFromSrc(Op);

Callers

nothing calls this directly

Calls 2

NumElementsFunction · 0.85
OpSizeAsBitsFunction · 0.85

Tested by

no test coverage detected