Esempio n. 1
0
        public static void Cmeq_V(ILEmitterCtx context)
        {
            if (Optimizations.UseSse41)
            {
                OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp;

                Type[] typesCmp = new Type[] { VectorIntTypesPerSizeLog2[op.Size], VectorIntTypesPerSizeLog2[op.Size] };

                Type typeSse = op.Size != 3 ? typeof(Sse2) : typeof(Sse41);

                context.EmitLdvec(op.Rn);

                if (op is OpCodeSimdReg64 binOp)
                {
                    context.EmitLdvec(binOp.Rm);
                }
                else
                {
                    VectorHelper.EmitCall(context, nameof(VectorHelper.VectorSingleZero));
                }

                context.EmitCall(typeSse.GetMethod(nameof(Sse2.CompareEqual), typesCmp));

                context.EmitStvec(op.Rd);

                if (op.RegisterSize == RegisterSize.Simd64)
                {
                    EmitVectorZeroUpper(context, op.Rd);
                }
            }
            else
            {
                EmitCmpOp(context, OpCodes.Beq_S, scalar: false);
            }
        }
Esempio n. 2
0
        private static void EmitSseOp(ILEmitterCtx context, string name, Type type)
        {
            OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp;

            context.EmitLdvec(op.Rn);

            Type baseType = VectorIntTypesPerSizeLog2[op.Size];

            if (op is OpCodeSimdReg64 binOp)
            {
                context.EmitLdvec(binOp.Rm);

                context.EmitCall(type.GetMethod(name, new Type[] { baseType, baseType }));
            }
            else
            {
                context.EmitCall(type.GetMethod(name, new Type[] { baseType }));
            }

            context.EmitStvec(op.Rd);

            if (op.RegisterSize == RegisterSize.Simd64)
            {
                EmitVectorZeroUpper(context, op.Rd);
            }
        }
Esempio n. 3
0
        public static void Orn_V(ILEmitterCtx context)
        {
            if (Optimizations.UseSse2)
            {
                OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp;

                Type[] typesSav   = new Type[] { typeof(long) };
                Type[] typesAntOr = new Type[] { typeof(Vector128 <long>), typeof(Vector128 <long>) };

                context.EmitLdvec(op.Rn);
                context.EmitLdvec(op.Rm);

                context.EmitLdc_I8(-1L);
                context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SetAllVector128), typesSav));

                context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.AndNot), typesAntOr));
                context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Or), typesAntOr));

                context.EmitStvec(op.Rd);

                if (op.RegisterSize == RegisterSize.Simd64)
                {
                    EmitVectorZeroUpper(context, op.Rd);
                }
            }
            else
            {
                EmitVectorBinaryOpZx(context, () =>
                {
                    context.Emit(OpCodes.Not);
                    context.Emit(OpCodes.Or);
                });
            }
        }
Esempio n. 4
0
        public static void Bic_V(ILEmitterCtx context)
        {
            if (Optimizations.UseSse2)
            {
                OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp;

                Type[] typesAndNot = new Type[] { typeof(Vector128 <byte>), typeof(Vector128 <byte>) };

                context.EmitLdvec(op.Rm);
                context.EmitLdvec(op.Rn);

                context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.AndNot), typesAndNot));

                context.EmitStvec(op.Rd);

                if (op.RegisterSize == RegisterSize.Simd64)
                {
                    EmitVectorZeroUpper(context, op.Rd);
                }
            }
            else
            {
                EmitVectorBinaryOpZx(context, () =>
                {
                    context.Emit(OpCodes.Not);
                    context.Emit(OpCodes.And);
                });
            }
        }
Esempio n. 5
0
        public static void Stp(ILEmitterCtx context)
        {
            OpCodeMemPair64 op = (OpCodeMemPair64)context.CurrOp;

            EmitLoadAddress(context);

            if (op is IOpCodeSimd64)
            {
                context.EmitLdvec(op.Rt);
            }
            else
            {
                context.EmitLdintzr(op.Rt);
            }

            EmitWriteCall(context, op.Size);

            context.EmitLdtmp();
            context.EmitLdc_I8(1 << op.Size);

            context.Emit(OpCodes.Add);

            if (op is IOpCodeSimd64)
            {
                context.EmitLdvec(op.Rt2);
            }
            else
            {
                context.EmitLdintzr(op.Rt2);
            }

            EmitWriteCall(context, op.Size);

            EmitWBackIfNeeded(context);
        }
