Exemplo n.º 1
0
        public static void Sli_V(AILEmitterCtx Context)
        {
            AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp;

            int Bytes = Op.GetBitsCount() >> 3;
            int Elems = Bytes >> Op.Size;

            int Shift = GetImmShl(Op);

            ulong Mask = Shift != 0 ? ulong.MaxValue >> (64 - Shift) : 0;

            for (int Index = 0; Index < Elems; Index++)
            {
                EmitVectorExtractZx(Context, Op.Rn, Index, Op.Size);

                Context.EmitLdc_I4(Shift);

                Context.Emit(OpCodes.Shl);

                EmitVectorExtractZx(Context, Op.Rd, Index, Op.Size);

                Context.EmitLdc_I8((long)Mask);

                Context.Emit(OpCodes.And);
                Context.Emit(OpCodes.Or);

                EmitVectorInsert(Context, Op.Rd, Index, Op.Size);
            }

            if (Op.RegisterSize == ARegisterSize.SIMD64)
            {
                EmitVectorZeroUpper(Context, Op.Rd);
            }
        }
Exemplo n.º 2
0
        private static void EmitVectorImmBinaryOp(AILEmitterCtx Context, Action Emit, long Imm, bool Signed)
        {
            AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp;

            int Bytes = Context.CurrOp.GetBitsCount() >> 3;

            for (int Index = 0; Index < (Bytes >> Op.Size); Index++)
            {
                Context.EmitLdvec(Op.Rd);
                Context.EmitLdc_I4(Index);
                Context.EmitLdc_I4(Op.Size);

                EmitVectorExtract(Context, Op.Rn, Index, Op.Size, Signed);

                Context.EmitLdc_I8(Imm);

                Emit();

                ASoftFallback.EmitCall(Context, nameof(ASoftFallback.InsertVec));

                Context.EmitStvec(Op.Rd);
            }

            if (Op.RegisterSize == ARegisterSize.SIMD64)
            {
                EmitVectorZeroUpper(Context, Op.Rd);
            }
        }
Exemplo n.º 3
0
        public static void Shl_V(AILEmitterCtx Context)
        {
            AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp;

            if (AOptimizations.UseSse2 && Op.Size > 0)
            {
                Type[] TypesSll = new Type[] { VectorUIntTypesPerSizeLog2[Op.Size], typeof(byte) };

                EmitLdvecWithUnsignedCast(Context, Op.Rn, Op.Size);

                Context.EmitLdc_I4(GetImmShl(Op));
                Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftLeftLogical), TypesSll));

                EmitStvecWithUnsignedCast(Context, Op.Rd, Op.Size);

                if (Op.RegisterSize == ARegisterSize.SIMD64)
                {
                    EmitVectorZeroUpper(Context, Op.Rd);
                }
            }
            else
            {
                EmitVectorUnaryOpZx(Context, () =>
                {
                    Context.EmitLdc_I4(GetImmShl(Op));

                    Context.Emit(OpCodes.Shl);
                });
            }
        }
Exemplo n.º 4
0
        public static void Sshr_V(AILEmitterCtx Context)
        {
            AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp;

            if (AOptimizations.UseSse2 && Op.Size > 0 &&
                Op.Size < 3)
            {
                Type[] TypesSra = new Type[] { VectorIntTypesPerSizeLog2[Op.Size], typeof(byte) };

                EmitLdvecWithSignedCast(Context, Op.Rn, Op.Size);

                Context.EmitLdc_I4(GetImmShr(Op));
                Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightArithmetic), TypesSra));

                EmitStvecWithSignedCast(Context, Op.Rd, Op.Size);

                if (Op.RegisterSize == ARegisterSize.SIMD64)
                {
                    EmitVectorZeroUpper(Context, Op.Rd);
                }
            }
            else
            {
                EmitShrImmOp(Context, ShrImmFlags.VectorSx);
            }
        }
