/** * @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 #include #include #include #include #include /** * @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 CCPU; /** * @class CInstruction * * Abstract class for instructions */ template 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 *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 *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& 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 *cpu) = 0; protected: /* members */ /** name of instruction */ std::string m_name; }; /*----------------------------------------------------------------------------*/ template const unsigned CInstruction::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(str.substr(1)); } catch(boost::bad_lexical_cast& ex) { throw CInstructionError("Invalid syntax of register"); } return reg; } /*----------------------------------------------------------------------------*/ template inline void CInstruction::checkRegister(CCPU *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: */