Esempio n. 6
0
        public static void Tbl_V(ILEmitterCtx context)
        {
            OpCodeSimdTbl64 op = (OpCodeSimdTbl64)context.CurrOp;

            context.EmitLdvec(op.Rm);

            for (int index = 0; index < op.Size; index++)
            {
                context.EmitLdvec((op.Rn + index) & 0x1f);
            }

            switch (op.Size)
            {
            case 1: VectorHelper.EmitCall(context,
                                          nameof(VectorHelper.Tbl1_V64),
                                          nameof(VectorHelper.Tbl1_V128)); break;

            case 2: VectorHelper.EmitCall(context,
                                          nameof(VectorHelper.Tbl2_V64),
                                          nameof(VectorHelper.Tbl2_V128)); break;

            case 3: VectorHelper.EmitCall(context,
                                          nameof(VectorHelper.Tbl3_V64),
                                          nameof(VectorHelper.Tbl3_V128)); break;

            case 4: VectorHelper.EmitCall(context,
                                          nameof(VectorHelper.Tbl4_V64),
                                          nameof(VectorHelper.Tbl4_V128)); break;

            default: throw new InvalidOperationException();
            }

            context.EmitStvec(op.Rd);
        }
Esempio n. 7
0
        public static void Usra_V(ILEmitterCtx context)
        {
            OpCodeSimdShImm64 op = (OpCodeSimdShImm64)context.CurrOp;

            if (Optimizations.UseSse2 && op.Size > 0)
            {
                Type[] typesSrl = new Type[] { VectorUIntTypesPerSizeLog2[op.Size], typeof(byte) };
                Type[] typesAdd = new Type[] { VectorUIntTypesPerSizeLog2[op.Size], VectorUIntTypesPerSizeLog2[op.Size] };

                context.EmitLdvec(op.Rd);
                context.EmitLdvec(op.Rn);

                context.EmitLdc_I4(GetImmShr(op));
                context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical), typesSrl));

                context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Add), typesAdd));

                context.EmitStvec(op.Rd);

                if (op.RegisterSize == RegisterSize.Simd64)
                {
                    EmitVectorZeroUpper(context, op.Rd);
                }
            }
            else
            {
                EmitVectorShrImmOpZx(context, ShrImmFlags.Accumulate);
            }
        }
Esempio n. 8
0
        public static void Cmhs_V(ILEmitterCtx context)
        {
            OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp;

            if (Optimizations.UseSse41 && op.Size < 3)
            {
                Type[] typesMax = new Type[] { VectorUIntTypesPerSizeLog2[op.Size], VectorUIntTypesPerSizeLog2[op.Size] };
                Type[] typesCmp = new Type[] { VectorIntTypesPerSizeLog2 [op.Size], VectorIntTypesPerSizeLog2 [op.Size] };

                Type typeSse = op.Size == 0 ? typeof(Sse2) : typeof(Sse41);

                context.EmitLdvec(op.Rn);
                context.EmitLdvec(op.Rm);

                context.EmitCall(typeSse.GetMethod(nameof(Sse2.Max), typesMax));

                context.EmitLdvec(op.Rn);

                context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.CompareEqual), typesCmp));

                context.EmitStvec(op.Rd);

                if (op.RegisterSize == RegisterSize.Simd64)
                {
                    EmitVectorZeroUpper(context, op.Rd);
                }
            }
            else
            {
                EmitCmpOp(context, OpCodes.Bge_Un_S, scalar: false);
            }
        }
