Download | Plain Text | Line Numbers


/**
 * @module instructions
 * @author Guenther Neuwirth (0626638), Manuel Mausz (0728348)
 * @brief  Implementations of CInstruction
 * @date   10.05.2009
 */
 
#include <map>
#include <assert.h>
#include "instructions.h"
 
using namespace std;
 
void CInstructionInc::compile(std::list<std::string>& params)
{
  if (params.size() != 1)
    throw runtime_error("Invalid paramater count - must be 1");
  m_regidx1 = parseRegister(params.front());
  params.pop_front();
}
 
/*----------------------------------------------------------------------------*/
 
void CInstructionInc::execute(CCPU *cpu)
{
  assert(cpu != NULL);
  assert(cpu->getRegisters() != NULL);
  checkRegister(cpu, m_regidx1);
  cpu->getRegisters()[ m_regidx1 ]++;
}
 
/*============================================================================*/
 
void CInstructionDec::compile(std::list<std::string>& params)
{
  if (params.size() != 1)
    throw runtime_error("Invalid paramater count - must be 1");
  m_regidx1 = parseRegister(params.front());
  params.pop_front();
}
 
/*----------------------------------------------------------------------------*/
 
void CInstructionDec::execute(CCPU *cpu)
{
  assert(cpu != NULL);
  assert(cpu->getRegisters() != NULL);
  checkRegister(cpu, m_regidx1);
  cpu->getRegisters()[ m_regidx1 ]--;
}
 
/*============================================================================*/
 
void CInstructionAdd::compile(std::list<std::string>& params)
{
  if (params.size() != 3)
    throw runtime_error("Invalid paramater count - must be 3");
  m_regidx1 = parseRegister(params.front());
  params.pop_front();
  m_regidx2 = parseRegister(params.front());
  params.pop_front();
  m_regidx3 = parseRegister(params.front());
  params.pop_front();
}
 
/*----------------------------------------------------------------------------*/
 
void CInstructionAdd::execute(CCPU *cpu)
{
  assert(cpu != NULL);
  assert(cpu->getRegisters() != NULL);
  checkRegister(cpu, m_regidx1);
  checkRegister(cpu, m_regidx2);
  checkRegister(cpu, m_regidx3);
  cpu->getRegisters()[ m_regidx1 ] = cpu->getRegisters()[ m_regidx2 ]
    + cpu->getRegisters()[ m_regidx3 ];
}
 
/*============================================================================*/
 
void CInstructionSub::compile(std::list<std::string>& params)
{
  if (params.size() != 3)
    throw runtime_error("Invalid paramater count - must be 3");
  m_regidx1 = parseRegister(params.front());
  params.pop_front();
  m_regidx2 = parseRegister(params.front());
  params.pop_front();
  m_regidx3 = parseRegister(params.front());
  params.pop_front();
}
 
/*----------------------------------------------------------------------------*/
 
void CInstructionSub::execute(CCPU *cpu)
{
  assert(cpu != NULL);
  assert(cpu->getRegisters() != NULL);
  checkRegister(cpu, m_regidx1);
  checkRegister(cpu, m_regidx2);
  checkRegister(cpu, m_regidx3);
  cpu->getRegisters()[ m_regidx1 ] = cpu->getRegisters()[ m_regidx2 ]
    - cpu->getRegisters()[ m_regidx3 ];
}
 
/*============================================================================*/
 
void CInstructionMul::compile(std::list<std::string>& params)
{
  if (params.size() != 3)
    throw runtime_error("Invalid paramater count - must be 3");
  m_regidx1 = parseRegister(params.front());
  params.pop_front();
  m_regidx2 = parseRegister(params.front());
  params.pop_front();
  m_regidx3 = parseRegister(params.front());
  params.pop_front();
}
 
/*----------------------------------------------------------------------------*/
 
void CInstructionMul::execute(CCPU *cpu)
{
  checkRegister(cpu, m_regidx1);
  checkRegister(cpu, m_regidx2);
  checkRegister(cpu, m_regidx3);
  cpu->getRegisters()[ m_regidx1 ] = cpu->getRegisters()[ m_regidx2 ]
    * cpu->getRegisters()[ m_regidx3 ];
}
 
/*============================================================================*/
 
void CInstructionDiv::compile(std::list<std::string>& params)
{
  if (params.size() != 3)
    throw runtime_error("Invalid paramater count - must be 3");
  m_regidx1 = parseRegister(params.front());
  params.pop_front();
  m_regidx2 = parseRegister(params.front());
  params.pop_front();
  m_regidx3 = parseRegister(params.front());
  params.pop_front();
}
 
/*----------------------------------------------------------------------------*/
 
void CInstructionDiv::execute(CCPU *cpu)
{
  assert(cpu != NULL);
  assert(cpu->getRegisters() != NULL);
  checkRegister(cpu, m_regidx1);
  checkRegister(cpu, m_regidx2);
  checkRegister(cpu, m_regidx3);
  cpu->getRegisters()[ m_regidx1 ] = cpu->getRegisters()[ m_regidx2 ]
    / cpu->getRegisters()[ m_regidx3 ];
}
 
/*============================================================================*/
 
void CInstructionLoad::compile(std::list<std::string>& params)
{
  if (params.size() != 2)
    throw runtime_error("Invalid paramater count - must be 2");
  m_regidx1 = parseRegister(params.front());
  params.pop_front();
  m_regidx2 = parseRegister(params.front());
  params.pop_front();
}
 
