Esempio n. 1
0
        public static void Vcvt_FD(ArmEmitterContext context)
        {
            OpCode32SimdS op = (OpCode32SimdS)context.CurrOp;

            int vm = op.Vm;
            int vd;

            if (op.Size == 3)
            {
                vd = FlipVdBits(op.Vd, false);
                // Double to single.
                Operand fp = ExtractScalar(context, OperandType.FP64, vm);

                Operand res = context.ConvertToFP(OperandType.FP32, fp);

                InsertScalar(context, vd, res);
            }
            else
            {
                vd = FlipVdBits(op.Vd, true);
                // Single to double.
                Operand fp = ExtractScalar(context, OperandType.FP32, vm);

                Operand res = context.ConvertToFP(OperandType.FP64, fp);

                InsertScalar(context, vd, res);
            }
        }
Esempio n. 2
0
        public static void Fcvtn_V(ArmEmitterContext context)
        {
            OpCodeSimd op = (OpCodeSimd)context.CurrOp;

            int sizeF = op.Size & 1;

            if (Optimizations.UseSse2 && sizeF == 1)
            {
                Operand d = GetVec(op.Rd);
                Operand n = GetVec(op.Rn);

                Operand res = context.AddIntrinsic(Intrinsic.X86Movlhps, d, context.VectorZero());

                Operand nInt = context.AddIntrinsic(Intrinsic.X86Cvtpd2ps, n);

                nInt = context.AddIntrinsic(Intrinsic.X86Movlhps, nInt, nInt);

                Intrinsic movInst = op.RegisterSize == RegisterSize.Simd128
                    ? Intrinsic.X86Movlhps
                    : Intrinsic.X86Movhlps;

                res = context.AddIntrinsic(movInst, res, nInt);

                context.Copy(GetVec(op.Rd), res);
            }
            else
            {
                OperandType type = sizeF == 0 ? OperandType.FP32 : OperandType.FP64;

                int elems = 4 >> sizeF;

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

                Operand res = part == 0 ? context.VectorZero() : context.Copy(GetVec(op.Rd));

                for (int index = 0; index < elems; index++)
                {
                    Operand ne = context.VectorExtract(type, GetVec(op.Rn), 0);

                    if (sizeF == 0)
                    {
                        Delegate dlg = new _U16_F32(SoftFloat32_16.FPConvert);

                        Operand e = context.Call(dlg, ne);

                        e = context.ZeroExtend16(OperandType.I64, e);

                        res = EmitVectorInsert(context, res, e, part + index, 1);
                    }
                    else /* if (sizeF == 1) */
                    {
                        Operand e = context.ConvertToFP(OperandType.FP32, ne);

                        res = context.VectorInsert(res, e, part + index);
                    }
                }

                context.Copy(GetVec(op.Rd), res);
            }
        }
Esempio n. 3
0
        public static void Fcvtl_V(ArmEmitterContext context)
        {
            OpCodeSimd op = (OpCodeSimd)context.CurrOp;

            int sizeF = op.Size & 1;

            if (Optimizations.UseSse2 && sizeF == 1)
            {
                Operand n = GetVec(op.Rn);
                Operand res;

                if (op.RegisterSize == RegisterSize.Simd128)
                {
                    res = context.AddIntrinsic(Intrinsic.X86Movhlps, n, n);
                }
                else
                {
                    res = n;
                }

                res = context.AddIntrinsic(Intrinsic.X86Cvtps2pd, res);

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

                int elems = 4 >> sizeF;

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

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

                        Delegate dlg = new _F32_U16(SoftFloat16_32.FPConvert);

                        Operand e = context.Call(dlg, ne);

                        res = context.VectorInsert(res, e, index);
                    }
                    else /* if (sizeF == 1) */
                    {
                        Operand ne = context.VectorExtract(OperandType.FP32, GetVec(op.Rn), part + index);

                        Operand e = context.ConvertToFP(OperandType.FP64, ne);

                        res = context.VectorInsert(res, e, index);
                    }
                }

                context.Copy(GetVec(op.Rd), res);
            }
        }
Esempio n. 4
0
        private static Operand EmitFPConvert(ArmEmitterContext context, Operand value, OperandType type, bool signed)
        {
            Debug.Assert(value.Type == OperandType.I32 || value.Type == OperandType.I64);

            if (signed)
            {
                return(context.ConvertToFP(type, value));
            }
            else
            {
                return(context.ConvertToFPUI(type, value));
            }
        }
