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