public static void EmitAddsVCheck(AILEmitterCtx Context)
        {
            //V = (Rd ^ Rn) & (Rd ^ Rm) & ~(Rn ^ Rm) < 0
            Context.EmitSttmp();
            Context.EmitLdtmp();
            Context.EmitLdtmp();

            EmitDataLoadRn(Context);

            Context.Emit(OpCodes.Xor);

            Context.EmitLdtmp();

            EmitDataLoadOper2(Context);

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

            EmitDataLoadOpers(Context);

            Context.Emit(OpCodes.Xor);
            Context.Emit(OpCodes.Not);
            Context.Emit(OpCodes.And);

            Context.EmitLdc_I(0);

            Context.Emit(OpCodes.Clt);

            Context.EmitStflg((int)APState.VBit);
        }
        public static void Bsl_V(AILEmitterCtx Context)
        {
            EmitVectorTernaryOpZx(Context, () =>
            {
                Context.EmitSttmp();
                Context.EmitLdtmp();

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

                Context.EmitLdtmp();

                Context.Emit(OpCodes.Xor);
            });
        }
Beispiel #3
0
        private static void EmitVectorBsl(AILEmitterCtx Context)
        {
            EmitVectorTernaryZx(Context, () =>
            {
                Context.EmitSttmp();
                Context.EmitLdtmp();

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

                Context.EmitLdtmp();

                Context.Emit(OpCodes.Xor);
            });
        }
Beispiel #4
0
        public static void Bsl_V(AILEmitterCtx Context)
        {
            if (AOptimizations.UseSse2)
            {
                AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;

                Type[] Types = new Type[]
                {
                    VectorUIntTypesPerSizeLog2[Op.Size],
                    VectorUIntTypesPerSizeLog2[Op.Size]
                };

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

                Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Xor), Types));

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

                Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.And), Types));

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

                Context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.Xor), Types));

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

                if (Op.RegisterSize == ARegisterSize.SIMD64)
                {
                    EmitVectorZeroUpper(Context, Op.Rd);
                }
            }
            else
            {
                EmitVectorTernaryOpZx(Context, () =>
                {
                    Context.EmitSttmp();
                    Context.EmitLdtmp();

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

                    Context.EmitLdtmp();

                    Context.Emit(OpCodes.Xor);
                });
            }
        }