Esempio n. 9
0
        private static void EmitBifBit(ILEmitterCtx context, bool notRm)
        {
            OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp;

            if (Optimizations.UseSse2)
            {
                Type[] typesXorAndNot = new Type[] { typeof(Vector128 <byte>), typeof(Vector128 <byte>) };

                string nameAndNot = notRm ? nameof(Sse2.AndNot) : nameof(Sse2.And);

                context.EmitLdvec(op.Rd);
                context.EmitLdvec(op.Rm);
                context.EmitLdvec(op.Rn);
                context.EmitLdvec(op.Rd);

                context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Xor), typesXorAndNot));
                context.EmitCall(typeof(Sse2).GetMethod(nameAndNot, typesXorAndNot));
                context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Xor), typesXorAndNot));

                context.EmitStvec(op.Rd);

                if (op.RegisterSize == RegisterSize.Simd64)
                {
                    EmitVectorZeroUpper(context, op.Rd);
                }
            }
            else
            {
                int elems = op.RegisterSize == RegisterSize.Simd128 ? 2 : 1;

                for (int index = 0; index < elems; index++)
                {
                    EmitVectorExtractZx(context, op.Rd, index, 3);
                    context.Emit(OpCodes.Dup);

                    EmitVectorExtractZx(context, op.Rn, index, 3);

                    context.Emit(OpCodes.Xor);

                    EmitVectorExtractZx(context, op.Rm, index, 3);

                    if (notRm)
                    {
                        context.Emit(OpCodes.Not);
                    }

                    context.Emit(OpCodes.And);

                    context.Emit(OpCodes.Xor);

                    EmitVectorInsert(context, op.Rd, index, 3);
                }

                if (op.RegisterSize == RegisterSize.Simd64)
                {
                    EmitVectorZeroUpper(context, op.Rd);
                }
            }
        }
Esempio n. 10
0
        public static void Xtn_V(ILEmitterCtx context)
        {
            OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp;

            if (Optimizations.UseSsse3)
            {
                Type[] typesSve = new Type[] { typeof(long), typeof(long) };

                string nameMov = op.RegisterSize == RegisterSize.Simd128
                    ? nameof(Sse.MoveLowToHigh)
                    : nameof(Sse.MoveHighToLow);

                context.EmitLdvec(op.Rd);
                VectorHelper.EmitCall(context, nameof(VectorHelper.VectorSingleZero));

                context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.MoveLowToHigh)));

                context.EmitLdvec(op.Rn);                        // value

                context.EmitLdc_I8(_masksE0_TrnUzpXtn[op.Size]); // mask
                context.Emit(OpCodes.Dup);                       // mask

                context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SetVector128), typesSve));

                context.EmitCall(typeof(Ssse3).GetMethod(nameof(Ssse3.Shuffle), GetTypesSflUpk(0)));

                context.EmitCall(typeof(Sse).GetMethod(nameMov));

                context.EmitStvec(op.Rd);
            }
            else
            {
                int elems = 8 >> op.Size;

                int part = op.RegisterSize == RegisterSize.Simd128 ? elems : 0;

                if (part != 0)
                {
                    context.EmitLdvec(op.Rd);
                    context.EmitStvectmp();
                }

                for (int index = 0; index < elems; index++)
                {
                    EmitVectorExtractZx(context, op.Rn, index, op.Size + 1);

                    EmitVectorInsertTmp(context, part + index, op.Size);
                }

                context.EmitLdvectmp();
                context.EmitStvec(op.Rd);

                if (part == 0)
                {
                    EmitVectorZeroUpper(context, op.Rd);
                }
            }
        }