Exemplo n.º 5
0
        public static void Usra_V(AILEmitterCtx Context)
        {
            AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp;

            if (AOptimizations.UseSse2 && Op.Size > 0)
            {
                Type[] TypesSrl = new Type[] { VectorUIntTypesPerSizeLog2[Op.Size], typeof(byte) };
                Type[] TypesAdd = new Type[] { VectorUIntTypesPerSizeLog2[Op.Size], VectorUIntTypesPerSizeLog2[Op.Size] };

                EmitLdvecWithUnsignedCast(Context, Op.Rd, Op.Size);
                EmitLdvecWithUnsignedCast(Context, Op.Rn, Op.Size);

                Context.EmitLdc_I4(GetImmShr(Op));

                Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical), TypesSrl));
                Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Add), TypesAdd));

                EmitStvecWithUnsignedCast(Context, Op.Rd, Op.Size);

                if (Op.RegisterSize == ARegisterSize.SIMD64)
                {
                    EmitVectorZeroUpper(Context, Op.Rd);
                }
            }
            else
            {
                EmitVectorShrImmOpZx(Context, ShrImmFlags.Accumulate);
            }
        }
Exemplo n.º 6
0
        private static void EmitVectorShr(AILEmitterCtx Context, ShrFlags Flags)
        {
            AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp;

            int Shift = (8 << (Op.Size + 1)) - Op.Imm;

            if (Flags.HasFlag(ShrFlags.Accumulate))
            {
                Action Emit = () =>
                {
                    Context.EmitLdc_I4(Shift);

                    Context.Emit(OpCodes.Shr_Un);
                    Context.Emit(OpCodes.Add);
                };

                EmitVectorOp(Context, Emit, OperFlags.RdRn, Signed: false);
            }
            else
            {
                EmitVectorUnaryZx(Context, () =>
                {
                    Context.EmitLdc_I4(Shift);

                    Context.Emit(OpCodes.Shr_Un);
                });
            }
        }
Exemplo n.º 7
0
        public static void Ushll_V(AILEmitterCtx Context)
        {
            AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp;

            int Shift = Op.Imm - (8 << Op.Size);

            EmitVectorShImmWidenBinaryZx(Context, () => Context.Emit(OpCodes.Shl), Shift);
        }
Exemplo n.º 8
0
        public static void Sshr_V(AILEmitterCtx Context)
        {
            AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp;

            int Shift = (8 << (Op.Size + 1)) - Op.Imm;

            EmitVectorShImmBinarySx(Context, () => Context.Emit(OpCodes.Shr), Shift);
        }
Exemplo n.º 9
0
        private static void EmitShrImmOp(AILEmitterCtx Context, ShrImmFlags Flags)
        {
            AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp;

            bool Scalar     = (Flags & ShrImmFlags.Scalar) != 0;
            bool Signed     = (Flags & ShrImmFlags.Signed) != 0;
            bool Round      = (Flags & ShrImmFlags.Round) != 0;
            bool Accumulate = (Flags & ShrImmFlags.Accumulate) != 0;

            int Shift = GetImmShr(Op);

            long RoundConst = 1L << (Shift - 1);

            int Bytes = Op.GetBitsCount() >> 3;
            int Elems = !Scalar ? Bytes >> Op.Size : 1;

            for (int Index = 0; Index < Elems; Index++)
            {
                EmitVectorExtract(Context, Op.Rn, Index, Op.Size, Signed);

                if (Op.Size <= 2)
                {
                    if (Round)
                    {
                        Context.EmitLdc_I8(RoundConst);

                        Context.Emit(OpCodes.Add);
                    }

                    Context.EmitLdc_I4(Shift);

                    Context.Emit(Signed ? OpCodes.Shr : OpCodes.Shr_Un);
                }
                else /* if (Op.Size == 3) */
                {
                    EmitShrImm_64(Context, Signed, Round ? RoundConst : 0L, Shift);
                }

                if (Accumulate)
                {
                    EmitVectorExtract(Context, Op.Rd, Index, Op.Size, Signed);

                    Context.Emit(OpCodes.Add);
                }

                EmitVectorInsertTmp(Context, Index, Op.Size);
            }

            Context.EmitLdvectmp();
            Context.EmitStvec(Op.Rd);

            if ((Op.RegisterSize == ARegisterSize.SIMD64) || Scalar)
            {
                EmitVectorZeroUpper(Context, Op.Rd);
            }
        }