/*----------------------------------------------------------------------------*/
 
void CInstructionLoad::execute(CCPU *cpu)
{
  assert(cpu != NULL);
  assert(cpu->getRegisters() != NULL);
  assert(cpu->getMemory() != NULL);
  checkRegister(cpu, m_regidx1);
  checkRegister(cpu, m_regidx2);
  CDat val(cpu->getRegisters()[ m_regidx2 ]);
  cpu->getRegisters()[ m_regidx1 ] = (*cpu->getMemory())[ val ];
}
 
/*============================================================================*/
 
void CInstructionStore::compile(std::list<std::string>& params)
{
  if (params.size() != 2)
    throw runtime_error("Invalid paramater count - must be 2");
  m_regidx1 = parseRegister(params.front());
  params.pop_front();
  m_regidx2 = parseRegister(params.front());
  params.pop_front();
}
 
/*----------------------------------------------------------------------------*/
 
void CInstructionStore::execute(CCPU *cpu)
{
  assert(cpu != NULL);
  assert(cpu->getRegisters() != NULL);
  assert(cpu->getMemory() != NULL);
  checkRegister(cpu, m_regidx1);
  checkRegister(cpu, m_regidx2);
  CDat val(cpu->getRegisters()[ m_regidx2 ]);
  (*cpu->getMemory())[ val ] = cpu->getRegisters()[ m_regidx1 ];
}
 
/*============================================================================*/
 
void CInstructionTest::compile(std::list<std::string>& params)
{
  if (params.size() != 1)
    throw runtime_error("Invalid paramater count - must be 1");
  m_regidx1 = parseRegister(params.front());
  params.pop_front();
}
 
/*----------------------------------------------------------------------------*/
 
void CInstructionTest::execute(CCPU *cpu)
{
  assert(cpu != NULL);
  assert(cpu->getRegisters() != NULL);
  checkRegister(cpu, m_regidx1);
  if (cpu->getRegisters()[ m_regidx1 ] == CDat(0))
    cpu->setFlagZero(true);
  if (cpu->getRegisters()[ m_regidx1 ] < CDat(0))
    cpu->setFlagSign(true);
}
 
/*============================================================================*/
 
void CInstructionJumpA::compile(std::list<std::string>& params)
{
  if (params.size() != 1)
    throw runtime_error("Invalid paramater count - must be 1");
  m_addr = params.front();
  params.pop_front();
}
 
/*----------------------------------------------------------------------------*/
 
void CInstructionJumpA::execute(CCPU *cpu)
{
  assert(cpu != NULL);
  assert(cpu->getRegisters() != NULL);
  assert(cpu->getProgram() != NULL);
  if (m_addr.empty())
    throw runtime_error("Empty address");
  cpu->getRegisters()[ 0 ] = cpu->getProgram()->findLabel(m_addr);
}
 
/*============================================================================*/
 
void CInstructionJumpZ::compile(std::list<std::string>& params)
{
  if (params.size() != 1)
    throw runtime_error("Invalid paramater count - must be 1");
  m_addr = params.front();
  params.pop_front();
}
 
/*----------------------------------------------------------------------------*/
 
void CInstructionJumpZ::execute(CCPU *cpu)
{
  assert(cpu != NULL);
  assert(cpu->getRegisters() != NULL);
  assert(cpu->getProgram() != NULL);
  if (!cpu->getFlagZero())
    return;
  if (m_addr.empty())
    throw runtime_error("Empty address");
  cpu->getRegisters()[ 0 ] = cpu->getProgram()->findLabel(m_addr);
}
 
/*============================================================================*/
 
void CInstructionJumpS::compile(std::list<std::string>& params)
{
  if (params.size() != 1)
    throw runtime_error("Invalid paramater count - must be 1");
  m_addr = params.front();
  params.pop_front();
}
 
/*----------------------------------------------------------------------------*/
 
void CInstructionJumpS::execute(CCPU *cpu)
{
  assert(cpu != NULL);
  assert(cpu->getRegisters() != NULL);
  assert(cpu->getProgram() != NULL);
  if (!cpu->getFlagSign())
    return;
  if (m_addr.empty())
    throw runtime_error("Empty address");
  cpu->getRegisters()[ 0 ] = cpu->getProgram()->findLabel(m_addr);
}
 
/*============================================================================*/
 
void CInstructionWrite::compile(std::list<std::string>& params)
{
  if (params.size() != 2)
    throw runtime_error("Invalid paramater count - must be 2");
  m_dev = params.front();
  params.pop_front();
  m_regidx1 = parseRegister(params.front());
  params.pop_front();
}
 
/*----------------------------------------------------------------------------*/
 
void CInstructionWrite::execute(CCPU *cpu)
{
  assert(cpu != NULL);
  assert(cpu->getRegisters() != NULL);
  checkRegister(cpu, m_regidx1);
  if (m_dev.empty())
    throw runtime_error("Empty device");
 
  CDisplay *display = NULL;
  std::set<CDisplay *> displays = cpu->getDisplays();
  std::set<CDisplay *>::iterator it;
  for(it = displays.begin(); it != displays.end(); ++it)
  {
    if ((*it)->getName() == m_dev)
    {
      display = *it;
      break;
    }
  }
  if (display == NULL)
    throw runtime_error("Unknown display");
 
  display->display(cpu->getRegisters()[ m_regidx1 ]);
}
 
 
/* vim: set et sw=2 ts=2: */