Esempio n. 11
0
        private static void EmitSse2cvtF_Unsigned(ILEmitterCtx context, bool scalar)
        {
            OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp;

            Type[] typesMulAdd = new Type[] { typeof(Vector128 <float>), typeof(Vector128 <float>) };
            Type[] typesSrlSll = new Type[] { typeof(Vector128 <int>), typeof(byte) };
            Type[] typesCvt    = new Type[] { typeof(Vector128 <int>) };
            Type[] typesSav    = new Type[] { typeof(int) };

            context.EmitLdvec(op.Rn);

            context.EmitLdc_I4(16);
            context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical), typesSrlSll));

            context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ConvertToVector128Single), typesCvt));

            context.EmitLdc_I4(0x47800000); // 65536.0f (1 << 16)
            context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SetAllVector128), typesSav));

            context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.Multiply), typesMulAdd));

            context.EmitLdvec(op.Rn);

            context.EmitLdc_I4(16);
            context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftLeftLogical), typesSrlSll));

            context.EmitLdc_I4(16);
            context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical), typesSrlSll));

            context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ConvertToVector128Single), typesCvt));

            context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.Add), typesMulAdd));

            if (op is OpCodeSimdShImm64 fixedOp)
            {
                int fBits = GetImmShr(fixedOp);

                // BitConverter.Int32BitsToSingle(fpScaled) == 1f / MathF.Pow(2f, fBits)
                int fpScaled = 0x3F800000 - fBits * 0x800000;

                context.EmitLdc_I4(fpScaled);
                context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SetAllVector128), typesSav));

                context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.Multiply), typesMulAdd));
            }

            context.EmitStvec(op.Rd);

            if (scalar)
            {
                EmitVectorZero32_128(context, op.Rd);
            }
            else if (op.RegisterSize == RegisterSize.Simd64)
            {
                EmitVectorZeroUpper(context, op.Rd);
            }
        }
Esempio n. 12
0
        public static void Fcvtl_V(ILEmitterCtx context)
        {
            OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp;

            int sizeF = op.Size & 1;

            if (Optimizations.UseSse2 && sizeF == 1)
            {
                Type[] typesCvt = new Type[] { typeof(Vector128 <float>) };

                context.EmitLdvec(op.Rn);

                if (op.RegisterSize == RegisterSize.Simd128)
                {
                    context.EmitLdvec(op.Rn);

                    context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.MoveHighToLow)));
                }

                context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ConvertToVector128Double), typesCvt));

                context.EmitStvec(op.Rd);
            }
            else
            {
                int elems = 4 >> sizeF;

                int part = op.RegisterSize == RegisterSize.Simd128 ? elems : 0;

                for (int index = 0; index < elems; index++)
                {
                    if (sizeF == 0)
                    {
                        EmitVectorExtractZx(context, op.Rn, part + index, 1);
                        context.Emit(OpCodes.Conv_U2);

                        context.EmitLdarg(TranslatedSub.StateArgIdx);

                        context.EmitCall(typeof(SoftFloat16_32), nameof(SoftFloat16_32.FPConvert));
                    }
                    else /* if (sizeF == 1) */
                    {
                        EmitVectorExtractF(context, op.Rn, part + index, 0);

                        context.Emit(OpCodes.Conv_R8);
                    }

                    EmitVectorInsertTmpF(context, index, sizeF);
                }

                context.EmitLdvectmp();
                context.EmitStvec(op.Rd);
            }
        }
Esempio n. 13
0
        public static void Sha1su1_V(ILEmitterCtx context)
        {
            OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp;

            context.EmitLdvec(op.Rd);
            context.EmitLdvec(op.Rn);

            SoftFallback.EmitCall(context, nameof(SoftFallback.Sha1SchedulePart2));

            context.EmitStvec(op.Rd);
        }
Esempio n. 14
0
        private static void EmitVectorZip(ILEmitterCtx context, int part)
        {
            OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp;

            if (Optimizations.UseSse2)
            {
                string nameUpk = part == 0
                    ? nameof(Sse2.UnpackLow)
                    : nameof(Sse2.UnpackHigh);

                context.EmitLdvec(op.Rn);
                context.EmitLdvec(op.Rm);

                if (op.RegisterSize == RegisterSize.Simd128)
                {
                    context.EmitCall(typeof(Sse2).GetMethod(nameUpk, GetTypesSflUpk(op.Size)));
                }
                else
                {
                    context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.UnpackLow), GetTypesSflUpk(op.Size)));
                    VectorHelper.EmitCall(context, nameof(VectorHelper.VectorSingleZero));

                    context.EmitCall(typeof(Sse2).GetMethod(nameUpk, GetTypesSflUpk(3)));
                }

                context.EmitStvec(op.Rd);
            }
            else
            {
                int words = op.GetBitsCount() >> 4;
                int pairs = words >> op.Size;

                int Base = part != 0 ? pairs : 0;

                for (int index = 0; index < pairs; index++)
                {
                    int idx = index << 1;

                    EmitVectorExtractZx(context, op.Rn, Base + index, op.Size);
                    EmitVectorExtractZx(context, op.Rm, Base + index, op.Size);

                    EmitVectorInsertTmp(context, idx + 1, op.Size);
                    EmitVectorInsertTmp(context, idx, op.Size);
                }

                context.EmitLdvectmp();
                context.EmitStvec(op.Rd);

                if (op.RegisterSize == RegisterSize.Simd64)
                {
                    EmitVectorZeroUpper(context, op.Rd);
                }
            }
        }
