Пример #1
0
        private static void EmitVectorAddv(AILEmitterCtx Context)
        {
            AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;

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

            EmitVectorZeroLower(Context, Op.Rd);
            EmitVectorZeroUpper(Context, Op.Rd);

            Context.EmitLdvec(Op.Rd);
            Context.EmitLdc_I4(0);
            Context.EmitLdc_I4(Op.Size);

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

            for (int Index = 1; Index < (Bytes >> Op.Size); Index++)
            {
                EmitVectorExtractZx(Context, Op.Rn, Op.Size, Index);

                Context.Emit(OpCodes.Add);
            }

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

            Context.EmitStvec(Op.Rd);
        }
Пример #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);
            }
        }
Пример #3
0
        private static void EmitCcmp(AILEmitterCtx Context, CcmpOp CmpOp)
        {
            AOpCodeCcmp Op = (AOpCodeCcmp)Context.CurrOp;

            AILLabel LblTrue = new AILLabel();
            AILLabel LblEnd  = new AILLabel();

            Context.EmitCondBranch(LblTrue, Op.Cond);

            Context.EmitLdc_I4((Op.NZCV >> 0) & 1);

            Context.EmitStflg((int)APState.VBit);

            Context.EmitLdc_I4((Op.NZCV >> 1) & 1);

            Context.EmitStflg((int)APState.CBit);

            Context.EmitLdc_I4((Op.NZCV >> 2) & 1);

            Context.EmitStflg((int)APState.ZBit);

            Context.EmitLdc_I4((Op.NZCV >> 3) & 1);

            Context.EmitStflg((int)APState.NBit);

            Context.Emit(OpCodes.Br_S, LblEnd);

            Context.MarkLabel(LblTrue);

            EmitDataLoadOpers(Context);

            if (CmpOp == CcmpOp.Cmp)
            {
                Context.Emit(OpCodes.Sub);

                Context.EmitZNFlagCheck();

                EmitSubsCCheck(Context);
                EmitSubsVCheck(Context);
            }
            else if (CmpOp == CcmpOp.Cmn)
            {
                Context.Emit(OpCodes.Add);

                Context.EmitZNFlagCheck();

                EmitAddsCCheck(Context);
                EmitAddsVCheck(Context);
            }
            else
            {
                throw new ArgumentException(nameof(CmpOp));
            }

            Context.Emit(OpCodes.Pop);

            Context.MarkLabel(LblEnd);
        }
Пример #4
0
        private static void EmitZeroCVFlags(AILEmitterCtx Context)
        {
            Context.EmitLdc_I4(0);

            Context.EmitStflg((int)APState.VBit);

            Context.EmitLdc_I4(0);

            Context.EmitStflg((int)APState.CBit);
        }
Пример #5
0
        private static void EmitVectorInsert(AILEmitterCtx Context, int Reg, int Index, int Size)
        {
            Context.EmitLdvec(Reg);
            Context.EmitLdc_I4(Index);
            Context.EmitLdc_I4(Size);

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

            Context.EmitStvec(Reg);
        }
Пример #6
0
        public static void EmitVectorExtract(AILEmitterCtx Context, int Reg, int Index, int Size, bool Signed)
        {
            ThrowIfInvalid(Index, Size);

            Context.EmitLdvec(Reg);
            Context.EmitLdc_I4(Index);
            Context.EmitLdc_I4(Size);

            AVectorHelper.EmitCall(Context, Signed
                ? nameof(AVectorHelper.VectorExtractIntSx)
                : nameof(AVectorHelper.VectorExtractIntZx));
        }
Пример #7
0
        public static void Dup_S(AILEmitterCtx Context)
        {
            AOpCodeSimdIns Op = (AOpCodeSimdIns)Context.CurrOp;

            Context.EmitLdvec(Op.Rn);
            Context.EmitLdc_I4(Op.DstIndex);
            Context.EmitLdc_I4(Op.Size);

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

            Context.EmitStvec(Op.Rd);
        }
