diff --git a/AGC/AGC.csproj b/AGC/AGC.csproj
index 07743e2..fb5cf8b 100644
--- a/AGC/AGC.csproj
+++ b/AGC/AGC.csproj
@@ -48,6 +48,7 @@
+
diff --git a/AGC/Base/DoublePrecision.cs b/AGC/Base/DoublePrecision.cs
index 56fa503..e284504 100644
--- a/AGC/Base/DoublePrecision.cs
+++ b/AGC/Base/DoublePrecision.cs
@@ -5,7 +5,40 @@
namespace Apollo.Virtual.AGC.Base
{
+ // https://github.com/rburkey2005/virtualagc/blob/master/yaAGC/agc_engine.c
public class DoublePrecision
{
+ public SinglePrecision MostSignificantWord { get; protected set; }
+ public SinglePrecision LeastSignificantWord { get; protected set; }
+
+ public DoublePrecision(ushort most, ushort least)
+ {
+ MostSignificantWord = new SinglePrecision(most);
+ LeastSignificantWord = new SinglePrecision(least);
+ }
+
+ ///
+ /// Double Precision Addition
+ ///
+ /// left operand
+ /// right operand
+ ///
+ public static DoublePrecision operator +(DoublePrecision left, DoublePrecision right)
+ {
+ // single preceision add the least significant word and most significant word
+ var lsw = left.LeastSignificantWord + right.LeastSignificantWord;
+ var msw = left.MostSignificantWord + right.MostSignificantWord;
+
+ // check for overflow and adjust
+ if (lsw.IsPositiveOverflow)
+ msw += OnesCompliment.PositiveOne;
+ else if (lsw.IsNegativeOverflow)
+ msw += OnesCompliment.NegativeOne;
+
+ lsw.OverflowCorrect();
+
+
+ return new DoublePrecision(msw, lsw);
+ }
}
}
diff --git a/AGC/Base/OnesCompliment.cs b/AGC/Base/OnesCompliment.cs
index f472961..fbf1b7a 100644
--- a/AGC/Base/OnesCompliment.cs
+++ b/AGC/Base/OnesCompliment.cs
@@ -8,6 +8,7 @@ namespace Apollo.Virtual.AGC.Base
public class OnesCompliment
{
public const ushort NegativeZero = 0xFFFF;
+ public const ushort PositiveZero = 0x0000;
public const ushort PositiveOne = 0x0001;
public const ushort NegativeOne = 0xFFFE;
diff --git a/AGC/Base/SinglePrecision.cs b/AGC/Base/SinglePrecision.cs
index ec15d06..91a11fa 100644
--- a/AGC/Base/SinglePrecision.cs
+++ b/AGC/Base/SinglePrecision.cs
@@ -17,6 +17,22 @@ public SinglePrecision(int v)
{
}
+ public bool IsPositiveOverflow
+ {
+ get
+ {
+ return (Value & 0xC000) == 0x4000;
+ }
+ }
+
+ public bool IsNegativeOverflow
+ {
+ get
+ {
+ return (Value & 0xC000) == 0x8000;
+ }
+ }
+
///
/// Single Precision Addition
///
diff --git a/AGC/Instructions/DoubleAddToStorage.cs b/AGC/Instructions/DoubleAddToStorage.cs
new file mode 100644
index 0000000..d3dace7
--- /dev/null
+++ b/AGC/Instructions/DoubleAddToStorage.cs
@@ -0,0 +1,52 @@
+using Apollo.Virtual.AGC.Base;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace Apollo.Virtual.AGC.Instructions
+{
+ ///
+ /// DAS - 0010 00
+ /// QuarterCode Instruction
+ ///
+ /// A double-precision (DP) add of the A,L register pair to a pair of variables in erasable memory
+ ///
+ class DoubleAddToStorage : IInstruction
+ {
+ public ushort Code
+ {
+ get { return 0x00; }
+ }
+
+ public Processor CPU { get; set; }
+
+ public void Execute(ushort K)
+ {
+ // find previous address
+ var K0 = (ushort)(K - 1);
+
+ // read DP values from registers and memroy
+ var dp1 = new DoublePrecision(CPU.A.Read(), CPU.L.Read());
+ var dp2 = new DoublePrecision(CPU.Memory[K0], CPU.Memory[K]);
+
+ // create sum
+ var sum = dp1 + dp2;
+
+ // store result in memory
+ CPU.Memory[K0] = sum.MostSignificantWord;
+ CPU.Memory[K] = sum.LeastSignificantWord;
+
+ // L always cleared to +0
+ CPU.L.Write(OnesCompliment.PositiveZero);
+
+ // A set based upon overflow
+ if(sum.MostSignificantWord.IsPositiveOverflow)
+ CPU.A.Write(OnesCompliment.PositiveOne);
+ else if(sum.MostSignificantWord.IsNegativeOverflow)
+ CPU.A.Write(OnesCompliment.NegativeOne);
+ else
+ CPU.A.Write(OnesCompliment.PositiveZero);
+ }
+ }
+}
diff --git a/AGC/Instructions/QuarterCode2.cs b/AGC/Instructions/QuarterCode2.cs
index d3a6482..1d57b94 100644
--- a/AGC/Instructions/QuarterCode2.cs
+++ b/AGC/Instructions/QuarterCode2.cs
@@ -16,6 +16,7 @@ class QuarterCode2 : ExtraInstructionList
{
public QuarterCode2(Processor cpu) : base(cpu, 3)
{
+ Add(new DoubleAddToStorage());
Add(new AddToStorage());
}
diff --git a/Tests/AGC.Tests/AGC.Tests.csproj b/Tests/AGC.Tests/AGC.Tests.csproj
index f46dbe7..a3db25e 100644
--- a/Tests/AGC.Tests/AGC.Tests.csproj
+++ b/Tests/AGC.Tests/AGC.Tests.csproj
@@ -59,6 +59,7 @@
+
diff --git a/Tests/AGC.Tests/Instructions/DoubleAddToStorage.cs b/Tests/AGC.Tests/Instructions/DoubleAddToStorage.cs
new file mode 100644
index 0000000..5887c7f
--- /dev/null
+++ b/Tests/AGC.Tests/Instructions/DoubleAddToStorage.cs
@@ -0,0 +1,83 @@
+using Apollo.Virtual.AGC.Base;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace AGC.Tests.Instructions
+{
+ [TestClass]
+ public class DoubleAddToStorage : BaseTest
+ {
+ [TestMethod]
+ public void DoubleAddToStorage_LswValue()
+ {
+ // arrange
+ Memory[0x0] = 0x0;
+ Memory[0x1] = OnesCompliment.PositiveOne;
+
+ Memory[0x200] = 0x0;
+ Memory[0x201] = OnesCompliment.PositiveOne;
+
+ Memory.LoadFixedRom(new ushort[] {
+ Instruction(0x02, 0x201)
+ });
+
+ // act
+ CPU.Execute();
+
+ // assert
+ Assert.AreEqual(2, Memory[0x201]);
+ Assert.AreEqual(0, Memory[0x000]);
+ }
+
+ [TestMethod]
+ public void DoubleAddToStorage_LswPositiveOverflow()
+ {
+ // arrange
+ Memory[0x0] = 0x0;
+ Memory[0x1] = 0x3FFF;
+
+ Memory[0x200] = 0x0;
+ Memory[0x201] = OnesCompliment.PositiveOne;
+
+ Memory.LoadFixedRom(new ushort[] {
+ Instruction(0x02, 0x201)
+ });
+
+ // act
+ CPU.Execute();
+
+ // assert
+ Assert.AreEqual(1, Memory[0x200]);
+ Assert.AreEqual(0, Memory[0x201]);
+ Assert.AreEqual(0, Memory[0x000]);
+ }
+
+ [TestMethod]
+ public void DoubleAddToStorage_MswPositiveOverflow()
+ {
+ // arrange
+ Memory[0x0] = 0x3FFF;
+ Memory[0x1] = 0x3FFF;
+
+ Memory[0x200] = 0x0;
+ Memory[0x201] = OnesCompliment.PositiveOne;
+
+ Memory.LoadFixedRom(new ushort[] {
+ Instruction(0x02, 0x201)
+ });
+
+ // act
+ CPU.Execute();
+
+ // assert
+ Assert.AreEqual(0x0000, Memory[0x200]);
+ Assert.AreEqual(0x0000, Memory[0x201]);
+ Assert.AreEqual(OnesCompliment.PositiveOne, Memory[0x000]);
+ Assert.AreEqual(OnesCompliment.PositiveZero, Memory[0x001]);
+ }
+ }
+}