From 1170927105f6e866300fc1d9ac684e6a1c6ecb56 Mon Sep 17 00:00:00 2001 From: jnosek Date: Wed, 15 Jul 2015 14:54:27 -0400 Subject: [PATCH] Added new SinglePrecision class Needed to organize SinglePrecision code in preparation for DoublePrecision operations --- AGC/AGC.csproj | 2 + AGC/Base/DoublePrecision.cs | 11 +++ AGC/Base/ErasableMemory.cs | 10 ++- AGC/Base/FixedMemory.cs | 5 +- AGC/Base/OnesCompliment.cs | 92 +++++++++++++++++-------- AGC/Base/SinglePrecision.cs | 52 ++++++++++++++ AGC/Instructions/Augment.cs | 8 +-- AGC/Instructions/CountCompareAndSkip.cs | 13 ++-- AGC/Registers/Accumulator.cs | 10 +-- AGC/Registers/CycleRightRegister.cs | 9 ++- 10 files changed, 157 insertions(+), 55 deletions(-) create mode 100644 AGC/Base/DoublePrecision.cs create mode 100644 AGC/Base/SinglePrecision.cs diff --git a/AGC/AGC.csproj b/AGC/AGC.csproj index 93fd596..07743e2 100644 --- a/AGC/AGC.csproj +++ b/AGC/AGC.csproj @@ -37,11 +37,13 @@ + + diff --git a/AGC/Base/DoublePrecision.cs b/AGC/Base/DoublePrecision.cs new file mode 100644 index 0000000..56fa503 --- /dev/null +++ b/AGC/Base/DoublePrecision.cs @@ -0,0 +1,11 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Apollo.Virtual.AGC.Base +{ + public class DoublePrecision + { + } +} diff --git a/AGC/Base/ErasableMemory.cs b/AGC/Base/ErasableMemory.cs index 0a39fbb..6646930 100644 --- a/AGC/Base/ErasableMemory.cs +++ b/AGC/Base/ErasableMemory.cs @@ -17,12 +17,18 @@ public ErasableMemory(ushort address, MemoryBank bank) public void Write(ushort value) { - Set(value.OverflowCorrect()); + var v = new OnesCompliment(value); + v.OverflowCorrect(); + + Set(v); } public ushort Read() { - return Get().SignExtend(); + var v = new OnesCompliment(Get()); + v.SignExtend(); + + return v; } } } diff --git a/AGC/Base/FixedMemory.cs b/AGC/Base/FixedMemory.cs index a01da44..d243993 100644 --- a/AGC/Base/FixedMemory.cs +++ b/AGC/Base/FixedMemory.cs @@ -22,7 +22,10 @@ public void Write(ushort value) public ushort Read() { - return Get().SignExtend(); + var v = new OnesCompliment(Get()); + v.SignExtend(); + + return v; } } } diff --git a/AGC/Base/OnesCompliment.cs b/AGC/Base/OnesCompliment.cs index 485c07c..f472961 100644 --- a/AGC/Base/OnesCompliment.cs +++ b/AGC/Base/OnesCompliment.cs @@ -5,18 +5,64 @@ namespace Apollo.Virtual.AGC.Base { - public static class OnesCompliment + public class OnesCompliment { public const ushort NegativeZero = 0xFFFF; public const ushort PositiveOne = 0x0001; public const ushort NegativeOne = 0xFFFE; + public ushort Value { get; protected set; } + + public OnesCompliment(ushort v) + { + Value = v; + } + + public OnesCompliment(int v) + { + Value = ConvertToOnesCompliment(v); + } + + public bool IsNegativeZero { + get + { + return Value == NegativeZero; + } + } + + public bool IsPositiveZero + { + get + { + return Value == 0; + } + } + + public bool IsNegative + { + get + { + return (Value & 0x8000) > 0; + } + } + + /// + /// Automatically return ushort value for OnesCompliment value + /// + /// + /// + public static implicit operator ushort(OnesCompliment a) + { + return a.Value; + } + + /// /// Mainly used for converting 2's compliment negative numbers into Ones Compliment values /// /// 2's Compliment Value (normal .net value) /// Ones Compliment coded value - public static ushort ToOnesCompliment(this int value) + protected static ushort ConvertToOnesCompliment(int value) { // if this is negative, // return the 14 lower bits of the 1's compliment of the positive value @@ -31,36 +77,14 @@ public static ushort ToOnesCompliment(this int value) return (ushort)value; } - /// - /// - /// - /// - /// - /// - public static ushort Add(this ushort left, ushort right) - { - var sum = left + right; - - // if we have overflow, most likely from subtracting negative numbers - if ((sum & 0x10000) > 0) - { - // we need to ones compliment correct the negative number by adding 1 and taking the lower 16 bits - // this process is called "end around carry" - sum = sum + 1; - sum = sum & 0xFFFF; - } - - return (ushort)sum; - } - /// /// Performs overflow correction on a 16bit value, converting it to a 15 bit value /// /// /// - public static ushort OverflowCorrect(this ushort value) + public void OverflowCorrect() { - uint newValue = value; + uint newValue = Value; // get lower 14 bits uint lowerBits = newValue & 0x3FFF; @@ -68,7 +92,7 @@ public static ushort OverflowCorrect(this ushort value) // move 16-th bit, into 15th position, isolate it, and set it in above value; newValue = (newValue >> 1 & 0x4000) | lowerBits; - return (ushort)newValue; + Value = (ushort)newValue; } /// @@ -76,9 +100,9 @@ public static ushort OverflowCorrect(this ushort value) /// /// /// - public static ushort SignExtend(this ushort value) + public void SignExtend() { - uint newValue = value; + uint newValue = Value; // take lower 15-bits newValue = newValue & 0x7FFF; @@ -86,7 +110,15 @@ public static ushort SignExtend(this ushort value) // shift left 1 and take 16th bit, combine with lower 15 bits newValue = ((newValue << 1) & 0x8000) | newValue; - return (ushort)newValue; + Value = (ushort)newValue; + } + } + + public static class OnesComplimentHelpers + { + public static OnesCompliment ToOnesCompliment(this int v) + { + return new OnesCompliment(v); } } } diff --git a/AGC/Base/SinglePrecision.cs b/AGC/Base/SinglePrecision.cs new file mode 100644 index 0000000..ec15d06 --- /dev/null +++ b/AGC/Base/SinglePrecision.cs @@ -0,0 +1,52 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Apollo.Virtual.AGC.Base +{ + public class SinglePrecision : OnesCompliment + { + public SinglePrecision(ushort v) + : base(v) + { + } + + public SinglePrecision(int v) + : base(v) + { + } + + /// + /// Single Precision Addition + /// + /// left operand + /// right operand + /// + public static SinglePrecision operator +(SinglePrecision left, OnesCompliment right) + { + var sum = left.Value + right.Value; + + // if we have overflow, most likely from subtracting negative numbers + if ((sum & 0x10000) > 0) + { + // we need to ones compliment correct the negative number by adding 1 and taking the lower 16 bits + // this process is called "end around carry" + sum = sum + 1; + sum = sum & 0xFFFF; + } + + return new SinglePrecision(sum); + } + + public static SinglePrecision operator +(SinglePrecision left, ushort right) + { + return left + new SinglePrecision(right); + } + + public static SinglePrecision operator ~(SinglePrecision a) + { + return new SinglePrecision((ushort)~a.Value); + } + } +} diff --git a/AGC/Instructions/Augment.cs b/AGC/Instructions/Augment.cs index 39ff3ee..98f5777 100644 --- a/AGC/Instructions/Augment.cs +++ b/AGC/Instructions/Augment.cs @@ -22,17 +22,17 @@ public ushort Code public void Execute(ushort K) { - var value = CPU.Memory[K]; + var value = new SinglePrecision(CPU.Memory[K]); // if negative - if((value & 0x8000) > 0) + if(value.IsNegative) { - CPU.Memory[K] = value.Add(OnesCompliment.NegativeOne); + CPU.Memory[K] = value + OnesCompliment.NegativeOne; } // if positive else { - CPU.Memory[K] = value.Add(OnesCompliment.PositiveOne); + CPU.Memory[K] = value + OnesCompliment.PositiveOne; } } } diff --git a/AGC/Instructions/CountCompareAndSkip.cs b/AGC/Instructions/CountCompareAndSkip.cs index ee8fe24..022bf8f 100644 --- a/AGC/Instructions/CountCompareAndSkip.cs +++ b/AGC/Instructions/CountCompareAndSkip.cs @@ -23,16 +23,15 @@ public ushort Code public void Execute(ushort K) { // retrieve value from memory - var value = CPU.Memory[K]; + var value = new SinglePrecision(CPU.Memory[K]); // 1) compute the Diminished ABSolute value found at K and set in A // if negative, NOT 1's to get ABS - var isNegative = (value & 0x8000) > 0; - var abs = (ushort)(isNegative ? ~value : value); + var abs = value.IsNegative ? ~value : value; if (abs > 1) - CPU.A.Write(abs.Add(OnesCompliment.NegativeOne)); + CPU.A.Write(abs + OnesCompliment.NegativeOne); else CPU.A.Write(0); @@ -44,17 +43,17 @@ public void Execute(ushort K) // if greater than +0 we do nothing, continue to next instruction as usual // if == +0 increment by 1 - if (value == 0) + if (value.IsPositiveZero) CPU.Z.Increment(); // if == -0 increment by 3 - else if(value == OnesCompliment.NegativeZero) + else if(value.IsNegativeZero) { CPU.Z.Increment(); CPU.Z.Increment(); CPU.Z.Increment(); } // if < 0 increment by 2 - else if (isNegative) + else if (value.IsNegative) { CPU.Z.Increment(); CPU.Z.Increment(); diff --git a/AGC/Registers/Accumulator.cs b/AGC/Registers/Accumulator.cs index c30501f..4fc3103 100644 --- a/AGC/Registers/Accumulator.cs +++ b/AGC/Registers/Accumulator.cs @@ -15,15 +15,7 @@ public Accumulator(MemoryBank bank) public void Add(ushort value) { - uint sum = Get().Add(value); - - // if we have overflow, most likely from subtracting negative numbers - if((sum & 0x10000) > 0) - { - // we need to Single Precision correct the negative number by adding 1 and taking the lower 16 bits - sum = sum + 1; - sum = sum & 0xFFFF; - } + var sum = new SinglePrecision(value) + Get(); Set(sum); } diff --git a/AGC/Registers/CycleRightRegister.cs b/AGC/Registers/CycleRightRegister.cs index a91f43c..da1fb45 100644 --- a/AGC/Registers/CycleRightRegister.cs +++ b/AGC/Registers/CycleRightRegister.cs @@ -15,13 +15,18 @@ public CycleRightRegister(MemoryBank bank) public ushort Read() { - return Get().SignExtend(); + var v = new OnesCompliment(Get()); + v.SignExtend(); + return v; } public void Write(ushort value) { // first overflow correct the value - value = value.OverflowCorrect(); + var v = new OnesCompliment(value); + v.OverflowCorrect(); + + value = v; // get bit position 1, and move it to position 15 var leastSignificateBit = (value & 0x1) << 14;