예제 #1
0
        public static void Fmov_Itof1(ILEmitterCtx context)
        {
            OpCodeSimdCvt64 op = (OpCodeSimdCvt64)context.CurrOp;

            context.EmitLdintzr(op.Rn);

            EmitIntZeroUpperIfNeeded(context);

            EmitVectorInsert(context, op.Rd, 1, 3);
        }
예제 #2
0
        public static void Fmov_Ftoi1(ILEmitterCtx context)
        {
            OpCodeSimdCvt64 op = (OpCodeSimdCvt64)context.CurrOp;

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

            EmitIntZeroUpperIfNeeded(context);

            context.EmitStintzr(op.Rd);
        }
예제 #3
0
        public static void Scvtf_Gp(ILEmitterCtx context)
        {
            OpCodeSimdCvt64 op = (OpCodeSimdCvt64)context.CurrOp;

            context.EmitLdintzr(op.Rn);

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

            EmitFloatCast(context, op.Size);

            EmitScalarSetF(context, op.Rd, op.Size);
        }
예제 #4
0
        public static void Ucvtf_Gp_Fixed(ILEmitterCtx context)
        {
            OpCodeSimdCvt64 op = (OpCodeSimdCvt64)context.CurrOp;

            context.EmitLdintzr(op.Rn);

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

            context.Emit(OpCodes.Conv_R_Un);

            EmitFloatCast(context, op.Size);

            EmitI2fFBitsMul(context, op.Size, op.FBits);

            EmitScalarSetF(context, op.Rd, op.Size);
        }
예제 #5
0
        private static void EmitFcvtz__Gp_Fixed(ILEmitterCtx context, bool signed)
        {
            OpCodeSimdCvt64 op = (OpCodeSimdCvt64)context.CurrOp;

            EmitVectorExtractF(context, op.Rn, 0, op.Size);

            if (signed)
            {
                EmitScalarFcvts(context, op.Size, op.FBits);
            }
            else
            {
                EmitScalarFcvtu(context, op.Size, op.FBits);
            }

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

            context.EmitStintzr(op.Rd);
        }
예제 #6
0
        private static void EmitSse41Fcvt_Signed_Gp(ILEmitterCtx context, RoundMode roundMode, bool isFixed)
        {
            OpCodeSimdCvt64 op = (OpCodeSimdCvt64)context.CurrOp;

            if (op.Size == 0)
            {
                Type[] typesCmpMul = new Type[] { typeof(Vector128 <float>), typeof(Vector128 <float>) };
                Type[] typesAnd    = new Type[] { typeof(Vector128 <long>), typeof(Vector128 <long>) };
                Type[] typesRndCvt = new Type[] { typeof(Vector128 <float>) };
                Type[] typesCvt    = new Type[] { typeof(Vector128 <int>) };
                Type[] typesSav    = new Type[] { typeof(int) };

                //string nameCvt;
                int fpMaxVal;

                if (op.RegisterSize == RegisterSize.Int32)
                {
                    //nameCvt  = nameof(Sse.ConvertToInt32);
                    fpMaxVal = 0x4F000000; // 2.14748365E9f (2147483648)
                }
                else
                {
                    //nameCvt  = nameof(Sse.ConvertToInt64);
                    fpMaxVal = 0x5F000000; // 9.223372E18f (9223372036854775808)
                }

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

                context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.CompareOrdered), typesCmpMul));

                context.EmitLdvec(op.Rn);

                context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.And), typesAnd));

                if (isFixed)
                {
                    // BitConverter.Int32BitsToSingle(fpScaled) == MathF.Pow(2f, op.FBits)
                    int fpScaled = 0x40000000 + (op.FBits - 1) * 0x800000;

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

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

                context.EmitCall(typeof(Sse41).GetMethod(GetSse41NameRnd(roundMode), typesRndCvt));

                context.EmitStvectmp();
                context.EmitLdvectmp();

                // TODO: Use Sse.ConvertToInt64 once it is fixed (in .NET Core 3.0),
                // remove the following if/else and uncomment the code.

                //context.EmitCall(typeof(Sse).GetMethod(nameCvt, typesRndCvt));

                if (op.RegisterSize == RegisterSize.Int32)
                {
                    context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.ConvertToInt32), typesRndCvt));
                }
                else
                {
                    context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ConvertToVector128Double), typesRndCvt));
                    context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ConvertToInt64), new Type[] { typeof(Vector128 <double>) }));
                }

                context.EmitLdvectmp();

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

                context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.CompareGreaterThanOrEqual), typesCmpMul));

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

                if (op.RegisterSize == RegisterSize.Int32)
                {
                    context.Emit(OpCodes.Xor);
                    context.Emit(OpCodes.Conv_U8);
                }
                else
                {
                    context.Emit(OpCodes.Conv_I8);
                    context.Emit(OpCodes.Xor);
                }

                context.EmitStintzr(op.Rd);
            }
            else /* if (op.Size == 1) */
            {
                Type[] typesCmpMul = new Type[] { typeof(Vector128 <double>), typeof(Vector128 <double>) };
                Type[] typesAnd    = new Type[] { typeof(Vector128 <long>), typeof(Vector128 <long>) };
                Type[] typesRndCvt = new Type[] { typeof(Vector128 <double>) };
                Type[] typesCvt    = new Type[] { typeof(Vector128 <int>) };
                Type[] typesSav    = new Type[] { typeof(long) };

                string nameCvt;
                long   fpMaxVal;

                if (op.RegisterSize == RegisterSize.Int32)
                {
                    nameCvt  = nameof(Sse2.ConvertToInt32);
                    fpMaxVal = 0x41E0000000000000L; // 2147483648.0000000d (2147483648)
                }
                else
                {
                    nameCvt  = nameof(Sse2.ConvertToInt64);
                    fpMaxVal = 0x43E0000000000000L; // 9.2233720368547760E18d (9223372036854775808)
                }

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

                context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.CompareOrdered), typesCmpMul));

                context.EmitLdvec(op.Rn);

                context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.And), typesAnd));

                if (isFixed)
                {
                    // BitConverter.Int64BitsToDouble(fpScaled) == Math.Pow(2d, op.FBits)
                    long fpScaled = 0x4000000000000000L + (op.FBits - 1) * 0x10000000000000L;

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

                    context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Multiply), typesCmpMul));
                }

                context.EmitCall(typeof(Sse41).GetMethod(GetSse41NameRnd(roundMode), typesRndCvt));

                context.EmitStvectmp();
                context.EmitLdvectmp();

                context.EmitCall(typeof(Sse2).GetMethod(nameCvt, typesRndCvt));

                context.EmitLdvectmp();

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

                context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.CompareGreaterThanOrEqual), typesCmpMul));

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

                if (op.RegisterSize == RegisterSize.Int32)
                {
                    context.Emit(OpCodes.Xor);
                    context.Emit(OpCodes.Conv_U8);
                }
                else
                {
                    context.Emit(OpCodes.Conv_I8);
                    context.Emit(OpCodes.Xor);
                }

                context.EmitStintzr(op.Rd);
            }
        }