Esempio n. 15
0
        public static void Aesd_V(ILEmitterCtx context)
        {
            OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp;

            context.EmitLdvec(op.Rd);
            context.EmitLdvec(op.Rn);

            SoftFallback.EmitCall(context, nameof(SoftFallback.Decrypt));

            context.EmitStvec(op.Rd);
        }
Esempio n. 16
0
        public static void Sha1p_V(ILEmitterCtx context)
        {
            OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp;

            context.EmitLdvec(op.Rd);
            EmitVectorExtractZx(context, op.Rn, 0, 2);
            context.EmitLdvec(op.Rm);

            SoftFallback.EmitCall(context, nameof(SoftFallback.HashParity));

            context.EmitStvec(op.Rd);
        }
Esempio n. 17
0
        public static void Sha256h_V(ILEmitterCtx context)
        {
            OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp;

            context.EmitLdvec(op.Rd);
            context.EmitLdvec(op.Rn);
            context.EmitLdvec(op.Rm);

            SoftFallback.EmitCall(context, nameof(SoftFallback.HashLower));

            context.EmitStvec(op.Rd);
        }
Esempio n. 18
0
        public static void Rshrn_V(ILEmitterCtx context)
        {
            if (Optimizations.UseSsse3)
            {
                OpCodeSimdShImm64 op = (OpCodeSimdShImm64)context.CurrOp;

                Type[] typesAdd = new Type[] { VectorUIntTypesPerSizeLog2[op.Size + 1], VectorUIntTypesPerSizeLog2[op.Size + 1] };
                Type[] typesSrl = new Type[] { VectorUIntTypesPerSizeLog2[op.Size + 1], typeof(byte) };
                Type[] typesSfl = new Type[] { typeof(Vector128 <sbyte>), typeof(Vector128 <sbyte>) };
                Type[] typesSav = new Type[] { UIntTypesPerSizeLog2[op.Size + 1] };
                Type[] typesSve = new Type[] { typeof(long), typeof(long) };

                string nameMov = op.RegisterSize == RegisterSize.Simd128
                    ? nameof(Sse.MoveLowToHigh)
                    : nameof(Sse.MoveHighToLow);

                int shift = GetImmShr(op);

                long roundConst = 1L << (shift - 1);

                context.EmitLdvec(op.Rd);
                VectorHelper.EmitCall(context, nameof(VectorHelper.VectorSingleZero));

                context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.MoveLowToHigh)));

                context.EmitLdvec(op.Rn);

                context.EmitLdc_I8(roundConst);
                context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SetAllVector128), typesSav));

                context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Add), typesAdd));

                context.EmitLdc_I4(shift);
                context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical), typesSrl)); // value

                context.EmitLdc_I8(_masks_RshrnShrn[op.Size]);                                      // mask
                context.Emit(OpCodes.Dup);                                                          // mask

                context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SetVector128), typesSve));

                context.EmitCall(typeof(Ssse3).GetMethod(nameof(Ssse3.Shuffle), typesSfl));

                context.EmitCall(typeof(Sse).GetMethod(nameMov));

                context.EmitStvec(op.Rd);
            }
            else
            {
                EmitVectorShrImmNarrowOpZx(context, round: true);
            }
        }
