예제 #1
0
        private static void EmitSbc(ILEmitterCtx context, bool setFlags)
        {
            EmitAluLoadOpers(context);

            context.Emit(OpCodes.Sub);

            context.EmitLdflg((int)PState.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 != RegisterSize.Int32)
            {
                context.Emit(OpCodes.Conv_U8);
            }

            context.Emit(OpCodes.Sub);

            if (setFlags)
            {
                context.EmitZnFlagCheck();

                EmitSbcsCCheck(context);
                EmitSubsVCheck(context);
            }

            EmitAluStore(context);
        }
예제 #2
0
        private static void EmitRrxC(ILEmitterCtx context, bool setCarry)
        {
            // Rotate right by 1 with carry.
            if (setCarry)
            {
                context.Emit(OpCodes.Dup);

                context.EmitLdc_I4(1);

                context.Emit(OpCodes.And);

                context.EmitSttmp();
            }

            context.EmitLsr(1);

            context.EmitLdflg((int)PState.CBit);

            context.EmitLsl(31);

            context.Emit(OpCodes.Or);

            if (setCarry)
            {
                context.EmitLdtmp();
                context.EmitStflg((int)PState.CBit);
            }
        }
예제 #3
0
        public static void EmitSbcsCCheck(ILEmitterCtx context)
        {
            // C = (Rn == Rm && CIn) || Rn > Rm
            EmitAluLoadOpers(context);

            context.Emit(OpCodes.Ceq);

            context.EmitLdflg((int)PState.CBit);

            context.Emit(OpCodes.And);

            EmitAluLoadOpers(context);

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

            context.EmitStflg((int)PState.CBit);
        }
예제 #4
0
        private static void EmitAluStore(ILEmitterCtx context)
        {
            IOpCode32Alu op = (IOpCode32Alu)context.CurrOp;

            if (op.Rd == RegisterAlias.Aarch32Pc)
            {
                if (op.SetFlags)
                {
                    // TODO: Load SPSR etc.

                    context.EmitLdflg((int)PState.TBit);

                    ILLabel lblThumb = new ILLabel();
                    ILLabel lblEnd   = new ILLabel();

                    context.Emit(OpCodes.Brtrue_S, lblThumb);

                    context.EmitLdc_I4(~3);

                    context.Emit(OpCodes.Br_S, lblEnd);

                    context.MarkLabel(lblThumb);

                    context.EmitLdc_I4(~1);

                    context.MarkLabel(lblEnd);

                    context.Emit(OpCodes.And);
                    context.Emit(OpCodes.Conv_U8);
                    context.Emit(OpCodes.Ret);
                }
                else
                {
                    EmitAluWritePc(context);
                }
            }
            else
            {
                context.EmitStint(GetRegisterAlias(context.Mode, op.Rd));
            }
        }
예제 #5
0
        public static void EmitAdcsCCheck(ILEmitterCtx context)
        {
            // C = (Rd == Rn && CIn) || Rd < Rn
            context.EmitSttmp();
            context.EmitLdtmp();
            context.EmitLdtmp();

            EmitAluLoadRn(context);

            context.Emit(OpCodes.Ceq);

            context.EmitLdflg((int)PState.CBit);

            context.Emit(OpCodes.And);

            context.EmitLdtmp();

            EmitAluLoadRn(context);

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

            context.EmitStflg((int)PState.CBit);
        }
예제 #6
0
        private static void EmitLoadOrStore(ILEmitterCtx context, int size, AccessType accType)
        {
            OpCode32Mem op = (OpCode32Mem)context.CurrOp;

            if (op.Index || op.WBack)
            {
                EmitLoadFromRegister(context, op.Rn);

                context.EmitLdc_I4(op.Imm);

                context.Emit(op.Add ? OpCodes.Add : OpCodes.Sub);

                context.EmitSttmp();
            }

            if (op.Index)
            {
                context.EmitLdtmp();
            }
            else
            {
                EmitLoadFromRegister(context, op.Rn);
            }

            if ((accType & AccessType.Load) != 0)
            {
                if ((accType & AccessType.Signed) != 0)
                {
                    EmitReadSx32Call(context, size);
                }
                else
                {
                    EmitReadZxCall(context, size);
                }

                if (op.WBack)
                {
                    context.EmitLdtmp();

                    EmitStoreToRegister(context, op.Rn);
                }

                if (size == DWordSizeLog2)
                {
                    context.Emit(OpCodes.Dup);

                    context.EmitLdflg((int)PState.EBit);

                    ILLabel lblBigEndian = new ILLabel();
                    ILLabel lblEnd       = new ILLabel();

                    context.Emit(OpCodes.Brtrue_S, lblBigEndian);

                    //Little endian mode.
                    context.Emit(OpCodes.Conv_U4);

                    EmitStoreToRegister(context, op.Rt);

                    context.EmitLsr(32);

                    context.Emit(OpCodes.Conv_U4);

                    EmitStoreToRegister(context, op.Rt | 1);

                    context.Emit(OpCodes.Br_S, lblEnd);

                    //Big endian mode.
                    context.MarkLabel(lblBigEndian);

                    context.EmitLsr(32);

                    context.Emit(OpCodes.Conv_U4);

                    EmitStoreToRegister(context, op.Rt);

                    context.Emit(OpCodes.Conv_U4);

                    EmitStoreToRegister(context, op.Rt | 1);

                    context.MarkLabel(lblEnd);
                }
                else
                {
                    EmitStoreToRegister(context, op.Rt);
                }
            }
            else
            {
                if (op.WBack)
                {
                    context.EmitLdtmp();

                    EmitStoreToRegister(context, op.Rn);
                }

                EmitLoadFromRegister(context, op.Rt);

                if (size == DWordSizeLog2)
                {
                    context.Emit(OpCodes.Conv_U8);

                    context.EmitLdflg((int)PState.EBit);

                    ILLabel lblBigEndian = new ILLabel();
                    ILLabel lblEnd       = new ILLabel();

                    context.Emit(OpCodes.Brtrue_S, lblBigEndian);

                    //Little endian mode.
                    EmitLoadFromRegister(context, op.Rt | 1);

                    context.Emit(OpCodes.Conv_U8);

                    context.EmitLsl(32);

                    context.Emit(OpCodes.Or);

                    context.Emit(OpCodes.Br_S, lblEnd);

                    //Big endian mode.
                    context.MarkLabel(lblBigEndian);

                    context.EmitLsl(32);

                    EmitLoadFromRegister(context, op.Rt | 1);

                    context.Emit(OpCodes.Conv_U8);

                    context.Emit(OpCodes.Or);

                    context.MarkLabel(lblEnd);
                }

                EmitWriteCall(context, size);
            }
        }