Exemple #1
0
        private static string DisassembleEmulatorBusSource(MicroInstruction instruction, out bool loadS)
        {
            EmulatorBusSource bs = (EmulatorBusSource)instruction.BS;

            switch (bs)
            {
            case EmulatorBusSource.ReadSLocation:
                loadS = false;

                if (instruction.RSELECT == 0)
                {
                    return("M");
                }
                else
                {
                    return(String.Format("$S{0}", Conversion.ToOctal((int)instruction.RSELECT)));
                }

            case EmulatorBusSource.LoadSLocation:
                loadS = true;
                return(String.Empty);

            default:
                loadS = false;
                throw new InvalidOperationException(String.Format("Unhandled Emulator BS {0}", bs));
            }
        }
Exemple #2
0
            protected override ushort GetBusSource(MicroInstruction instruction)
            {
                EmulatorBusSource ebs = (EmulatorBusSource)instruction.BS;

                switch (ebs)
                {
                case EmulatorBusSource.ReadSLocation:
                    if (instruction.RSELECT != 0)
                    {
                        return(_cpu._s[_rb][instruction.RSELECT]);
                    }
                    else
                    {
                        // "...when reading data from the S registers onto the processor bus,
                        //  the RSELECT value 0 causes the current value of the M register to
                        //  appear on the bus..."
                        return(_cpu._m);
                    }

                case EmulatorBusSource.LoadSLocation:
                    // "When an S register is being loaded from M, the processor bus receives an
                    // undefined value rather than being set to zero."
                    _loadS = true;
                    return(0xffff);          // Technically this is an "undefined value," we're defining it as -1.

                default:
                    throw new InvalidOperationException(String.Format("Unhandled bus source {0}", instruction.BS));
                }
            }
            protected override void ExecuteSpecialFunction2(MicroInstruction instruction)
            {
                DisplayHorizontalF2 dh2 = (DisplayHorizontalF2)instruction.F2;

                switch (dh2)
                {
                case DisplayHorizontalF2.EVENFIELD:
                    _nextModifier |= (ushort)(_displayController.EVENFIELD ? 1 : 0);
                    break;

                case DisplayHorizontalF2.SETMODE:
                    // "If bit 0 = 1, the bit clock rate is set to 100ns period (at the start of the next scan line),
                    // and a 1 is merged into NEXT[9]."
                    _displayController.SETMODE(_busData);

                    if ((_busData & 0x8000) != 0)
                    {
                        _nextModifier |= 1;
                    }
                    break;

                default:
                    throw new InvalidOperationException(String.Format("Unhandled display word F2 {0}.", dh2));
                }
            }
Exemple #4
0
 private static void CacheMicrocodeROM()
 {
     for (int i = 0; i < _uCodeRom.Length; i++)
     {
         _decodeCache[i] = new MicroInstruction(_uCodeRom[i]);
     }
 }
Exemple #5
0
            protected override void ExecuteSpecialFunction2PostBusSource(MicroInstruction instruction)
            {
                TridentF2 tf2 = (TridentF2)instruction.F2;

                switch (tf2)
                {
                case TridentF2.ReadKDTA:
                    //
                    // <-KDTA is actually MD<- (SF 6), repurposed to gate disk data onto the bus
                    // iff BS is None.  Otherwise it behaves like a normal MD<-.  We'll let
                    // the normal Task implementation handle the actual MD<- operation.
                    //
                    if (instruction.BS == BusSource.None)
                    {
                        // _busData at this point should be 0xffff.  We could technically
                        // just directly assign the bits...
                        _busData &= _tridentController.KDTA;
                    }
                    break;

                case TridentF2.STATUS:
                    _busData &= _tridentController.STATUS;
                    break;

                case TridentF2.EMPTY:
                    _tridentController.WaitForEmpty();
                    break;
                }
            }
Exemple #6
0
        private static string DisassembleOrbitSpecialFunction2(MicroInstruction instruction)
        {
            OrbitF2 of2 = (OrbitF2)instruction.F2;

            switch (of2)
            {
            case OrbitF2.OrbitDBCWidthSet:
                return("OrbitDBCWidthSet<- ");

            case OrbitF2.OrbitXY:
                return("OrbitXY<- ");

            case OrbitF2.OrbitHeight:
                return("OrbitHeight<- ");

            case OrbitF2.OrbitFontData:
                return("OrbitFontData<- ");

            case OrbitF2.OrbitInk:
                return("OrbitInk<- ");

            case OrbitF2.OrbitControl:
                return("OrbitControl<- ");

            case OrbitF2.OrbitROSCommand:
                return("OrbitROSCommand<- ");

            default:
                return(String.Format("Orbit F2 {0}", Conversion.ToOctal((int)of2)));
            }
        }