Exemplo n.º 10
0
        public static void Srshr_V(AILEmitterCtx Context)
        {
            AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp;

            int Shift = GetImmShr(Op);

            long RoundConst = 1L << (Shift - 1);

            EmitVectorRoundShImmBinarySx(Context, () => Context.Emit(OpCodes.Shr), Shift, RoundConst);
        }
Exemplo n.º 11
0
        public static void Shl_S(AILEmitterCtx Context)
        {
            AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp;

            Context.EmitLdvecsi(Op.Rn);
            Context.EmitLdc_I4(Op.Imm - (8 << Op.Size));

            Context.Emit(OpCodes.Shl);

            Context.EmitStvecsi(Op.Rd);
        }
Exemplo n.º 12
0
        public static void Sshr_S(AILEmitterCtx Context)
        {
            AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp;

            Context.EmitLdvecsi(Op.Rn);
            Context.EmitLdc_I4((8 << (Op.Size + 1)) - Op.Imm);

            Context.Emit(OpCodes.Shr);

            Context.EmitStvecsi(Op.Rd);
        }
Exemplo n.º 13
0
        public static void Shl_V(AILEmitterCtx Context)
        {
            AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp;

            EmitVectorUnaryOpZx(Context, () =>
            {
                Context.EmitLdc_I4(GetImmShl(Op));

                Context.Emit(OpCodes.Shl);
            });
        }
Exemplo n.º 14
0
        public static void Ushr_S(AILEmitterCtx Context)
        {
            AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp;

            EmitScalarUnaryOpZx(Context, () =>
            {
                Context.EmitLdc_I4(GetImmShr(Op));

                Context.Emit(OpCodes.Shr_Un);
            });
        }
Exemplo n.º 15
0
        public static void Sshr_S(AILEmitterCtx Context)
        {
            AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp;

            EmitVectorExtractSx(Context, Op.Rn, 0, Op.Size);

            Context.EmitLdc_I4(GetImmShr(Op));

            Context.Emit(OpCodes.Shr);

            EmitScalarSet(Context, Op.Rd, Op.Size);
        }
Exemplo n.º 16
0
        public static void Ssra_V(AILEmitterCtx Context)
        {
            AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp;

            Action Emit = () =>
            {
                Context.Emit(OpCodes.Shr);
                Context.Emit(OpCodes.Add);
            };

            EmitVectorShImmTernarySx(Context, Emit, GetImmShr(Op));
        }
Exemplo n.º 17
0
        public static void Ushll_V(AILEmitterCtx Context)
        {
            AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp;

            Context.EmitLdvec(Op.Rn);
            Context.EmitLdc_I4(Op.Imm - (8 << Op.Size));
            Context.EmitLdc_I4(Op.Size);

            ASoftFallback.EmitCall(Context,
                                   nameof(ASoftFallback.Ushll),
                                   nameof(ASoftFallback.Ushll2));

            Context.EmitStvec(Op.Rd);
        }
Exemplo n.º 18
0
        public static void Ssra_V(AILEmitterCtx Context)
        {
            AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp;

            int Shift = (8 << (Op.Size + 1)) - Op.Imm;

            Action Emit = () =>
            {
                Context.Emit(OpCodes.Shr);
                Context.Emit(OpCodes.Add);
            };

            EmitVectorShImmTernarySx(Context, Emit, Shift);
        }
Exemplo n.º 19
0
        public static void Usra_V(AILEmitterCtx Context)
        {
            AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp;

            Action Emit = () =>
            {
                Context.EmitLdc_I4(GetImmShr(Op));

                Context.Emit(OpCodes.Shr_Un);
                Context.Emit(OpCodes.Add);
            };

            EmitVectorOp(Context, Emit, OperFlags.RdRn, Signed: false);
        }
Exemplo n.º 20
0
        public static void Fcvtzu_V_Fix(AILEmitterCtx Context)
        {
            AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp;

            Context.EmitLdvec(Op.Rn);
            Context.EmitLdc_I4((8 << (Op.Size + 1)) - Op.Imm);
            Context.EmitLdc_I4(Op.Size - 2);

            ASoftFallback.EmitCall(Context,
                                   nameof(ASoftFallback.Fcvtzu_V_64),
                                   nameof(ASoftFallback.Fcvtzu_V_128));

            Context.EmitStvec(Op.Rd);
        }