Esempio n. 5
0
        private static Operand EmitFPConvert(ArmEmitterContext context, Operand value, int size, bool signed)
        {
            Debug.Assert(value.Type == OperandType.I32 || value.Type == OperandType.I64);
            Debug.Assert((uint)size < 2);

            OperandType type = size == 0 ? OperandType.FP32 : OperandType.FP64;

            if (signed)
            {
                return(context.ConvertToFP(type, value));
            }
            else
            {
                return(context.ConvertToFPUI(type, value));
            }
        }
Esempio n. 6
0
        public static void Fcvt_S(ArmEmitterContext context)
        {
            OpCodeSimd op = (OpCodeSimd)context.CurrOp;

            if (op.Size == 0 && op.Opc == 1) // Single -> Double.
            {
                if (Optimizations.UseSse2)
                {
                    Operand n = GetVec(op.Rn);

                    Operand res = context.AddIntrinsic(Intrinsic.X86Cvtss2sd, context.VectorZero(), n);

                    context.Copy(GetVec(op.Rd), res);
                }
                else
                {
                    Operand ne = context.VectorExtract(OperandType.FP32, GetVec(op.Rn), 0);

                    Operand res = context.ConvertToFP(OperandType.FP64, ne);

                    context.Copy(GetVec(op.Rd), context.VectorInsert(context.VectorZero(), res, 0));
                }
            }
            else if (op.Size == 1 && op.Opc == 0) // Double -> Single.
            {
                if (Optimizations.UseSse2)
                {
                    Operand n = GetVec(op.Rn);

                    Operand res = context.AddIntrinsic(Intrinsic.X86Cvtsd2ss, context.VectorZero(), n);

                    context.Copy(GetVec(op.Rd), res);
                }
                else
                {
                    Operand ne = context.VectorExtract(OperandType.FP64, GetVec(op.Rn), 0);

                    Operand res = context.ConvertToFP(OperandType.FP32, ne);

                    context.Copy(GetVec(op.Rd), context.VectorInsert(context.VectorZero(), res, 0));
                }
            }
            else if (op.Size == 0 && op.Opc == 3) // Single -> Half.
            {
                Operand ne = context.VectorExtract(OperandType.FP32, GetVec(op.Rn), 0);

                Delegate dlg = new _U16_F32(SoftFloat32_16.FPConvert);

                Operand res = context.Call(dlg, ne);

                res = context.ZeroExtend16(OperandType.I64, res);

                context.Copy(GetVec(op.Rd), EmitVectorInsert(context, context.VectorZero(), res, 0, 1));
            }
            else if (op.Size == 3 && op.Opc == 0) // Half -> Single.
            {
                Operand ne = EmitVectorExtractZx(context, op.Rn, 0, 1);

                Delegate dlg = new _F32_U16(SoftFloat16_32.FPConvert);

                Operand res = context.Call(dlg, ne);

                context.Copy(GetVec(op.Rd), context.VectorInsert(context.VectorZero(), res, 0));
            }
            else if (op.Size == 1 && op.Opc == 3) // Double -> Half.
            {
                throw new NotImplementedException("Double-precision to half-precision.");
            }
            else if (op.Size == 3 && op.Opc == 1) // Double -> Half.
            {
                throw new NotImplementedException("Half-precision to double-precision.");
            }
            else // Invalid encoding.
            {
                Debug.Assert(false, $"type == {op.Size} && opc == {op.Opc}");
            }
        }
Esempio n. 7
0
        // VCVT: convert vector elements (32-bit) between floating-point and fixed point
        public static void Vcvt_V2(ArmEmitterContext context)
        {
            OpCode32SimdCvtFFixed op = (OpCode32SimdCvtFFixed)context.CurrOp;

            var toFixed  = op.Opc == 1;
            int fracBits = op.Fbits;
            var unsigned = op.U; // Sign of I32 (destination/source)

            if (toFixed)         // F32 to S32 or U32 (fixed)
            {
                EmitVectorUnaryOpF32(context, (op1) =>
                {
                    var a           = context.Multiply(op1, ConstF(MathF.Pow(2f, fracBits)));
                    var rounded     = EmitUnaryMathCall(context, nameof(MathF.Truncate), a);
                    MethodInfo info = unsigned ? typeof(SoftFallback).GetMethod(nameof(SoftFallback.SatF32ToU32)) : typeof(SoftFallback).GetMethod(nameof(SoftFallback.SatF32ToS32));
                    return(context.Call(info, rounded));
                });
            }
            else // S32 or U32 (fixed) to F32
            {
                EmitVectorUnaryOpI32(context, (op1) =>
                {
                    var f = unsigned ? context.ConvertToFPUI(OperandType.FP32, op1) : context.ConvertToFP(OperandType.FP32, op1);
                    return(context.Multiply(f, ConstF(1f / MathF.Pow(2f, fracBits))));
                }, !unsigned);
            }
        }