Exemple #7
0
        private static string DisassembleTridentSpecialFunction2(MicroInstruction instruction)
        {
            TridentF2 tf2 = (TridentF2)instruction.F2;

            switch (tf2)
            {
            case TridentF2.EMPTY:
                return("EMPTY ");

            case TridentF2.KTAG:
                return("KTAG<- ");

            case TridentF2.ReadKDTA:
                return("<-KDTA ");

            case TridentF2.RESET:
                return("RESET ");

            case TridentF2.STATUS:
                return("STATUS ");

            case TridentF2.WAIT:
            case TridentF2.WAIT2:
                return("WAIT ");

            case TridentF2.WriteKDTA:
                return("KDTA<- ");

            default:
                return(String.Format("Trident F2 {0}", Conversion.ToOctal((int)tf2)));
            }
        }
Exemple #8
0
            protected override void ExecuteSpecialFunction1(MicroInstruction instruction)
            {
                EthernetF1 ef1 = (EthernetF1)instruction.F1;

                switch (ef1)
                {
                case EthernetF1.EILFCT:
                    // Nothing; handled in Early handler.
                    break;

                case EthernetF1.EPFCT:
                    // Post Function. Gates interface status to BUS[8-15]. Resets the interface at
                    // the end of the cycle and removes wakeup for this task.
                    _busData &= _ethernetController.Status;
                    _ethernetController.ResetInterface();
                    _wakeup = false;
                    Log.Write(LogComponent.EthernetController, "EPFCT: Status {0}, bus now {1}",
                              Conversion.ToOctal(_ethernetController.Status),
                              Conversion.ToOctal(_busData));
                    break;

                case EthernetF1.EWFCT:
                    // Countdown Wakeup Function. Sets a flip flop in the interface that will
                    // cause a wakeup to the Ether task on the next tick of SWAKMRT. This
                    // function must be issued in the instruction after a TASK. The resulting
                    // wakeup is cleared when the Ether task next runs.
                    Log.Write(LogComponent.EthernetController, "Enabling countdown wakeups.");
                    _ethernetController.CountdownWakeup = true;
                    break;

                default:
                    throw new NotImplementedException(String.Format("Unimplemented Ethernet F1 {0}", ef1));
                }
            }
Exemple #9
0
            protected override ushort GetBusSource(MicroInstruction instruction)
            {
                //
                // The Trident tasks are wired to be RAM-enabled tasks so they can use
                // S registers.
                // This code is stolen from the Emulator task; we should REALLY refactor this
                // since both this and the Orbit Task need it.
                //
                EmulatorBusSource ebs = (EmulatorBusSource)instruction.BS;

                switch (ebs)
                {
                case EmulatorBusSource.ReadSLocation:
                    if (instruction.RSELECT != 0)
                    {
                        return(_cpu._s[_rb][instruction.RSELECT]);
                    }
                    else
                    {
                        // "...when reading data from the S registers onto the processor bus,
                        //  the RSELECT value 0 causes the current value of the M register to
                        //  appear on the bus..."
                        return(_cpu._m);
                    }

                case EmulatorBusSource.LoadSLocation:
                    // "When an S register is being loaded from M, the processor bus receives an
                    // undefined value rather than being set to zero."
                    _loadS = true;
                    return(0xffff);          // Technically this is an "undefined value," we're defining it as -1.

                default:
                    throw new InvalidOperationException(String.Format("Unhandled bus source {0}", instruction.BS));
                }
            }
Exemple #10
0
            protected override void ExecuteSpecialFunction2(MicroInstruction instruction)
            {
                TridentF2 tf2 = (TridentF2)instruction.F2;

                switch (tf2)
                {
                case TridentF2.KTAG:
                    _tridentController.TagInstruction(_busData);
                    break;

                case TridentF2.WriteKDTA:
                    _tridentController.KDTA = _busData;
                    break;

                case TridentF2.WAIT:
                case TridentF2.WAIT2:
                    // Identical to BLOCK
                    this.BlockTask();
                    break;

                case TridentF2.RESET:
                    _tridentController.ControllerReset();
                    break;

                case TridentF2.STATUS:
                case TridentF2.EMPTY:
                    // Handled in PostBusSource override.
                    break;

                default:
                    throw new InvalidOperationException(String.Format("Unhandled trident special function 2 {0}", tf2));
                }
            }
