IF YOU HAVE JUST ARRIVED HERE, PLEASE SEE: http://megalomaniacbore.blogspot.co.uk/2014/04/virtual-cpu-in-c-4001-cpu.html
This is the full listing as of 28/4/2014
-- Main.cpp ---
#include <iostream>
#include <exception>
#include "Electronics.h"
#include "Memory.h"
#include "CPU.h"
using namespace std;
using namespace CPU_4001;
void DefaultProgram(Memory*);
void ReportMemory(Memory*);
void ClearMemory (Memory*);
void LoadMemory(Memory*);
void SaveMemory(Memory*);
void ShowMenu();
const bool ChooseFromMenu(const char&, Memory*);
const bool IsExitOption(const char& selection);
void ProgramEntry(Memory*);
bool _debugMode = false;
void ToggleDebugMode();
int main ()
{ 
 cout << "Init Memory...";
 Memory* theMemory = new Memory();
 cout << "Ready" << endl;
 
 // Changes here: We have the CPU ONLY active
 // for the cycle from the menu through, however
 // we don't want to loose the memory, so that is
 // created outside the loop
 bool quitAll = false;
 char selectedOption = ' ';
 do
 {  
  // Show the menu & read in a
  // character (plus enter) for
  // the next option to perform
  ShowMenu();
  cin >> selectedOption;
  // Check if we're exiting
  if ( !IsExitOption(selectedOption) )
  {
   // Check if we're running
   if ( ChooseFromMenu(selectedOption, theMemory) )
   { 
    cout << "************************************" << endl;
    // Create the CPU    
    CPU* theCPU = new CPU(theMemory, _debugMode);    
    // Run the program in memory    
    theCPU->Run();
    // The CPU is done
    delete theCPU;
    cout << "************************************" << endl;
   }
  }
  else
  {
   quitAll = true;
  }  
 }
 while ( !quitAll );
 delete theMemory;
}
void ProgramEntry(Memory* p_Memory)
{
 cout << "Entering Program Entry, by memory address:" << endl;
 cout << "N : Next address" << endl;
 cout << "B : Previous Address" << endl;
 cout << "<BYTE> changes current address + increment address" << endl;
 if ( p_Memory != nullptr )
 {
  bool exitEditor = false;
  byte value;
  std::string input;
  byte currentAddress = 2; // This is our base address
  do
  {
   cout << "[" << (int)currentAddress << "] (" << (int)p_Memory->Read(currentAddress) << ") > ";
   cin >> input;
   
   // Now we need to know
   // what our options are
   // first off, if we enter
   // a number it'll just
   // get added to the current
   // memory address and
   // the memory address
   // will increase by 1
   try
   {    
    // We also offer other options
    if ( input == "x" || input == "X" )
    {
     exitEditor = true;
    }
    else if ( input == "b" || input == "B" || input == "back" )
    {
     --currentAddress;
    }
    else if ( input == "n" || input == "N" || input == "next" )
    {
     ++currentAddress;
    }
    else
    {
     // So lets convert the string input
     // to a number
     int temp = atoi(input.c_str());
     value = (byte)temp;    
     p_Memory->Write(currentAddress, value);
     ++currentAddress;
    }
   }
   catch (std::exception& ex)
   {
    // Ptoblem
   }
  }
  while ( !exitEditor );
 }
}
void ShowMenu()
{
 cout << endl << "===== Menu =====" << endl;
 cout << "1. Load Default Program" << endl;
 cout << "2. Clear the Memory" << endl;
 cout << "3. Report Memory" << endl;
 cout << "R. Run the current memory state through the CPU" << endl;
 cout << "E. Enter Program Editor" << endl;
 cout << endl;
 cout << "D. Toggle Debug Settings [" << _debugMode << "]" << endl;
 cout << "L. Load Memory" << endl;
 cout << "S. Save Memory" << endl;
 cout << endl;
 cout << "X. Exit Interpter" << endl;
 cout << endl;
 cout << "Selection: ";
}
const bool IsExitOption(const char& selection)
{
 return (selection == 'x' || selection == 'X');
}
const bool ChooseFromMenu(const char& selection, 
 Memory* theMemory)
{
 bool l_RunThroughCPU = false;
 switch (selection)
 {
  case '1': 
   DefaultProgram(theMemory);
   break;
  case '2':
   ClearMemory(theMemory);
   break;
  case '3':
   ReportMemory(theMemory);
   break;
  case 'r':
  case 'R':
   l_RunThroughCPU = true;
   break;
  case 'e':
  case 'E':
   ProgramEntry(theMemory);
   break;
  case 'd':
  case 'D':
   ToggleDebugMode();
   break;
  case 's':
  case 'S':
   SaveMemory(theMemory);
   break;  
  case 'l':
  case 'L':
   LoadMemory(theMemory);
   break;
 }
 return l_RunThroughCPU;
}
void ClearMemory(Memory* theMemory)
{
 if ( theMemory != nullptr )
 {
  cout << "Clearing the memory...";
  theMemory->Clear();
  cout << "Complete" << endl;
 }
}
void DefaultProgram(Memory* theMemory)
{
 if ( theMemory != nullptr )
 {
  ClearMemory(theMemory);
  // Add the program
  cout << "Adding our default machine code program..." << endl;
  // Load0 value 1
  theMemory->Write(1, 1);
  theMemory->Write(2, 1);
  // Load1 Value 2
  theMemory->Write(3, 2);
  theMemory->Write(4, 2);
  // Add
  theMemory->Write(5, 3);
  // Store to 12
  theMemory->Write(6, 5);
  theMemory->Write(7, 12);
  // Print from 12
  theMemory->Write(8, 6);
  theMemory->Write(9, 12);
  // Beep
  theMemory->Write(10, 4);
  // HALT
  theMemory->Write(11, 0);
 }
}
void ReportMemory(Memory* theMemory)
{
 // Now, we only need to add "(int)" here, because the cout
 // stream does not know to use our "byte" as a number, the
 // C++ language would just assume that our memory spot is
 // an "unsigned char"... or character, so we'd output garbage.
 // (int) in front simply means "Treat this as a number"...
 cout << "Memory Size: " << (int)theMemory->c_MaxAddress << endl;
 cout << "Do you want to list the memory?";
 char yesNo;
 cin >> yesNo;
 if ( yesNo == 'Y' || yesNo == 'y' )
 {
  for (byte currentAddress = 0; currentAddress < theMemory->c_MaxAddress; ++currentAddress)
  {
   // Again, add "(int)" to force usage as a number
   cout << "Address [" << (int)currentAddress << "] = " << (int)theMemory->Read(currentAddress) << endl;
  }
 }
}
void LoadMemory(Memory* theMemory)
{
 if ( theMemory != nullptr )
 {
  cout << endl << "Load Memory from: ";
  string filename;
  cin >> filename;
  theMemory->Load(filename);
  cout << endl;
 }
}
void SaveMemory(Memory* theMemory)
{
 if ( theMemory != nullptr )
 {
  cout << endl << "Save Memory to: ";
  string filename;
  cin >> filename;
  theMemory->Save(filename);
  cout << endl;
 }
}
void ToggleDebugMode ()
{
 _debugMode = !_debugMode;
}
-- Electronics.h --
#ifndef ELECTRONICS_HEADER
#define ELECTRONICS_HEADER
// We only include memory for the type "byte" to be known
#include "Memory.h"
namespace CPU_4001
{
 class Electronics
 {
  private:
   // The function is static so we can just call it without
   // needing to instantiate a copy of "Electronics"
   static void Adder (
    const bool& A,  // Bit from top of sum
    const bool& B,  // bit from bottom of sum
    const bool& Cin, // Carry from previous column
    bool& Cout,   // Carry out
    bool& Sum,   // Sum of binary addition
    const bool& p_Debug = false);
  public:
   // We're going to add both bytes 
   // inside their own memory, hence
   // they're passed in by reference
   static void AddTwoBytes (
    byte& p_Register0,
    byte& p_Register1,
    byte& p_Result,
    bool& p_Overflow,
    const bool& p_Debug = false);
   // We saw the adder trace table, 
   // this function lets us put it
   // to the test!
   static void TestAdder();
   // Test routine for the adding of bytes
   //static void TestAddTwoBytes();
 };
}
#endif
-- Electronics.cpp --
#include "Electronics.h"
#include <iostream>
#include <bitset>
namespace CPU_4001
{
 // The trace table for the adder:
 // A  B  Cin  |  Cout  Sum
 // 0  0  0    |  0     0
 // 0  0  1    |  0     1
 // 0  1  0    |  0     1
 // 0  1  1    |  1     0
 // 1  0  0    |  0     1
 // 1  0  1    |  1     0
 // 1  1  0    |  1     0
 // 1  1  1    |  1     1
 void Electronics::Adder(
  const bool& A,
  const bool& B,
  const bool& Cin,
  bool& Cout,
  bool& Sum,
  const bool& p_Debug)
 {
  // The logic here you can follow,
  // but it comes from an electronic
  // diagram of an adder :)
  Sum = Cin ^ (A ^ B);
  Cout = (A & B) | (Cin & (A ^ B));  
  if ( p_Debug )
  {
   std::cout << "Adder: " << A << " " << B << " " << Cin << " | " << Cout << " " << Sum << std::endl;
  }
 }
 // Tests the adder
 void Electronics::TestAdder()
 {
  using namespace std;
  bool Cout = false;
  bool Sum = false;
  // 0 0 0
  bool A = false;
  bool B = false;
  bool Cin = false;
  Adder (A, B, Cin, Cout, Sum);
  cout << A << " " << B << " " << Cin << " | " << Cout << " " << Sum << endl;
  // 0 0 1
  A = false;
  B = false;
  Cin = true;
  Adder (A, B, Cin, Cout, Sum);
  cout << A << " " << B << " " << Cin << " | " << Cout << " " << Sum << endl;
  
  // 0 1 0
  A = false;
  B = true;
  Cin = false;
  Adder (A, B, Cin, Cout, Sum);
  cout << A << " " << B << " " << Cin << " | " << Cout << " " << Sum << endl;
  // 0 1 1
  A = false;
  B = true;
  Cin = true;
  Adder (A, B, Cin, Cout, Sum);
  cout << A << " " << B << " " << Cin << " | " << Cout << " " << Sum << endl;
  // 1 0 0
  A = true;
  B = false;
  Cin = false;
  Adder (A, B, Cin, Cout, Sum);
  cout << A << " " << B << " " << Cin << " | " << Cout << " " << Sum << endl;
  // 1 0 1
  A = true;
  B = false;
  Cin = true;
  Adder (A, B, Cin, Cout, Sum);
  cout << A << " " << B << " " << Cin << " | " << Cout << " " << Sum << endl;
  // 1 1 0
  A = true;
  B = true;
  Cin = false;
  Adder (A, B, Cin, Cout, Sum);
  cout << A << " " << B << " " << Cin << " | " << Cout << " " << Sum << endl;
  // 1 1 1
  A = true;
  B = true;
  Cin = true;
  Adder (A, B, Cin, Cout, Sum);
  cout << A << " " << B << " " << Cin << " | " << Cout << " " << Sum << endl;
  cout << endl;
 }
 void Electronics::AddTwoBytes (
  byte& p_Register0,
  byte& p_Register1,
  byte& p_Result,
  bool& p_Overflow,
  const bool& p_Debug)
 {
  bool l_CarryIn = false;
  bool l_CarryOut = false;
  bool l_Sum = false;
  // For each bit we need to mask the
  // right most bit out of the register
  // meaning, we start at 00000001 and
  // for each loop move the register
  // so the bit we're interested is over
  // the 8th position.
  // Our mask never changes
  byte l_mask = 0x01;
  // For each bit we run the masking 
  // then adder and handle switching
  // the result into the register.
  // You can find more efficient ways!
  for (int i = 0; i < 8; ++i) // 8 bits in a byte
  {   
   if ( p_Debug )
   {
    std::cout << "Cycle: " << i << std::endl;
    std::bitset<8> msk { l_mask };
    std::cout << "Mask: " << msk << std::endl;
    std::bitset<8> reg0 { p_Register0 };
    std::bitset<8> reg1 { p_Register1 };
    std::cout << "Register 0 [" << reg0 << "]" << std::endl;
    std::cout << "Register 1 [" << reg1 << "]" << std::endl;
   }
   // Get the A & B bits by shift & masking
   // the register
   bool A = ( ( ( p_Register0 >> i ) & l_mask) == 1);
   bool B = ( ( ( p_Register1 >> i ) & l_mask) == 1);
   // We have the carry in and the A & B now, so
   // we can call the adder
   // Because the Carry out, and the Sum, are separate
   // in our code here, we don't need to alter "reg0" or
   // "reg1", we can just logically add the bits set
   // into the p_Result below!
   Adder(A, B, l_CarryIn, l_CarryOut, l_Sum, p_Debug);
   if ( p_Debug )
   {
    // This should be a value from our Adder trace table!
    std::cout << "Adding: " << A << " " << B << " " << l_CarryIn << " | " << l_CarryOut << " " << l_Sum << std::endl;
   }
   // The carry out simply becomes the carry in
   // I'm sure you can see one way to optimise this already!
   l_CarryIn = l_CarryOut;
   // Now the register change based on sum, but
   // we also output the binary
   if ( p_Debug )
   {
    std::bitset<8> resultBefore { p_Result };
    std::cout << "Result Change: " << resultBefore << " -> ";
   }
   // Now the logic
   // Now instead of pushing the logical
   // summing into "Register0" parameter,
   // we push it into the p_Result parameter!
   if ( l_Sum )
   {
    // Mask is shifted, and always 1 in the i position
    // so we always add a 1 back into the target
    // register in the right location
    p_Result = p_Result | ( l_mask << i);
   }
   else
   {
    // We know the mask is ON, so inversing it and moving it
    // will give us an always off...
    p_Result = p_Result & ~(l_mask << i);
   }
   // The register changed, so finish the debug statements
   if ( p_Debug )
   {
    std::bitset<8> resultAfter { p_Result };
    std::cout << resultAfter << std::endl;
   }
  }
  // The final carry out becomes our
  // over flow
  p_Overflow = l_CarryOut;
 }
 // Out test is now invalid, so we'll just remove it
 // from our code.
 /*void Electronics::TestAddTwoBytes ()
 {
  using namespace std;
  byte A = 0;
  byte B = 0;
  bool Overflow = false;
  cout << (int)A << "\t+\t" << (int)B << "\t=";
  AddTwoBytes(A, B, Overflow);
  cout<< (int)A;
  if ( Overflow )
  {
   cout << " it over flowed!";   
  }
  cout << std::endl;
  A = 0;
  B = 1;
  Overflow = false;
  cout << (int)A << "\t+\t" << (int)B << "\t=";
  AddTwoBytes(A, B, Overflow);
  cout<< (int)A;
  if ( Overflow )
  {
   cout << " it over flowed!";   
  }
  cout << std::endl;
  A = 60;
  B = 14;
  Overflow = false;
  cout << (int)A << "\t+\t" << (int)B << "\t=";
  AddTwoBytes(A, B, Overflow);
  cout<< (int)A;
  if ( Overflow )
  {
   cout << " it over flowed!";   
  }
  cout << std::endl;
  A = 42;
  B = 42;
  Overflow = false;
  cout << (int)A << "\t+\t" << (int)B << "\t=";
  AddTwoBytes(A, B, Overflow);
  cout<< (int)A;
  if ( Overflow )
  {
   cout << " it over flowed!";   
  }
  cout << std::endl;
  A = 128;
  B = 16;
  Overflow = false;
  cout << (int)A << "\t+\t" << (int)B << "\t=";
  AddTwoBytes(A, B, Overflow);
  cout<< (int)A;
  if ( Overflow )
  {
   cout << " it over flowed!";   
  }
  cout << std::endl;
  A = 200;
  B = 50;
  Overflow = false;
  cout << (int)A << "\t+\t" << (int)B << "\t=";
  AddTwoBytes(A, B, Overflow);
  cout<< (int)A;
  if ( Overflow )
  {
   cout << " it over flowed!";   
  }
  cout << std::endl;
  A = 250;
  B = 60;
  Overflow = false;
  cout << (int)A << "\t+\t" << (int)B << "\t=";
  AddTwoBytes(A, B, Overflow);
  cout<< (int)A;
  if ( Overflow )
  {
   cout << " it over flowed!";   
  }
  cout << std::endl;
  A = 255;
  B = 255;
  Overflow = false;
  cout << (int)A << "\t+\t" << (int)B << "\t=";
  AddTwoBytes(A, B, Overflow);
  cout<< (int)A;
  if ( Overflow )
  {
   cout << " it over flowed!";   
  }
  cout << std::endl;
 }*/
}
-- Memory.h --
#ifndef CPU_MEMORY
#define CPU_MEMORY
#include <string>
namespace CPU_4001
{
 // Because C++ does not work directly in byte sized memory as numbers
 // we'll use the byte sized character type as our byte of memory.
 typedef unsigned char byte;
 class Memory
 {
  public:
   /// A constant we're going to define which
   /// tells us the maximum address we can
   /// read or write from.
   const byte c_MaxAddress;
  private:
   /// This is the memory space we're going to
   /// be using.
   byte* m_MemorySpace;
  public:
   /// Construct a Memory class instance
   /// for us, and clear the memory
   Memory();
   /// Delete the memory class, releasing
   /// all the allocated memory space
   ~Memory();
   /// Function to clear the memory values all to zero
   void Clear();
   /// Function to read the given address value
   const byte& Read (const byte& p_Address);
   /// Function to write the value to the given address
   void Write (const byte& p_Address, const byte& p_Value);
   /// Save to file
   void Save(const std::string& p_Filename);
   /// Load from file
   void Load(const std::string& p_Filename);
 };
}
#endif
-- Memory.cpp --
#include "Memory.h"
#include <iostream>
#include <fstream>
#include <cstdlib>
namespace CPU_4001
{
 Memory::Memory()
  :
  c_MaxAddress(255),  // The maximum constant
  m_MemorySpace (new byte[c_MaxAddress]) // The memory
 {
  Clear(); // Our only function, clears the memory
     // in C++ we allocate the variables in the
     // constructor header, NOT here in the 
     // Constructor body!
 }
 Memory::~Memory()
 {
  if ( m_MemorySpace != nullptr )
  {
   delete[] m_MemorySpace;
   m_MemorySpace = nullptr;
  }
 }
 void Memory::Clear()
 {
  for (byte i = 0; i < c_MaxAddress; ++i)
  {
   m_MemorySpace[i] = 0;
  }
 }
 const byte& Memory::Read(const byte& p_Address)
 {
  return m_MemorySpace[p_Address];
 }
 void Memory::Write(const byte& p_Address, const byte& p_Value)
 {
  m_MemorySpace[p_Address] = p_Value;
 }
 void Memory::Save(const std::string& p_Filename)
 {
  using namespace std;
  ofstream file (p_Filename, ios_base::out);
  if ( file.good() )
  {   
   for (byte i = 0; i < c_MaxAddress; ++i)
   {
    file << (int)m_MemorySpace[i] << endl;
   }
   file.close();
  }
  else
  {
   cout << "Bad path [" << p_Filename << "]" << endl;
  }
 }
 void Memory::Load(const std::string& p_Filename)
 {
  Clear();
  using namespace std;
  ifstream file(p_Filename, ios_base::in);
  if ( file.good() )
  {
   int i = 0;   
   int temp;
   while ( file.good() )
   {
    string buff;
    //cout << "Load [" << i << "]" << endl;
    file >> buff;
    //cout << "Loaded [" << buff << "]" << endl;
    temp = atoi(buff.c_str());
    //cout << "atoi [" << (int)temp << "]" << endl;
    m_MemorySpace[i] = (byte)temp;
    ++i;
   }
   file.close();
  }
  else
  {
   cout << "File not found [" << p_Filename << "]" << endl;
  }
 }
}
-- CPU.h --
#ifndef CPU_PROCESSOR
#define CPU_PROCESSOR
#include "Memory.h"
#include <string>
namespace CPU_4001
{
 
