Exemplo n.º 1
0
        public static void EmitScalarTernaryOpF32(
            ArmEmitterContext context,
            Intrinsic inst32pt1,
            Intrinsic inst64pt1,
            Intrinsic inst32pt2,
            Intrinsic inst64pt2,
            bool isNegD = false)
        {
            OpCode32SimdRegS op = (OpCode32SimdRegS)context.CurrOp;

            bool doubleSize = (op.Size & 1) != 0;

            Intrinsic inst1 = doubleSize ? inst64pt1 : inst32pt1;
            Intrinsic inst2 = doubleSize ? inst64pt2 : inst32pt2;

            EmitScalarTernaryOpSimd32(context, (d, n, m) =>
            {
                Operand res = context.AddIntrinsic(inst1, n, m);

                if (isNegD)
                {
                    Operand mask = doubleSize
                        ? X86GetScalar(context, -0d)
                        : X86GetScalar(context, -0f);

                    d = doubleSize
                        ? context.AddIntrinsic(Intrinsic.X86Xorpd, mask, d)
                        : context.AddIntrinsic(Intrinsic.X86Xorps, mask, d);
                }

                return(context.AddIntrinsic(inst2, d, res));
            });
        }
Exemplo n.º 2
0
        public static void Vnmul_S(ArmEmitterContext context)
        {
            OpCode32SimdRegS op = (OpCode32SimdRegS)context.CurrOp;

            if (Optimizations.UseSse2)
            {
                EmitScalarBinaryOpSimd32(context, (n, m) =>
                {
                    if ((op.Size & 1) == 0)
                    {
                        Operand res  = context.AddIntrinsic(Intrinsic.X86Mulss, n, m);
                        Operand mask = X86GetScalar(context, -0f);
                        return(context.AddIntrinsic(Intrinsic.X86Xorps, mask, res));
                    }
                    else
                    {
                        Operand res  = context.AddIntrinsic(Intrinsic.X86Mulsd, n, m);
                        Operand mask = X86GetScalar(context, -0d);
                        return(context.AddIntrinsic(Intrinsic.X86Xorpd, mask, res));
                    }
                });
            }
            else
            {
                EmitScalarBinaryOpF32(context, (op1, op2) => context.Negate(context.Multiply(op1, op2)));
            }
        }
Exemplo n.º 3
0
        public static void EmitScalarBinaryOpF32(ArmEmitterContext context, Intrinsic inst32, Intrinsic inst64)
        {
            OpCode32SimdRegS op = (OpCode32SimdRegS)context.CurrOp;

            Intrinsic inst = (op.Size & 1) != 0 ? inst64 : inst32;

            EmitScalarBinaryOpSimd32(context, (n, m) => context.AddIntrinsic(inst, n, m));
        }
Exemplo n.º 4
0
        public static void EmitScalarBinaryOpF32(ArmEmitterContext context, Func2I emit)
        {
            OpCode32SimdRegS op = (OpCode32SimdRegS)context.CurrOp;

            OperandType type = (op.Size & 1) != 0 ? OperandType.FP64 : OperandType.FP32;

            Operand n = ExtractScalar(context, type, op.Vn);
            Operand m = ExtractScalar(context, type, op.Vm);

            InsertScalar(context, op.Vd, emit(n, m));
        }
Exemplo n.º 5
0
        public static void EmitScalarTernaryOpF32(ArmEmitterContext context, Intrinsic inst32, Intrinsic inst64)
        {
            OpCode32SimdRegS op = (OpCode32SimdRegS)context.CurrOp;

            bool doubleSize = (op.Size & 1) != 0;

            Intrinsic inst = doubleSize ? inst64 : inst32;

            EmitScalarTernaryOpSimd32(context, (d, n, m) =>
            {
                return(context.AddIntrinsic(inst, d, n, m));
            });
        }