Exemple #11
0
        private static string DisassembleEmulatorSpecialFunction1(MicroInstruction instruction)
        {
            EmulatorF1 ef1 = (EmulatorF1)instruction.F1;

            switch (ef1)
            {
            case EmulatorF1.SWMODE:
                return("SWMODE ");

            case EmulatorF1.WRTRAM:
                return("WRTRAM ");

            case EmulatorF1.RDRAM:
                return("RDRAM ");

            case EmulatorF1.LoadRMR:
                return("RMR← ");

            case EmulatorF1.LoadESRB:
                return("ESRB← ");

            case EmulatorF1.RSNF:
                return("RSNF ");

            case EmulatorF1.STARTF:
                return("STARTF ");

            default:
                return(String.Format("F1 {0}", Conversion.ToOctal((int)ef1)));
            }
        }
Exemple #12
0
        private static string DisassembleEmulatorSpecialFunction2(MicroInstruction instruction)
        {
            EmulatorF2 ef2 = (EmulatorF2)instruction.F2;

            switch (ef2)
            {
            case EmulatorF2.ACDEST:
                return("ACDEST ");

            case EmulatorF2.ACSOURCE:
                return("ACSOURCE ");

            case EmulatorF2.MAGIC:
                return("MAGIC ");

            case EmulatorF2.LoadDNS:
                return("DNS← ");

            case EmulatorF2.BUSODD:
                return("BUSODD ");

            case EmulatorF2.LoadIR:
                return("IR← ");

            case EmulatorF2.IDISP:
                return("IDISP ");

            default:
                return(String.Format("F2 {0}", Conversion.ToOctal((int)ef2)));
            }
        }
Exemple #13
0
            protected override void ExecuteSpecialFunction1Early(MicroInstruction instruction)
            {
                OrbitF1 of1 = (OrbitF1)instruction.F1;

                switch (of1)
                {
                case OrbitF1.OrbitDeltaWC:
                    _busData &= _cpu._system.OrbitController.GetDeltaWC();
                    break;

                case OrbitF1.OrbitDBCWidthRead:
                    _busData &= _cpu._system.OrbitController.GetDBCWidth();
                    break;

                case OrbitF1.OrbitOutputData:
                    _busData &= _cpu._system.OrbitController.GetOutputDataAlto();
                    break;

                case OrbitF1.OrbitStatus:
                    _busData &= _cpu._system.OrbitController.GetOrbitStatus();

                    // branch:
                    // "OrbitStatus sets NEXT[7] of IACS os *not* on, i.e. if Orbit is
                    //  not in a character segment."
                    //
                    if (!_cpu._system.OrbitController.IACS)
                    {
                        _nextModifier |= 0x4;
                    }
                    break;
                }
            }
Exemple #14
0
            protected override void ExecuteSpecialFunction2Early(MicroInstruction instruction)
            {
                EmulatorF2 ef2 = (EmulatorF2)instruction.F2;

                switch (ef2)
                {
                case EmulatorF2.ACSOURCE:
                    // Early: modify R select field:
                    // "...it replaces the two-low order bits of the R select field with
                    // the complement of the SrcAC field of IR, (IR[1-2] XOR 3), allowing the emulator
                    // to address its accumulators (which are assigned to R0-R3)."
                    _rSelect = (_rSelect & 0xfffc) | ((((uint)_cpu._ir & 0x6000) >> 13) ^ 3);
                    break;

                case EmulatorF2.ACDEST:
                // "...causes (IR[3-4] XOR 3) to be used as the low-order two bits of the RSELECT field.
                // This address the accumulators from the destination field of the instruction.  The selected
                // register may be loaded or read."
                case EmulatorF2.LoadDNS:
                    //
                    // "...DNS also addresses R from (3-IR[3 - 4])..."
                    //
                    _rSelect = (_rSelect & 0xfffc) | ((((uint)_cpu._ir & 0x1800) >> 11) ^ 3);
                    break;
                }
            }
Exemple #15
0
        private static string DisassembleSpecialFunction2(MicroInstruction instruction, TaskType task)
        {
            switch (task)
            {
            case TaskType.Emulator:
                return(DisassembleEmulatorSpecialFunction2(instruction));

            default:
                return(String.Format("F2 {0}", Conversion.ToOctal((int)instruction.F2)));
            }
        }
