Exemplo n.º 1
0
        // By Scalar

        public static void EmitVectorByScalarOpSimd32(ArmEmitterContext context, Func2I vectorFunc)
        {
            OpCode32SimdRegElem op = (OpCode32SimdRegElem)context.CurrOp;

            Operand n = GetVecA32(op.Qn);
            Operand d = GetVecA32(op.Qd);

            int     index    = op.Vm & 3;
            int     dupeMask = (index << 6) | (index << 4) | (index << 2) | index;
            Operand m        = GetVecA32(op.Vm >> 2);

            m = context.AddIntrinsic(Intrinsic.X86Shufps, m, m, Const(dupeMask));

            if (!op.Q) // Register swap: move relevant doubleword to destination side.
            {
                n = EmitMoveDoubleWordToSide(context, n, op.Vn, op.Vd);
            }

            Operand res = vectorFunc(n, m);

            if (!op.Q) // Register insert.
            {
                res = EmitDoubleWordInsert(context, d, res, op.Vd);
            }

            context.Copy(d, res);
        }
Exemplo n.º 2
0
        // Pairwise

        public static void EmitVectorPairwiseOpF32(ArmEmitterContext context, Func2I emit)
        {
            OpCode32SimdReg op = (OpCode32SimdReg)context.CurrOp;

            int sizeF = op.Size & 1;

            OperandType type = sizeF != 0 ? OperandType.FP64 : OperandType.FP32;

            int elems = op.GetBytesCount() >> (sizeF + 2);
            int pairs = elems >> 1;

            Operand res  = GetVecA32(op.Qd);
            Operand mvec = GetVecA32(op.Qm);
            Operand nvec = GetVecA32(op.Qn);

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

                Operand n1 = context.VectorExtract(type, nvec, op.Fn + pairIndex);
                Operand n2 = context.VectorExtract(type, nvec, op.Fn + pairIndex + 1);

                res = context.VectorInsert(res, emit(n1, n2), op.Fd + index);

                Operand m1 = context.VectorExtract(type, mvec, op.Fm + pairIndex);
                Operand m2 = context.VectorExtract(type, mvec, op.Fm + pairIndex + 1);

                res = context.VectorInsert(res, emit(m1, m2), op.Fd + index + pairs);
            }

            context.Copy(GetVecA32(op.Qd), res);
        }
Exemplo n.º 3
0
        public static void EmitVectorBinaryOpSimd32(ArmEmitterContext context, Func2I vectorFunc, int side = -1)
        {
            OpCode32SimdReg op = (OpCode32SimdReg)context.CurrOp;

            Operand n = GetVecA32(op.Qn);
            Operand m = GetVecA32(op.Qm);
            Operand d = GetVecA32(op.Qd);

            if (side == -1)
            {
                side = op.Vd;
            }

            if (!op.Q) // Register swap: move relevant doubleword to destination side.
            {
                n = EmitMoveDoubleWordToSide(context, n, op.Vn, side);
                m = EmitMoveDoubleWordToSide(context, m, op.Vm, side);
            }

            Operand res = vectorFunc(n, m);

            if (!op.Q) // Register insert.
            {
                if (side != op.Vd)
                {
                    res = EmitMoveDoubleWordToSide(context, res, side, op.Vd);
                }
                res = EmitDoubleWordInsert(context, d, res, op.Vd);
            }

            context.Copy(d, res);
        }
Exemplo n.º 4
0
        private static void EmitCmpOp(ArmEmitterContext context, Func2I emitCmp, bool scalar)
        {
            OpCodeSimd op = (OpCodeSimd)context.CurrOp;

            Operand res = context.VectorZero();

            int elems = !scalar?op.GetBytesCount() >> op.Size : 1;

            ulong szMask = ulong.MaxValue >> (64 - (8 << op.Size));

            for (int index = 0; index < elems; index++)
            {
                Operand ne = EmitVectorExtractSx(context, op.Rn, index, op.Size);
                Operand me;

                if (op is OpCodeSimdReg binOp)
                {
                    me = EmitVectorExtractSx(context, binOp.Rm, index, op.Size);
                }
                else
                {
                    me = Const(0L);
                }

                Operand isTrue = emitCmp(ne, me);

                Operand mask = context.ConditionalSelect(isTrue, Const(szMask), Const(0L));

                res = EmitVectorInsert(context, res, mask, index, op.Size);
            }

            context.Copy(GetVec(op.Rd), res);
        }
