Download | Plain Text | Line Numbers


/**
 * @module cinstruction
 * @author Guenther Neuwirth (0626638), Manuel Mausz (0728348)
 * @brief  Abstract class for instructions
 * @date   26.05.2009
 */
 
#ifndef CINSTRUCTION_H
#define CINSTRUCTION_H 1
 
#include <iostream>
#include <list>
#include <sstream>
#include <boost/lexical_cast.hpp>
#include <assert.h>
#include <stdexcept>
 
/**
 * @class CInstructionError
 *
 * Exception thrown by implemententations of CInstruction
 */
class CInstructionError
 : public std::invalid_argument
{
  public:
    /**
     * @method CInstructionError
     * @brief  Default exception ctor
     * @param  what  message to pass along
     * @return -
     * @globalvars none
     * @exception  none
     * @pre  none
     * @post none
     */
    CInstructionError(const std::string& what)
      : std::invalid_argument(what)
    {}
};
 
#include "ccpu.h"
 
/* forward declare CCPU */
template <class T>
class CCPU;
 
/**
 * @class CInstruction
 *
 * Abstract class for instructions
 */
template <class T>
class CInstruction
{
  public:
    /**
     * @method CInstruction
     * @brief  Default ctor
     * @param  name  name of instruction
     * @return -
     * @globalvars none
     * @exception  none
     * @pre  none
     * @post none
     */
    CInstruction(std::string name)
      : m_name(name)
    {}
 
    /**
     * @method ~CInstruction
     * @brief  Default dtor
     * @param  -
     * @return -
     * @globalvars none
     * @exception  none
     * @pre  none
     * @post none
     */
    virtual ~CInstruction()
    {}
 
    /**
     * @method operator==
     * @brief  implementation of operator ==
     * @param  name reference to std::string
     * @return true if instructionname is name
     * @globalvars none
     * @exception  none
     * @pre  none
     * @post none
     */
    virtual bool operator==(std::string& name)
    {
      return name == m_name;
    }
 
    /**
     * @method operator()
     * @brief  implementation of operator (CCPU)
     * @param  cpu  pointer to cpu
     * @return -
     * @globalvars none
     * @exception  CInstructionError
     * @pre  none
     * @post none
     */
    virtual CInstruction& operator()(CCPU<T> *cpu)
    {
      execute(cpu);
      return *this;
    }
 
    /**
     * @method getName
     * @brief  returns instruction name
     * @param  -
     * @return name of instruction
     * @globalvars none
     * @exception  none
     * @pre  none
     * @post none
     */
    virtual const std::string& getName()
    {
      return m_name;
    }
 
    /**
     * @method dump
     * @brief  dumps information about instruction to outputstream
     * @param  stream  outputstream
     * @return reference to outputstream
     * @globalvars none
     * @exception  none
     * @pre  none
     * @post none
     */
    virtual std::ostream& dump(std::ostream& stream)
    {
      stream << m_name;
      return stream;
    }
 
    /**
     * @method operator<<
     * @brief  Shift/output operator for outputstream
     * @param  stream  reference to outputstream
     * @param  instr   object which will be printed to stream
     * @return reference to outputstream
     * @globalvars none
     * @exception  none
     * @pre  none
     * @post none
     */
    friend std::ostream& operator<<(std::ostream& stream, CInstruction& instr)
    {
      return instr.dump(stream);
    }
 
    /**
     * @method parseRegister
     * @brief  parses register syntax Rx (e.g. "R1")
     * @param  str  register in assembler syntax
     * @return registernumber
     * @globalvars none
     * @exception  CInstructionError
     * @pre  str != NULL
     * @post none
     */
    virtual const unsigned parseRegister(const std::string& str);
 
    /**
     * @method checkRegister
     * @brief  performs a register boundary check
     *         does the register exist in cpu?
     * @param  cpu     pointer to cpu
     * @param  regidx  registernumber
     * @return -
     * @globalvars none
     * @exception  CInstructionError
     * @pre  none
     * @post none
     */
    virtual void checkRegister(CCPU<T> *cpu, const unsigned regidx);
 
    /**
     * @method factory
     * @brief  creates a new instance of this instruction
     * @param  -
     * @return new instruction instance
     * @globalvars none
     * @exception  none
     * @pre  none
     * @post none
     */
    virtual CInstruction *factory() = 0;
 
    /**
     * @method compile
     * @brief  parses instruction parameters and prepares the
     *         instruction for executing
     * @param  params  list of parameters of this instruction
     * @return -
     * @globalvars none
     * @exception  CInstructionError
     * @pre  none
     * @post none
     */
    virtual void compile(std::list<std::string>& params) = 0;
 
    /**
     * @method execute
     * @brief  executes the instruction
     * @param  cpu  pointer to cpu
     * @return -
     * @globalvars none
     * @exception  CInstructionError
     * @pre  cpu valid (memory, program, registers valid)
     * @post none
     */
    virtual void execute(CCPU<T> *cpu) = 0;
 
  protected:
    /* members */
    /** name of instruction */
    std::string m_name;
};
 
/*----------------------------------------------------------------------------*/
 
template<class T>
const unsigned CInstruction<T>::parseRegister(const std::string& str)
{
  unsigned reg;
  if (str.length() < 2 || str[0] != 'r')
    throw CInstructionError("Invalid syntax of register");
 
  try
  {
    reg = boost::lexical_cast<unsigned>(str.substr(1));
  }
  catch(boost::bad_lexical_cast& ex)
  {
    throw CInstructionError("Invalid syntax of register");
  }
 
  return reg;
}
 
/*----------------------------------------------------------------------------*/
 
template<class T>
inline void CInstruction<T>::checkRegister(CCPU<T> *cpu, const unsigned regidx)
{
  assert(cpu != NULL);
  if (regidx >= cpu->getRegisterCount())
  {
    std::stringstream sstr;
    sstr << "Register R" << regidx << " doesn't exist (out of bound)";
    throw CInstructionError(sstr.str());
  }
}
 
#endif
 
/* vim: set et sw=2 ts=2: */