Exemple #16
0
            /// <summary>
            /// Executes a single microinstruction.
            /// </summary>
            /// <returns>An InstructionCompletion indicating whether this instruction calls for a task switch or not.</returns>
            public InstructionCompletion ExecuteNext()
            {
                MicroInstruction instruction = UCodeMemory.GetInstruction(_mpc, _taskType);

                /*
                 * if (_taskType == TaskType.Emulator && UCodeMemory.GetBank(_taskType) == MicrocodeBank.RAM0)
                 * {
                 *  Console.WriteLine("{0}: {1}", Conversion.ToOctal(_mpc), UCodeDisassembler.DisassembleInstruction(instruction, _taskType));
                 * }*/

                return(ExecuteInstruction(instruction));
            }
Exemple #17
0
        private static string DisassembleBusSource(MicroInstruction instruction, TaskType task, out bool loadS)
        {
            switch (task)
            {
            case TaskType.Emulator:
                return(DisassembleEmulatorBusSource(instruction, out loadS));

            default:
                loadS = false;
                return(String.Format("BS {0}", Conversion.ToOctal((int)instruction.BS)));
            }
        }
Exemple #18
0
            protected override void ExecuteSpecialFunction1(MicroInstruction instruction)
            {
                DiskF1 df1 = (DiskF1)instruction.F1;

                switch (df1)
                {
                case DiskF1.LoadKDATA:
                    // "The KDATA register is loaded from BUS[0-15]."
                    _diskController.KDATA = _busData;
                    break;

                case DiskF1.LoadKADR:
                    // "This causes the KADR register to be loaded from BUS[8-14].
                    //  in addition, it causes the head address bit to be loaded from KDATA[13]."
                    // (the latter is done by DiskController)
                    _diskController.KADR = (ushort)((_busData & 0xff));
                    break;

                case DiskF1.LoadKCOMM:
                    _diskController.KCOM = (ushort)((_busData & 0x7c00) >> 10);
                    break;

                case DiskF1.CLRSTAT:
                    _diskController.ClearStatus();
                    break;

                case DiskF1.INCRECNO:
                    _diskController.IncrementRecord();
                    break;

                case DiskF1.LoadKSTAT:
                    // "KSTAT[12-15] are loaded from BUS[12-15].  (Actually BUS[13] is ORed onto
                    //  KSTAT[13].)"

                    // From the schematic (and ucode source, based on the values it actually uses for BUS[13]), BUS[13]
                    // is also inverted.  So there's that, too.

                    // build BUS[12-15] with bit 13 flipped.
                    int modifiedBusData = (_busData & 0xb) | ((~_busData) & 0x4);

                    // OR in BUS[12-15] after masking in KSTAT[13] so it is ORed in properly.
                    _diskController.KSTAT = (ushort)(((_diskController.KSTAT & 0xfff4)) | modifiedBusData);
                    break;

                case DiskF1.STROBE:
                    _diskController.Strobe();
                    break;

                default:
                    throw new InvalidOperationException(String.Format("Unhandled disk special function 1 {0}", df1));
                }
            }
Exemple #19
0
            protected override void ExecuteSpecialFunction1Early(MicroInstruction instruction)
            {
                EthernetF1 ef1 = (EthernetF1)instruction.F1;

                switch (ef1)
                {
                case EthernetF1.EILFCT:
                    // Early: Input Look Function. Gates the contents of the FIFO to BUS[0-15] but does
                    // not increment the read pointer.
                    _busData &= _ethernetController.ReadInputFifo(true /* do not increment read pointer */);
                    break;
                }
            }
Exemple #20
0
            protected override InstructionCompletion ExecuteInstruction(MicroInstruction instruction)
            {
                // The Ethernet task only remains awake if there are pending data wakeups
                if (_ethernetController.CountdownWakeup)
                {
                    //
                    // The resulting [Countdown] wakeup is cleared when the Ether task next runs.
                    _ethernetController.CountdownWakeup = false;
                    _wakeup = false;
                }

                return(base.ExecuteInstruction(instruction));
            }
Exemple #21
0
            protected override void ExecuteSpecialFunction2(MicroInstruction instruction)
            {
                DisplayWordF2 dw2 = (DisplayWordF2)instruction.F2;

                switch (dw2)
                {
                case DisplayWordF2.LoadDDR:
                    _displayController.LoadDDR(_busData);
                    break;

                default:
                    throw new InvalidOperationException(String.Format("Unhandled display word F2 {0}.", dw2));
                }
            }