Exemplo n.º 5
0
        public static void EmitVectorByScalarLongOpI32(ArmEmitterContext context, Func2I emit, bool signed)
        {
            OpCode32SimdRegElem op = (OpCode32SimdRegElem)context.CurrOp;

            Operand m = ExtractElement(context, op.Vm, op.Size, signed);

            if (op.Size == 2)
            {
                m = signed ? context.SignExtend32(OperandType.I64, m) : context.ZeroExtend32(OperandType.I64, m);
            }

            Operand res = context.VectorZero();

            int elems = op.GetBytesCount() >> op.Size;

            for (int index = 0; index < elems; index++)
            {
                Operand ne = EmitVectorExtract32(context, op.Qn, op.In + index, op.Size, signed);

                if (op.Size == 2)
                {
                    ne = signed ? context.SignExtend32(OperandType.I64, ne) : context.ZeroExtend32(OperandType.I64, ne);
                }

                res = EmitVectorInsert(context, res, emit(ne, m), index, op.Size + 1);
            }

            context.Copy(GetVecA32(op.Qd), res);
        }
Exemplo n.º 6
0
        public static void EmitVectorPairwiseLongOpI32(ArmEmitterContext context, Func2I emit, bool signed)
        {
            OpCode32SimdReg op = (OpCode32SimdReg)context.CurrOp;

            int elems = op.GetBytesCount() >> op.Size;
            int pairs = elems >> 1;

            Operand res = GetVecA32(op.Qd);

            for (int index = 0; index < pairs; index++)
            {
                int     pairIndex = index * 2;
                Operand m1        = EmitVectorExtract32(context, op.Qm, op.Im + pairIndex, op.Size, signed);
                Operand m2        = EmitVectorExtract32(context, op.Qm, op.Im + pairIndex + 1, op.Size, signed);

                if (op.Size == 2)
                {
                    m1 = signed ? context.SignExtend32(OperandType.I64, m1) : context.ZeroExtend32(OperandType.I64, m1);
                    m2 = signed ? context.SignExtend32(OperandType.I64, m2) : context.ZeroExtend32(OperandType.I64, m2);
                }

                res = EmitVectorInsert(context, res, emit(m1, m2), op.Id + index, op.Size + 1);
            }

            context.Copy(GetVecA32(op.Qd), res);
        }
Exemplo n.º 7
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.º 8
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.º 9
0
        public static void EmitVectorImmBinaryQdQmOpI32(ArmEmitterContext context, Func2I emit, bool signed)
        {
            OpCode32SimdShImm op = (OpCode32SimdShImm)context.CurrOp;

            Operand res = GetVecA32(op.Qd);

            int elems = op.GetBytesCount() >> op.Size;

            for (int index = 0; index < elems; index++)
            {
                Operand de = EmitVectorExtract32(context, op.Qd, op.Id + index, op.Size, signed);
                Operand me = EmitVectorExtract32(context, op.Qm, op.Im + index, op.Size, signed);

                res = EmitVectorInsert(context, res, emit(de, me), op.Id + index, op.Size);
            }

            context.Copy(GetVecA32(op.Qd), res);
        }
Exemplo n.º 10
0
        private static void EmitVectorShImmWidenBinaryOp(ArmEmitterContext context, Func2I emit, int imm, bool signed)
        {
            OpCodeSimd op = (OpCodeSimd)context.CurrOp;

            Operand res = context.VectorZero();

            int elems = 8 >> op.Size;

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

            for (int index = 0; index < elems; index++)
            {
                Operand ne = EmitVectorExtract(context, op.Rn, part + index, op.Size, signed);

                res = EmitVectorInsert(context, res, emit(ne, Const(imm)), index, op.Size + 1);
            }

            context.Copy(GetVec(op.Rd), res);
        }
Exemplo n.º 11
0
        public static void EmitVectorByScalarOpI32(ArmEmitterContext context, Func2I emit, bool signed)
        {
            OpCode32SimdRegElem op = (OpCode32SimdRegElem)context.CurrOp;

            Operand m = ExtractElement(context, op.Vm, op.Size, signed);

            Operand res = GetVecA32(op.Qd);

            int elems = op.GetBytesCount() >> op.Size;

            for (int index = 0; index < elems; index++)
            {
                Operand ne = EmitVectorExtract32(context, op.Qn, op.In + index, op.Size, signed);

                res = EmitVectorInsert(context, res, emit(ne, m), op.Id + index, op.Size);
            }

            context.Copy(GetVecA32(op.Qd), res);
        }