Exemplo n.º 21
0
        public static void Ushr_V(AILEmitterCtx Context)
        {
            AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp;

            Context.EmitLdvec(Op.Rn);
            Context.EmitLdc_I4((8 << (Op.Size + 1)) - Op.Imm);
            Context.EmitLdc_I4(Op.Size);

            ASoftFallback.EmitCall(Context,
                                   nameof(ASoftFallback.Ushr64),
                                   nameof(ASoftFallback.Ushr128));

            Context.EmitStvec(Op.Rd);
        }
Exemplo n.º 22
0
        public static void Srsra_V(AILEmitterCtx Context)
        {
            AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp;

            if (AOptimizations.UseSse2 && Op.Size > 0 &&
                Op.Size < 3)
            {
                Type[] TypesShs = new Type[] { VectorIntTypesPerSizeLog2[Op.Size], typeof(byte) };
                Type[] TypesAdd = new Type[] { VectorIntTypesPerSizeLog2[Op.Size], VectorIntTypesPerSizeLog2[Op.Size] };

                int Shift = GetImmShr(Op);
                int ESize = 8 << Op.Size;

                EmitLdvecWithSignedCast(Context, Op.Rd, Op.Size);
                EmitLdvecWithSignedCast(Context, Op.Rn, Op.Size);

                Context.Emit(OpCodes.Dup);
                Context.EmitStvectmp();

                Context.EmitLdc_I4(ESize - Shift);
                Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftLeftLogical), TypesShs));

                Context.EmitLdc_I4(ESize - 1);
                Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightLogical), TypesShs));

                Context.EmitLdvectmp();

                Context.EmitLdc_I4(Shift);
                Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.ShiftRightArithmetic), TypesShs));

                Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Add), TypesAdd));
                Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Add), TypesAdd));

                EmitStvecWithSignedCast(Context, Op.Rd, Op.Size);

                if (Op.RegisterSize == ARegisterSize.SIMD64)
                {
                    EmitVectorZeroUpper(Context, Op.Rd);
                }
            }
            else
            {
                EmitVectorShrImmOpSx(Context, ShrImmFlags.Round | ShrImmFlags.Accumulate);
            }
        }
Exemplo n.º 23
0
        private static void EmitVectorShrImmNarrowOpZx(AILEmitterCtx Context, bool Round)
        {
            AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp;

            int Shift = GetImmShr(Op);

            long RoundConst = 1L << (Shift - 1);

            int Elems = 8 >> Op.Size;

            int Part = Op.RegisterSize == ARegisterSize.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);

                if (Round)
                {
                    Context.EmitLdc_I8(RoundConst);

                    Context.Emit(OpCodes.Add);
                }

                Context.EmitLdc_I4(Shift);

                Context.Emit(OpCodes.Shr_Un);

                EmitVectorInsertTmp(Context, Part + Index, Op.Size);
            }

            Context.EmitLdvectmp();
            Context.EmitStvec(Op.Rd);

            if (Part == 0)
            {
                EmitVectorZeroUpper(Context, Op.Rd);
            }
        }
Exemplo n.º 24
0
        public static void Sqrshrn_V(AILEmitterCtx Context)
        {
            AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp;

            int Shift = GetImmShr(Op);

            long RoundConst = 1L << (Shift - 1);

            Action Emit = () =>
            {
                Context.EmitLdc_I8(RoundConst);

                Context.Emit(OpCodes.Add);

                Context.EmitLdc_I4(Shift);

                Context.Emit(OpCodes.Shr);
            };

            EmitVectorSaturatingNarrowOpSxSx(Context, Emit);
        }
Exemplo n.º 25
0
        private static void EmitVectorShImmBinaryOp(AILEmitterCtx Context, Action Emit, int Imm, bool Signed)
        {
            AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp;

            int Bytes = Context.CurrOp.GetBitsCount() >> 3;

            for (int Index = 0; Index < (Bytes >> Op.Size); Index++)
            {
                EmitVectorExtract(Context, Op.Rn, Index, Op.Size, Signed);

                Context.EmitLdc_I4(Imm);

                Emit();

                EmitVectorInsert(Context, Op.Rd, Index, Op.Size);
            }

            if (Op.RegisterSize == ARegisterSize.SIMD64)
            {
                EmitVectorZeroUpper(Context, Op.Rd);
            }
        }