Beispiel #5
0
        public static void EmitVectorOpByElem(AILEmitterCtx Context, Action Emit, int Elem, bool Ternary, bool Signed)
        {
            AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;

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

            EmitVectorExtract(Context, Op.Rm, Elem, Op.Size, Signed);
            Context.EmitSttmp();

            for (int Index = 0; Index < Elems; Index++)
            {
                if (Ternary)
                {
                    EmitVectorExtract(Context, Op.Rd, Index, Op.Size, Signed);
                }

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

                Emit();

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

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

            if (Op.RegisterSize == ARegisterSize.SIMD64)
            {
                EmitVectorZeroUpper(Context, Op.Rd);
            }
        }
Beispiel #6
0
        private static void EmitLoad(AILEmitterCtx Context, AccessType AccType, bool Pair)
        {
            AOpCodeMemEx Op = (AOpCodeMemEx)Context.CurrOp;

            bool Ordered   = (AccType & AccessType.Ordered) != 0;
            bool Exclusive = (AccType & AccessType.Exclusive) != 0;

            if (Ordered)
            {
                EmitBarrier(Context);
            }

            if (Exclusive)
            {
                EmitMemoryCall(Context, nameof(AMemory.SetExclusive), Op.Rn);
            }

            Context.EmitLdint(Op.Rn);
            Context.EmitSttmp();

            Context.EmitLdarg(ATranslatedSub.MemoryArgIdx);
            Context.EmitLdtmp();

            EmitReadZxCall(Context, Op.Size);

            Context.EmitStintzr(Op.Rt);

            if (Pair)
            {
                Context.EmitLdarg(ATranslatedSub.MemoryArgIdx);
                Context.EmitLdtmp();
                Context.EmitLdc_I8(1 << Op.Size);

                Context.Emit(OpCodes.Add);

                EmitReadZxCall(Context, Op.Size);

                Context.EmitStintzr(Op.Rt2);
            }
        }
Beispiel #7
0
        public static void EmitAdcsCCheck(AILEmitterCtx Context)
        {
            //C = (Rd == Rn && CIn) || Rd < Rn
            Context.EmitSttmp();
            Context.EmitLdtmp();
            Context.EmitLdtmp();

            EmitDataLoadRn(Context);

            Context.Emit(OpCodes.Ceq);

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

            Context.Emit(OpCodes.And);

            Context.EmitLdtmp();

            EmitDataLoadRn(Context);

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

            Context.EmitStflg((int)APState.CBit);
        }
Beispiel #8
0
        private static void EmitWBackIfNeeded(AILEmitterCtx Context)
        {
            //Check whenever the current OpCode has post-indexed write back, if so write it.
            //Note: AOpCodeMemPair inherits from AOpCodeMemImm, so this works for both.
            if (Context.CurrOp is AOpCodeMemImm Op && Op.WBack)
            {
                Context.EmitLdtmp();

                if (Op.PostIdx)
                {
                    Context.EmitLdc_I(Op.Imm);

                    Context.Emit(OpCodes.Add);
                }

                Context.EmitStint(Op.Rn);
            }
        }
Beispiel #9
0
        public static void Ldp(AILEmitterCtx Context)
        {
            AOpCodeMemPair Op = (AOpCodeMemPair)Context.CurrOp;

            void EmitReadAndStore(int Rt)
            {
                if (Op.Extend64)
                {
                    EmitReadSx64Call(Context, Op.Size);
                }
                else
                {
                    EmitReadZxCall(Context, Op.Size);
                }

                if (Op is IAOpCodeSimd)
                {
                    Context.EmitStvec(Rt);
                }
                else
                {
                    Context.EmitStintzr(Rt);
                }
            }

            Context.EmitLdarg(ATranslatedSub.MemoryArgIdx);

            EmitLoadAddress(Context);

            EmitReadAndStore(Op.Rt);

            Context.EmitLdarg(ATranslatedSub.MemoryArgIdx);
            Context.EmitLdtmp();
            Context.EmitLdc_I8(1 << Op.Size);

            Context.Emit(OpCodes.Add);

            EmitReadAndStore(Op.Rt2);

            EmitWBackIfNeeded(Context);
        }
Beispiel #10
0
        public static void Stp(AILEmitterCtx Context)
        {
            AOpCodeMemPair Op = (AOpCodeMemPair)Context.CurrOp;

            Context.EmitLdarg(ATranslatedSub.MemoryArgIdx);

            EmitLoadAddress(Context);

            if (Op is IAOpCodeSimd)
            {
                Context.EmitLdvec(Op.Rt);
            }
            else
            {
                Context.EmitLdintzr(Op.Rt);
            }

            EmitWriteCall(Context, Op.Size);

            Context.EmitLdarg(ATranslatedSub.MemoryArgIdx);
            Context.EmitLdtmp();
            Context.EmitLdc_I8(1 << Op.Size);

            Context.Emit(OpCodes.Add);

            if (Op is IAOpCodeSimd)
            {
                Context.EmitLdvec(Op.Rt2);
            }
            else
            {
                Context.EmitLdintzr(Op.Rt2);
            }

            EmitWriteCall(Context, Op.Size);

            EmitWBackIfNeeded(Context);
        }
        private static void EmitQxtn(AILEmitterCtx Context, bool Signed, bool Scalar)
        {
            AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;

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

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

            int Part = (!Scalar & (Op.RegisterSize == ARegisterSize.SIMD128) ? Elems : 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, Signed);

                Context.Emit(OpCodes.Dup);

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

                Context.Emit(Signed ? 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(Signed ? 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));
        }
Beispiel #12
0
        public static void EmitSaturatingNarrowOp(
            AILEmitterCtx Context,
            Action Emit,
            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;

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

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

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

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

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

                Emit();

                Context.Emit(OpCodes.Dup);

                Context.EmitLdc_I8(TMaxValue);

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

                Context.Emit(OpCodes.Pop);

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

                Context.Emit(OpCodes.Br_S, LblGeEnd);

                Context.MarkLabel(LblLe);

                Context.Emit(OpCodes.Dup);

                Context.EmitLdc_I8(TMinValue);

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

                Context.Emit(OpCodes.Pop);

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

                Context.MarkLabel(LblGeEnd);

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

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

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

            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));
        }