Skip to content

Commit

Permalink
Added Double Precision DAS Instruction
Browse files Browse the repository at this point in the history
  • Loading branch information
jnosek committed Jul 16, 2015
1 parent fd6f1a9 commit b4f55a6
Show file tree
Hide file tree
Showing 8 changed files with 188 additions and 0 deletions.
1 change: 1 addition & 0 deletions AGC/AGC.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
<Compile Include="Instructions\ClearAndAdd.cs" />
<Compile Include="Instructions\ClearAndSubtract.cs" />
<Compile Include="Instructions\CountCompareAndSkip.cs" />
<Compile Include="Instructions\DoubleAddToStorage.cs" />
<Compile Include="Instructions\QuarterCode5.cs" />
<Compile Include="Instructions\TransferToStorage.cs" />
<Compile Include="Registers\CycleRightRegister.cs" />
Expand Down
33 changes: 33 additions & 0 deletions AGC/Base/DoublePrecision.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

/// <summary>
/// Double Precision Addition
/// </summary>
/// <param name="left">left operand</param>
/// <param name="right">right operand</param>
/// <returns></returns>
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);
}
}
}
1 change: 1 addition & 0 deletions AGC/Base/OnesCompliment.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
16 changes: 16 additions & 0 deletions AGC/Base/SinglePrecision.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,22 @@ public SinglePrecision(int v)
{
}

public bool IsPositiveOverflow
{
get
{
return (Value & 0xC000) == 0x4000;
}
}

public bool IsNegativeOverflow
{
get
{
return (Value & 0xC000) == 0x8000;
}
}

/// <summary>
/// Single Precision Addition
/// </summary>
Expand Down
52 changes: 52 additions & 0 deletions AGC/Instructions/DoubleAddToStorage.cs
Original file line number Diff line number Diff line change
@@ -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
{
/// <summary>
/// DAS - 0010 00
/// QuarterCode Instruction
///
/// A double-precision (DP) add of the A,L register pair to a pair of variables in erasable memory
/// </summary>
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);
}
}
}
1 change: 1 addition & 0 deletions AGC/Instructions/QuarterCode2.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ class QuarterCode2 : ExtraInstructionList
{
public QuarterCode2(Processor cpu) : base(cpu, 3)
{
Add(new DoubleAddToStorage());
Add(new AddToStorage());
}

Expand Down
1 change: 1 addition & 0 deletions Tests/AGC.Tests/AGC.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@
<Compile Include="Instructions\ClearAndAdd.cs" />
<Compile Include="Instructions\ClearAndSubtract.cs" />
<Compile Include="Instructions\CountCompareAndSkip.cs" />
<Compile Include="Instructions\DoubleAddToStorage.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Registers\CycleRightRegister.cs" />
</ItemGroup>
Expand Down
83 changes: 83 additions & 0 deletions Tests/AGC.Tests/Instructions/DoubleAddToStorage.cs
Original file line number Diff line number Diff line change
@@ -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]);
}
}
}

0 comments on commit b4f55a6

Please sign in to comment.