Пример #8
0
        private static void EmitVectorExtract(AILEmitterCtx Context, int Reg, int Index, bool Signed)
        {
            AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;

            Context.EmitLdvec(Reg);
            Context.EmitLdc_I4(Index);
            Context.EmitLdc_I4(Op.Size);

            ASoftFallback.EmitCall(Context, Signed
                ? nameof(ASoftFallback.ExtractSVec)
                : nameof(ASoftFallback.ExtractVec));
        }
Пример #9
0
        private static void EmitVectorShl(AILEmitterCtx Context, bool Signed)
        {
            //This instruction shifts the value on vector A by the number of bits
            //specified on the signed, lower 8 bits of vector B. If the shift value
            //is greater or equal to the data size of each lane, then the result is zero.
            //Additionally, negative shifts produces right shifts by the negated shift value.
            AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;

            int MaxShift = 8 << Op.Size;

            EmitVectorBinaryZx(Context, () =>
            {
                AILLabel LblShl  = new AILLabel();
                AILLabel LblZero = new AILLabel();
                AILLabel LblEnd  = new AILLabel();

                void EmitShift(OpCode ILOp)
                {
                    Context.Emit(OpCodes.Dup);

                    Context.EmitLdc_I4(MaxShift);

                    Context.Emit(OpCodes.Bge_S, LblZero);
                    Context.Emit(ILOp);
                    Context.Emit(OpCodes.Br_S, LblEnd);
                }

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

                Context.EmitLdc_I4(0);

                Context.Emit(OpCodes.Bge_S, LblShl);
                Context.Emit(OpCodes.Neg);

                EmitShift(Signed
                    ? OpCodes.Shr
                    : OpCodes.Shr_Un);

                Context.MarkLabel(LblShl);

                EmitShift(OpCodes.Shl);

                Context.MarkLabel(LblZero);

                Context.Emit(OpCodes.Pop);
                Context.Emit(OpCodes.Pop);

                Context.EmitLdc_I8(0);

                Context.MarkLabel(LblEnd);
            });
        }
Пример #10
0
        public static void Fmov_S(AILEmitterCtx Context)
        {
            AOpCodeSimdFmov Op = (AOpCodeSimdFmov)Context.CurrOp;

            Context.EmitLdc_I8(Op.Imm);
            Context.EmitLdc_I4(0);
            Context.EmitLdc_I4(Op.Size + 2);

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

            Context.EmitStvec(Op.Rd);
        }
Пример #11
0
        public static void Fmov_Ftoi1(AILEmitterCtx Context)
        {
            AOpCodeSimdCvt Op = (AOpCodeSimdCvt)Context.CurrOp;

            Context.EmitLdvec(Op.Rn);
            Context.EmitLdc_I4(1);
            Context.EmitLdc_I4(3);

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

            Context.EmitStintzr(Op.Rd);
        }
Пример #12
0
        public static void Fmov_Itof1(AILEmitterCtx Context)
        {
            AOpCodeSimdCvt Op = (AOpCodeSimdCvt)Context.CurrOp;

            Context.EmitLdintzr(Op.Rn);
            Context.EmitLdc_I4(1);
            Context.EmitLdc_I4(3);

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

            Context.EmitStvec(Op.Rd);
        }
Пример #13
0
        public static void EmitVectorInsertTmp(AILEmitterCtx Context, int Index, int Size)
        {
            ThrowIfInvalid(Index, Size);

            Context.EmitLdvectmp();
            Context.EmitLdc_I4(Index);
            Context.EmitLdc_I4(Size);

            AVectorHelper.EmitCall(Context, nameof(AVectorHelper.VectorInsertInt));

            Context.EmitStvectmp();
        }