Exemplo n.º 26
0
        private static void EmitVectorShImmWidenBinaryOp(AILEmitterCtx Context, Action Emit, int Imm, bool Signed)
        {
            AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp;

            int Elems = 8 >> Op.Size;

            int Part = Op.RegisterSize == ARegisterSize.SIMD128 ? Elems : 0;

            for (int Index = 0; Index < Elems; Index++)
            {
                EmitVectorExtract(Context, Op.Rn, Part + Index, Op.Size, Signed);

                Context.EmitLdc_I4(Imm);

                Emit();

                EmitVectorInsertTmp(Context, Index, Op.Size + 1);
            }

            Context.EmitLdvectmp();
            Context.EmitStvec(Op.Rd);
        }
Exemplo n.º 27
0
        private static void EmitVectorShImmNarrowBinaryOp(AILEmitterCtx Context, Action Emit, int Imm, bool Signed)
        {
            AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp;

            int Elems = 8 >> Op.Size;

            int Part = Op.RegisterSize == ARegisterSize.SIMD128 ? Elems : 0;

            for (int Index = 0; Index < Elems; Index++)
            {
                EmitVectorExtract(Context, Op.Rn, Index, Op.Size + 1, Signed);

                Context.EmitLdc_I4(Imm);

                Emit();

                EmitVectorInsert(Context, Op.Rd, Part + Index, Op.Size);
            }

            if (Part == 0)
            {
                EmitVectorZeroUpper(Context, Op.Rd);
            }
        }
Exemplo n.º 28
0
        private static void EmitShrImmSaturatingNarrowOp(AILEmitterCtx Context, ShrImmSaturatingNarrowFlags Flags)
        {
            AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp;

            bool Scalar    = (Flags & ShrImmSaturatingNarrowFlags.Scalar) != 0;
            bool SignedSrc = (Flags & ShrImmSaturatingNarrowFlags.SignedSrc) != 0;
            bool SignedDst = (Flags & ShrImmSaturatingNarrowFlags.SignedDst) != 0;
            bool Round     = (Flags & ShrImmSaturatingNarrowFlags.Round) != 0;

            int Shift = GetImmShr(Op);

            long RoundConst = 1L << (Shift - 1);

            int Elems = !Scalar ? 8 >> Op.Size : 1;

            int Part = !Scalar && (Op.RegisterSize == ARegisterSize.SIMD128) ? Elems : 0;

            if (Scalar)
            {
                EmitVectorZeroLowerTmp(Context);
            }

            if (Part != 0)
            {
                Context.EmitLdvec(Op.Rd);
                Context.EmitStvectmp();
            }

            for (int Index = 0; Index < Elems; Index++)
            {
                EmitVectorExtract(Context, Op.Rn, Index, Op.Size + 1, SignedSrc);

                if (Op.Size <= 1 || !Round)
                {
                    if (Round)
                    {
                        Context.EmitLdc_I8(RoundConst);

                        Context.Emit(OpCodes.Add);
                    }

                    Context.EmitLdc_I4(Shift);

                    Context.Emit(SignedSrc ? OpCodes.Shr : OpCodes.Shr_Un);
                }
                else /* if (Op.Size == 2 && Round) */
                {
                    EmitShrImm_64(Context, SignedSrc, RoundConst, Shift); // Shift <= 32
                }

                EmitSatQ(Context, Op.Size, SignedSrc, SignedDst);

                EmitVectorInsertTmp(Context, Part + Index, Op.Size);
            }

            Context.EmitLdvectmp();
            Context.EmitStvec(Op.Rd);

            if (Part == 0)
            {
                EmitVectorZeroUpper(Context, Op.Rd);
            }
        }
Exemplo n.º 29
0
        public static void Ushll_V(AILEmitterCtx Context)
        {
            AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp;

            EmitVectorShImmWidenBinaryZx(Context, () => Context.Emit(OpCodes.Shl), GetImmShl(Op));
        }
Exemplo n.º 30
0
 public static int GetImmShr(AOpCodeSimdShImm Op)
 {
     return((8 << (Op.Size + 1)) - Op.Imm);
 }