public static void Vtbl(ArmEmitterContext context)
        {
            OpCode32SimdTbl op = (OpCode32SimdTbl)context.CurrOp;

            bool extension = op.Opc == 1;

            int elems = op.GetBytesCount() >> op.Size;

            int length = op.Length + 1;

            (int Qx, int Ix)[] tableTuples = new (int, int)[length];
Example #2
0
        public static void Vtbl(ArmEmitterContext context)
        {
            OpCode32SimdTbl op = (OpCode32SimdTbl)context.CurrOp;

            bool extension = op.Opc == 1;
            int  length    = op.Length + 1;

            if (Optimizations.UseSsse3)
            {
                Operand d = GetVecA32(op.Qd);
                Operand m = EmitMoveDoubleWordToSide(context, GetVecA32(op.Qm), op.Vm, 0);

                Operand res;
                Operand mask = X86GetAllElements(context, 0x0707070707070707L);

                // Fast path for single register table.
                {
                    Operand n = EmitMoveDoubleWordToSide(context, GetVecA32(op.Qn), op.Vn, 0);

                    Operand mMask = context.AddIntrinsic(Intrinsic.X86Pcmpgtb, m, mask);
                    mMask = context.AddIntrinsic(Intrinsic.X86Por, mMask, m);

                    res = context.AddIntrinsic(Intrinsic.X86Pshufb, n, mMask);
                }

                for (int index = 1; index < length; index++)
                {
                    int newVn = (op.Vn + index) & 0x1F;
                    (int qn, int ind) = GetQuadwordAndSubindex(newVn, op.RegisterSize);
                    Operand ni = EmitMoveDoubleWordToSide(context, GetVecA32(qn), newVn, 0);

                    Operand idxMask = X86GetAllElements(context, 0x0808080808080808L * index);

                    Operand mSubMask = context.AddIntrinsic(Intrinsic.X86Psubb, m, idxMask);

                    Operand mMask = context.AddIntrinsic(Intrinsic.X86Pcmpgtb, mSubMask, mask);
                    mMask = context.AddIntrinsic(Intrinsic.X86Por, mMask, mSubMask);

                    Operand res2 = context.AddIntrinsic(Intrinsic.X86Pshufb, ni, mMask);

                    res = context.AddIntrinsic(Intrinsic.X86Por, res, res2);
                }

                if (extension)
                {
                    Operand idxMask  = X86GetAllElements(context, (0x0808080808080808L * length) - 0x0101010101010101L);
                    Operand zeroMask = context.VectorZero();

                    Operand mPosMask = context.AddIntrinsic(Intrinsic.X86Pcmpgtb, m, idxMask);
                    Operand mNegMask = context.AddIntrinsic(Intrinsic.X86Pcmpgtb, zeroMask, m);

                    Operand mMask = context.AddIntrinsic(Intrinsic.X86Por, mPosMask, mNegMask);

                    Operand dMask = context.AddIntrinsic(Intrinsic.X86Pand, EmitMoveDoubleWordToSide(context, d, op.Vd, 0), mMask);

                    res = context.AddIntrinsic(Intrinsic.X86Por, res, dMask);
                }

                res = EmitMoveDoubleWordToSide(context, res, 0, op.Vd);

                context.Copy(d, EmitDoubleWordInsert(context, d, res, op.Vd));
            }
            else
            {
                int elems = op.GetBytesCount() >> op.Size;

                (int Qx, int Ix)[] tableTuples = new (int, int)[length];