Exemple #1
0
        private static void EmitLoadOrStore(ArmEmitterContext context, int size, AccessType accType)
        {
            OpCode32Mem op = (OpCode32Mem)context.CurrOp;

            Operand n = context.Copy(GetIntA32(context, op.Rn));

            Operand temp = null;

            if (op.Index || op.WBack)
            {
                temp = op.Add
                    ? context.Add(n, Const(op.Immediate))
                    : context.Subtract(n, Const(op.Immediate));
            }

            if (op.WBack)
            {
                SetIntA32(context, op.Rn, temp);
            }

            Operand address;

            if (op.Index)
            {
                address = temp;
            }
            else
            {
                address = n;
            }

            if ((accType & AccessType.Load) != 0)
            {
                void Load(int rt, int offs, int loadSize)
                {
                    Operand addr = context.Add(address, Const(offs));

                    if ((accType & AccessType.Signed) != 0)
                    {
                        EmitLoadSx32(context, addr, rt, loadSize);
                    }
                    else
                    {
                        EmitLoadZx(context, addr, rt, loadSize);
                    }
                }

                if (size == DWordSizeLog2)
                {
                    Operand lblBigEndian = Label();
                    Operand lblEnd       = Label();

                    context.BranchIfTrue(lblBigEndian, GetFlag(PState.EFlag));

                    Load(op.Rt, 0, WordSizeLog2);
                    Load(op.Rt | 1, 4, WordSizeLog2);

                    context.Branch(lblEnd);

                    context.MarkLabel(lblBigEndian);

                    Load(op.Rt | 1, 0, WordSizeLog2);
                    Load(op.Rt, 4, WordSizeLog2);

                    context.MarkLabel(lblEnd);
                }
                else
                {
                    Load(op.Rt, 0, size);
                }
            }
            else
            {
                void Store(int rt, int offs, int storeSize)
                {
                    Operand addr = context.Add(address, Const(offs));

                    EmitStore(context, addr, rt, storeSize);
                }

                if (size == DWordSizeLog2)
                {
                    Operand lblBigEndian = Label();
                    Operand lblEnd       = Label();

                    context.BranchIfTrue(lblBigEndian, GetFlag(PState.EFlag));

                    Store(op.Rt, 0, WordSizeLog2);
                    Store(op.Rt | 1, 4, WordSizeLog2);

                    context.Branch(lblEnd);

                    context.MarkLabel(lblBigEndian);

                    Store(op.Rt | 1, 0, WordSizeLog2);
                    Store(op.Rt, 4, WordSizeLog2);

                    context.MarkLabel(lblEnd);
                }
                else
                {
                    Store(op.Rt, 0, size);
                }
            }
        }
Exemple #2
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);
            }
        }