예제 #1
0
        public static void Fccmp_S(AILEmitterCtx Context)
        {
            AOpCodeSimdFcond Op = (AOpCodeSimdFcond)Context.CurrOp;

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

            Context.EmitCondBranch(LblTrue, Op.Cond);

            //TODO: Share this logic with Ccmp.
            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);

            Fcmp_S(Context);

            Context.MarkLabel(LblEnd);
        }
예제 #2
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);
        }
예제 #3
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);
        }
예제 #4
0
        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);
        }
예제 #5
0
        public static void EmitSetNZCV(AILEmitterCtx Context, int NZCV)
        {
            Context.EmitLdc_I4((NZCV >> 0) & 1);

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

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

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

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

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

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

            Context.EmitStflg((int)APState.NBit);
        }
예제 #6
0
        public static void EmitAddsCCheck(AILEmitterCtx Context)
        {
            //C = Rd < Rn
            Context.Emit(OpCodes.Dup);

            EmitDataLoadRn(Context);

            Context.Emit(OpCodes.Clt_Un);

            Context.EmitStflg((int)APState.CBit);
        }
예제 #7
0
        public static void EmitSubsCCheck(AILEmitterCtx Context)
        {
            //C = Rn == Rm || Rn > Rm = !(Rn < Rm)
            EmitDataLoadOpers(Context);

            Context.Emit(OpCodes.Clt_Un);

            Context.EmitLdc_I4(1);

            Context.Emit(OpCodes.Xor);

            Context.EmitStflg((int)APState.CBit);
        }
예제 #8
0
        public static void EmitSubsCCheck(AILEmitterCtx Context)
        {
            //C = Rn == Rm || Rn > Rm
            EmitDataLoadOpers(Context);

            Context.Emit(OpCodes.Ceq);

            EmitDataLoadOpers(Context);

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

            Context.EmitStflg((int)APState.CBit);
        }
예제 #9
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);
        }
예제 #10
0
        public static void Fcmp_S(AILEmitterCtx Context)
        {
            AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;

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

            //Handle NaN case.
            //If any number is NaN, then NZCV = 0011.
            if (CmpWithZero)
            {
                EmitNaNCheck(Context, Op.Rn);
            }
            else
            {
                EmitNaNCheck(Context, Op.Rn);
                EmitNaNCheck(Context, Op.Rm);

                Context.Emit(OpCodes.Or);
            }

            AILLabel LblNaN = new AILLabel();
            AILLabel LblEnd = new AILLabel();

            Context.Emit(OpCodes.Brtrue_S, LblNaN);

            void EmitLoadOpers()
            {
                EmitVectorExtractF(Context, Op.Rn, 0, Op.Size);

                if (CmpWithZero)
                {
                    if (Op.Size == 0)
                    {
                        Context.EmitLdc_R4(0);
                    }
                    else /* if (SizeF == 1) */
                    {
                        Context.EmitLdc_R8(0);
                    }
                }
                else
                {
                    EmitVectorExtractF(Context, Op.Rm, 0, Op.Size);
                }
            }

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

            //V = 0
            Context.EmitLdc_I4(0);

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

            Context.Emit(OpCodes.Br_S, LblEnd);

            Context.MarkLabel(LblNaN);

            EmitSetNZCV(Context, 0b0011);

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