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