Exemplo n.º 6
0
        public static void EmitScalarTernaryOpF32(ArmEmitterContext context, Intrinsic inst32pt1, Intrinsic inst64pt1, Intrinsic inst32pt2, Intrinsic inst64pt2)
        {
            OpCode32SimdRegS op = (OpCode32SimdRegS)context.CurrOp;

            bool doubleSize = (op.Size & 1) != 0;

            Intrinsic inst1 = doubleSize ? inst64pt1 : inst32pt1;
            Intrinsic inst2 = doubleSize ? inst64pt2 : inst32pt2;

            EmitScalarTernaryOpSimd32(context, (d, n, m) =>
            {
                Operand res = context.AddIntrinsic(inst1, n, m);
                return(context.AddIntrinsic(inst2, d, res));
            });
        }
Exemplo n.º 7
0
        public static void EmitScalarBinaryOpI32(ArmEmitterContext context, Func2I emit)
        {
            OpCode32SimdRegS op = (OpCode32SimdRegS)context.CurrOp;

            OperandType type = (op.Size & 1) != 0 ? OperandType.I64 : OperandType.I32;

            if (op.Size < 2)
            {
                throw new NotSupportedException("Cannot perform a scalar SIMD operation on integers smaller than 32 bits.");
            }

            Operand n = ExtractScalar(context, type, op.Vn);
            Operand m = ExtractScalar(context, type, op.Vm);

            InsertScalar(context, op.Vd, emit(n, m));
        }
Exemplo n.º 8
0
        public static void EmitScalarBinaryOpSimd32(ArmEmitterContext context, Func2I scalarFunc)
        {
            OpCode32SimdRegS op = (OpCode32SimdRegS)context.CurrOp;

            bool    doubleSize = (op.Size & 1) != 0;
            int     shift      = doubleSize ? 1 : 2;
            Operand n          = GetVecA32(op.Vn >> shift);
            Operand m          = GetVecA32(op.Vm >> shift);
            Operand d          = GetVecA32(op.Vd >> shift);

            n = EmitSwapScalar(context, n, op.Vn, doubleSize);
            m = EmitSwapScalar(context, m, op.Vm, doubleSize);

            Operand res = scalarFunc(n, m);

            // Insert scalar into vector.
            res = EmitScalarInsert(context, d, res, op.Vd, doubleSize);

            context.Copy(d, res);
        }
Exemplo n.º 9
0
        public static void Vnmls_S(ArmEmitterContext context)
        {
            OpCode32SimdRegS op = (OpCode32SimdRegS)context.CurrOp;

            if (Optimizations.FastFP && Optimizations.UseSse2)
            {
                EmitScalarTernaryOpSimd32(context, (d, n, m) =>
                {
                    if ((op.Size & 1) == 0)
                    {
                        Operand res  = context.AddIntrinsic(Intrinsic.X86Mulss, n, m);
                        Operand mask = X86GetScalar(context, -0f);
                        d            = context.AddIntrinsic(Intrinsic.X86Xorps, mask, d);
                        return(context.AddIntrinsic(Intrinsic.X86Addss, d, res));
                    }
                    else
                    {
                        Operand res  = context.AddIntrinsic(Intrinsic.X86Mulsd, n, m);
                        Operand mask = X86GetScalar(context, -0d);
                        d            = context.AddIntrinsic(Intrinsic.X86Xorpd, mask, res);
                        return(context.AddIntrinsic(Intrinsic.X86Addsd, d, res));
                    }
                });
            }
            else if (Optimizations.FastFP)
            {
                EmitScalarTernaryOpF32(context, (op1, op2, op3) =>
                {
                    return(context.Add(context.Negate(op1), context.Multiply(op2, op3)));
                });
            }
            else
            {
                EmitScalarTernaryOpF32(context, (op1, op2, op3) =>
                {
                    return(EmitSoftFloatCall(context, nameof(SoftFloat32.FPNegMulSub), op1, op2, op3));
                });
            }
        }