Esempio n. 19
0
        public static void EmitSseOrSse2OpF(ILEmitterCtx context, string name, bool scalar)
        {
            OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp;

            int sizeF = op.Size & 1;

            context.EmitLdvec(op.Rn);

            Type type;
            Type baseType;

            if (sizeF == 0)
            {
                type     = typeof(Sse);
                baseType = typeof(Vector128 <float>);
            }
            else /* if (sizeF == 1) */
            {
                type     = typeof(Sse2);
                baseType = typeof(Vector128 <double>);
            }

            if (op is OpCodeSimdReg64 binOp)
            {
                context.EmitLdvec(binOp.Rm);

                context.EmitCall(type.GetMethod(name, new Type[] { baseType, baseType }));
            }
            else
            {
                context.EmitCall(type.GetMethod(name, new Type[] { baseType }));
            }

            context.EmitStvec(op.Rd);

            if (scalar)
            {
                if (sizeF == 0)
                {
                    EmitVectorZero32_128(context, op.Rd);
                }
                else /* if (sizeF == 1) */
                {
                    EmitVectorZeroUpper(context, op.Rd);
                }
            }
            else if (op.RegisterSize == RegisterSize.Simd64)
            {
                EmitVectorZeroUpper(context, op.Rd);
            }
        }
Esempio n. 20
0
        public static void Cmle_V(ILEmitterCtx context)
        {
            if (Optimizations.UseSse42)
            {
                OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp;

                Type[] typesCmp = new Type[] { VectorIntTypesPerSizeLog2[op.Size], VectorIntTypesPerSizeLog2[op.Size] };
                Type[] typesAnt = new Type[] { typeof(Vector128 <long>), typeof(Vector128 <long>) };
                Type[] typesSav = new Type[] { typeof(long) };

                Type typeSse = op.Size != 3 ? typeof(Sse2) : typeof(Sse42);

                context.EmitLdvec(op.Rn);
                VectorHelper.EmitCall(context, nameof(VectorHelper.VectorSingleZero));

                context.EmitCall(typeSse.GetMethod(nameof(Sse2.CompareGreaterThan), typesCmp));

                context.EmitLdc_I8(-1L);
                context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SetAllVector128), typesSav));

                context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.AndNot), typesAnt));

                context.EmitStvec(op.Rd);

                if (op.RegisterSize == RegisterSize.Simd64)
                {
                    EmitVectorZeroUpper(context, op.Rd);
                }
            }
            else
            {
                EmitCmpOp(context, OpCodes.Ble_S, scalar: false);
            }
        }
Esempio n. 21
0
        public static void EmitVectorZeroUpper(ILEmitterCtx context, int reg)
        {
            if (Optimizations.UseSse)
            {
                // TODO: Use Sse2.MoveScalar once it is fixed (in .NET Core 3.0),
                // as of the time of writing it just crashes the JIT.

                /*Type[] typesMov = new Type[] { typeof(Vector128<ulong>) };
                 *
                 * context.EmitLdvec(reg);
                 *
                 * context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.MoveScalar), typesMov));
                 *
                 * context.EmitStvec(reg);*/

                context.EmitLdvec(reg);
                VectorHelper.EmitCall(context, nameof(VectorHelper.VectorSingleZero));

                context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.MoveLowToHigh)));

                context.EmitStvec(reg);
            }
            else
            {
                EmitVectorInsert(context, reg, 1, 3, 0);
            }
        }
Esempio n. 22
0
        public static void Scvtf_V(ILEmitterCtx context)
        {
            OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp;

            int sizeF = op.Size & 1;

            if (Optimizations.UseSse2 && sizeF == 0)
            {
                Type[] typesCvt = new Type[] { typeof(Vector128 <int>) };

                context.EmitLdvec(op.Rn);

                context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ConvertToVector128Single), typesCvt));

                context.EmitStvec(op.Rd);

                if (op.RegisterSize == RegisterSize.Simd64)
                {
                    EmitVectorZeroUpper(context, op.Rd);
                }
            }
            else
            {
                EmitVectorCvtf(context, signed: true);
            }
        }
