Пример #1
0
        private static void EmitTableVectorLookup(ArmEmitterContext context, bool isTbl)
        {
            OpCodeSimdTbl op = (OpCodeSimdTbl)context.CurrOp;

            if (Optimizations.UseSsse3)
            {
                Operand d = GetVec(op.Rd);
                Operand m = GetVec(op.Rm);

                Operand res;

                Operand mask = X86GetAllElements(context, 0x0F0F0F0F0F0F0F0FL);

                // Fast path for single register table.
                {
                    Operand n = GetVec(op.Rn);

                    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 < op.Size; index++)
                {
                    Operand ni = GetVec((op.Rn + index) & 0x1F);

                    Operand idxMask = X86GetAllElements(context, 0x1010101010101010L * 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 (!isTbl)
                {
                    Operand idxMask  = X86GetAllElements(context, (0x1010101010101010L * op.Size) - 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, d, mMask);

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

                if (op.RegisterSize == RegisterSize.Simd64)
                {
                    res = context.VectorZeroUpper64(res);
                }

                context.Copy(d, res);
            }
            else
            {
                Operand d = GetVec(op.Rd);

                List <Operand> args = new List <Operand>();

                if (!isTbl)
                {
                    args.Add(d);
                }

                args.Add(GetVec(op.Rm));

                args.Add(Const(op.RegisterSize == RegisterSize.Simd64 ? 8 : 16));

                for (int index = 0; index < op.Size; index++)
                {
                    args.Add(GetVec((op.Rn + index) & 0x1F));
                }

                Delegate dlg = null;

                switch (op.Size)
                {
                case 1: dlg = isTbl
                        ? (Delegate) new _V128_V128_S32_V128(SoftFallback.Tbl1)
                        : (Delegate) new _V128_V128_V128_S32_V128(SoftFallback.Tbx1);
                    break;

                case 2: dlg = isTbl
                        ? (Delegate) new _V128_V128_S32_V128_V128(SoftFallback.Tbl2)
                        : (Delegate) new _V128_V128_V128_S32_V128_V128(SoftFallback.Tbx2);
                    break;

                case 3: dlg = isTbl
                        ? (Delegate) new _V128_V128_S32_V128_V128_V128(SoftFallback.Tbl3)
                        : (Delegate) new _V128_V128_V128_S32_V128_V128_V128(SoftFallback.Tbx3);
                    break;

                case 4: dlg = isTbl
                        ? (Delegate) new _V128_V128_S32_V128_V128_V128_V128(SoftFallback.Tbl4)
                        : (Delegate) new _V128_V128_V128_S32_V128_V128_V128_V128(SoftFallback.Tbx4);
                    break;
                }

                context.Copy(d, context.Call(dlg, args.ToArray()));
            }
        }
Пример #2
0
        public static void Tbl_V(ArmEmitterContext context)
        {
            OpCodeSimdTbl op = (OpCodeSimdTbl)context.CurrOp;

            if (Optimizations.UseSsse3)
            {
                Operand n = GetVec(op.Rn);
                Operand m = GetVec(op.Rm);

                Operand mask = X86GetAllElements(context, 0x0F0F0F0F0F0F0F0FL);

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

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

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

                for (int index = 1; index < op.Size; index++)
                {
                    Operand ni = GetVec((op.Rn + index) & 0x1f);

                    Operand indexMask = X86GetAllElements(context, 0x1010101010101010L * index);

                    Operand mMinusMask = context.AddIntrinsic(Intrinsic.X86Psubb, m, indexMask);

                    Operand mMask2 = context.AddIntrinsic(Intrinsic.X86Pcmpgtb, mMinusMask, mask);

                    mMask2 = context.AddIntrinsic(Intrinsic.X86Por, mMask2, mMinusMask);

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

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

                if (op.RegisterSize == RegisterSize.Simd64)
                {
                    res = context.VectorZeroUpper64(res);
                }

                context.Copy(GetVec(op.Rd), res);
            }
            else
            {
                Operand[] args = new Operand[1 + op.Size];

                args[0] = GetVec(op.Rm);

                for (int index = 0; index < op.Size; index++)
                {
                    args[1 + index] = GetVec((op.Rn + index) & 0x1f);
                }

                Delegate dlg = null;

                switch (op.Size)
                {
                case 1: dlg = op.RegisterSize == RegisterSize.Simd64
                        ? (Delegate) new _V128_V128_V128(SoftFallback.Tbl1_V64)
                        : (Delegate) new _V128_V128_V128(SoftFallback.Tbl1_V128); break;

                case 2: dlg = op.RegisterSize == RegisterSize.Simd64
                        ? (Delegate) new _V128_V128_V128_V128(SoftFallback.Tbl2_V64)
                        : (Delegate) new _V128_V128_V128_V128(SoftFallback.Tbl2_V128); break;

                case 3: dlg = op.RegisterSize == RegisterSize.Simd64
                        ? (Delegate) new _V128_V128_V128_V128_V128(SoftFallback.Tbl3_V64)
                        : (Delegate) new _V128_V128_V128_V128_V128(SoftFallback.Tbl3_V128); break;

                case 4: dlg = op.RegisterSize == RegisterSize.Simd64
                        ? (Delegate) new _V128_V128_V128_V128_V128_V128(SoftFallback.Tbl4_V64)
                        : (Delegate) new _V128_V128_V128_V128_V128_V128(SoftFallback.Tbl4_V128); break;
                }

                context.Copy(GetVec(op.Rd), context.Call(dlg, args));
            }
        }