/// <summary> /// "EX (SP),IX" operation /// </summary> /// <remarks> /// /// The low-order byte in IX is exchanged with the contents of the /// memory address specified by the contents of SP, and the /// high-order byte of IX is exchanged with the next highest memory /// address (SP+1). /// /// ================================= /// | 1 | 1 | 0 | 1 | 1 | 1 | 0 | 1 | /// ================================= /// | 1 | 1 | 1 | 0 | 0 | 0 | 1 | 1 | /// ================================= /// T-States: 4, 4, 3, 4, 3, 5 (23) /// </remarks> private void ExSPiIX() { var spOld = _registers.SP; var ix = GetIndexReg(); var l = ReadMemory(spOld); ClockP3(); WriteMemory(spOld, (byte)(ix & 0xFF)); ClockP4(); var h = ReadMemory(++spOld); ClockP3(); WriteMemory(spOld, (byte)(ix >> 8)); ClockP4(); _registers.MW = (ushort)(h << 8 | l); SetIndexReg(_registers.MW); ClockP1(); StackDebugSupport?.RecordStackContentManipulationEvent( new StackContentManipulationEvent((ushort)(_registers.PC - 2), IndexMode == OpIndexMode.IX ? "ex (sp),ix" : "ex (sp),iy", _registers.SP, _registers.MW, Tacts)); }
/// <summary> /// "LD SP,IX" operation /// </summary> /// <remarks> /// /// The 2-byte contents of IX are loaded to SP. /// /// ================================= /// | 1 | 1 | 0 | 1 | 1 | 1 | 0 | 1 | /// ================================= /// | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 1 | /// ================================= /// T-States: 4, 6 (10) /// Contention breakdown: pc:4,pc+1:6 /// </remarks> private void LdSPIX() { var oldSP = _registers.SP; _registers.SP = GetIndexReg(); ClockP2(); StackDebugSupport?.RecordStackPointerManipulationEvent( new StackPointerManipulationEvent((ushort)(_registers.PC - 2), IndexMode == OpIndexMode.IX ? "ld sp,ix" : "ld sp,iy", oldSP, _registers.SP, Tacts )); }
/// <summary> /// "PUSH IX" operation /// </summary> /// <remarks> /// /// The contents of IX are pushed to the external memory last-in, /// first-out (LIFO) stack. SP holds the 16-bit address of the /// current top of the Stack. This instruction first decrements SP /// and loads the high-order byte of IX to the memory address /// specified by SP; then decrements SP again and loads the low-order /// byte to the memory location corresponding to this new address /// in SP. /// /// ================================= /// | 1 | 1 | 0 | 1 | 1 | 1 | 0 | 1 | /// ================================= /// | 1 | 1 | 1 | 0 | 0 | 1 | 0 | 1 | /// ================================= /// T-States: 4, 5, 3, 3 (15) /// Contention breakdown: pc:4,pc+1:5,sp-1:3,sp-2:3 /// </remarks> private void PushIx() { var ix = GetIndexReg(); _registers.SP--; ClockP1(); WriteMemory(_registers.SP, (byte)(ix >> 8)); ClockP3(); _registers.SP--; WriteMemory(_registers.SP, (byte)(ix & 0xFF)); ClockP3(); StackDebugSupport?.RecordStackContentManipulationEvent( new StackContentManipulationEvent((ushort)(_registers.PC - 2), IndexMode == OpIndexMode.IX ? "push ix" : "push iy", _registers.SP, ix, Tacts)); }
/// <summary> /// "POP IX" operation /// </summary> /// <remarks> /// /// The top two bytes of the external memory last-in, first-out (LIFO) /// stack are popped to IX. SP holds the 16-bit address of the current /// top of the Stack. This instruction first loads to the low-order /// portion of IX the byte at the memory location corresponding to the /// contents of SP; then SP is incremented and the contents of the /// corresponding adjacent memory location are loaded to the high-order /// portion of IX. SP is incremented again. /// /// ================================= /// | 1 | 1 | 0 | 1 | 1 | 1 | 0 | 1 | /// ================================= /// | 1 | 1 | 1 | 0 | 0 | 0 | 0 | 1 | /// ================================= /// T-States: 4, 4, 3, 3 (14) /// Contention breakdown: pc:4,pc+1:4,sp:3,sp+1:3 /// </remarks> private void PopIx() { var oldSp = _registers.SP; ushort val = ReadMemory(_registers.SP); ClockP3(); _registers.SP++; val += (ushort)(ReadMemory(_registers.SP) * 0x100); ClockP3(); _registers.SP++; SetIndexReg(val); StackDebugSupport?.RecordStackContentManipulationEvent( new StackContentManipulationEvent((ushort)(_registers.PC - 2), IndexMode == OpIndexMode.IX ? "pop ix" : "pop iy", oldSp, GetIndexReg(), Tacts)); }