예제 #1
0
 public static void Sqneg_S(AILEmitterCtx Context)
 {
     EmitScalarSaturatingUnaryOpSx(Context, () => Context.Emit(OpCodes.Neg));
 }
예제 #2
0
 public static void Smull_V(AILEmitterCtx Context)
 {
     EmitVectorWidenRnRmBinaryOpSx(Context, () => Context.Emit(OpCodes.Mul));
 }
예제 #3
0
 public static void Sub_V(AILEmitterCtx Context)
 {
     EmitVectorBinaryOpZx(Context, () => Context.Emit(OpCodes.Sub));
 }
예제 #4
0
 public static void Fmul_V(AILEmitterCtx Context)
 {
     EmitVectorBinaryOpF(Context, () => Context.Emit(OpCodes.Mul));
 }
예제 #5
0
 public static void Mul_Ve(AILEmitterCtx Context)
 {
     EmitVectorBinaryOpByElemZx(Context, () => Context.Emit(OpCodes.Mul));
 }
예제 #6
0
 public static void Fadd_V(AILEmitterCtx Context)
 {
     EmitVectorBinaryOpF(Context, () => Context.Emit(OpCodes.Add));
 }
예제 #7
0
 public static void Fdiv_V(AILEmitterCtx Context)
 {
     EmitVectorBinaryOpF(Context, () => Context.Emit(OpCodes.Div));
 }
예제 #8
0
        public static void B(AILEmitterCtx Context)
        {
            AOpCodeBImmAl Op = (AOpCodeBImmAl)Context.CurrOp;

            Context.Emit(OpCodes.Br, Context.GetLabel(Op.Imm));
        }
예제 #9
0
        public static void Fcmp_S(AILEmitterCtx Context)
        {
            AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;

            bool CmpWithZero = !(Op is AOpCodeSimdFcond) ? Op.Bit3 : false;

            //todo
            //Context.TryMarkCondWithoutCmp();

            void EmitLoadOpers()
            {
                Context.EmitLdvecsf(Op.Rn);

                if (CmpWithZero)
                {
                    EmitLdcImmF(Context, 0, Op.Size);
                }
                else
                {
                    Context.EmitLdvecsf(Op.Rm);
                }
            }

            //Z = Rn == Rm
            EmitLoadOpers();

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

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

            //C = Rn >= Rm
            EmitLoadOpers();

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

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

            //N = Rn < Rm
            EmitLoadOpers();

            Context.Emit(OpCodes.Clt);

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

            //Handle NaN case. If any number is NaN, then NZCV = 0011.
            AILLabel LblNotNaN = new AILLabel();

            if (CmpWithZero)
            {
                EmitNaNCheck(Context, Op.Rn);
            }
            else
            {
                EmitNaNCheck(Context, Op.Rn);
                EmitNaNCheck(Context, Op.Rm);

                Context.Emit(OpCodes.Or);
            }

            Context.Emit(OpCodes.Brfalse_S, LblNotNaN);

            Context.EmitLdc_I4(1);
            Context.EmitLdc_I4(1);

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

            Context.MarkLabel(LblNotNaN);
        }
예제 #10
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;

            Action Emit = () =>
            {
                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);
            };

            if (Signed)
            {
                EmitVectorBinaryOpSx(Context, Emit);
            }
            else
            {
                EmitVectorBinaryOpZx(Context, Emit);
            }
        }
예제 #11
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);
            }
        }
예제 #12
0
        public static void Ushll_V(AILEmitterCtx Context)
        {
            AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp;

            EmitVectorShImmWidenBinaryZx(Context, () => Context.Emit(OpCodes.Shl), GetImmShl(Op));
        }
