/// <summary> /// Change Processor State. /// </summary> private void ARM_CPS() { ARMMode Mode = (ARMMode)(Opcode & 0x1f); bool mmod = IsOpcodeBitSet(17); uint imod = (Opcode >> 18) & 3; if ((imod & 2) != 0) { bool Value = (imod & 1) != 0; if (IsOpcodeBitSet(6)) { Registers.SetFlag(ARMFlag.FIQDisable, Value); } if (IsOpcodeBitSet(7)) { Registers.SetFlag(ARMFlag.IRQDisable, Value); } if (IsOpcodeBitSet(8)) { Registers.SetFlag(ARMFlag.AbortDisable, Value); } } else if (mmod) { Registers.Mode = Mode; } }
/// <summary> /// Store Multiple. /// </summary> private void ARM_STM() { ushort RegisterList = (ushort)(Opcode & 0xffff); int Rn = (int)((Opcode >> 16) & 0xf); bool W = IsOpcodeBitSet(21); bool S = IsOpcodeBitSet(22); bool U = IsOpcodeBitSet(23); bool P = IsOpcodeBitSet(24); uint Address; if (U) { Address = Registers[Rn] + (uint)(P ? 4 : 0); } else { Address = Registers[Rn] + (uint)(P ? 0 : 4); for (int Index = 0; Index < 16; Index++) { if ((RegisterList & (1 << Index)) != 0) { Address -= 4; } } } uint Count = 0; ARMMode OldMode = Registers.Mode; if (S) { Registers.Mode = ARMMode.User; } for (int Index = 0; Index < 16; Index++) { if ((RegisterList & (1 << Index)) != 0) { WriteUInt32E(Address + Count, Registers[Index]); Count += 4; } } Registers.Mode = OldMode; if (W) { if (U) { Registers[Rn] += Count; } else { Registers[Rn] -= Count; } } }
/// <summary> /// Store Return State. /// </summary> private void ARM_SRS() { uint Address = ARM_GetSRSAddress(); ARMMode OldMode = Registers.Mode; Registers.Mode = (ARMMode)(Opcode & 0x1f); WriteUInt32E(Address, Registers[14]); WriteUInt32E(Address + 4, Registers.SPSR); Registers.Mode = OldMode; }
/// <summary> /// Load Multiple. /// </summary> private void ARM_LDM() { ushort RegisterList = (ushort)(Opcode & 0xffff); bool PC = (RegisterList & 0x8000) != 0; int Rn = (int)((Opcode >> 16) & 0xf); bool W = IsOpcodeBitSet(21); bool S = IsOpcodeBitSet(22); ARMMode OldMode = Registers.Mode; if (S && !PC) { Registers.Mode = ARMMode.User; } uint Address = ARM_GetLoadAndStoreMultipleAddress() & 0xfffffffc; for (int Index = 0; Index < 15; Index++) { if ((RegisterList & (1 << Index)) != 0) { Registers[Index] = ReadUInt32E(Address); Address += 4; } } Registers.Mode = OldMode; if (PC) { uint Value = ReadUInt32E(Address); Registers[15] = Value & 0xfffffffe; Registers.SetFlag(ARMFlag.Thumb, (Value & 1) != 0); if (S) { Registers.CPSR = Registers.SPSR; } } }
/// <summary> /// Gets the Address used for the general Load and Store instructions. /// </summary> /// <returns>The Base Address to Load or Store</returns> private uint ARM_GetLoadAndStoreAddress() { int Rn = (int)((Opcode >> 16) & 0xf); bool W = IsOpcodeBitSet(21); bool U = IsOpcodeBitSet(23); bool P = IsOpcodeBitSet(24); bool I = IsOpcodeBitSet(25); ARMMode OldMode = Registers.Mode; if (!P && W) { Registers.Mode = ARMMode.User; } uint Offset = 0; if (I) //Register { int Rm = (int)(Opcode & 0xf); uint Shift = (Opcode >> 5) & 3; int ShiftImmediate = (int)((Opcode >> 7) & 0x1f); switch (Shift) { case 0: Offset = Registers[Rm] << ShiftImmediate; break; //LSL case 1: Offset = ShiftImmediate != 0 ? Registers[Rm] >> ShiftImmediate : 0; break; //LSR case 2: //ASR if (ShiftImmediate == 0) { Offset = (Registers[Rm] & 0x80000000) != 0 ? 0xffffffff : 0; } else { Offset = Registers[Rm] >> ShiftImmediate; } break; case 3: //ROR if (ShiftImmediate == 0) { Offset = (Registers[Rm] >> 1) | (Registers.IsFlagSet(ARMFlag.Carry) ? 0x80000000 : 0); } else { Offset = ROR(Registers[Rm], ShiftImmediate); } break; } } else //Immediate { Offset = Opcode & 0xfff; } uint Address = 0; if (P) { if (W) //Pre-Indexed { if (U) { Registers[Rn] += Offset; } else { Registers[Rn] -= Offset; } Address = Registers[Rn]; } else //Offset { Address = U ? Registers[Rn] + Offset : Registers[Rn] - Offset; } } else { if (!W) //Post-Indexed { Address = Registers[Rn]; if (U) { Registers[Rn] += Offset; } else { Registers[Rn] -= Offset; } } } Registers.Mode = OldMode; return(Address); }