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: */