Esempio n. 23
0
        public static void Not_V(ILEmitterCtx context)
        {
            if (Optimizations.UseSse2)
            {
                OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp;

                Type[] typesSav    = new Type[] { typeof(byte) };
                Type[] typesAndNot = new Type[] { typeof(Vector128 <byte>), typeof(Vector128 <byte>) };

                context.EmitLdvec(op.Rn);

                context.EmitLdc_I4(byte.MaxValue);
                context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SetAllVector128), typesSav));

                context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.AndNot), typesAndNot));

                context.EmitStvec(op.Rd);

                if (op.RegisterSize == RegisterSize.Simd64)
                {
                    EmitVectorZeroUpper(context, op.Rd);
                }
            }
            else
            {
                EmitVectorUnaryOpZx(context, () => context.Emit(OpCodes.Not));
            }
        }
Esempio n. 24
0
        public static void Rev16_V(ILEmitterCtx context)
        {
            if (Optimizations.UseSsse3)
            {
                OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp;

                Type[] typesSve = new Type[] { typeof(long), typeof(long) };
                Type[] typesSfl = new Type[] { typeof(Vector128 <sbyte>), typeof(Vector128 <sbyte>) };

                context.EmitLdvec(op.Rn);                                                                                        // value

                context.EmitLdc_I8(14L << 56 | 15L << 48 | 12L << 40 | 13L << 32 | 10L << 24 | 11L << 16 | 08L << 8 | 09L << 0); // maskE1
                context.EmitLdc_I8(06L << 56 | 07L << 48 | 04L << 40 | 05L << 32 | 02L << 24 | 03L << 16 | 00L << 8 | 01L << 0); // maskE0

                context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.SetVector128), typesSve));

                context.EmitCall(typeof(Ssse3).GetMethod(nameof(Ssse3.Shuffle), typesSfl));

                context.EmitStvec(op.Rd);

                if (op.RegisterSize == RegisterSize.Simd64)
                {
                    EmitVectorZeroUpper(context, op.Rd);
                }
            }
            else
            {
                EmitRev_V(context, containerSize: 1);
            }
        }
Esempio n. 25
0
        private static void EmitWriteVector(ILEmitterCtx context, int size)
        {
            EmitAddressCheck(context, size);

            ILLabel lblFastPath = new ILLabel();
            ILLabel lblSlowPath = new ILLabel();
            ILLabel lblEnd      = new ILLabel();

            context.Emit(OpCodes.Brfalse_S, lblFastPath);

            context.MarkLabel(lblSlowPath);

            EmitWriteVectorFallback(context, size);

            context.Emit(OpCodes.Br, lblEnd);

            context.MarkLabel(lblFastPath);

            EmitPtPointerLoad(context, lblSlowPath);

            context.EmitLdvec(_tempVecValue);

            switch (size)
            {
            case 2: context.EmitCall(typeof(Sse), nameof(Sse.StoreScalar));  break;

            case 3: context.EmitCall(typeof(Sse2), nameof(Sse2.StoreScalar)); break;

            case 4: context.EmitCall(typeof(Sse), nameof(Sse.StoreAligned)); break;

            default: throw new InvalidOperationException($"Invalid vector store size of {1 << size} bytes.");
            }

            context.MarkLabel(lblEnd);
        }
        public static void Ext_V(ILEmitterCtx context)
        {
            OpCodeSimdExt64 op = (OpCodeSimdExt64)context.CurrOp;

            context.EmitLdvec(op.Rd);
            context.EmitStvectmp();

            int bytes = op.GetBitsCount() >> 3;

            int position = op.Imm4;

            for (int index = 0; index < bytes; index++)
            {
                int reg = op.Imm4 + index < bytes ? op.Rn : op.Rm;

                if (position == bytes)
                {
                    position = 0;
                }

                EmitVectorExtractZx(context, reg, position++, 0);
                EmitVectorInsertTmp(context, index, 0);
            }

            context.EmitLdvectmp();
            context.EmitStvec(op.Rd);

            if (op.RegisterSize == RegisterSize.Simd64)
            {
                EmitVectorZeroUpper(context, op.Rd);
            }
        }