예제 #13
0
        public static void EmitSaturatingBinaryOp(AILEmitterCtx Context, Action Emit, SaturatingFlags Flags)
        {
            AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;

            bool Scalar = (Flags & SaturatingFlags.Scalar) != 0;
            bool Signed = (Flags & SaturatingFlags.Signed) != 0;

            bool Add = (Flags & SaturatingFlags.Add) != 0;
            bool Sub = (Flags & SaturatingFlags.Sub) != 0;

            bool Accumulate = (Flags & SaturatingFlags.Accumulate) != 0;

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

            if (Scalar)
            {
                EmitVectorZeroLowerTmp(Context);
            }

            if (Add || Sub)
            {
                for (int Index = 0; Index < Elems; Index++)
                {
                    EmitVectorExtract(Context, Op.Rn, Index, Op.Size, Signed);
                    EmitVectorExtract(Context, ((AOpCodeSimdReg)Op).Rm, Index, Op.Size, Signed);

                    if (Op.Size <= 2)
                    {
                        Context.Emit(Add ? OpCodes.Add : OpCodes.Sub);

                        EmitSatQ(Context, Op.Size, true, Signed);
                    }
                    else /* if (Op.Size == 3) */
                    {
                        if (Add)
                        {
                            EmitBinarySatQAdd(Context, Signed);
                        }
                        else /* if (Sub) */
                        {
                            EmitBinarySatQSub(Context, Signed);
                        }
                    }

                    EmitVectorInsertTmp(Context, Index, Op.Size);
                }
            }
            else if (Accumulate)
            {
                for (int Index = 0; Index < Elems; Index++)
                {
                    EmitVectorExtract(Context, Op.Rn, Index, Op.Size, !Signed);
                    EmitVectorExtract(Context, Op.Rd, Index, Op.Size, Signed);

                    if (Op.Size <= 2)
                    {
                        Context.Emit(OpCodes.Add);

                        EmitSatQ(Context, Op.Size, true, Signed);
                    }
                    else /* if (Op.Size == 3) */
                    {
                        EmitBinarySatQAccumulate(Context, Signed);
                    }

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

                    Emit();

                    EmitSatQ(Context, Op.Size, true, Signed);

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

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

            if ((Op.RegisterSize == ARegisterSize.SIMD64) || Scalar)
            {
                EmitVectorZeroUpper(Context, Op.Rd);
            }
        }
예제 #14
0
 public static void Usubw_V(AILEmitterCtx Context)
 {
     EmitVectorWidenRmBinaryOpZx(Context, () => Context.Emit(OpCodes.Sub));
 }
 public static void Addp_V(AILEmitterCtx Context)
 {
     EmitVectorPairwiseOpZx(Context, () => Context.Emit(OpCodes.Add));
 }
예제 #16
0
 public static void Not_V(AILEmitterCtx Context)
 {
     EmitVectorUnaryOpZx(Context, () => Context.Emit(OpCodes.Not));
 }
예제 #17
0
 public static void Fadd_S(AILEmitterCtx Context)
 {
     EmitScalarBinaryOpF(Context, () => Context.Emit(OpCodes.Add));
 }
예제 #18
0
 public static void Orr_Vi(AILEmitterCtx Context)
 {
     EmitVectorImmBinaryOp(Context, () => Context.Emit(OpCodes.Or));
 }
예제 #19
0
 public static void Fdiv_S(AILEmitterCtx Context)
 {
     EmitScalarBinaryOpF(Context, () => Context.Emit(OpCodes.Div));
 }
예제 #20
0
 public static void Mvni_V(AILEmitterCtx Context)
 {
     EmitVectorImmUnaryOp(Context, () => Context.Emit(OpCodes.Not));
 }
예제 #21
0
 public static void Fmul_Se(AILEmitterCtx Context)
 {
     EmitScalarBinaryOpByElemF(Context, () => Context.Emit(OpCodes.Mul));
 }
예제 #22
0
        private static void EmitReadCall(AILEmitterCtx Context, Extension Ext, int Size)
        {
            bool IsSimd = GetIsSimd(Context);

            string Name = null;

            if (Size < 0 || Size > (IsSimd ? 4 : 3))
            {
                throw new ArgumentOutOfRangeException(nameof(Size));
            }

            if (IsSimd)
            {
                switch (Size)
                {
                case 0: Name = nameof(AMemory.ReadVector8);   break;

                case 1: Name = nameof(AMemory.ReadVector16);  break;

                case 2: Name = nameof(AMemory.ReadVector32);  break;

                case 3: Name = nameof(AMemory.ReadVector64);  break;

                case 4: Name = nameof(AMemory.ReadVector128); break;
                }
            }
            else
            {
                switch (Size)
                {
                case 0: Name = nameof(AMemory.ReadByte);   break;

                case 1: Name = nameof(AMemory.ReadUInt16); break;

                case 2: Name = nameof(AMemory.ReadUInt32); break;

                case 3: Name = nameof(AMemory.ReadUInt64); break;
                }
            }

            Context.EmitCall(typeof(AMemory), Name);

            if (!IsSimd)
            {
                if (Ext == Extension.Sx32 ||
                    Ext == Extension.Sx64)
                {
                    switch (Size)
                    {
                    case 0: Context.Emit(OpCodes.Conv_I1); break;

                    case 1: Context.Emit(OpCodes.Conv_I2); break;

                    case 2: Context.Emit(OpCodes.Conv_I4); break;
                    }
                }

                if (Size < 3)
                {
                    Context.Emit(Ext == Extension.Sx64
                        ? OpCodes.Conv_I8
                        : OpCodes.Conv_U8);
                }
            }
        }
예제 #23
0
 public static void Fneg_S(AILEmitterCtx Context)
 {
     EmitScalarUnaryOpF(Context, () => Context.Emit(OpCodes.Neg));
 }
 public static void Rsubhn_V(AILEmitterCtx Context)
 {
     EmitHighNarrow(Context, () => Context.Emit(OpCodes.Sub), Round: true);
 }
예제 #25
0
 public static void Neg_V(AILEmitterCtx Context)
 {
     EmitVectorUnaryOpSx(Context, () => Context.Emit(OpCodes.Neg));
 }
        private static void EmitSaturatingExtNarrow(AILEmitterCtx Context, bool SignedSrc, bool SignedDst, bool Scalar)
        {
            AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;

            int Elems = (!Scalar ? 8 >> Op.Size : 1);
            int ESize = 8 << Op.Size;

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

            int TMaxValue = (SignedDst ? (1 << (ESize - 1)) - 1 : (int)((1L << ESize) - 1L));
            int TMinValue = (SignedDst ? -((1 << (ESize - 1))) : 0);

            Context.EmitLdc_I8(0L);
            Context.EmitSttmp();

            for (int Index = 0; Index < Elems; Index++)
            {
                AILLabel LblLe    = new AILLabel();
                AILLabel LblGeEnd = new AILLabel();

                EmitVectorExtract(Context, Op.Rn, Index, Op.Size + 1, SignedSrc);

                Context.Emit(OpCodes.Dup);

                Context.EmitLdc_I4(TMaxValue);
                Context.Emit(OpCodes.Conv_U8);

                Context.Emit(SignedSrc ? OpCodes.Ble_S : OpCodes.Ble_Un_S, LblLe);

                Context.Emit(OpCodes.Pop);

                Context.EmitLdc_I4(TMaxValue);

                Context.EmitLdc_I8(0x8000000L);
                Context.EmitSttmp();

                Context.Emit(OpCodes.Br_S, LblGeEnd);

                Context.MarkLabel(LblLe);

                Context.Emit(OpCodes.Dup);

                Context.EmitLdc_I4(TMinValue);
                Context.Emit(OpCodes.Conv_I8);

                Context.Emit(SignedSrc ? OpCodes.Bge_S : OpCodes.Bge_Un_S, LblGeEnd);

                Context.Emit(OpCodes.Pop);

                Context.EmitLdc_I4(TMinValue);

                Context.EmitLdc_I8(0x8000000L);
                Context.EmitSttmp();

                Context.MarkLabel(LblGeEnd);

                if (Scalar)
                {
                    EmitVectorZeroLower(Context, Op.Rd);
                }

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

            if (Part == 0)
            {
                EmitVectorZeroUpper(Context, Op.Rd);
            }

            Context.EmitLdarg(ATranslatedSub.StateArgIdx);
            Context.EmitLdarg(ATranslatedSub.StateArgIdx);
            Context.EmitCallPropGet(typeof(AThreadState), nameof(AThreadState.Fpsr));
            Context.EmitLdtmp();
            Context.Emit(OpCodes.Conv_I4);
            Context.Emit(OpCodes.Or);
            Context.EmitCallPropSet(typeof(AThreadState), nameof(AThreadState.Fpsr));
        }
예제 #27
0
 public static void Sub_S(AILEmitterCtx Context)
 {
     EmitScalarBinaryOpZx(Context, () => Context.Emit(OpCodes.Sub));
 }
 public static void Addhn_V(AILEmitterCtx Context)
 {
     EmitHighNarrow(Context, () => Context.Emit(OpCodes.Add), Round: false);
 }
예제 #29
0
 public static void Uaddl_V(AILEmitterCtx Context)
 {
     EmitVectorWidenRnRmBinaryOpZx(Context, () => Context.Emit(OpCodes.Add));
 }
예제 #30
0
 public static void And_V(AILEmitterCtx Context)
 {
     EmitVectorBinaryZx(Context, () => Context.Emit(OpCodes.And));
 }