diff --git a/AGC/Memory/IMemoryBus.cs b/AGC/Memory/IMemoryBus.cs
new file mode 100644
index 0000000..332fcae
--- /dev/null
+++ b/AGC/Memory/IMemoryBus.cs
@@ -0,0 +1,16 @@
+namespace Apollo.Virtual.AGC.Memory
+{
+ public interface IMemoryBus
+ {
+ OnesCompliment this[ushort a] { get; set; }
+ int MaxAddress { get; }
+
+ ///
+ /// The AGC has memory mapped registerss, so they need a method to regiser themselves to the MemoryBus
+ ///
+ ///
+ ///
+ ///
+ RegisterType MapRegister(ushort address) where RegisterType : MemoryWord;
+ }
+}
\ No newline at end of file
diff --git a/AGC/MemoryMap.cs b/AGC/MemoryMap.cs
index 0e818de..5283114 100644
--- a/AGC/MemoryMap.cs
+++ b/AGC/MemoryMap.cs
@@ -1,8 +1,10 @@
using Apollo.Virtual.AGC.Memory;
+using System;
+using System.Diagnostics;
namespace Apollo.Virtual.AGC
{
- public class MemoryMap
+ public class MemoryMap : IMemoryBus
{
const uint EB_Address = 0x03;
const uint FB_Address = 0x04;
@@ -34,7 +36,7 @@ public class MemoryMap
///
/// Divided into 8 (E0 - E7) banks controlled by register EB or BB
///
- private MemoryBank[] switchedErasable = new MemoryBank[]
+ private MemoryBank[] switchedErasable = new MemoryBank[]
{
new MemoryBank(256, 0x300),
new MemoryBank(256, 0x300),
@@ -79,19 +81,15 @@ public class MemoryMap
///
private MemoryBank ioChannels = new MemoryBank(512);
+ public int MaxAddress => throw new NotImplementedException();
+
public OnesCompliment this[ushort a]
{
- get
- {
- return GetWord(a).Read();
- }
- set
- {
- GetWord(a).Write(value);
- }
+ get => GetWord(a).Read();
+ set => GetWord(a).Write(value);
}
- public IWord GetWord(ushort address)
+ private IWord GetWord(ushort address)
{
// registers
if (address <= 0x031)
@@ -100,7 +98,7 @@ public IWord GetWord(ushort address)
int bank = 0;
// look at bits in address to determine appropriate bank and memory type
- switch(address & 0xF00)
+ switch (address & 0xF00)
{
case 0x000:
case 0x100:
@@ -144,11 +142,13 @@ public IWord GetWord(ushort address)
///
///
///
- internal RegisterType AddRegister(ushort address) where RegisterType : MemoryWord
+ RegisterType IMemoryBus.MapRegister(ushort address)
{
// reflectively get constructor that takes memory bank and call it
var constructor = typeof(RegisterType).GetConstructor(new[] { typeof(ushort), typeof(MemoryBank) });
+ Debug.Assert(constructor != null, $"Register of type {typeof(RegisterType).Name} does not have usable constructor");
+
var r = constructor.Invoke(new object[] { address, unswitchedErasable }) as RegisterType;
// add to memory space and return the object created
diff --git a/AGC/Processor.cs b/AGC/Processor.cs
index 923bd68..bf7e2fd 100644
--- a/AGC/Processor.cs
+++ b/AGC/Processor.cs
@@ -1,4 +1,6 @@
-using Apollo.Virtual.AGC.Memory;
+using AGC;
+using Apollo.Virtual.AGC.Instructions;
+using Apollo.Virtual.AGC.Memory;
using Apollo.Virtual.AGC.Registers;
namespace Apollo.Virtual.AGC
@@ -10,10 +12,10 @@ namespace Apollo.Virtual.AGC
///
public class Processor
{
- internal MemoryMap Memory;
+ internal IMemoryBus Memory;
- private InstructionSet instructions;
- private ExtraCodeInstructionSet extraCodeInstructions;
+ private readonly InstructionList standardInstructions;
+ private readonly InstructionList extraCodeInstructions;
///
/// used to allow more than 8 instruction codes
@@ -215,60 +217,60 @@ public class Processor
#endregion
- public Processor(MemoryMap memory)
+ public Processor(IMemoryBus memory)
{
this.Memory = memory;
- instructions = new InstructionSet();
- extraCodeInstructions = new ExtraCodeInstructionSet();
+ standardInstructions = StandardInstructions.Build(this);
+ extraCodeInstructions = ExtraInstructions.Build(this);
// configure registers
// main registers?
- A = memory.AddRegister(0x00);
- L = memory.AddRegister(0x01);
- Q = memory.AddRegister(0x02);
- EB = memory.AddRegister(0x03);
- FB = memory.AddRegister(0x4);
- Z = memory.AddRegister(0x05);
- BB = memory.AddRegister(0x06);
+ A = memory.MapRegister(0x00);
+ L = memory.MapRegister(0x01);
+ Q = memory.MapRegister(0x02);
+ EB = memory.MapRegister(0x03);
+ FB = memory.MapRegister(0x4);
+ Z = memory.MapRegister(0x05);
+ BB = memory.MapRegister(0x06);
//memory[0x7] = 0; // this is always set to 0, TODO: need to hard code?
// interrupt helper registers
- ARUPT = memory.AddRegister(0x08);
- LRUPT = memory.AddRegister(0x09);
- QRUPT = memory.AddRegister(0x0A);
+ ARUPT = memory.MapRegister(0x08);
+ LRUPT = memory.MapRegister(0x09);
+ QRUPT = memory.MapRegister(0x0A);
// 0XB, 0XC are spares. not used?
- ZRUPT = memory.AddRegister(0x0D);
- BBRUPT = memory.AddRegister(0x0E);
- BRUPT = memory.AddRegister(0x0F);
+ ZRUPT = memory.MapRegister(0x0D);
+ BBRUPT = memory.MapRegister(0x0E);
+ BRUPT = memory.MapRegister(0x0F);
// editing registers
- CYR = memory.AddRegister(0x10);
- SR = memory.AddRegister(0x11);
- CYL = memory.GetWord(0x12);
- EDOP = memory.GetWord(0x13);
+ CYR = memory.MapRegister(0x10);
+ SR = memory.MapRegister(0x11);
+ CYL = memory.MapRegister(0x12); // temp
+ EDOP = memory.MapRegister(0x13); // temp
// time registers
- TIME2 = memory.GetWord(0x14);
- TIME1 = memory.GetWord(0x15);
- TIME3 = memory.GetWord(0x16);
- TIME4 = memory.GetWord(0x17);
- TIME5 = memory.GetWord(0x18);
- TIME6 = memory.GetWord(0x19);
+ TIME2 = memory.MapRegister(0x14); // temp
+ TIME1 = memory.MapRegister(0x15); // temp
+ TIME3 = memory.MapRegister(0x16); // temp
+ TIME4 = memory.MapRegister(0x17); // temp
+ TIME5 = memory.MapRegister(0x18); // temp
+ TIME6 = memory.MapRegister(0x19); // temp
// orientation registers
- CDUX = memory.AddRegister(0x1A);
- CDUY = memory.AddRegister(0x1B);
- CDUZ = memory.AddRegister(0x1C);
- OPTY = memory.AddRegister(0x1D);
- OPTX = memory.AddRegister(0x1E);
- PIPAX = memory.AddRegister(0x1F);
- PIPAY = memory.AddRegister(0x20);
- PIPAZ = memory.AddRegister(0x21);
+ CDUX = memory.MapRegister(0x1A);
+ CDUY = memory.MapRegister(0x1B);
+ CDUZ = memory.MapRegister(0x1C);
+ OPTY = memory.MapRegister(0x1D);
+ OPTX = memory.MapRegister(0x1E);
+ PIPAX = memory.MapRegister(0x1F);
+ PIPAY = memory.MapRegister(0x20);
+ PIPAZ = memory.MapRegister(0x21);
// LM Only Pitch, Yaw, and Roll registers
- INLINK = memory.AddRegister(0x25);
+ INLINK = memory.MapRegister(0x25);
// prime Z to start at the boot interrupt
Z.Write(new OnesCompliment(0x800));
@@ -277,13 +279,15 @@ public Processor(MemoryMap memory)
public void Execute()
{
// get address of instruction to run
- var address = Memory.GetWord(Z.Read().NativeValue);
+ ushort address = Z.Read().NativeValue;
// update Z
Z.Increment();
+ // get instruction
+ ushort instruction = Memory[address].NativeValue;
// we only care about 15-bit instructions
- var instruction = address.Read() & 0x7FFF;
+ instruction &= 0x7FFF;
var code = (ushort)(instruction >> 12);
var K = (ushort)(instruction & 0xFFF);
@@ -292,7 +296,6 @@ public void Execute()
if (ExtraCodeFlag)
{
// reset CPU for instruction to execute
- extraCodeInstructions[code].CPU = this;
extraCodeInstructions[code].Execute(K);
// clear the extra code flag
@@ -301,8 +304,7 @@ public void Execute()
else
{
// reset CPU for instruction to execute
- instructions[code].CPU = this;
- instructions[code].Execute(K);
+ standardInstructions[code].Execute(K);
}
}
}