Esempio n. 27
0
        public static void Shl_V(ILEmitterCtx context)
        {
            OpCodeSimdShImm64 op = (OpCodeSimdShImm64)context.CurrOp;

            int shift = GetImmShl(op);

            if (Optimizations.UseSse2 && op.Size > 0)
            {
                Type[] typesSll = new Type[] { VectorUIntTypesPerSizeLog2[op.Size], typeof(byte) };

                context.EmitLdvec(op.Rn);

                context.EmitLdc_I4(shift);
                context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftLeftLogical), typesSll));

                context.EmitStvec(op.Rd);

                if (op.RegisterSize == RegisterSize.Simd64)
                {
                    EmitVectorZeroUpper(context, op.Rd);
                }
            }
            else
            {
                EmitVectorUnaryOpZx(context, () =>
                {
                    context.EmitLdc_I4(shift);

                    context.Emit(OpCodes.Shl);
                });
            }
        }
Esempio n. 28
0
        public static void Sshr_V(ILEmitterCtx context)
        {
            OpCodeSimdShImm64 op = (OpCodeSimdShImm64)context.CurrOp;

            if (Optimizations.UseSse2 && op.Size > 0 && op.Size < 3)
            {
                Type[] typesSra = new Type[] { VectorIntTypesPerSizeLog2[op.Size], typeof(byte) };

                context.EmitLdvec(op.Rn);

                context.EmitLdc_I4(GetImmShr(op));
                context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightArithmetic), typesSra));

                context.EmitStvec(op.Rd);

                if (op.RegisterSize == RegisterSize.Simd64)
                {
                    EmitVectorZeroUpper(context, op.Rd);
                }
            }
            else
            {
                EmitShrImmOp(context, ShrImmFlags.VectorSx);
            }
        }
Esempio n. 29
0
        private static void EmitWriteVectorFallback(ILEmitterCtx context, int size)
        {
            context.EmitLdarg(TranslatedSub.MemoryArgIdx);
            context.EmitLdint(_tempIntAddress);

            if (context.CurrOp.RegisterSize == RegisterSize.Int32)
            {
                context.Emit(OpCodes.Conv_U8);
            }

            context.EmitLdvec(_tempVecValue);

            string fallbackMethodName = null;

            switch (size)
            {
            case 0: fallbackMethodName = nameof(MemoryManager.WriteVector8);   break;

            case 1: fallbackMethodName = nameof(MemoryManager.WriteVector16);  break;

            case 2: fallbackMethodName = nameof(MemoryManager.WriteVector32);  break;

            case 3: fallbackMethodName = nameof(MemoryManager.WriteVector64);  break;

            case 4: fallbackMethodName = nameof(MemoryManager.WriteVector128); break;
            }

            context.EmitCall(typeof(MemoryManager), fallbackMethodName);
        }
Esempio n. 30
0
        public static void Shll_V(ILEmitterCtx context)
        {
            OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp;

            int shift = 8 << op.Size;

            if (Optimizations.UseSse41)
            {
                Type[] typesSll = new Type[] { VectorUIntTypesPerSizeLog2[op.Size + 1], typeof(byte) };
                Type[] typesCvt = new Type[] { VectorUIntTypesPerSizeLog2[op.Size] };

                string[] namesCvt = new string[] { nameof(Sse41.ConvertToVector128Int16),
                                                   nameof(Sse41.ConvertToVector128Int32),
                                                   nameof(Sse41.ConvertToVector128Int64) };

                context.EmitLdvec(op.Rn);

                if (op.RegisterSize == RegisterSize.Simd128)
                {
                    context.Emit(OpCodes.Ldc_I4_8);
                    context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical128BitLane), typesSll));
                }

                context.EmitCall(typeof(Sse41).GetMethod(namesCvt[op.Size], typesCvt));

                context.EmitLdc_I4(shift);
                context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftLeftLogical), typesSll));

                context.EmitStvec(op.Rd);
            }
            else
            {
                EmitVectorShImmWidenBinaryZx(context, () => context.Emit(OpCodes.Shl), shift);
            }
        }