Пример #14
0
        public static void EmitVectorInsert(AILEmitterCtx Context, int Reg, int Index, int Size, long Value)
        {
            ThrowIfInvalid(Index, Size);

            Context.EmitLdc_I8(Value);
            Context.EmitLdvec(Reg);
            Context.EmitLdc_I4(Index);
            Context.EmitLdc_I4(Size);

            AVectorHelper.EmitCall(Context, nameof(AVectorHelper.VectorInsertInt));

            Context.EmitStvec(Reg);
        }
Пример #15
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);
        }
Пример #16
0
        public static void Fcvtzu_V(AILEmitterCtx Context)
        {
            AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;

            Context.EmitLdvec(Op.Rn);
            Context.EmitLdc_I4(0);
            Context.EmitLdc_I4(Op.SizeF);

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

            Context.EmitStvec(Op.Rd);
        }
Пример #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);
        }
Пример #18
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);
        }
Пример #19
0
        public static void EmitVectorExtract(AILEmitterCtx Context, int Reg, int Index, int Size, bool Signed)
        {
            ThrowIfInvalid(Index, Size);

            IAOpCodeSimd Op = (IAOpCodeSimd)Context.CurrOp;

            Context.EmitLdvec(Reg);
            Context.EmitLdc_I4(Index);
            Context.EmitLdc_I4(Size);

            ASoftFallback.EmitCall(Context, Signed
                ? nameof(ASoftFallback.VectorExtractIntSx)
                : nameof(ASoftFallback.VectorExtractIntZx));
        }
Пример #20
0
        public static void EmitVectorInsertTmp(AILEmitterCtx Context, int Index, int Size)
        {
            if (Size < 0 || Size > 3)
            {
                throw new ArgumentOutOfRangeException(nameof(Size));
            }

            Context.EmitLdvectmp();
            Context.EmitLdc_I4(Index);
            Context.EmitLdc_I4(Size);

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

            Context.EmitStvectmp();
        }
Пример #21
0
        public static void Fmul_Vs(AILEmitterCtx Context)
        {
            AOpCodeSimdRegElem Op = (AOpCodeSimdRegElem)Context.CurrOp;

            Context.EmitLdvec(Op.Rn);
            Context.EmitLdvec(Op.Rm);
            Context.EmitLdc_I4(Op.Index);
            Context.EmitLdc_I4(Op.SizeF);

            ASoftFallback.EmitCall(Context,
                                   nameof(ASoftFallback.Fmul_Ve64),
                                   nameof(ASoftFallback.Fmul_Ve128));

            Context.EmitStvec(Op.Rd);
        }
Пример #22
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);
            }
        }
Пример #23
0
        public static void EmitRoundMathCall(AILEmitterCtx Context, MidpointRounding RoundMode)
        {
            IAOpCodeSimd Op = (IAOpCodeSimd)Context.CurrOp;

            int SizeF = Op.Size & 1;

            Context.EmitLdc_I4((int)RoundMode);

            MethodInfo MthdInfo;

            Type[] Types = new Type[] { null, typeof(MidpointRounding) };

            Types[0] = SizeF == 0
                ? typeof(float)
                : typeof(double);

            if (SizeF == 0)
            {
                MthdInfo = typeof(MathF).GetMethod(nameof(MathF.Round), Types);
            }
            else /* if (SizeF == 1) */
            {
                MthdInfo = typeof(Math).GetMethod(nameof(Math.Round), Types);
            }

            Context.EmitCall(MthdInfo);
        }
Пример #24
0
        private static void EmitSbc(AILEmitterCtx Context, bool SetFlags)
        {
            EmitDataLoadOpers(Context);

            Context.Emit(OpCodes.Sub);

            Context.EmitLdflg((int)APState.CBit);

            Type[] MthdTypes = new Type[] { typeof(bool) };

            MethodInfo MthdInfo = typeof(Convert).GetMethod(nameof(Convert.ToInt32), MthdTypes);

            Context.EmitCall(MthdInfo);

            Context.EmitLdc_I4(1);

            Context.Emit(OpCodes.Xor);

            if (Context.CurrOp.RegisterSize != ARegisterSize.Int32)
            {
                Context.Emit(OpCodes.Conv_U8);
            }

            Context.Emit(OpCodes.Sub);

            if (SetFlags)
            {
                Context.EmitZNFlagCheck();

                EmitSbcsCCheck(Context);
                EmitSubsVCheck(Context);
            }

            EmitDataStore(Context);
        }
