From 7704bca35d69a04694906165269a3b7efac030e6 Mon Sep 17 00:00:00 2001 From: Josh Dersch Date: Tue, 6 Sep 2016 12:48:33 -0700 Subject: [PATCH] Cleanup of ugly Shifter code, a few tweaks to task-switch logic (now only calls OnTaskSwitch if a switch actually occurred), and moved back to .NET framework 4.5.2 (from 4.6) which works better on Mono. --- Contralto/App.config | 10 +- Contralto/CPU/CPU.cs | 25 ++-- Contralto/CPU/Shifter.cs | 196 +++++++++++----------------- Contralto/CPU/Tasks/EmulatorTask.cs | 7 +- Contralto/CPU/Tasks/Task.cs | 12 +- Contralto/Contralto.csproj | 6 +- Contralto/Logging/Log.cs | 2 +- 7 files changed, 110 insertions(+), 148 deletions(-) diff --git a/Contralto/App.config b/Contralto/App.config index d226eef..2c94bf2 100644 --- a/Contralto/App.config +++ b/Contralto/App.config @@ -6,10 +6,10 @@ - + - + @@ -17,16 +17,16 @@ 2 - + - + 34 - + 0 diff --git a/Contralto/CPU/CPU.cs b/Contralto/CPU/CPU.cs index dd0a6e4..f8e949f 100644 --- a/Contralto/CPU/CPU.cs +++ b/Contralto/CPU/CPU.cs @@ -130,10 +130,10 @@ namespace Contralto.CPU } // Execute the initial task switch. + _currentTask = null; TaskSwitch(); - _currentTask = _nextTask; - _nextTask = null; + _currentTask = _nextTask; } public void Clock() @@ -146,14 +146,14 @@ namespace Contralto.CPU TaskSwitch(); break; - case InstructionCompletion.Normal: - if (_nextTask != null) + case InstructionCompletion.Normal: + // If we have a new task, switch to it now. + if (_currentTask != _nextTask) { - // If we have a new task, switch to it now. _currentTask = _nextTask; - _nextTask = null; - _currentTask.OnTaskSwitch(); - } + _currentTask.FirstInstructionAfterSwitch = true; + _currentTask.OnTaskSwitch(); + } break; case InstructionCompletion.MemoryWait: @@ -180,7 +180,7 @@ namespace Contralto.CPU _tasks[i].SoftReset(); } } - + Log.Write(LogComponent.CPU, "Silent Boot; microcode banks initialized to {0}", Conversion.ToOctal(_rmr)); UCodeMemory.LoadBanksFromRMR(_rmr); @@ -251,14 +251,13 @@ namespace Contralto.CPU } private void TaskSwitch() - { + { // Select the highest-priority eligible task for (int i = _tasks.Length - 1; i >= 0; i--) { if (_tasks[i] != null && _tasks[i].Wakeup) { - _nextTask = _tasks[i]; - _nextTask.FirstInstructionAfterSwitch = true; + _nextTask = _tasks[i]; /* if (_nextTask != _currentTask && _currentTask != null) @@ -286,7 +285,7 @@ namespace Contralto.CPU private ushort _aluC0; // RMR (Reset Mode Register) - ushort _rmr; + ushort _rmr; // Task data private Task _nextTask; // The task to switch two after the next microinstruction diff --git a/Contralto/CPU/Shifter.cs b/Contralto/CPU/Shifter.cs index 293bd5e..323d52d 100644 --- a/Contralto/CPU/Shifter.cs +++ b/Contralto/CPU/Shifter.cs @@ -24,8 +24,14 @@ namespace Contralto.CPU None, ShiftLeft, ShiftRight, - RotateLeft, - RotateRight, + RotateLeft, + } + + public enum ShifterModifier + { + None, + Magic, + DNS, } // NOTE: FOR NOVA (NOVEL) SHIFTS (from aug '76 manual): @@ -43,11 +49,9 @@ namespace Contralto.CPU public static void Reset() { - _op = ShifterOp.None; - _count = 0; + _op = ShifterOp.None; _output = 0; - _magic = false; - _dns = false; + _modifier = ShifterModifier.None; _dnsCarry = 0; } @@ -66,50 +70,39 @@ namespace Contralto.CPU } /// - /// Returns the last DNS-style Carry bit from the last operation (via DoOperation). + /// Returns the last DNS-style Carry bit from the last operation (via DoOperation), + /// or sets the carry-in for the next DNS-style shift. /// public static int DNSCarry { get { return _dnsCarry; } - } - - public static void SetOperation(ShifterOp op, int count) - { - _op = op; - _count = count; - } - - /// - /// TODO: this is kind of clumsy. - /// - /// - public static void SetMagic(bool magic) - { - _magic = magic; - } - - /// - /// TODO: this is still kind of clumsy. - /// - /// - public static void SetDNS(bool dns, int carry) - { - // Sanity check - if (carry != 0 && carry != 1) + set { - throw new InvalidOperationException("carry can only be 0 or 1."); + // Sanity check + if (value != 0 && value != 1) + { + throw new InvalidOperationException("Invalid DNSCarry value."); + } + _dnsCarry = value; } - - _dns = dns; - _dnsCarry = carry; } + public static void SetOperation(ShifterOp op) + { + _op = op; + } + + public static void SetModifier(ShifterModifier mod) + { + _modifier = mod; + } + /// - /// Does the last specified operation to the specified inputs; the result + /// Does the last specified operation to the specified inputs; the result /// can be read from Output. /// /// Normal input to be shifted - /// CPU t register, for MAGIC shifts only + /// CPU t register, used for MAGIC shifts only public static ushort DoOperation(ushort input, ushort t) { switch(_op) @@ -119,98 +112,65 @@ namespace Contralto.CPU break; case ShifterOp.ShiftLeft: - _output = (ushort)(input << _count); + _output = (ushort)(input << 1); - if (_magic) + switch (_modifier) { - // "MAGIC places the high order bit of T into the low order bit of the - // shifter output on left shifts..." - _output |= (ushort)((t & 0x8000) >> 15); + case ShifterModifier.Magic: + // "MAGIC places the high order bit of T into the low order bit of the + // shifter output on left shifts..." + _output |= (ushort)((t & 0x8000) >> 15); + break; - if (_count != 1) - { - throw new NotImplementedException("magic LCY 8 not implemented yet."); - } - } - else if (_dns) - { - // - // "Rotate the 17 input bits left by one bit. This has the effect of rotating - // bit 0 left into the carry position and the carry bit into bit 15." - // - - // Put input carry into bit 15. - _output = (ushort)(_output | _dnsCarry); - - // update carry - _dnsCarry = ((input & 0x8000) >> 15); + case ShifterModifier.DNS: + // + // "Rotate the 17 input bits left by one bit. This has the effect of rotating + // bit 0 left into the carry position and the carry bit into bit 15." + // + + // Put input carry into bit 15. + _output |= (ushort)(_dnsCarry); + + // update carry + _dnsCarry = ((input & 0x8000) >> 15); + break; } + break; case ShifterOp.ShiftRight: - _output = (ushort)(input >> _count); + _output = (ushort)(input >> 1); - if (_magic) + switch (_modifier) { - // "...and places the low order bit of T into the high order bit position - // of the shifter output on right shifts." - _output |= (ushort)((t & 0x1) << 15); + case ShifterModifier.Magic: + _output |= (ushort)((t & 0x1) << 15); + break; - if (_count != 1) - { - throw new NotImplementedException("magic LCY 8 not implemented yet."); - } - } - else if (_dns) - { - // - // "Rotate the 17 bits right by one bit. Bit 15 is rotated into the carry position - // and the carry bit into bit 0." - // + case ShifterModifier.DNS: + // + // "Rotate the 17 bits right by one bit. Bit 15 is rotated into the carry position + // and the carry bit into bit 0." + // - // Put input carry into bit 0. - _output |= (ushort)(_output | (_dnsCarry << 15)); + // Put input carry into bit 0. + _output |= (ushort)(_dnsCarry << 15); - // update carry - _dnsCarry = input & 0x1; + // update carry + _dnsCarry = input & 0x1; + break; } break; - case ShifterOp.RotateLeft: - if (_dns) - { - // - // "Swap the 8-bit halves of the 16-bit result. The carry is not affected." - // - _output = (ushort)(((input & 0xff00) >> 8) | ((input & 0x00ff) << 8)); - } - else - { - // TODO: optimize, this is stupid - _output = input; - for (int i = 0; i < _count; i++) - { - int c = (_output & 0x8000) >> 15; - _output = (ushort)((_output << 1) | c); - } - } - break; - - case ShifterOp.RotateRight: - // TODO: optimize, this is still stupid - _output = input; - for (int i = 0; i < _count; i++) - { - int c = (_output & 0x1) << 15; - _output = (ushort)((_output >> 1) | c); - } - - if (_dns) - { - // Should never happen - throw new InvalidOperationException("DNS on Rotate Right, not possible."); - } - break; + case ShifterOp.RotateLeft: + // + // "Swap the 8-bit halves of the 16-bit result. The carry is not affected." + // NOTE: The hardware reference (Section 2) seems to indicate that L LCY 8 is modified by MAGIC and/or DNS, + // but this does not appear to actually be the case. Nothing in the documentation elsewhere, the microcode, + // or the schematics indicates that L LCY 8 ever does anything other than a simple swap. + // + _output = (ushort)(((input & 0xff00) >> 8) | ((input & 0x00ff) << 8)); + break; default: throw new InvalidOperationException(String.Format("Unhandled shift operation {0}", _op)); @@ -220,10 +180,8 @@ namespace Contralto.CPU } private static ShifterOp _op; - private static ushort _output; - private static int _count; - private static bool _magic; - private static bool _dns; + private static ushort _output; + private static ShifterModifier _modifier; private static int _dnsCarry; } } diff --git a/Contralto/CPU/Tasks/EmulatorTask.cs b/Contralto/CPU/Tasks/EmulatorTask.cs index 826035b..67866fc 100644 --- a/Contralto/CPU/Tasks/EmulatorTask.cs +++ b/Contralto/CPU/Tasks/EmulatorTask.cs @@ -302,7 +302,7 @@ namespace Contralto.CPU break; case EmulatorF2.MAGIC: - Shifter.SetMagic(true); + Shifter.SetModifier(ShifterModifier.Magic); break; case EmulatorF2.LoadDNS: @@ -361,11 +361,12 @@ namespace Contralto.CPU carry = (~carry) & 0x1; } break; - } + } // Tell the Shifter to do a Nova-style shift with the // given carry bit. - Shifter.SetDNS(true, carry); + Shifter.SetModifier(ShifterModifier.DNS); + Shifter.DNSCarry = carry; break; diff --git a/Contralto/CPU/Tasks/Task.cs b/Contralto/CPU/Tasks/Task.cs index e72b41b..0b520c5 100644 --- a/Contralto/CPU/Tasks/Task.cs +++ b/Contralto/CPU/Tasks/Task.cs @@ -202,7 +202,9 @@ namespace Contralto.CPU break; case BusSource.ReadMouse: - _busData = _cpu._system.Mouse.PollMouseBits(); + // "BUS[12-15]<-MOUSE; BUS[0-13]<- -1" + // (Note -- BUS[0-13] appears to be a typo, and should likely be BUS[0-11]). + _busData = (ushort)(_cpu._system.Mouse.PollMouseBits() | 0xfff0); break; case BusSource.ReadDisp: @@ -338,15 +340,15 @@ namespace Contralto.CPU break; case SpecialFunction1.LLSH1: - Shifter.SetOperation(ShifterOp.ShiftLeft, 1); + Shifter.SetOperation(ShifterOp.ShiftLeft); break; case SpecialFunction1.LRSH1: - Shifter.SetOperation(ShifterOp.ShiftRight, 1); + Shifter.SetOperation(ShifterOp.ShiftRight); break; case SpecialFunction1.LLCY8: - Shifter.SetOperation(ShifterOp.RotateLeft, 8); + Shifter.SetOperation(ShifterOp.RotateLeft); break; case SpecialFunction1.Constant: @@ -518,7 +520,7 @@ namespace Contralto.CPU // if (swMode) { - //Log.Write(LogType.Verbose, LogComponent.Microcode, "SWMODE: uPC {0}, next uPC {1} (NEXT is {2})", Conversion.ToOctal(_mpc), Conversion.ToOctal(instruction.NEXT | nextModifier), Conversion.ToOctal(instruction.NEXT)); + Log.Write(LogType.Verbose, LogComponent.Microcode, "SWMODE: uPC {0}, next uPC {1} (NEXT is {2})", Conversion.ToOctal(_mpc), Conversion.ToOctal(instruction.NEXT | nextModifier), Conversion.ToOctal(instruction.NEXT)); UCodeMemory.SwitchMode((ushort)(instruction.NEXT | nextModifier), _taskType); } diff --git a/Contralto/Contralto.csproj b/Contralto/Contralto.csproj index 220f110..845ffea 100644 --- a/Contralto/Contralto.csproj +++ b/Contralto/Contralto.csproj @@ -9,7 +9,7 @@ Properties Contralto Contralto - v4.6 + v4.5.2 512 publish\ true @@ -208,7 +208,9 @@ - + + Designer + PreserveNewest diff --git a/Contralto/Logging/Log.cs b/Contralto/Logging/Log.cs index c5df200..a931bd6 100644 --- a/Contralto/Logging/Log.cs +++ b/Contralto/Logging/Log.cs @@ -74,7 +74,7 @@ namespace Contralto.Logging { // TODO: make configurable _components = LogComponent.None; // LogComponent.HostNetworkInterface | LogComponent.EthernetPacket; // | LogComponent.HostEthernet | LogComponent.EthernetController; // LogComponent.DiskController | LogComponent.DiskSectorTask | LogComponent.Debug | LogComponent.CPU; // LogComponent.EthernetController; // | LogComponent.Microcode | LogComponent.Memory | LogComponent.CPU; - _type = LogType.None; // LogType.Normal | LogType.Warning | LogType.Error | LogType.Verbose; + _type = LogType.Normal | LogType.Warning | LogType.Error | LogType.Verbose; //_logStream = new StreamWriter("log.txt"); }