Exemple #22
0
            protected override void ExecuteSpecialFunction2(MicroInstruction instruction)
            {
                DisplayVerticalF2 dv2 = (DisplayVerticalF2)instruction.F2;

                switch (dv2)
                {
                case DisplayVerticalF2.EVENFIELD:
                    _nextModifier |= (ushort)(_displayController.EVENFIELD ? 1 : 0);
                    break;

                default:
                    throw new InvalidOperationException(String.Format("Unhandled display vertical F2 {0}.", dv2));
                }
            }
Exemple #23
0
            protected override ushort GetBusSource(MicroInstruction instruction)
            {
                EthernetBusSource ebs = (EthernetBusSource)instruction.BS;

                switch (ebs)
                {
                case EthernetBusSource.EIDFCT:
                    // Input Data Function. Gates the contents of the FIFO to BUS[0-15], and
                    // increments the read pointer at the end of the cycle.
                    return(_ethernetController.ReadInputFifo(false /* increment read pointer */));

                default:
                    throw new NotImplementedException(String.Format("Unimplemented Ethernet BS {0}", ebs));
                }
            }
Exemple #24
0
            protected override ushort GetBusSource(MicroInstruction instruction)
            {
                DiskBusSource dbs = (DiskBusSource)instruction.BS;

                switch (dbs)
                {
                case DiskBusSource.ReadKSTAT:
                    return(_diskController.KSTAT);

                case DiskBusSource.ReadKDATA:
                    return(_diskController.KDATA);

                default:
                    throw new InvalidOperationException(String.Format("Unhandled bus source {0}", instruction.BS));
                }
            }
Exemple #25
0
            protected override void ExecuteSpecialFunction2(MicroInstruction instruction)
            {
                OrbitF2 of2 = (OrbitF2)instruction.F2;

                switch (of2)
                {
                case OrbitF2.OrbitDBCWidthSet:
                    _cpu._system.OrbitController.SetDBCWidth(_busData);
                    break;

                case OrbitF2.OrbitXY:
                    _cpu._system.OrbitController.SetXY(_busData);
                    break;

                case OrbitF2.OrbitHeight:
                    _cpu._system.OrbitController.SetHeight(_busData);

                    // branch:
                    // "OrbitHeight sets NEXT[7] if the refresh timer has expired, i.e.
                    //  if the image buffer needs refreshing."
                    //
                    if (_cpu._system.OrbitController.RefreshTimerExpired)
                    {
                        _nextModifier |= 0x4;
                    }
                    break;

                case OrbitF2.OrbitFontData:
                    _cpu._system.OrbitController.WriteFontData(_busData);
                    break;

                case OrbitF2.OrbitInk:
                    _cpu._system.OrbitController.WriteInkData(_busData);
                    break;

                case OrbitF2.OrbitControl:
                    _cpu._system.OrbitController.Control(_busData);
                    break;

                case OrbitF2.OrbitROSCommand:
                    _cpu._system.OrbitController.SendROSCommand(_busData);
                    break;

                default:
                    throw new InvalidOperationException(String.Format("Unhandled orbit F2 {0}.", of2));
                }
            }
Exemple #26
0
            protected override void ExecuteSpecialFunction1Early(MicroInstruction instruction)
            {
                EmulatorF1 ef1 = (EmulatorF1)instruction.F1;

                switch (ef1)
                {
                case EmulatorF1.RSNF:
                    //
                    // Early:
                    // "...decoded by the Ethernet interface, which gates the host address wired on the
                    // backplane onto BUS[8-15].  BUS[0-7] is not driven and will therefore be -1.  If
                    // no Ethernet interface is present, BUS will be -1.
                    //
                    _busData &= (ushort)((0xff00 | _cpu._system.EthernetController.Address));
                    break;
                }
            }
Exemple #27
0
            protected override void ExecuteSpecialFunction2(MicroInstruction instruction)
            {
                CursorF2 cf2 = (CursorF2)instruction.F2;

                switch (cf2)
                {
                case CursorF2.LoadXPREG:
                    // Load cursor X-position register from bus
                    _cpu._system.DisplayController.LoadXPREG(_busData);
                    break;

                case CursorF2.LoadCSR:
                    // Load cursor shift register from bus
                    _cpu._system.DisplayController.LoadCSR(_busData);
                    break;

                default:
                    throw new InvalidOperationException(String.Format("Unhandled cursor F2 {0}.", cf2));
                }
            }
