From 4cbb74c03352b70b83069d7490587f09022f9835 Mon Sep 17 00:00:00 2001 From: Josh Dersch Date: Wed, 9 Mar 2016 16:05:45 -0800 Subject: [PATCH] Fixed two microcode bugs related to task switching behavior. Dance, StarWars and *SMALLTALK* work! --- Contralto/AltoSystem.cs | 2 +- Contralto/CPU/CPU.cs | 30 ++++++++---- Contralto/CPU/Tasks/CursorTask.cs | 2 +- Contralto/CPU/Tasks/DiskTask.cs | 6 +-- Contralto/CPU/Tasks/DisplayHorizontalTask.cs | 2 +- Contralto/CPU/Tasks/DisplayVerticalTask.cs | 2 +- Contralto/CPU/Tasks/DisplayWordTask.cs | 2 +- Contralto/CPU/Tasks/EthernetTask.cs | 2 +- Contralto/CPU/Tasks/MemoryRefreshTask.cs | 2 +- Contralto/CPU/Tasks/Task.cs | 27 ++++++++--- Contralto/Disk/Josh.dsk | Bin 2601648 -> 2601648 bytes Contralto/Disk/allgames.dsk | Bin 2601648 -> 2601648 bytes Contralto/Disk/bravox.dsk | Bin 2601648 -> 2601648 bytes Contralto/Disk/diag.dsk | Bin 2601648 -> 2601648 bytes Contralto/Disk/st76boot.dsk | Bin 2601648 -> 2601648 bytes Contralto/Disk/st76new.dsk | Bin 2601648 -> 2601648 bytes Contralto/Disk/xmsmall.dsk | Bin 2601648 -> 2601648 bytes Contralto/IO/DiskController.cs | 3 +- Contralto/UI/Debugger.cs | 47 +++++++++++-------- 19 files changed, 80 insertions(+), 47 deletions(-) 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 9ab14089215c7edf8f3e7e6d6fe827d7c14dbf13..791a29d8d8ac19359508e1c9e57a3de572bf0373 100644 GIT binary patch delta 180 zcmWl~xfOyy6hKk<;wUI6DB=dVu~c9kmN2~#ka|eSs9`cIvJW1?J=gpP+f3df%Id$J zsv9k>78}zuIG96WfhAmcSYZtx0XEnoM1&poh;cxIBThKuf-6#F$Z^9R4?OWgf%2!N G`j`=I4lm#U delta 180 zcmWl~Hx$e^ zk2FN&7b#IDrb3k(bs98j(WXO}gdTkc3>h(I!ju_v7A#q@X2X^pdk!2qebaEhWq))= BFY5pR diff --git a/Contralto/Disk/allgames.dsk b/Contralto/Disk/allgames.dsk index 7aabfb65911c914212acbd75aa75b1fd38678d0a..6e412a82f0949b8b8727ab0337e408b8bb73a9fc 100644 GIT binary patch delta 33564 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 diff --git a/Contralto/Disk/bravox.dsk b/Contralto/Disk/bravox.dsk index b723972b22a0ecd91f248f5ea2a36dbaadbe8ef5..4c390acb0bf84a61bffad1edee29f145e4d99c41 100644 GIT binary patch delta 356 zcmXZUze@sf7{~GN^S%3e-c?tg+SQr;GCM4Ymau3j7lUYMP=b^il9pPWTZ9N9XmYr% zKcGe7f@f;!Kad(+gPemJS{nLj4X@#W=kxCL@2NAeCe3Xj#88-*H)V>1Pe(~feeQZH zM&bK$)g=46P~$?4a$U0dVncrP$l;2uy(CN*>j97R8I2@4!B$pF@!L6lQnTo5T=ezZ zufNq!lzyjeV}}s8_?Ri=XedkfPnH z%PW4|QivR!s delta 339 zcmW;Fze@sf7zXfrzjt5tuC%VS?96^>c1aK|VNKy;i$jA)q!LJ;OODPVLY=ML5V$Agrh4<1?4 zB>$`4)Twn=ZgaU!#SyjmWJ~P*+ zDa6Hnxvr5raB31F5QP}%V89rRLmUz?0h3_D6ih=BQZNIvkcK(1AOrJ|g#}oIC0K?W PNx&nyvCnNqEQp0PAQ~UP%vdg)b!bb7FmFWFiWsA7A`;}aCZ?R z1Oy8^+bK+IATQzY6bBBR^>Lxrn9kHk=*v^Czx6_9>xF-haaTnCnVn<(sG36;S-qk! z;)o(5W9dAPy2Gc&=w*=X`GK|&F@d(vjhKjLqQyV8Y(x=590^>&K@u7%Tq2E(IkmEz z_rzyJO#A_o^&xW*0gDBu=Flu*VU?oq)5s;HrEng{Rg`wzMx BUq%1` delta 264 zcmWm7KT85}9LMqR&(2HDyE6ZsrTHhjQE*oXauGo#X=v*i)X>r<7~CU}+p3{CM1tRA zXiEqL2RGLnbT#lTA71d;-jmgvnqc^;6NiW(iWrU%hXotQI6(rZ zdfiM;-(x>vkvgHk@ShfmYyZPAyIy0NL<(tSkcERB&Tx)A3b;TKC6rOYC91g6jivki Fw*%4OWBdRB diff --git a/Contralto/Disk/st76boot.dsk b/Contralto/Disk/st76boot.dsk index a87c2f59bb752ebc230c1a5d2f33dcb775424c4e..ef56fbd487563384329d97e088cec27a6dc4fea7 100644 GIT binary patch delta 2479 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 Aod5s; delta 257 zcmXxazfQtX7>4nFr?m*wmi|LT1w=oiv5Bh;T!FLk0vLqLXyQpn@4&?n)+U6Usf$kC zA;B~xUAzQ#Urjpvl4p3*pLa_CM8YaRrqjyuLA*YZv&^2q*5oB|L?Bcg>5nDG{H3zk zT85xNecQ&ZAUn}r0}hn#n%PY~)HLm%%17p%K|!(~n^1#8sH^?BasNq2lADq($p~Ar zBe^BnmF%t9pA}S7Z-pNUnk4g`4*`VGhGXc!33TBU&fpw+(1!tBzz{Cs3Rul|*Uil@ DZI);i diff --git a/Contralto/Disk/xmsmall.dsk b/Contralto/Disk/xmsmall.dsk index 6333a3980977be5c9972a2bbf76088cf331995b5..0e644fa52b234e0ecb75e599ef6c7ac7d3136707 100644 GIT binary patch delta 224 zcmW;5Ne;nK0D$55o*HUaQ?4k0x0lP}-( zd6Cy&%ayyE?JhOBIQd@adouPtwR-4tA;f=td?~36Q%DFAh+usP_M2@GpWo^u!zfWq zQDd4JW|^bTJPRzc#4;~p{&M|3#mgwr@mX3qT!IJsrC delta 222 zcmW;5I}X8M0KoC@`_!YJ^(tD_qbvp;dWY`LpraVXY%p}`*6L z$@40cU(1u*o9(SM>6`;U3VfLczFI%@u@K@vJ-w7vhAAY3*o$y;JcPUS@>U-i#hGG` y8uKi$$P#sySz(nm*4d!JCR=Q?!!Aws*yn&2Z4No&m<}hLa>hAbF48z#y7w

ttO3 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 ******"); } }