Пример #25
0
        private static void EmitCvtToUInt(AILEmitterCtx Context, int Size)
        {
            if (Size < 0 || Size > 1)
            {
                throw new ArgumentOutOfRangeException(nameof(Size));
            }

            Context.EmitLdc_I4(0);

            if (Context.CurrOp.RegisterSize == ARegisterSize.Int32)
            {
                if (Size == 0)
                {
                    ASoftFallback.EmitCall(Context, nameof(ASoftFallback.SatSingleToUInt32));
                }
                else /* if (Size == 1) */
                {
                    ASoftFallback.EmitCall(Context, nameof(ASoftFallback.SatDoubleToUInt32));
                }
            }
            else
            {
                if (Size == 0)
                {
                    ASoftFallback.EmitCall(Context, nameof(ASoftFallback.SatSingleToUInt64));
                }
                else /* if (Size == 1) */
                {
                    ASoftFallback.EmitCall(Context, nameof(ASoftFallback.SatDoubleToUInt64));
                }
            }
        }
Пример #26
0
        public static void Frinta_S(AILEmitterCtx Context)
        {
            AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;

            Context.EmitLdvecsf(Op.Rn);
            Context.EmitLdc_I4((int)MidpointRounding.AwayFromZero);

            MethodInfo MthdInfo;

            if (Op.Size == 0)
            {
                Type[] Types = new Type[] { typeof(float), typeof(MidpointRounding) };

                MthdInfo = typeof(MathF).GetMethod(nameof(MathF.Round), Types);
            }
            else if (Op.Size == 1)
            {
                Type[] Types = new Type[] { typeof(double), typeof(MidpointRounding) };

                MthdInfo = typeof(Math).GetMethod(nameof(Math.Round), Types);
            }
            else
            {
                throw new InvalidOperationException();
            }

            Context.EmitCall(MthdInfo);

            Context.EmitStvecsf(Op.Rd);
        }
Пример #27
0
        // TSrc (16bit, 32bit, 64bit; signed, unsigned) > TDst (8bit, 16bit, 32bit; signed, unsigned).
        public static void EmitSatQ(
            AILEmitterCtx Context,
            int SizeDst,
            bool SignedSrc,
            bool SignedDst)
        {
            if (SizeDst > 2)
            {
                throw new ArgumentOutOfRangeException(nameof(SizeDst));
            }

            Context.EmitLdc_I4(SizeDst);
            Context.EmitLdarg(ATranslatedSub.StateArgIdx);

            if (SignedSrc)
            {
                ASoftFallback.EmitCall(Context, SignedDst
                    ? nameof(ASoftFallback.SignedSrcSignedDstSatQ)
                    : nameof(ASoftFallback.SignedSrcUnsignedDstSatQ));
            }
            else
            {
                ASoftFallback.EmitCall(Context, SignedDst
                    ? nameof(ASoftFallback.UnsignedSrcSignedDstSatQ)
                    : nameof(ASoftFallback.UnsignedSrcUnsignedDstSatQ));
            }
        }
Пример #28
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);
            }
        }
Пример #29
0
        private static void EmitCountLeadingBits(AILEmitterCtx Context, Action Emit)
        {
            AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;

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

            int ESize = 8 << Op.Size;

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

                Context.EmitLdc_I4(ESize);

                Emit();

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

            if (Op.RegisterSize == ARegisterSize.SIMD64)
            {
                EmitVectorZeroUpper(Context, Op.Rd);
            }
        }
Пример #30
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);
            }
        }