Exemple #28
0
        private static string DisassembleOrbitSpecialFunction1(MicroInstruction instruction)
        {
            OrbitF1 of1 = (OrbitF1)instruction.F1;

            switch (of1)
            {
            case OrbitF1.OrbitBlock:
                return("OrbitBlock ");

            case OrbitF1.OrbitDeltaWC:
                return("<-OrbitDeltaWC ");

            case OrbitF1.OrbitDBCWidthRead:
                return("<-OrbitDBCWidthRead ");

            case OrbitF1.OrbitStatus:
                return("<-OrbitStatus ");

            default:
                return(String.Format("Orbit F1 {0}", Conversion.ToOctal((int)of1)));
            }
        }
Exemple #29
0
        private static void Init()
        {
            //
            // Max 3 banks of microcode RAM
            _uCodeRam = new UInt32[1024 * 3];

            if (Configuration.SystemType == SystemType.AltoI)
            {
                LoadAltoIMicrocode(_uCodeRomsAltoI);
            }
            else
            {
                LoadAltoIIMicrocode(_uCodeRomsAltoII);
            }

            //
            // Cache 5k of instructions: max 2K ROM, 3K RAM.
            _decodeCache = new MicroInstruction[1024 * 5];

            // Precache ROM
            CacheMicrocodeROM();

            // Precache (empty) RAM
            for (ushort i = 0; i < _uCodeRam.Length; i++)
            {
                UpdateRAMCache(i);
            }

            // Start in ROM0
            _microcodeBank = new MicrocodeBank[16];
            _ramAddr       = 0;
            _ramBank       = 0;
            _ramSelect     = true;
            _lowHalfsel    = true;

            // Cache the system type from the configuration
            _systemType = Configuration.SystemType;
        }
Exemple #30
0
            protected override void ExecuteSpecialFunction2(MicroInstruction instruction)
            {
                DiskF2 df2 = (DiskF2)instruction.F2;

                switch (df2)
                {
                case DiskF2.INIT:
                    _nextModifier |= GetInitModifier();
                    break;

                case DiskF2.RWC:
                    // "NEXT<-NEXT OR (IF current record to be written THEN 3 ELSE IF
                    // current record to be checked THEN 2 ELSE 0.")
                    // Current record is in bits 8-9 of the command register; this is shifted
                    // by INCREC by the microcode to present the next set of bits.
                    int command = (_diskController.KADR & 0x00c0) >> 6;

                    _nextModifier |= GetInitModifier();

                    switch (command)
                    {
                    case 0:
                        // read, no modification.
                        break;

                    case 1:
                        // check, OR in 2
                        _nextModifier |= 0x2;
                        break;

                    case 2:
                    case 3:
                        // write, OR in 3
                        _nextModifier |= 0x3;
                        break;
                    }
                    break;

                case DiskF2.XFRDAT:
                    // "NEXT <- NEXT OR (IF current command wants data transfer THEN 1 ELSE 0)
                    _nextModifier |= GetInitModifier();

                    if (_diskController.DataXfer)
                    {
                        _nextModifier |= 0x1;
                    }
                    break;

                case DiskF2.RECNO:
                    _nextModifier |= GetInitModifier();
                    _nextModifier |= _diskController.RECNO;
                    break;

                case DiskF2.NFER:
                    // "NEXT <- NEXT OR (IF fatal error in latches THEN 0 ELSE 1)"
                    _nextModifier |= GetInitModifier();

                    if (!_diskController.FatalError)
                    {
                        _nextModifier |= 0x1;
                    }
                    break;

                case DiskF2.STROBON:
                    // "NEXT <- NEXT OR (IF seek strobe still on THEN 1 ELSE 0)"
                    _nextModifier |= GetInitModifier();
                    if ((_diskController.KSTAT & DiskController.STROBE) != 0)
                    {
                        _nextModifier |= 0x1;
                    }
                    break;

                case DiskF2.SWRNRDY:
                    // "NEXT <- NEXT OR (IF disk not ready to accept command THEN 1 ELSE 0)
                    _nextModifier |= GetInitModifier();
                    if (!_diskController.Ready)
                    {
                        _nextModifier |= 0x1;
                    }
                    break;

                default:
                    throw new InvalidOperationException(String.Format("Unhandled disk special function 2 {0}", df2));
                }
            }