public static void Stm(ArmEmitterContext context) { IOpCode32MemMult op = (IOpCode32MemMult)context.CurrOp; Operand n = context.Copy(GetIntA32(context, op.Rn)); Operand baseAddress = context.Add(n, Const(op.Offset)); int mask = op.RegisterMask; int offset = 0; for (int register = 0; mask != 0; mask >>= 1, register++) { if ((mask & 1) != 0) { Operand address = context.Add(baseAddress, Const(offset)); EmitStore(context, address, register, WordSizeLog2); // Note: If Rn is also specified on the register list, // and Rn is the first register on this list, then the // value that is written to memory is the unmodified value, // before the write back. If it is on the list, but it's // not the first one, then the value written to memory // varies between CPUs. if (offset == 0 && op.PostOffset != 0) { // Emit write back after the first write. SetIntA32(context, op.Rn, context.Add(n, Const(op.PostOffset))); } offset += 4; } } }
public static void Ldm(ArmEmitterContext context) { IOpCode32MemMult op = (IOpCode32MemMult)context.CurrOp; Operand n = GetIntA32(context, op.Rn); Operand baseAddress = context.Add(n, Const(op.Offset)); bool writesToPc = (op.RegisterMask & (1 << RegisterAlias.Aarch32Pc)) != 0; bool writeBack = op.PostOffset != 0 && (op.Rn != RegisterAlias.Aarch32Pc || !writesToPc); if (writeBack) { SetIntA32(context, op.Rn, context.Add(n, Const(op.PostOffset))); } int mask = op.RegisterMask; int offset = 0; for (int register = 0; mask != 0; mask >>= 1, register++) { if ((mask & 1) != 0) { Operand address = context.Add(baseAddress, Const(offset)); EmitLoadZx(context, address, register, WordSizeLog2); offset += 4; } } }