Exemplo n.º 12
0
        private static void EmitCmpOpI32(
            ArmEmitterContext context,
            Func2I signedOp,
            Func2I unsignedOp,
            bool zero,
            bool signed)
        {
            if (zero)
            {
                if (signed)
                {
                    EmitVectorUnaryOpSx32(context, (m) =>
                    {
                        OperandType type = m.Type;
                        Operand zeroV    = (type == OperandType.I64) ? Const(0L) : Const(0);

                        return(ZerosOrOnes(context, signedOp(m, zeroV), type));
                    });
                }
                else
                {
                    EmitVectorUnaryOpZx32(context, (m) =>
                    {
                        OperandType type = m.Type;
                        Operand zeroV    = (type == OperandType.I64) ? Const(0L) : Const(0);

                        return(ZerosOrOnes(context, unsignedOp(m, zeroV), type));
                    });
                }
            }
            else
            {
                if (signed)
                {
                    EmitVectorBinaryOpSx32(context, (n, m) => ZerosOrOnes(context, signedOp(n, m), n.Type));
                }
                else
                {
                    EmitVectorBinaryOpZx32(context, (n, m) => ZerosOrOnes(context, unsignedOp(n, m), n.Type));
                }
            }
        }
Exemplo n.º 13
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.º 14
0
        public static void EmitVectorBinaryOpF32(ArmEmitterContext context, Func2I emit)
        {
            OpCode32SimdReg op = (OpCode32SimdReg)context.CurrOp;

            int sizeF = op.Size & 1;

            OperandType type = sizeF != 0 ? OperandType.FP64 : OperandType.FP32;

            int elems = op.GetBytesCount() >> (sizeF + 2);

            Operand res = GetVecA32(op.Qd);

            for (int index = 0; index < elems; index++)
            {
                Operand ne = context.VectorExtract(type, GetVecA32(op.Qn), op.Fn + index);
                Operand me = context.VectorExtract(type, GetVecA32(op.Qm), op.Fm + index);

                res = context.VectorInsert(res, emit(ne, me), op.Fd + index);
            }

            context.Copy(GetVecA32(op.Qd), res);
        }
Exemplo n.º 15
0
        public static void EmitVectorPairwiseOpI32(ArmEmitterContext context, Func2I emit, bool signed)
        {
            OpCode32SimdReg op = (OpCode32SimdReg)context.CurrOp;

            int elems = op.GetBytesCount() >> op.Size;
            int pairs = elems >> 1;

            Operand res = GetVecA32(op.Qd);

            for (int index = 0; index < pairs; index++)
            {
                int     pairIndex = index << 1;
                Operand n1        = EmitVectorExtract32(context, op.Qn, op.In + pairIndex, op.Size, signed);
                Operand n2        = EmitVectorExtract32(context, op.Qn, op.In + pairIndex + 1, op.Size, signed);

                Operand m1 = EmitVectorExtract32(context, op.Qm, op.Im + pairIndex, op.Size, signed);
                Operand m2 = EmitVectorExtract32(context, op.Qm, op.Im + pairIndex + 1, op.Size, signed);

                res = EmitVectorInsert(context, res, emit(n1, n2), op.Id + index, op.Size);
                res = EmitVectorInsert(context, res, emit(m1, m2), op.Id + index + pairs, op.Size);
            }

            context.Copy(GetVecA32(op.Qd), res);
        }
Exemplo n.º 16
0
 private static void EmitVectorShImmWidenBinaryZx(ArmEmitterContext context, Func2I emit, int imm)
 {
     EmitVectorShImmWidenBinaryOp(context, emit, imm, signed: false);
 }
Exemplo n.º 17
0
 public static void EmitVectorImmBinaryQdQmOpSx32(ArmEmitterContext context, Func2I emit)
 {
     EmitVectorImmBinaryQdQmOpI32(context, emit, true);
 }
Exemplo n.º 18
0
 public static void EmitVectorBinaryOpZx32(ArmEmitterContext context, Func2I emit)
 {
     EmitVectorBinaryOpI32(context, emit, false);
 }