diff --git a/AGC/AGC.csproj b/AGC/AGC.csproj index b3912b5..e16bef8 100644 --- a/AGC/AGC.csproj +++ b/AGC/AGC.csproj @@ -40,6 +40,8 @@ + + diff --git a/AGC/Base/FixedMemory.cs b/AGC/Base/FixedMemory.cs index 7ccbde0..bf88b9c 100644 --- a/AGC/Base/FixedMemory.cs +++ b/AGC/Base/FixedMemory.cs @@ -16,7 +16,7 @@ public FixedMemory(MemoryAddress memory) public void Write(ushort value) { - throw new InvalidOperationException("Cannot write to a fixed memory location"); + //throw new InvalidOperationException("Cannot write to a fixed memory location"); } public ushort Address diff --git a/AGC/ExtraCodeInstructionSet.cs b/AGC/ExtraCodeInstructionSet.cs index df5f226..3acf8ef 100644 --- a/AGC/ExtraCodeInstructionSet.cs +++ b/AGC/ExtraCodeInstructionSet.cs @@ -18,6 +18,7 @@ public ExtraCodeInstructionSet(Processor cpu) Add(new BranchZeroToFixed { CPU = CPU }); Add(new ExtraQuarterCode(CPU)); + Add(new BranchZeroOrMinusToFixed { CPU = CPU }); } public new IInstruction this[ushort code] diff --git a/AGC/InstructionSet.cs b/AGC/InstructionSet.cs index dabd553..559d108 100644 --- a/AGC/InstructionSet.cs +++ b/AGC/InstructionSet.cs @@ -17,7 +17,8 @@ public InstructionSet(Processor cpu) CPU = cpu; Add(new TransferControl { CPU = CPU }); - Add(new QuarterCode { CPU = CPU }); + Add(new QuarterCode(CPU)); + Add(new ClearAndAdd { CPU = CPU }); Add(new Add { CPU = CPU }); } diff --git a/AGC/Instructions/BranchZeroOrMinusToFixed.cs b/AGC/Instructions/BranchZeroOrMinusToFixed.cs new file mode 100644 index 0000000..367f806 --- /dev/null +++ b/AGC/Instructions/BranchZeroOrMinusToFixed.cs @@ -0,0 +1,32 @@ +using Apollo.Virtual.AGC.Base; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Apollo.Virtual.AGC.Instructions +{ + /// + /// BZMF - EX 0110 + /// + /// Jumps to a fixed memory location if the accumulator is 0 or negative + /// + class BranchZeroOrMinusToFixed : IInstruction + { + public ushort Code + { + get { return 0x06; } + } + + public Processor CPU { get; set; } + + public void Execute(ushort K) + { + var value = CPU.A.Read(); + + // if +0 or negative, jump + if (value == 0 || (value & 0x8000) > 0) + CPU.Z.Write(K); + } + } +} diff --git a/AGC/Instructions/BranchZeroToFixed.cs b/AGC/Instructions/BranchZeroToFixed.cs index 73e8787..665d650 100644 --- a/AGC/Instructions/BranchZeroToFixed.cs +++ b/AGC/Instructions/BranchZeroToFixed.cs @@ -9,7 +9,7 @@ namespace Apollo.Virtual.AGC.Instructions /// /// BZF - EX 0001 /// - /// Jumps to a memory location in the fixed bank if the accumulator is 0 + /// Jumps to a fixed memory location if the accumulator is 0 /// class BranchZeroToFixed : IInstruction { @@ -22,7 +22,14 @@ public ushort Code public void Execute(ushort K) { - if (CPU.A.Read() == 0) + // if in overflow, no jump + if(CPU.A.IsOverflow) + return; + + var value = CPU.A.Read(); + + // if +0 or -0, then jump + if (value == 0 || value == SinglePrecision.NegativeZero) CPU.Z.Write(K); } } diff --git a/AGC/Instructions/ClearAndAdd.cs b/AGC/Instructions/ClearAndAdd.cs new file mode 100644 index 0000000..bb560ad --- /dev/null +++ b/AGC/Instructions/ClearAndAdd.cs @@ -0,0 +1,34 @@ +using Apollo.Virtual.AGC.Base; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Apollo.Virtual.AGC.Instructions +{ + /// + /// CA - 0011 + /// + /// Moves the contents of memory at location K into the accumulator + /// + class ClearAndAdd : IInstruction + { + public ushort Code + { + get { return 0x3; } + } + + public Processor CPU { get; set; } + + public void Execute(ushort K) + { + var value = CPU.Memory[K]; + + // set value in accumulator + CPU.A.Write(value); + + // value in K is re-written + CPU.Memory[K] = value; + } + } +} diff --git a/AGC/Instructions/QuarterCode.cs b/AGC/Instructions/QuarterCode.cs index b94006d..f169133 100644 --- a/AGC/Instructions/QuarterCode.cs +++ b/AGC/Instructions/QuarterCode.cs @@ -14,8 +14,10 @@ namespace Apollo.Virtual.AGC.Instructions /// class QuarterCode : InstructionList, IInstruction { - public QuarterCode() : base(3) + public QuarterCode(Processor CPU) : base(3) { + this.CPU = CPU; + Add(new AddToStorage { CPU = this.CPU }); } diff --git a/AGC/Registers/FullRegister.cs b/AGC/Registers/FullRegister.cs index e43ea60..8043219 100644 --- a/AGC/Registers/FullRegister.cs +++ b/AGC/Registers/FullRegister.cs @@ -28,6 +28,17 @@ public ushort Read() return memory.Read(); } + public bool IsOverflow + { + get + { + // look at bits 16 and 15 to see if they are different + var value = (ushort)(Read() & 0xC000); + + return value == 0x8000 || value == 0x4000; + } + } + MemoryAddress IRegister.Memory { set { this.memory = value; } diff --git a/Tests/AGC.Tests/AGC.Tests.csproj b/Tests/AGC.Tests/AGC.Tests.csproj index 2c5144e..c399a66 100644 --- a/Tests/AGC.Tests/AGC.Tests.csproj +++ b/Tests/AGC.Tests/AGC.Tests.csproj @@ -52,7 +52,11 @@ + + + + diff --git a/Tests/AGC.Tests/Instructions/Add.cs b/Tests/AGC.Tests/Instructions/Add.cs index a5fabd2..97323cb 100644 --- a/Tests/AGC.Tests/Instructions/Add.cs +++ b/Tests/AGC.Tests/Instructions/Add.cs @@ -18,13 +18,13 @@ public void AddTwoPositiveNumbers() Memory[0x200] = 10; Memory[0x201] = 15; - // insert add instructions + // insert instructions Memory.LoadFixedRom(new ushort[] { 0x06000 | 0x200, 0x06000 | 0x201 }); - // act - run the additions + // act - run the instructions CPU.Execute(); CPU.Execute(); @@ -39,13 +39,13 @@ public void AddTwoNegativeNumbers() Memory[0x200] = SinglePrecision.To(-10); Memory[0x201] = SinglePrecision.To(-15); - // insert add instructions + // insert instructions Memory.LoadFixedRom(new ushort[] { 0x06000 | 0x200, 0x06000 | 0x201 }); - // act - run the additions + // act - run the instructions CPU.Execute(); CPU.Execute(); @@ -60,13 +60,13 @@ public void AddPostive1AndNegative1() Memory[0x200] = SinglePrecision.To(-10); Memory[0x201] = 15; - // insert add instructions + // insert instructions Memory.LoadFixedRom(new ushort[] { 0x06000 | 0x200, 0x06000 | 0x201 }); - // act - run the additions + // act - run the instructions CPU.Execute(); CPU.Execute(); @@ -81,13 +81,13 @@ public void AddTwoNumbersThatEqualNegativeZero() Memory[0x200] = 0xC000; // most negative number 15 bit number Memory[0x201] = SinglePrecision.To(-1); - // insert add instructions + // insert instructions Memory.LoadFixedRom(new ushort[] { 0x06000 | 0x200, 0x06000 | 0x201 }); - // act - run the additions + // act - run the instructions CPU.Execute(); CPU.Execute(); @@ -105,13 +105,13 @@ public void AddTwoNumbersThatEqualPositiveZero() Memory[0x200] = 0x3FFF; // most positive number 15 bit number Memory[0x201] = 1; - // insert add instructions + // insert instructions Memory.LoadFixedRom(new ushort[] { 0x06000 | 0x200, 0x06000 | 0x201 }); - // act - run the additions + // act - run the instructions CPU.Execute(); CPU.Execute(); @@ -129,13 +129,13 @@ public void AddTwoNegativeNumbersThatCauseUnderflow() Memory[0x200] = 0xC000; // most negative number 15 bit number Memory[0x201] = SinglePrecision.To(-3); - // insert add instructions + // insert instructions Memory.LoadFixedRom(new ushort[] { 0x06000 | 0x200, 0x06000 | 0x201 }); - // act - run the additions + // act - run the instructions CPU.Execute(); CPU.Execute(); @@ -153,13 +153,13 @@ public void AddTwoPositiveNumbersThatCauseOverflow() Memory[0x200] = 0x3FFF; // most positive number 15 bit number Memory[0x201] = 3; - // insert add instructions + // insert instructions Memory.LoadFixedRom(new ushort[] { 0x06000 | 0x200, 0x06000 | 0x201 }); - // act - run the additions + // act - run the instructions CPU.Execute(); CPU.Execute(); @@ -177,13 +177,13 @@ public void AddNegativeZeroAndPositiveNumber() Memory[0x200] = SinglePrecision.NegativeZero; Memory[0x201] = 4; - // insert add instructions + // insert instructions Memory.LoadFixedRom(new ushort[] { 0x06000 | 0x200, 0x06000 | 0x201 }); - // act - run the additions + // act - run the instructions CPU.Execute(); CPU.Execute(); @@ -201,13 +201,13 @@ public void AddNegativeZeroAndNegativeNumber() Memory[0x200] = SinglePrecision.NegativeZero; Memory[0x201] = SinglePrecision.To(-4); - // insert add instructions + // insert instructions Memory.LoadFixedRom(new ushort[] { 0x06000 | 0x200, 0x06000 | 0x201 }); - // act - run the additions + // act - run the instructions CPU.Execute(); CPU.Execute(); @@ -217,5 +217,29 @@ public void AddNegativeZeroAndNegativeNumber() // assert Assert.AreEqual(SinglePrecision.To(-4), Memory[0x202]); } + + [TestMethod] + public void Add1AndNegative1EqualsNegative0() + { + // arrange + Memory[0x200] = 0x01; + Memory[0x201] = SinglePrecision.To(-1); + + // insert instructions + Memory.LoadFixedRom(new ushort[] { + 0x06000 | 0x200, + 0x06000 | 0x201 + }); + + // act - run the instructions + CPU.Execute(); + CPU.Execute(); + + //save acumulator value to a place in memory so we can view the overflow corrected value, for now + Memory[0x202] = Memory[0x0]; + + // assert + Assert.AreEqual(SinglePrecision.NegativeZero, Memory[0x202]); + } } } diff --git a/Tests/AGC.Tests/Instructions/AddToStorage.cs b/Tests/AGC.Tests/Instructions/AddToStorage.cs new file mode 100644 index 0000000..f1811f2 --- /dev/null +++ b/Tests/AGC.Tests/Instructions/AddToStorage.cs @@ -0,0 +1,56 @@ +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 AddToStorage : BaseTest + { + [TestMethod] + public void AddToStorageTwoPositiveNumbers() + { + // arrange + Memory[0x000] = 10; + Memory[0x201] = 15; + + // insert instructions + Memory.LoadFixedRom(new ushort[] { + 0x02C00 | 0x201 + }); + + // act - run the instructions + CPU.Execute(); + CPU.Execute(); + + // assert + Assert.AreEqual(25, Memory[0x0]); + Assert.AreEqual(25, Memory[0x201]); + } + + [TestMethod] + public void AddToStorageTwoNegativeNumbers() + { + // arrange + Memory[0x000] = SinglePrecision.To(-10); + Memory[0x201] = SinglePrecision.To(-15); + + // insert instructions + Memory.LoadFixedRom(new ushort[] { + 0x02C00 | 0x201 + }); + + // act - run the instructions + CPU.Execute(); + CPU.Execute(); + + // assert + Assert.AreEqual(SinglePrecision.To(-25), Memory[0x0]); + Assert.AreEqual(SinglePrecision.To(-25), Memory[0x201]); + } + } +} diff --git a/Tests/AGC.Tests/Instructions/Augment.cs b/Tests/AGC.Tests/Instructions/Augment.cs index 2357539..2e72620 100644 --- a/Tests/AGC.Tests/Instructions/Augment.cs +++ b/Tests/AGC.Tests/Instructions/Augment.cs @@ -17,7 +17,7 @@ public void AugmentPositiveNumber() // arrange Memory[0x200] = 10; - // insert add instructions + // insert instructions Memory.LoadFixedRom(new ushort[] { 0x00006, // EXTEND instruction 0x02800 | 0x200 @@ -37,7 +37,7 @@ public void AugmentNegativeNumber() // arrange Memory[0x200] = SinglePrecision.To(-10); - // insert add instructions + // insert instructions Memory.LoadFixedRom(new ushort[] { 0x00006, // EXTEND instruction 0x02800 | 0x200 diff --git a/Tests/AGC.Tests/Instructions/BranchZeroOrMinusToFixed.cs b/Tests/AGC.Tests/Instructions/BranchZeroOrMinusToFixed.cs new file mode 100644 index 0000000..8b06c53 --- /dev/null +++ b/Tests/AGC.Tests/Instructions/BranchZeroOrMinusToFixed.cs @@ -0,0 +1,102 @@ +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 BranchZeroOrMinusToFixed : BaseTest + { + [TestMethod] + public void BranchZeroOrMinusToFixedPositiveZero() + { + // arrange + Memory[0x0] = 0; + + // insert instructions + Memory.LoadFixedRom(new ushort[] { + 0x00006, // EXTEND instruction + 0x06000 | 0x400 // instruction and address in fixed memory + }); + + // act - run the instructions + CPU.Execute(); + CPU.Execute(); + + // assert + + // check for address to jump to in Z register + Assert.AreEqual(0x400, Memory[0x005]); + } + + [TestMethod] + public void BranchZeroOrMinusToFixedNegativeZero() + { + // arrange + Memory[0x0] = SinglePrecision.NegativeZero; + + // insert instructions + Memory.LoadFixedRom(new ushort[] { + 0x00006, // EXTEND instruction + 0x06000 | 0x500 // instruction and address in fixed memory + }); + + // act - run the instructions + CPU.Execute(); + CPU.Execute(); + + // assert + + // check for address to jump to in Z register + Assert.AreEqual(0x500, Memory[0x005]); + } + + [TestMethod] + public void BranchZeroOrMinusToFixedNegative() + { + // arrange + Memory[0x0] = SinglePrecision.To(-5); + + // insert instructions + Memory.LoadFixedRom(new ushort[] { + 0x00006, // EXTEND instruction + 0x06000 | 0x500 // instruction and address in fixed memory + }); + + // act - run the instructions + CPU.Execute(); + CPU.Execute(); + + // assert + + // check for address to jump to in Z register + Assert.AreEqual(0x500, Memory[0x005]); + } + + [TestMethod] + public void BranchZeroOrMinusToFixedNoJump() + { + // arrange + Memory[0x0] = 5; + + // insert instructions + Memory.LoadFixedRom(new ushort[] { + 0x00006, // EXTEND instruction + 0x06000 | 0x500 // instruction and address in fixed memory + }); + + // act - run the instructions + CPU.Execute(); + CPU.Execute(); + + // assert + + // check for address to jump to in Z register + Assert.AreEqual(0x802, Memory[0x005]); + } + } +} diff --git a/Tests/AGC.Tests/Instructions/BranchZeroToFixed.cs b/Tests/AGC.Tests/Instructions/BranchZeroToFixed.cs new file mode 100644 index 0000000..9ec5bd3 --- /dev/null +++ b/Tests/AGC.Tests/Instructions/BranchZeroToFixed.cs @@ -0,0 +1,80 @@ +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 BranchZeroToFixed : BaseTest + { + [TestMethod] + public void BranchZeroToFixedPositiveZero() + { + // arrange + Memory[0x0] = 0; + + // insert instructions + Memory.LoadFixedRom(new ushort[] { + 0x00006, // EXTEND instruction + 0x01000 | 0x400 // instruction and address in fixed memory + }); + + // act - run the instructions + CPU.Execute(); + CPU.Execute(); + + // assert + + // check for address to jump to in Z register + Assert.AreEqual(0x400, Memory[0x005]); + } + + [TestMethod] + public void BranchZeroToFixedNegativeZero() + { + // arrange + Memory[0x0] = SinglePrecision.NegativeZero; + + // insert instructions + Memory.LoadFixedRom(new ushort[] { + 0x00006, // EXTEND instruction + 0x01000 | 0x500 // instruction and address in fixed memory + }); + + // act - run the instructions + CPU.Execute(); + CPU.Execute(); + + // assert + + // check for address to jump to in Z register + Assert.AreEqual(0x500, Memory[0x005]); + } + + [TestMethod] + public void BranchZeroToFixedNoJump() + { + // arrange + Memory[0x0] = 5; + + // insert instructions + Memory.LoadFixedRom(new ushort[] { + 0x00006, // EXTEND instruction + 0x01000 | 0x500 // instruction and address in fixed memory + }); + + // act - run the instructions + CPU.Execute(); + CPU.Execute(); + + // assert + + // check for address to jump to in Z register + Assert.AreEqual(0x802, Memory[0x005]); + } + } +} diff --git a/Tests/AGC.Tests/Instructions/UnitTest1.cs b/Tests/AGC.Tests/Instructions/UnitTest1.cs new file mode 100644 index 0000000..bfe791b --- /dev/null +++ b/Tests/AGC.Tests/Instructions/UnitTest1.cs @@ -0,0 +1,49 @@ +using System; +using Microsoft.VisualStudio.TestTools.UnitTesting; + +namespace AGC.Tests.Instructions +{ + [TestClass] + public class ClearAndAdd : BaseTest + { + [TestMethod] + public void ClearAndAddFixedMemory() + { + // arrange + + // insert instructions and test data + Memory.LoadFixedRom(new ushort[] { + 0x03000 | 0x801, // CA instruction and address + 10 //value + }); + + // act - run the instructions + CPU.Execute(); + + // assert + + // check for value in the accumulator + Assert.AreEqual(10, Memory[0x0]); + } + + [TestMethod] + public void ClearAndAddEraseableMemory() + { + // arrange + Memory[0x200] = 10; + + // insert instructions and test data + Memory.LoadFixedRom(new ushort[] { + 0x03000 | 0x200 // CA instruction and address + }); + + // act - run the instructions + CPU.Execute(); + + // assert + + // check for value in the accumulator + Assert.AreEqual(10, Memory[0x0]); + } + } +}