diff --git a/Contralto/AltoSystem.cs b/Contralto/AltoSystem.cs index c262144..d2f6418 100644 --- a/Contralto/AltoSystem.cs +++ b/Contralto/AltoSystem.cs @@ -47,7 +47,7 @@ namespace Contralto t.AutoReset = true; t.Interval = 1000; t.Elapsed += T_Elapsed; - //t.Start(); + t.Start(); } public void Reset() diff --git a/Contralto/CPU/CPU.cs b/Contralto/CPU/CPU.cs index 80b5898..5e71484 100644 --- a/Contralto/CPU/CPU.cs +++ b/Contralto/CPU/CPU.cs @@ -121,18 +121,28 @@ namespace Contralto.CPU public void Clock() { - if (_currentTask.ExecuteNext()) + switch (_currentTask.ExecuteNext()) { - // Invoke the task switch, this will take effect after - // the NEXT instruction, not this one. - TaskSwitch(); + case InstructionCompletion.TaskSwitch: + // Invoke the task switch, this will take effect after + // the NEXT instruction completes, not this one. + TaskSwitch(); + break; + + case InstructionCompletion.Normal: + if (_nextTask != null) + { + // If we have a new task, switch to it now. + _currentTask = _nextTask; + _nextTask = null; + } + break; + + case InstructionCompletion.MemoryWait: + // We were waiting for memory on this cycle, we do nothing + // (no task switch even if one is pending) in this case. + break; } - else if (_nextTask != null) - { - // If we have a new task, switch to it now. - _currentTask = _nextTask; - _nextTask = null; - } } /// diff --git a/Contralto/CPU/Tasks/CursorTask.cs b/Contralto/CPU/Tasks/CursorTask.cs index d3748a1..4d73647 100644 --- a/Contralto/CPU/Tasks/CursorTask.cs +++ b/Contralto/CPU/Tasks/CursorTask.cs @@ -15,7 +15,7 @@ namespace Contralto.CPU _wakeup = false; } - protected override bool ExecuteInstruction(MicroInstruction instruction) + protected override InstructionCompletion ExecuteInstruction(MicroInstruction instruction) { // We put ourselves back to sleep immediately once we've started running _wakeup = false; diff --git a/Contralto/CPU/Tasks/DiskTask.cs b/Contralto/CPU/Tasks/DiskTask.cs index 9b1eb8b..ecb2b61 100644 --- a/Contralto/CPU/Tasks/DiskTask.cs +++ b/Contralto/CPU/Tasks/DiskTask.cs @@ -21,11 +21,11 @@ namespace Contralto.CPU _diskController = _cpu._system.DiskController; } - protected override bool ExecuteInstruction(MicroInstruction instruction) + protected override InstructionCompletion ExecuteInstruction(MicroInstruction instruction) { // Log.Write(LogComponent.Debug, "{0}: {1}", Conversion.ToOctal(_mpc), UCodeDisassembler.DisassembleInstruction(instruction, _taskType)); - bool task = base.ExecuteInstruction(instruction); + InstructionCompletion completion = base.ExecuteInstruction(instruction); // Deal with SECLATE semantics: If the Disk Sector task wakes up and runs before // the Disk Controller hits the SECLATE trigger time, then SECLATE remains false. @@ -37,7 +37,7 @@ namespace Contralto.CPU _diskController.DisableSeclate(); } - return task; + return completion; } protected override ushort GetBusSource(int bs) diff --git a/Contralto/CPU/Tasks/DisplayHorizontalTask.cs b/Contralto/CPU/Tasks/DisplayHorizontalTask.cs index 790f9ac..bc39f0a 100644 --- a/Contralto/CPU/Tasks/DisplayHorizontalTask.cs +++ b/Contralto/CPU/Tasks/DisplayHorizontalTask.cs @@ -18,7 +18,7 @@ namespace Contralto.CPU _displayController = _cpu._system.DisplayController; } - protected override bool ExecuteInstruction(MicroInstruction instruction) + protected override InstructionCompletion ExecuteInstruction(MicroInstruction instruction) { // We put ourselves back to sleep immediately once we've started running _wakeup = false; diff --git a/Contralto/CPU/Tasks/DisplayVerticalTask.cs b/Contralto/CPU/Tasks/DisplayVerticalTask.cs index b4d73f4..6047fa5 100644 --- a/Contralto/CPU/Tasks/DisplayVerticalTask.cs +++ b/Contralto/CPU/Tasks/DisplayVerticalTask.cs @@ -18,7 +18,7 @@ namespace Contralto.CPU _displayController = _cpu._system.DisplayController; } - protected override bool ExecuteInstruction(MicroInstruction instruction) + protected override InstructionCompletion ExecuteInstruction(MicroInstruction instruction) { // We put ourselves back to sleep immediately once we've started running _wakeup = false; diff --git a/Contralto/CPU/Tasks/DisplayWordTask.cs b/Contralto/CPU/Tasks/DisplayWordTask.cs index 89b7163..42095e0 100644 --- a/Contralto/CPU/Tasks/DisplayWordTask.cs +++ b/Contralto/CPU/Tasks/DisplayWordTask.cs @@ -19,7 +19,7 @@ namespace Contralto.CPU _displayController = _cpu._system.DisplayController; } - protected override bool ExecuteInstruction(MicroInstruction instruction) + protected override InstructionCompletion ExecuteInstruction(MicroInstruction instruction) { // We remove our wakeup only if there isn't a wakeup being generated for us by the // display controller. diff --git a/Contralto/CPU/Tasks/EthernetTask.cs b/Contralto/CPU/Tasks/EthernetTask.cs index 4dcd34c..6c0cd55 100644 --- a/Contralto/CPU/Tasks/EthernetTask.cs +++ b/Contralto/CPU/Tasks/EthernetTask.cs @@ -19,7 +19,7 @@ namespace Contralto.CPU _ethernetController = _cpu._system.EthernetController; } - protected override bool ExecuteInstruction(MicroInstruction instruction) + protected override InstructionCompletion ExecuteInstruction(MicroInstruction instruction) { // The Ethernet task only remains awake if there are pending data wakeups if (_ethernetController.CountdownWakeup) diff --git a/Contralto/CPU/Tasks/MemoryRefreshTask.cs b/Contralto/CPU/Tasks/MemoryRefreshTask.cs index d00348b..d4e7968 100644 --- a/Contralto/CPU/Tasks/MemoryRefreshTask.cs +++ b/Contralto/CPU/Tasks/MemoryRefreshTask.cs @@ -14,7 +14,7 @@ _wakeup = false; } - protected override bool ExecuteInstruction(MicroInstruction instruction) + protected override InstructionCompletion ExecuteInstruction(MicroInstruction instruction) { // // Based on readings of the MRT microcode, the MRT keeps its wakeup diff --git a/Contralto/CPU/Tasks/Task.cs b/Contralto/CPU/Tasks/Task.cs index 2e3e395..53beb52 100644 --- a/Contralto/CPU/Tasks/Task.cs +++ b/Contralto/CPU/Tasks/Task.cs @@ -7,6 +7,13 @@ namespace Contralto.CPU { public partial class AltoCPU { + public enum InstructionCompletion + { + Normal, + TaskSwitch, + MemoryWait, + } + // Task: // Base task class: provides implementation for non-task-specific microcode execution and // state. Task subclasses implement and execute Task-specific behavior and are called into @@ -92,7 +99,7 @@ namespace Contralto.CPU _wakeup = true; } - public bool ExecuteNext() + public InstructionCompletion ExecuteNext() { MicroInstruction instruction = UCodeMemory.GetInstruction(_mpc, _taskType); @@ -108,9 +115,9 @@ namespace Contralto.CPU /// provide their own overrides. /// /// True if a task switch has been requested by a TASK instruction, false otherwise. - protected virtual bool ExecuteInstruction(MicroInstruction instruction) + protected virtual InstructionCompletion ExecuteInstruction(MicroInstruction instruction) { - bool nextTask = false; + InstructionCompletion completion = InstructionCompletion.Normal; bool swMode = false; bool block = false; ushort aluData; @@ -135,7 +142,7 @@ namespace Contralto.CPU if (!_cpu._system.MemoryBus.Ready(instruction.MemoryOperation)) { // Suspend operation for this cycle. - return false; + return InstructionCompletion.MemoryWait; } } @@ -290,7 +297,8 @@ namespace Contralto.CPU // //if (!_firstInstructionAfterSwitch) { - nextTask = true; // Yield to other more important tasks + // Yield to other more important tasks + completion = InstructionCompletion.TaskSwitch; } break; @@ -430,7 +438,12 @@ namespace Contralto.CPU if (instruction.LoadL) { _cpu._l = aluData; - _cpu._m = aluData; + + // Only RAM-related tasks can modify M. (Currently only the Emulator.) + if (_taskType == TaskType.Emulator) + { + _cpu._m = aluData; + } // Save ALUC0 for use in the next ALUCY special function. _cpu._aluC0 = (ushort)ALU.Carry; @@ -470,7 +483,7 @@ namespace Contralto.CPU } _firstInstructionAfterSwitch = false; - return nextTask; + return completion; } protected virtual ushort GetBusSource(int bs) diff --git a/Contralto/Disk/Josh.dsk b/Contralto/Disk/Josh.dsk index 9ab1408..791a29d 100644 Binary files a/Contralto/Disk/Josh.dsk and b/Contralto/Disk/Josh.dsk differ diff --git a/Contralto/Disk/allgames.dsk b/Contralto/Disk/allgames.dsk index 7aabfb6..6e412a8 100644 Binary files a/Contralto/Disk/allgames.dsk and b/Contralto/Disk/allgames.dsk differ diff --git a/Contralto/Disk/bravox.dsk b/Contralto/Disk/bravox.dsk index b723972..4c390ac 100644 Binary files a/Contralto/Disk/bravox.dsk and b/Contralto/Disk/bravox.dsk differ diff --git a/Contralto/Disk/diag.dsk b/Contralto/Disk/diag.dsk index 1736cd9..f88bce1 100644 Binary files a/Contralto/Disk/diag.dsk and b/Contralto/Disk/diag.dsk differ diff --git a/Contralto/Disk/st76boot.dsk b/Contralto/Disk/st76boot.dsk index a87c2f5..ef56fbd 100644 Binary files a/Contralto/Disk/st76boot.dsk and b/Contralto/Disk/st76boot.dsk differ diff --git a/Contralto/Disk/st76new.dsk b/Contralto/Disk/st76new.dsk index a47b8cc..e386c02 100644 Binary files a/Contralto/Disk/st76new.dsk and b/Contralto/Disk/st76new.dsk differ diff --git a/Contralto/Disk/xmsmall.dsk b/Contralto/Disk/xmsmall.dsk index 6333a39..0e644fa 100644 Binary files a/Contralto/Disk/xmsmall.dsk and b/Contralto/Disk/xmsmall.dsk differ diff --git a/Contralto/IO/DiskController.cs b/Contralto/IO/DiskController.cs index 4b0eb26..6c5245e 100644 --- a/Contralto/IO/DiskController.cs +++ b/Contralto/IO/DiskController.cs @@ -609,7 +609,8 @@ namespace Contralto.IO // From the Hardware Manual, pg 43: // "Seek time (approx.): 15 + 8.6 * sqrt(dt) (msec) // - double seekTimeMsec = 15.0 + 8.6 * Math.Sqrt(dt); + //double seekTimeMsec = 15.0 + 8.6 * Math.Sqrt(dt); + double seekTimeMsec = 1.0; // why not just have this be fast for now. return (ulong)(seekTimeMsec * Conversion.MsecToNsec); } diff --git a/Contralto/UI/Debugger.cs b/Contralto/UI/Debugger.cs index f46bfd6..42c2227 100644 --- a/Contralto/UI/Debugger.cs +++ b/Contralto/UI/Debugger.cs @@ -808,6 +808,7 @@ namespace Contralto case ExecutionType.NextNovaInstruction: // For debugging floating point microcode: +#if FLOAT_DEBUG if (_system.CPU.CurrentTask.MPC == 0x10) // MPC is 20(octal) meaning a new Nova instruction. { if (_lastFPInstruction == 0) @@ -823,7 +824,8 @@ namespace Contralto // And see if this new one is also a floating point instruction... FloatDebugPre(_system.MemoryBus.DebugReadWord(TaskType.Emulator, _system.CPU.R[6])); } - } + } +#endif // See if we need to stop here if (_execAbort || // The Stop button was hit @@ -855,6 +857,7 @@ namespace Contralto return false; } +#if FLOAT_DEBUG // vars for float debug ushort _lastFPInstruction; ushort _ac0; @@ -864,6 +867,8 @@ namespace Contralto ushort _fpRegAddr; ushort _fpRegCount; + int _fpInstructionCount; + /// /// Temporary, for debugging floating point ucode issues /// @@ -874,6 +879,8 @@ namespace Contralto // Float instructions are from 70001-70022 octal if (instruction >= 0x7000 && instruction <= 0x7012) { + _fpInstructionCount++; + // Save instruction _lastFPInstruction = instruction; @@ -883,7 +890,7 @@ namespace Contralto _ac2 = _system.CPU.R[1]; _ac3 = _system.CPU.R[0]; - Console.Write("FP: "); + Console.Write("{0}:FP: ", _fpInstructionCount); switch (instruction) { case 0x7000: @@ -967,7 +974,7 @@ namespace Contralto case 0x7012: Console.WriteLine("FEXP {0},{1} ({2})", _ac0, _ac1, GetFloat(_ac0)); break; - } + } /* Console.WriteLine(" AC0={0} AC1={1} AC2={2} AC3={3}", @@ -979,9 +986,9 @@ namespace Contralto } private void FloatDebugPost() - { + { - Console.Write("Post: "); + Console.Write("{0}:Post: ", _fpInstructionCount); switch (_lastFPInstruction) { case 0x7000: @@ -1142,23 +1149,24 @@ namespace Contralto uint mantissa = (uint)(_system.MemoryBus.DebugReadWord(TaskType.Emulator, (ushort)(addr + 2)) << 16) | (uint)(_system.MemoryBus.DebugReadWord(TaskType.Emulator, (ushort)(addr + 3))); - - double val = 0.0; + + double valMantissa = 0.0; for (int i = 0; i < 32; i++) { double bit = (mantissa & (0x80000000 >> i)) != 0 ? 1.0 : 0.0; - val += (bit * (1.0 / Math.Pow(2.0, (double)i))); + valMantissa += (bit * (1.0 / Math.Pow(2.0, (double)i))); } - val = sign * (val) * Math.Pow(2.0, exponent - 1); + double val = sign * (valMantissa) * Math.Pow(2.0, exponent - 1); - if (double.IsInfinity(val) || double.IsNaN(val)) + //if (double.IsInfinity(val) || double.IsNaN(val)) { - Console.WriteLine(" ERROR: sign {0} exp {1} mantissa {2:x} value {3}", + Console.WriteLine(" Vec: sign {0} exp {1} mantissa {2:x} ({3}) value {4}", sign, exponent, mantissa, + valMantissa, val); } @@ -1199,28 +1207,29 @@ namespace Contralto (uint)(_system.MemoryBus.DebugReadWord(TaskType.Emulator, (ushort)(reg + 2 * _fpRegCount)) << 16) | (uint)(_system.MemoryBus.DebugReadWord(TaskType.Emulator, (ushort)(reg + 3 * _fpRegCount))); - double val = 0.0; + double valMantissa = 0.0; for (int i = 0; i < 32; i++) { double bit = (mantissa & (0x80000000 >> i)) != 0 ? 1.0 : 0.0; - val += (bit * (1.0 / Math.Pow(2.0, (double)i))); + valMantissa += (bit * (1.0 / Math.Pow(2.0, (double)i))); } - val = sign * (val) * Math.Pow(2.0, exponent - 1); + double val = sign * (valMantissa) * Math.Pow(2.0, exponent - 1); - if (double.IsInfinity(val) || double.IsNaN(val)) + //if (double.IsInfinity(val) || double.IsNaN(val)) { - Console.WriteLine(" ERROR: sign {0} exp {1} mantissa {2:x} value {3}", + Console.WriteLine(" UCode: sign {0} exp {1} mantissa {2:x} ({3}) value {4}", sign, exponent, mantissa, + valMantissa, val); } return val; } - +#endif private void SetExecutionState(ExecutionState state) { _execState = state; @@ -1343,8 +1352,8 @@ namespace Contralto private bool[] _novaBreakpointEnabled; private void HackButton_Click(object sender, EventArgs e) - { - Logging.Log.LogComponents |= Logging.LogComponent.TaskSwitch; + { + //_system.CPU.HAX = true; Log.Write(Logging.LogComponent.Debug, "***** HACK HIT ******"); } }