 class CPU
 {
  public:
   const byte c_ReservedAddress;
   const byte c_BaseAddress;
   const byte c_JumpToAddress;
   const byte c_AddressCeiling;
  private:
   byte m_ProgramCounter;
   byte m_Accumulator;
   byte m_Counter;
   byte m_Register0;
   byte m_Register1;
   bool m_OverflowError;
   bool m_UnderflowError;
   bool m_SignedMode;
   bool m_Halt;
   bool m_DebugMode;
   Memory* m_TheMemory;
   const byte Fetch();
   void Decode(const byte& p_OpCode);
   void Halt();
   void Add();
   void Multiply();
   void Beep();
   void Store();
   void Print();
   void ClearRegister0();
   void ClearRegister1();
   void ClearBoth();
   void JumpTo(); 
   void JumpEqual();
   // DOH, ALWAYS SAVE YOUR HEADER AND SOURCE FILES!
   void Copy0();
   void Copy1();
   void Log(const std::string& p_Message);
   void Load0();
   void Load1();
   void ClearAccumulator();
   void LoadAccumulatorFromRegister0();
   void LoadAccumulatorFromRegister1();
   void SaveAccumulatorToRegister0();
   void SaveAccumulatorToRegister1();
   void ClearCounter();
  public:
   CPU(Memory* p_TheMemory, const bool& p_DebugMode = false);
   ~CPU();
   void Reset();
   void Run();
 };
}
#endif
-- CPU.cpp --
#include "CPU.h"
#include <iostream>
#include "Electronics.h"
namespace CPU_4001
{
 CPU::CPU(Memory* p_TheMemory,
  const bool& p_DebugMode)
  :
  c_ReservedAddress(0),
  c_BaseAddress(2),
  c_JumpToAddress(1),
  c_AddressCeiling(253),
  m_ProgramCounter(c_BaseAddress),
  m_Accumulator(0),
  m_Counter(0),
  m_Register0(0),
  m_Register1(0),
  m_OverflowError(false),
  m_UnderflowError(false),
  m_SignedMode(false),
  m_TheMemory(p_TheMemory),  // DOH!
  m_Halt(false),
  m_DebugMode(p_DebugMode)
 {  
 }
 CPU::~CPU()
 {
  m_TheMemory = nullptr;
 }
 void CPU::Reset()
 {
  m_Halt = false;
  m_ProgramCounter = c_BaseAddress; // FIX!
  m_OverflowError = false;
  m_UnderflowError = false;
  m_SignedMode = false;
 }
 const byte CPU::Fetch()
 {
  byte l_opCode = 0;
  l_opCode = m_TheMemory->Read(m_ProgramCounter); // Whoops!
  ++m_ProgramCounter;
  if ( m_ProgramCounter > c_AddressCeiling )
  {
   Halt();
  }
  return l_opCode;
 }
 void CPU::Halt()
 {
  if ( m_DebugMode )
  {
   Log("Halt");
  }
  m_Halt = true;
 }
 void CPU::Add()
 {
  if ( m_DebugMode )
  {
   Log("Add");
   std::cout << "Before [" << (int)m_Register0 << ", " << (int)m_Register1 << "]" << std::endl;
  }  
  //m_Register0 = m_Register0 + m_Register1;
  Electronics::AddTwoBytes( // Binary add
   m_Register0,   // Register 0
   m_Register1,   // And Register 1 (Saving into reg0)
   m_Accumulator,   // Doh, we add into the accumulator!
   m_OverflowError);  // Set the overflow bit in the CPU
  if ( m_DebugMode )
  {
   std::cout << "After [" << (int)m_Register0 << ", " << (int)m_Register1 << "]" << std::endl;
   if ( m_OverflowError )
   {
    std::cout << "Overflow occurred!" << std::endl;
   }
  }
 }
 void CPU::Multiply()
 {
  if ( m_DebugMode )
  {
   Log("Add");
   std::cout << "Before [" << (int)m_Register0 << ", " << (int)m_Register1 << "]" << std::endl;
  }  
  ClearCounter();
  ClearAccumulator();
  for ( ; m_Counter < m_Register1; ++m_Counter)
  {
   Electronics::AddTwoBytes(
    m_Accumulator,
    m_Register0,
    m_Accumulator,
    m_OverflowError);
   if ( m_OverflowError ) break;
  }
  // So, we add the register 0, to accumulator
  // for register 1 times
  // We always start from zero in the
  // accumulator
  // And really in a real chip the "for" loop
  // here would be a logical operation
  if ( m_DebugMode )
  {
   std::cout << "After [" << (int)m_Register0 << ", " << (int)m_Register1 << "]" << std::endl;  
   // Why my overflow debug gone?... Grrr
   if ( m_OverflowError )
   {
    std::cout << "overflowed!" << std::endl;
   }
  }
 }
 void CPU::Beep()
 {
  if ( m_DebugMode )
  {
   Log("Beep");
  }
  std::cout << '\a';
 }
 void CPU::Store()
 {
  if ( m_DebugMode )
  {
   Log("Store");
  }
  // Load the target address into register 1
  m_Register1 = m_TheMemory->Read(m_ProgramCounter);
  if ( m_DebugMode )
  {
   std::cout << "Target Address: " << (int)m_Register1 << std::endl;
   std::cout << "Value to Write: " << (int)m_Register0 << std::endl;
  }
  ++m_ProgramCounter; // Skip the memory location data
  // Write the register 0 value to this address
  m_TheMemory->Write(m_Register1, m_Register0);
  // Remember the order of our parameters
  // was ADDRESS then VALUE!
  if ( m_DebugMode )
  {
   std::cout << "Written value: " << (int)m_TheMemory->Read(m_Register1) << std::endl;
  }
 }
 void CPU::Print()
 {
  if ( m_DebugMode )
  {
   Log("Print");
  }
  // Load the target addressinto register 1 // DOH!
  m_Register1 = m_TheMemory->Read(m_ProgramCounter);
  ++m_ProgramCounter;  
  
  // The value in the register is now the value to load
  m_Register0 = m_TheMemory->Read(m_Register1);
  if ( m_DebugMode )
  {
   std::cout << "Printing from: " << (int)m_Register1 << " -> value: " << (int)m_Register0 << std::endl;
  }
  // Output the register
  std::cout << (int)m_Register0 << std::endl;
  // I'm going to add endline!
 }
 void CPU::ClearRegister0()
 {
  if ( m_DebugMode )
  {
   Log("Clear 0"); 
  }
  
  m_Register0 = 0;
 }
 void CPU::ClearRegister1()
 {
  if ( m_DebugMode )
  {
   Log("Clear 1");
  }
  m_Register1 = 0;
 }
 void CPU::ClearBoth()
 {
  if ( m_DebugMode )
  {
   Log("Clear Both");
  }
  ClearRegister0();
  ClearRegister1();
 }
 void CPU::JumpTo ()
 {
  if ( m_DebugMode)
  {
   Log("Jump To");
  }
  // Read the program counter location
  // into the jump to address for use
  m_TheMemory->Write(
   c_JumpToAddress,  // Whoops
   m_TheMemory->Read(m_ProgramCounter));
  ++m_ProgramCounter;
  if ( m_DebugMode )
  {
   std::cout << "Jump Register set to [" << (int)m_TheMemory->Read(c_JumpToAddress) << "]" << std::endl;
  }
  // Read back the jump to address
  // as the program counter
  m_ProgramCounter = m_TheMemory->Read(c_JumpToAddress);
  if ( m_DebugMode )
  {
   std::cout << "Program Counter now [" << (int)m_ProgramCounter << "]" << std::endl;
  }
 }
 void CPU::JumpEqual()
 {
  if ( m_Register0 == m_Register1 )
  {
   if ( m_DebugMode )
   {
    Log ("Jump Equal - Jumping");
   }
   JumpTo();
  }
  else
  {
   if ( m_DebugMode )
   {
    Log ("Jump Equal - Not Jumping");
   }
   // Skip over the address of the jump!
   ++m_ProgramCounter;
  }
 } 
 void CPU::Copy0()
 {
  if ( m_DebugMode )
  {
   Log("Copy0");
  }
  m_Register1 = m_Register0;
 }
 void CPU::Copy1()
 {
  if ( m_DebugMode )
  {
   Log("Copy1");
  }
  m_Register0 = m_Register1;
 }
 void CPU::Log(const std::string& p_Message)
 {
  std::cout << p_Message << std::endl;
 }
 void CPU::Load0()
 {
  if ( m_DebugMode )
  {
   Log("Load0");
  }
  // Load the address
  m_Register0 = m_TheMemory->Read(m_ProgramCounter);
  //std::cout << "Register 0 Load Address [" << (int)m_Register0 << "]" << std::endl;
  // Skip past the address data
  ++m_ProgramCounter;
  // Read from memory
  m_Register0 = m_TheMemory->Read(m_Register0);
  //std::cout << "Register 0 [" << (int)m_Register0 << "]" << std::endl;
 }
 void CPU::Load1()
 {  
  if ( m_DebugMode )  
  {   
   Log("Load1");
  }
  
  // Load the Address
  m_Register1 = m_TheMemory->Read(m_ProgramCounter);
  //std::cout << "Register 1 Load Address [" << (int)m_Register1 << "]" << std::endl;
  // Skip past the address data
  ++m_ProgramCounter;
  // Read frommemory
  m_Register1 = m_TheMemory->Read(m_Register1);
  //std::cout << "Register 1 [" << (int)m_Register1 << "]" << std::endl;
 }
 void CPU::ClearAccumulator()
 {
  m_Accumulator = 0;
 }  
 void CPU::LoadAccumulatorFromRegister0()
 {
  m_Accumulator = m_Register0;
 }
 void CPU::LoadAccumulatorFromRegister1()
 {
  m_Accumulator = m_Register1;
 }
 void CPU::SaveAccumulatorToRegister0()
 {
  m_Register0 = m_Accumulator;
 }
 void CPU::SaveAccumulatorToRegister1()
 {
  m_Register1 = m_Accumulator;
 }
 void CPU::ClearCounter()
 {
  m_Counter = 0;
 }
 void CPU::Decode(const byte& p_OpCode) // DOH!
 {
  // Special, when the system has pre-halted in Fetch
  // We do not decode!
  if ( m_Halt ) return;
  switch (p_OpCode)
  {
   // HALT
   case 0:        
    Halt();
    break;   
   // Load 0
   case 1:
    Load0();
    break;
   // Load 1
   case 2:
    Load1();
    break;
   // Add
   case 3:
    Add();
    break;  
   // Beep
   case 4:
    Beep();
    break; 
   // Store operation
   case 5:
    Store();
    break;
   // Print operation
   case 6:
    Print();
    break;
   // Clear Register 0
   case 7:
    ClearRegister0();
    break;
   // Clear Register 1
   case 8:
    ClearRegister1();
    break;
   // Jump to
   case 9:
    JumpTo();
    break;
   // Jump Equal
   case 10:
    JumpEqual();
    break;
   // Copy 0
   case 11:
    Copy0();
    break;
   // Copy 1
   case 12:
    Copy1();
    break; 
   // Clear both
   case 13:
    ClearBoth();
    break;
   // Multiply
   case 14:
    Multiply();
    break;
   // Load Acc from Reg0
   case 20:
    LoadAccumulatorFromRegister0();
    break;
   // Load Acc from Reg1
   case 21:
    LoadAccumulatorFromRegister1();
    break;
   // Save acc to reg 0
   case 22:
    SaveAccumulatorToRegister0();
    break;
   // Save acc to reg 1
   case 23:
    SaveAccumulatorToRegister1();
    break;
   // Clear accumulator
   case 24:
    ClearAccumulator();
    break;
   // Clear Counter
   case 25:
    ClearCounter();
    break;
   default:
    Log("Unknown Op code - halting");
    Halt();
    break;
  }
 }
 void CPU::Run()
 {
  // While we don't see a HALT, keep going
  while (!m_Halt)
  {
   if ( m_DebugMode )
   {
    std::cout << "[" << (int)m_ProgramCounter << "]" << std::endl;
   }  
   // Fetch into the reserved memory
   // location
   m_TheMemory->Write(c_ReservedAddress, Fetch());
   
   // Decode from the memory reserved address
   Decode(m_TheMemory->Read(c_ReservedAddress));
  }
 }
}
No comments:
Post a Comment