From 26a97259f5a7b066cff2927e88c867fac2aaad87 Mon Sep 17 00:00:00 2001 From: manuel Date: Tue, 26 May 2009 23:10:13 +0200 Subject: template FTW!!!!!11 --- ue4/mycpu/Makefile | 2 +- ue4/mycpu/ccpu.cpp | 89 --------- ue4/mycpu/ccpu.h | 112 +++++++++-- ue4/mycpu/cdat.h | 109 +++++----- ue4/mycpu/cdisplay.h | 21 +- ue4/mycpu/cinstruction.cpp | 48 ----- ue4/mycpu/cinstruction.h | 50 ++++- ue4/mycpu/cmem.h | 33 ++-- ue4/mycpu/cprogram.cpp | 161 --------------- ue4/mycpu/cprogram.h | 173 +++++++++++++++- ue4/mycpu/displays.h | 20 +- ue4/mycpu/instructions.cpp | 341 -------------------------------- ue4/mycpu/instructions.h | 483 +++++++++++++++++++++++++++++++++++++++++---- ue4/mycpu/mycpu.cpp | 14 +- 14 files changed, 849 insertions(+), 807 deletions(-) delete mode 100644 ue4/mycpu/ccpu.cpp delete mode 100644 ue4/mycpu/cinstruction.cpp delete mode 100644 ue4/mycpu/cprogram.cpp delete mode 100644 ue4/mycpu/instructions.cpp diff --git a/ue4/mycpu/Makefile b/ue4/mycpu/Makefile index 0dbb51a..8022614 100644 --- a/ue4/mycpu/Makefile +++ b/ue4/mycpu/Makefile @@ -11,7 +11,7 @@ LDFLAGS= LIBS= -L/usr/local/lib -lboost_program_options BIN= mycpu -OBJS= cinstruction.o instructions.o cprogram.o ccpu.o mycpu.o +OBJS= mycpu.o HEADERS= cdat.h cmem.h cinstruction.h instructions.h cprogram.h cdisplay.h displays.h ccpu.h .SUFFIXES: .cpp .o diff --git a/ue4/mycpu/ccpu.cpp b/ue4/mycpu/ccpu.cpp deleted file mode 100644 index af86200..0000000 --- a/ue4/mycpu/ccpu.cpp +++ /dev/null @@ -1,89 +0,0 @@ -/** - * @module ccpu - * @author Guenther Neuwirth (0626638), Manuel Mausz (0728348) - * @brief CPU implementation. Used as a container for memory and instructions. - * Implements an run method to execute the program (= the instructions). - * @date 10.05.2009 - */ - -#ifdef DEBUG -# include -# include -#endif -#include "ccpu.h" -#include "displays.h" - -using namespace std; - -CCPU::CCPU(const unsigned cnt) - : m_regcnt(cnt), m_memory(NULL), m_program(NULL), m_flagzero(false), m_flagsign(false) -{ - /* create registers */ - m_registers = new CDat[cnt]; - for(unsigned i = 0; i < cnt; ++i) - m_registers[i] = 0; - - /* create displays */ - m_displays.insert(new CDisplayWDEZ); - m_displays.insert(new CDisplayWHEX); -} - -/*----------------------------------------------------------------------------*/ - -CCPU::~CCPU() -{ - /* delete registers */ - delete[] m_registers; - m_registers = NULL; - - /* delete displays */ - std::set::iterator it; - for (it = m_displays.begin() ; it != m_displays.end(); ++it) - delete *it; -} - -/*----------------------------------------------------------------------------*/ - -void CCPU::run() -{ - if (m_memory == NULL) - throw runtime_error("CPU has no memory"); - if (m_program == NULL) - throw runtime_error("CPU has no program to execute"); - if (m_regcnt == 0) - throw runtime_error("CPU has no registers"); - - bool run = true; - while(run) - { - unsigned pc = static_cast(m_registers[0]); - - /* end of the program reached */ - if (pc == m_program->size()) - break; - - /* pc is out of bound */ - if (pc > m_program->size()) - throw runtime_error("Programcounter is out of bound"); - - /* execute instruction */ - (*m_program->at(pc))(this); - ++m_registers[0]; - } -} - -/*----------------------------------------------------------------------------*/ - -#if DEBUG -void CCPU::dumpRegisters(std::ostream& out) -{ - out << "[REGISTER DUMP]" << endl; - for(unsigned i = 0; i < getRegisterCount(); ++i) - { - out << "[" << std::setw(4) << std::setfill('0') << i << "] " - << m_registers[i] << endl; - } -} -#endif - -/* vim: set et sw=2 ts=2: */ diff --git a/ue4/mycpu/ccpu.h b/ue4/mycpu/ccpu.h index 6849623..519cee9 100644 --- a/ue4/mycpu/ccpu.h +++ b/ue4/mycpu/ccpu.h @@ -3,7 +3,7 @@ * @author Guenther Neuwirth (0626638), Manuel Mausz (0728348) * @brief CPU implementation. Used as a container for memory and instructions. * Implements a run method to execute the program (= the instructions). - * @date 10.05.2009 + * @date 26.05.2009 */ #ifndef CCPU_H @@ -11,10 +11,19 @@ #include #include +#include +#ifdef DEBUG +# include +# include +#endif #include "cdat.h" #include "cmem.h" +#include "displays.h" #include "cprogram.h" -#include "cdisplay.h" + +/* forward declare CProgram */ +template +class CProgram; /** * @class CCPU @@ -22,8 +31,11 @@ * CPU implementation. Used as a container for memory and instructions. * Implements a run method to execute the program (= the instructions). */ +template class CCPU { + typedef typename std::set *>::iterator displayiterator; + public: /** * @method CCPU @@ -70,7 +82,7 @@ class CCPU * @exception none * @conditions none */ - CDat *getRegisters() const + T *getRegisters() const { return m_registers; } @@ -84,7 +96,7 @@ class CCPU * @exception none * @conditions none */ - void setMemory(CMem *memory) + void setMemory(CMem *memory) { m_memory = memory; } @@ -98,7 +110,7 @@ class CCPU * @exception none * @conditions none */ - CMem *getMemory() const + CMem *getMemory() const { return m_memory; } @@ -112,7 +124,7 @@ class CCPU * @exception none * @conditions none */ - void setProgram(const CProgram *program) + void setProgram(const CProgram *program) { m_program = program; } @@ -126,7 +138,7 @@ class CCPU * @exception none * @conditions none */ - const CProgram *getProgram() + const CProgram *getProgram() { return m_program; } @@ -140,7 +152,7 @@ class CCPU * @exception none * @conditions none */ - const std::set& getDisplays() + const std::set *>& getDisplays() { return m_displays; } @@ -227,15 +239,91 @@ class CCPU private: /* members */ - CDat *m_registers; + T *m_registers; unsigned m_regcnt; - CMem *m_memory; - const CProgram *m_program; - std::set m_displays; + CMem *m_memory; + const CProgram *m_program; + std::set *> m_displays; bool m_flagzero; bool m_flagsign; }; +/*----------------------------------------------------------------------------*/ + +template +CCPU::CCPU(const unsigned cnt) + : m_regcnt(cnt), m_memory(NULL), m_program(NULL), m_flagzero(false), m_flagsign(false) +{ + /* create registers */ + m_registers = new T[cnt]; + for(unsigned i = 0; i < cnt; ++i) + m_registers[i] = 0; + + /* create displays */ + m_displays.insert(new CDisplayWDEZ); + m_displays.insert(new CDisplayWHEX); +} + +/*----------------------------------------------------------------------------*/ + +template +CCPU::~CCPU() +{ + /* delete registers */ + delete[] m_registers; + m_registers = NULL; + + /* delete displays */ + for (displayiterator it = m_displays.begin() ; it != m_displays.end(); ++it) + delete *it; +} + +/*----------------------------------------------------------------------------*/ + +template +void CCPU::run() +{ + if (m_memory == NULL) + throw std::runtime_error("CPU has no memory"); + if (m_program == NULL) + throw std::runtime_error("CPU has no program to execute"); + if (m_regcnt == 0) + throw std::runtime_error("CPU has no registers"); + + bool run = true; + while(run) + { + unsigned pc = static_cast(m_registers[0]); + + /* end of the program reached */ + if (pc == m_program->size()) + break; + + /* pc is out of bound */ + if (pc > m_program->size()) + throw std::runtime_error("Programcounter is out of bound"); + + /* execute instruction */ + (*m_program->at(pc))(this); + ++m_registers[0]; + } +} + +/*----------------------------------------------------------------------------*/ + +#if DEBUG +template +void CCPU::dumpRegisters(std::ostream& out) +{ + out << "[REGISTER DUMP]" << std::endl; + for(unsigned i = 0; i < getRegisterCount(); ++i) + { + out << "[" << std::setw(4) << std::setfill('0') << i << "] " + << m_registers[i] << std::endl; + } +} +#endif + #endif /* vim: set et sw=2 ts=2: */ diff --git a/ue4/mycpu/cdat.h b/ue4/mycpu/cdat.h index a533fae..ca9d745 100644 --- a/ue4/mycpu/cdat.h +++ b/ue4/mycpu/cdat.h @@ -2,7 +2,7 @@ * @module cdat * @author Guenther Neuwirth (0626638), Manuel Mausz (0728348) * @brief Datatype template and datatype definition for CCPU and CMem - * @date 10.05.2009 + * @date 26.05.2009 */ #ifndef CDAT_H @@ -12,17 +12,17 @@ #include /** - * @class CDatT + * @class CDat * * Datatype template for CCPU and CMem. */ template -class CDatT - : boost::operators > +class CDat + : boost::operators > { public: /** - * @method CDatT + * @method CDat * @brief Default ctor * @param - * @return - @@ -30,11 +30,11 @@ class CDatT * @exception bad_alloc * @conditions none */ - CDatT() + CDat() {} /** - * @method ~CDatT + * @method ~CDat * @brief Default dtor * @param - * @return - @@ -42,40 +42,40 @@ class CDatT * @exception none * @conditions none */ - ~CDatT() + ~CDat() {} /** - * @method CDatT - * @brief Copy constructor for CDatT - * @param other reference to CDatT which will be copied + * @method CDat + * @brief Copy constructor for CDat + * @param other reference to CDat which will be copied * @return - * @globalvars none * @exception none * @conditions none */ - CDatT(const CDatT& other) + CDat(const CDat& other) : m_value(other.m_value) {} /** - * @method CDatT + * @method CDat * @brief Copy constructor for int - * @param newval new value for CDatT + * @param newval new value for CDat * @return - * @globalvars none * @exception none * @conditions none */ - CDatT(T newval) + CDat(T newval) : m_value(newval) {} /** * @method getValue - * @brief returns value of CDatT + * @brief returns value of CDat * @param - - * @return value of CDatT + * @return value of CDat * @globalvars none * @exception none * @conditions none @@ -102,13 +102,13 @@ class CDatT /** * @method operator< * @brief implementation of operator < - * @param x reference to CDatT + * @param x reference to CDat * @return true if cdat is less than object x * @globalvars none * @exception none * @conditions none */ - bool operator<(const CDatT& x) const + bool operator<(const CDat& x) const { return m_value < x.m_value; } @@ -116,13 +116,13 @@ class CDatT /** * @method operator== * @brief implementation of operator == - * @param x reference to CDatT + * @param x reference to CDat * @return true if cdat equals object x * @globalvars none * @exception none * @conditions none */ - bool operator==(const CDatT& x) const + bool operator==(const CDat& x) const { return m_value == x.m_value; } @@ -130,13 +130,13 @@ class CDatT /** * @method operator+= * @brief implementation of operator += - * @param x reference to CDatT - * @return refecence to CDatT + * @param x reference to CDat + * @return refecence to CDat * @globalvars none * @exception none * @conditions none */ - CDatT& operator+=(const CDatT& x) + CDat& operator+=(const CDat& x) { m_value += x.m_value; return *this; @@ -145,13 +145,13 @@ class CDatT /** * @method operator-= * @brief implementation of operator -= - * @param x reference to CDatT - * @return refecence to CDatT + * @param x reference to CDat + * @return refecence to CDat * @globalvars none * @exception none * @conditions none */ - CDatT& operator-=(const CDatT& x) + CDat& operator-=(const CDat& x) { m_value -= x.m_value; return *this; @@ -160,13 +160,13 @@ class CDatT /** * @method operator*= * @brief implementation of operator *= - * @param x reference to CDatT - * @return refecence to CDatT + * @param x reference to CDat + * @return refecence to CDat * @globalvars none * @exception none * @conditions none */ - CDatT& operator*=(const CDatT& x) + CDat& operator*=(const CDat& x) { m_value *= x.m_value; return *this; @@ -175,13 +175,13 @@ class CDatT /** * @method operator/= * @brief implementation of operator /= - * @param x reference to CDatT - * @return refecence to CDatT + * @param x reference to CDat + * @return refecence to CDat * @globalvars none * @exception none * @conditions none */ - CDatT& operator/=(const CDatT& x) + CDat& operator/=(const CDat& x) { m_value /= x.m_value; return *this; @@ -190,13 +190,13 @@ class CDatT /** * @method operator%= * @brief implementation of operator %= - * @param x reference to CDatT - * @return refecence to CDatT + * @param x reference to CDat + * @return refecence to CDat * @globalvars none * @exception none * @conditions none */ - CDatT& operator%=(const CDatT& x) + CDat& operator%=(const CDat& x) { m_value %= x.m_value; return *this; @@ -205,13 +205,13 @@ class CDatT /** * @method operator|= * @brief implementation of operator |= - * @param x reference to CDatT - * @return refecence to CDatT + * @param x reference to CDat + * @return refecence to CDat * @globalvars none * @exception none * @conditions none */ - CDatT& operator|=(const CDatT& x) + CDat& operator|=(const CDat& x) { m_value |= x.m_value; return *this; @@ -220,13 +220,13 @@ class CDatT /** * @method operator&= * @brief implementation of operator &= - * @param x reference to CDatT - * @return refecence to CDatT + * @param x reference to CDat + * @return refecence to CDat * @globalvars none * @exception none * @conditions none */ - CDatT& operator&=(const CDatT& x) + CDat& operator&=(const CDat& x) { m_value &= x.m_value; return *this; @@ -235,13 +235,13 @@ class CDatT /** * @method operator^= * @brief implementation of operator ^= - * @param x reference to CDatT - * @return refecence to CDatT + * @param x reference to CDat + * @return refecence to CDat * @globalvars none * @exception none * @conditions none */ - CDatT& operator^=(const CDatT& x) + CDat& operator^=(const CDat& x) { m_value ^= x.m_value; return *this; @@ -251,12 +251,12 @@ class CDatT * @method operator++ * @brief implementation of operator ++ * @param - - * @return refecence to CDatT + * @return refecence to CDat * @globalvars none * @exception none * @conditions none */ - CDatT& operator++() + CDat& operator++() { m_value++; return *this; @@ -266,12 +266,12 @@ class CDatT * @method operator-- * @brief implementation of operator -- * @param - - * @return refecence to CDatT + * @return refecence to CDat * @globalvars none * @exception none * @conditions none */ - CDatT& operator--() + CDat& operator--() { m_value--; return *this; @@ -287,7 +287,7 @@ class CDatT * @exception none * @conditions none */ - friend std::ostream& operator<<(std::ostream& stream, CDatT cdat) + friend std::ostream& operator<<(std::ostream& stream, CDat cdat) { stream << cdat.m_value; return stream; @@ -303,7 +303,7 @@ class CDatT * @exception none * @conditions none */ - friend std::istream& operator>>(std::istream & stream, CDatT& cdat) + friend std::istream& operator>>(std::istream & stream, CDat& cdat) { stream >> cdat.m_value; return stream; @@ -314,13 +314,6 @@ class CDatT T m_value; }; -/** - * @class CDat - * - * Datatype for CCPU and CMem - */ -typedef CDatT CDat; - #endif /* vim: set et sw=2 ts=2: */ diff --git a/ue4/mycpu/cdisplay.h b/ue4/mycpu/cdisplay.h index 82776ee..8d15eb9 100644 --- a/ue4/mycpu/cdisplay.h +++ b/ue4/mycpu/cdisplay.h @@ -2,23 +2,23 @@ * @module cdisplay * @author Guenther Neuwirth (0626638), Manuel Mausz (0728348) * @brief Abstract template class for displays - * @date 10.05.2009 + * @date 26.05.2009 */ #ifndef CDISPLAY_H #define CDISPLAY_H 1 /** - * @class CDisplayT + * @class CDisplay * * Abstract template class for displays */ template -class CDisplayT +class CDisplay { public: /** - * @method CDisplayT + * @method CDisplay * @brief Default ctor * @param name name of display * @return - @@ -26,12 +26,12 @@ class CDisplayT * @exception none * @conditions none */ - CDisplayT(std::string name) + CDisplay(std::string name) : m_name(name) {} /** - * @method ~CDisplayT + * @method ~CDisplay * @brief Default dtor * @param - * @return - @@ -39,7 +39,7 @@ class CDisplayT * @exception none * @conditions none */ - virtual ~CDisplayT() + virtual ~CDisplay() {} /** @@ -73,13 +73,6 @@ class CDisplayT std::string m_name; }; -/** - * @class CDisplay - * - * Memory definition for CCPU - */ -typedef CDisplayT CDisplay; - #endif /* vim: set et sw=2 ts=2: */ diff --git a/ue4/mycpu/cinstruction.cpp b/ue4/mycpu/cinstruction.cpp deleted file mode 100644 index a766015..0000000 --- a/ue4/mycpu/cinstruction.cpp +++ /dev/null @@ -1,48 +0,0 @@ -/** - * @module cinstruction - * @author Guenther Neuwirth (0626638), Manuel Mausz (0728348) - * @brief Abstract class for displays - * @date 13.05.2009 - */ - -#include -#include -#include -#include -#include "cinstruction.h" -#include "ccpu.h" - -using namespace std; - -const unsigned CInstruction::parseRegister(const std::string& str) -{ - unsigned reg; - if (str.length() < 2 || str[0] != 'r') - throw runtime_error("Invalid syntax of register"); - - try - { - reg = boost::lexical_cast(str.substr(1)); - } - catch(boost::bad_lexical_cast& ex) - { - throw runtime_error("Invalid syntax of register"); - } - - return reg; -} - -/*----------------------------------------------------------------------------*/ - -inline void CInstruction::checkRegister(CCPU *cpu, const unsigned regidx) -{ - assert(cpu != NULL); - if (regidx >= cpu->getRegisterCount()) - { - stringstream sstr; - sstr << "Register R" << regidx << " doesn't exist (out of bound)"; - throw runtime_error(sstr.str()); - } -} - -/* vim: set et sw=2 ts=2: */ diff --git a/ue4/mycpu/cinstruction.h b/ue4/mycpu/cinstruction.h index 4cc69de..8c35d2c 100644 --- a/ue4/mycpu/cinstruction.h +++ b/ue4/mycpu/cinstruction.h @@ -2,7 +2,7 @@ * @module cinstruction * @author Guenther Neuwirth (0626638), Manuel Mausz (0728348) * @brief Abstract class for displays - * @date 13.05.2009 + * @date 26.05.2009 */ #ifndef CINSTRUCTION_H @@ -10,8 +10,14 @@ #include #include +#include +#include +#include +#include +#include "ccpu.h" /* forward declare CCPU */ +template class CCPU; /** @@ -19,6 +25,7 @@ class CCPU; * * Abstract class for displays */ +template class CInstruction { public: @@ -70,7 +77,7 @@ class CInstruction * @exception std::runtime_error * @conditions none */ - virtual CInstruction& operator()(CCPU *cpu) + virtual CInstruction& operator()(CCPU *cpu) { execute(cpu); return *this; @@ -142,7 +149,7 @@ class CInstruction * @exception std::runtime_error * @conditions none */ - virtual void checkRegister(CCPU *cpu, const unsigned regidx); + virtual void checkRegister(CCPU *cpu, const unsigned regidx); /** * @method factory @@ -176,7 +183,7 @@ class CInstruction * @exception std::runtime_error * @conditions none */ - virtual void execute(CCPU *cpu) = 0; + virtual void execute(CCPU *cpu) = 0; protected: /* members */ @@ -184,6 +191,41 @@ class CInstruction std::string m_name; }; +/*----------------------------------------------------------------------------*/ + +template +const unsigned CInstruction::parseRegister(const std::string& str) +{ + unsigned reg; + if (str.length() < 2 || str[0] != 'r') + throw std::runtime_error("Invalid syntax of register"); + + try + { + reg = boost::lexical_cast(str.substr(1)); + } + catch(boost::bad_lexical_cast& ex) + { + throw std::runtime_error("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 std::runtime_error(sstr.str()); + } +} + #endif /* vim: set et sw=2 ts=2: */ diff --git a/ue4/mycpu/cmem.h b/ue4/mycpu/cmem.h index 5045c34..6b23111 100644 --- a/ue4/mycpu/cmem.h +++ b/ue4/mycpu/cmem.h @@ -2,7 +2,7 @@ * @module cmem * @author Guenther Neuwirth (0626638), Manuel Mausz (0728348) * @brief Memory template and memory definition for CCPU - * @date 10.05.2009 + * @date 26.05.2009 */ #ifndef CMEM_H @@ -17,21 +17,23 @@ # include # include #endif -#include "cdat.h" /** - * @class CVectorMem + * @class CMem * * Extends std::vector template for use as memory for CCPU. */ -template > -class CVectorMem - : public std::vector +template +class CMem + : public std::vector { - public: - using std::vector::size; - using std::vector::at; + typedef std::vector super; + typedef typename super::iterator iterator; + using super::size; + using super::begin; + using super::end; + public: /** * @method initialize * @brief initialize the vector with the content of istream. istream is @@ -88,22 +90,17 @@ class CVectorMem void dump(std::ostream& out) { out << "[MEMORY DUMP]" << std::endl; - for(unsigned i = 0; i < size(); ++i) + unsigned i = 0; + for(iterator it = begin(); it != end(); ++it) { out << "[" << std::setw(4) << std::setfill('0') << i << "] " - << at(i) << std::endl; + << *it << std::endl; + ++i; } } #endif }; -/** - * @class CMem - * - * Memory definition for CCPU - */ -typedef CVectorMem CMem; - #endif /* vim: set et sw=2 ts=2: */ diff --git a/ue4/mycpu/cprogram.cpp b/ue4/mycpu/cprogram.cpp deleted file mode 100644 index 3fcf734..0000000 --- a/ue4/mycpu/cprogram.cpp +++ /dev/null @@ -1,161 +0,0 @@ -/** - * @module cprogram - * @author Guenther Neuwirth (0626638), Manuel Mausz (0728348) - * @brief CProgram extends std::vector and adds a method for parsing programfile - * @date 12.05.2009 - */ - -#include -#include -#ifdef DEBUG -# include -# include -#endif -#include "cprogram.h" -#include "instructions.h" - -using namespace std; - -CProgram::CProgram() -{ - m_instrset.insert(new CInstructionInc); - m_instrset.insert(new CInstructionDec); - m_instrset.insert(new CInstructionAdd); - m_instrset.insert(new CInstructionSub); - m_instrset.insert(new CInstructionMul); - m_instrset.insert(new CInstructionDiv); - m_instrset.insert(new CInstructionLoad); - m_instrset.insert(new CInstructionStore); - m_instrset.insert(new CInstructionTest); - m_instrset.insert(new CInstructionLabel); - m_instrset.insert(new CInstructionJumpA); - m_instrset.insert(new CInstructionJumpZ); - m_instrset.insert(new CInstructionJumpS); - m_instrset.insert(new CInstructionWrite); -} - -/*----------------------------------------------------------------------------*/ - -CProgram::~CProgram() -{ - /* free instruction set */ - set::iterator it; - for (it = m_instrset.begin(); it != m_instrset.end(); ++it) - delete *it; - - /* free instruction */ - for (iterator it = begin(); it != end(); ++it) - delete *it; -} - -/*----------------------------------------------------------------------------*/ - -void CProgram::compile(std::istream& in) -{ - if (!in.good()) - return; - - string line; - unsigned i = 0; - while (!in.eof() && in.good()) - { - ++i; - - /* read stream per line */ - getline(in, line); - if (line.empty()) - continue; - - boost::trim(line); - boost::to_lower(line); - - /* ignore comments */ - if (line.find_first_of('#') == 0) - continue; - - /* get instruction name */ - size_t pos = line.find_first_of(' '); - string instrname(line.substr(0, pos)); - - /* search and create instruction */ - CInstruction *instrptr = NULL; - set::iterator it; - for (it = m_instrset.begin(); it != m_instrset.end(); ++it) - { - if (*(*it) == instrname) - { - instrptr = *it; - break; - } - } - if (instrptr == NULL) - { - stringstream sstr; - sstr << "Unknown instruction '" << instrname << "' on line " << i << "."; - throw runtime_error(sstr.str()); - } - - /* create instruction */ - CInstruction *instr = instrptr->factory(); - - /* parse instruction parameters */ - string params = (pos == string::npos) ? "" : line.substr(pos + 1); - boost::trim(params); - list instrparams; - boost::split(instrparams, params, boost::is_any_of(", \t"), boost::token_compress_on); - - /* let instruction parse the parameters. catch+throw exception */ - try - { - /* handle label instruction ourself, but still add a dummy instruction */ - if (instrname == "label") - { - if (instrparams.size() != 1) - throw runtime_error("Invalid paramater count - must be 1"); - string label(instrparams.front()); - if (label.length() < 2 || label[ label.length() - 1] != ':') - throw runtime_error("Label has invalid syntax"); - m_labels[ label.substr(0, label.length() - 1) ] = size(); - } - instr->compile(instrparams); - } - catch(runtime_error& ex) - { - stringstream sstr; - sstr << "Unable to compile instruction '" << instrname - << "' (line " << i << "): " << ex.what(); - throw runtime_error(sstr.str()); - } - - push_back(instr); - } -} - -/*----------------------------------------------------------------------------*/ - -unsigned CProgram::findLabel(const std::string& label) const -{ - map::const_iterator it; - it = m_labels.find(label); - if (it == m_labels.end()) - throw runtime_error("Unknown label '" + label + "'"); - return it->second; -} - -/*----------------------------------------------------------------------------*/ - -#if DEBUG -void CProgram::dump(std::ostream& out) -{ - out << "[PROGRAM DUMP]" << endl; - unsigned i = 0; - for(iterator it = begin(); it < end(); ++it) - { - out << "[" << std::setw(4) << std::setfill('0') << i << "] " - << *(*it) << endl; - ++i; - } -} -#endif - -/* vim: set et sw=2 ts=2: */ diff --git a/ue4/mycpu/cprogram.h b/ue4/mycpu/cprogram.h index 27e7647..43193ac 100644 --- a/ue4/mycpu/cprogram.h +++ b/ue4/mycpu/cprogram.h @@ -2,7 +2,7 @@ * @module cprogram * @author Guenther Neuwirth (0626638), Manuel Mausz (0728348) * @brief CProgram extends std::vector and adds a method for parsing programfile - * @date 10.05.2009 + * @date 26.05.2009 */ #ifndef CPROGRAM_H @@ -11,7 +11,18 @@ #include #include #include +#include +#include +#ifdef DEBUG +# include +# include +#endif #include "cinstruction.h" +#include "instructions.h" + +/* forward declare CInstruction */ +template +class CInstruction; /** * @class CProgram @@ -19,9 +30,17 @@ * CProgram extends std::vector and adds a method for parsing * programfile. This adds instances of CInstruction to CProgram itself. */ +template class CProgram - : public std::vector + : public std::vector *> { + typedef typename std::set *>::iterator setiterator; + typedef std::vector *> super; + typedef typename super::iterator iterator; + using super::begin; + using super::end; + using super::size; + public: /** * @method CProgram @@ -97,10 +116,158 @@ class CProgram private: /* members */ /** set of known instructions */ - std::set m_instrset; + std::set *> m_instrset; std::map m_labels; }; +/*----------------------------------------------------------------------------*/ + +template +CProgram::CProgram() +{ + m_instrset.insert(new CInstructionInc); + m_instrset.insert(new CInstructionDec); + m_instrset.insert(new CInstructionAdd); + m_instrset.insert(new CInstructionSub); + m_instrset.insert(new CInstructionMul); + m_instrset.insert(new CInstructionDiv); + m_instrset.insert(new CInstructionLoad); + m_instrset.insert(new CInstructionStore); + m_instrset.insert(new CInstructionTest); + m_instrset.insert(new CInstructionLabel); + m_instrset.insert(new CInstructionJumpA); + m_instrset.insert(new CInstructionJumpZ); + m_instrset.insert(new CInstructionJumpS); + m_instrset.insert(new CInstructionWrite); +} + +/*----------------------------------------------------------------------------*/ + +template +CProgram::~CProgram() +{ + /* free instruction set */ + for (setiterator it = m_instrset.begin(); it != m_instrset.end(); ++it) + delete *it; + + /* free instruction */ + for (iterator it2 = begin(); it2 != end(); ++it2) + delete *it2; +} + +/*----------------------------------------------------------------------------*/ + +template +void CProgram::compile(std::istream& in) +{ + if (!in.good()) + return; + + std::string line; + unsigned i = 0; + while (!in.eof() && in.good()) + { + ++i; + + /* read stream per line */ + std::getline(in, line); + if (line.empty()) + continue; + + boost::trim(line); + boost::to_lower(line); + + /* ignore comments */ + if (line.find_first_of('#') == 0) + continue; + + /* get instruction name */ + size_t pos = line.find_first_of(' '); + std::string instrname(line.substr(0, pos)); + + /* search and create instruction */ + CInstruction *instrptr = NULL; + setiterator it; + for (it = m_instrset.begin(); it != m_instrset.end(); ++it) + { + if (*(*it) == instrname) + { + instrptr = *it; + break; + } + } + if (instrptr == NULL) + { + std::stringstream sstr; + sstr << "Unknown instruction '" << instrname << "' on line " << i << "."; + throw std::runtime_error(sstr.str()); + } + + /* create instruction */ + CInstruction *instr = instrptr->factory(); + + /* parse instruction parameters */ + std::string params = (pos == std::string::npos) ? "" : line.substr(pos + 1); + boost::trim(params); + std::list instrparams; + boost::split(instrparams, params, boost::is_any_of(", \t"), boost::token_compress_on); + + /* let instruction parse the parameters. catch+throw exception */ + try + { + /* handle label instruction ourself, but still add a dummy instruction */ + if (instrname == "label") + { + if (instrparams.size() != 1) + throw std::runtime_error("Invalid paramater count - must be 1"); + std::string label(instrparams.front()); + if (label.length() < 2 || label[ label.length() - 1] != ':') + throw std::runtime_error("Label has invalid syntax"); + m_labels[ label.substr(0, label.length() - 1) ] = size(); + } + instr->compile(instrparams); + } + catch(std::runtime_error& ex) + { + std::stringstream sstr; + sstr << "Unable to compile instruction '" << instrname + << "' (line " << i << "): " << ex.what(); + throw std::runtime_error(sstr.str()); + } + + push_back(instr); + } +} + +/*----------------------------------------------------------------------------*/ + +template +unsigned CProgram::findLabel(const std::string& label) const +{ + std::map::const_iterator it; + it = m_labels.find(label); + if (it == m_labels.end()) + throw std::runtime_error("Unknown label '" + label + "'"); + return it->second; +} + +/*----------------------------------------------------------------------------*/ + +#if DEBUG +template +void CProgram::dump(std::ostream& out) +{ + out << "[PROGRAM DUMP]" << std::endl; + unsigned i = 0; + for(iterator it = begin(); it != end(); ++it) + { + out << "[" << std::setw(4) << std::setfill('0') << i << "] " + << *(*it) << std::endl; + ++i; + } +} +#endif + #endif /* vim: set et sw=2 ts=2: */ diff --git a/ue4/mycpu/displays.h b/ue4/mycpu/displays.h index d4f3f36..33d81bb 100644 --- a/ue4/mycpu/displays.h +++ b/ue4/mycpu/displays.h @@ -2,7 +2,7 @@ * @module displays * @author Guenther Neuwirth (0626638), Manuel Mausz (0728348) * @brief Implementations of CDisplay - * @date 10.05.2009 + * @date 26.05.2009 */ #ifndef DISPLAYS_H @@ -15,14 +15,15 @@ * @class CDisplayWDEZ * * Implementation of CDisplay - * Prints CDat to stdout as decimal + * Prints T to stdout as decimal */ +template class CDisplayWDEZ - : public CDisplay + : public CDisplay { public: CDisplayWDEZ() - : CDisplay("wdez") + : CDisplay("wdez") {} /** @@ -34,7 +35,7 @@ class CDisplayWDEZ * @exception none * @conditions none */ - void display(const CDat &value) + void display(const T &value) { std::cout << std::dec << value << std::endl; } @@ -46,14 +47,15 @@ class CDisplayWDEZ * @class CDisplayWHEX * * Implementation of CDisplay - * Prints CDat to stdout as decimal + * Prints T to stdout as decimal */ +template class CDisplayWHEX - : public CDisplay + : public CDisplay { public: CDisplayWHEX() - : CDisplay("whex") + : CDisplay("whex") {} /** @@ -65,7 +67,7 @@ class CDisplayWHEX * @exception none * @conditions none */ - void display(const CDat &value) + void display(const T &value) { std::cout << std::hex << value << std::endl; } diff --git a/ue4/mycpu/instructions.cpp b/ue4/mycpu/instructions.cpp deleted file mode 100644 index ef9e944..0000000 --- a/ue4/mycpu/instructions.cpp +++ /dev/null @@ -1,341 +0,0 @@ -/** - * @module instructions - * @author Guenther Neuwirth (0626638), Manuel Mausz (0728348) - * @brief Implementations of CInstruction - * @date 10.05.2009 - */ - -#include -#include -#include "instructions.h" - -using namespace std; - -void CInstructionInc::compile(std::list& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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 displays = cpu->getDisplays(); - std::set::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: */ diff --git a/ue4/mycpu/instructions.h b/ue4/mycpu/instructions.h index 4c36562..fcff3e7 100644 --- a/ue4/mycpu/instructions.h +++ b/ue4/mycpu/instructions.h @@ -2,7 +2,7 @@ * @module instructions * @author Guenther Neuwirth (0626638), Manuel Mausz (0728348) * @brief Implementations of CInstruction - * @date 10.05.2009 + * @date 26.05.2009 */ #ifndef INSTRUCTIONS_H @@ -10,6 +10,7 @@ #include "cinstruction.h" #include "ccpu.h" +#include "cprogram.h" /** * @class CInstructionInc @@ -18,12 +19,15 @@ * Syntax: inc R1 * (R1++) */ +template class CInstructionInc - : public CInstruction + : public CInstruction { + typedef CInstruction super; + public: CInstructionInc() - : CInstruction("inc") + : CInstruction("inc") {} CInstructionInc *factory() @@ -32,13 +36,35 @@ class CInstructionInc } void compile(std::list& params); - void execute(CCPU *cpu); + void execute(CCPU *cpu); protected: /** register number */ unsigned m_regidx1; }; +/*----------------------------------------------------------------------------*/ + +template +void CInstructionInc::compile(std::list& params) +{ + if (params.size() != 1) + throw std::runtime_error("Invalid paramater count - must be 1"); + m_regidx1 = super::parseRegister(params.front()); + params.pop_front(); +} + +/*----------------------------------------------------------------------------*/ + +template +void CInstructionInc::execute(CCPU *cpu) +{ + assert(cpu != NULL); + assert(cpu->getRegisters() != NULL); + super::checkRegister(cpu, m_regidx1); + cpu->getRegisters()[ m_regidx1 ]++; +} + /*============================================================================*/ /** @@ -48,12 +74,15 @@ class CInstructionInc * Syntax: dec R1 * (R1--) */ +template class CInstructionDec - : public CInstruction + : public CInstruction { + typedef CInstruction super; + public: CInstructionDec() - : CInstruction("dec") + : CInstruction("dec") {} CInstructionDec *factory() @@ -62,13 +91,35 @@ class CInstructionDec } void compile(std::list& params); - void execute(CCPU *cpu); + void execute(CCPU *cpu); protected: /** register number */ unsigned m_regidx1; }; +/*----------------------------------------------------------------------------*/ + +template +void CInstructionDec::compile(std::list& params) +{ + if (params.size() != 1) + throw std::runtime_error("Invalid paramater count - must be 1"); + m_regidx1 = super::parseRegister(params.front()); + params.pop_front(); +} + +/*----------------------------------------------------------------------------*/ + +template +void CInstructionDec::execute(CCPU *cpu) +{ + assert(cpu != NULL); + assert(cpu->getRegisters() != NULL); + super::checkRegister(cpu, m_regidx1); + cpu->getRegisters()[ m_regidx1 ]--; +} + /*============================================================================*/ /** @@ -78,12 +129,15 @@ class CInstructionDec * Syntax: add R1, R2, R3 * (R1 = R2 + R3) */ +template class CInstructionAdd - : public CInstruction + : public CInstruction { + typedef CInstruction super; + public: CInstructionAdd() - : CInstruction("add") + : CInstruction("add") {} CInstructionAdd *factory() @@ -92,7 +146,7 @@ class CInstructionAdd } void compile(std::list& params); - void execute(CCPU *cpu); + void execute(CCPU *cpu); protected: /** register number */ @@ -103,6 +157,35 @@ class CInstructionAdd unsigned m_regidx3; }; +/*----------------------------------------------------------------------------*/ + +template +void CInstructionAdd::compile(std::list& params) +{ + if (params.size() != 3) + throw std::runtime_error("Invalid paramater count - must be 3"); + m_regidx1 = super::parseRegister(params.front()); + params.pop_front(); + m_regidx2 = super::parseRegister(params.front()); + params.pop_front(); + m_regidx3 = super::parseRegister(params.front()); + params.pop_front(); +} + +/*----------------------------------------------------------------------------*/ + +template +void CInstructionAdd::execute(CCPU *cpu) +{ + assert(cpu != NULL); + assert(cpu->getRegisters() != NULL); + super::checkRegister(cpu, m_regidx1); + super::checkRegister(cpu, m_regidx2); + super::checkRegister(cpu, m_regidx3); + cpu->getRegisters()[ m_regidx1 ] = cpu->getRegisters()[ m_regidx2 ] + + cpu->getRegisters()[ m_regidx3 ]; +} + /*============================================================================*/ /** @@ -112,12 +195,15 @@ class CInstructionAdd * Syntax: sub R1, R2, R3 * (R1 = R2 - R3) */ +template class CInstructionSub - : public CInstruction + : public CInstruction { + typedef CInstruction super; + public: CInstructionSub() - : CInstruction("sub") + : CInstruction("sub") {} CInstructionSub *factory() @@ -126,7 +212,7 @@ class CInstructionSub } void compile(std::list& params); - void execute(CCPU *cpu); + void execute(CCPU *cpu); protected: /** register number */ @@ -137,6 +223,35 @@ class CInstructionSub unsigned m_regidx3; }; +/*----------------------------------------------------------------------------*/ + +template +void CInstructionSub::compile(std::list& params) +{ + if (params.size() != 3) + throw std::runtime_error("Invalid paramater count - must be 3"); + m_regidx1 = super::parseRegister(params.front()); + params.pop_front(); + m_regidx2 = super::parseRegister(params.front()); + params.pop_front(); + m_regidx3 = super::parseRegister(params.front()); + params.pop_front(); +} + +/*----------------------------------------------------------------------------*/ + +template +void CInstructionSub::execute(CCPU *cpu) +{ + assert(cpu != NULL); + assert(cpu->getRegisters() != NULL); + super::checkRegister(cpu, m_regidx1); + super::checkRegister(cpu, m_regidx2); + super::checkRegister(cpu, m_regidx3); + cpu->getRegisters()[ m_regidx1 ] = cpu->getRegisters()[ m_regidx2 ] + - cpu->getRegisters()[ m_regidx3 ]; +} + /*============================================================================*/ /** @@ -146,12 +261,15 @@ class CInstructionSub * Syntax: mul R1, R2, R3 * (R1 = R2 * R3) */ +template class CInstructionMul - : public CInstruction + : public CInstruction { + typedef CInstruction super; + public: CInstructionMul() - : CInstruction("mul") + : CInstruction("mul") {} CInstructionMul *factory() @@ -160,7 +278,7 @@ class CInstructionMul } void compile(std::list& params); - void execute(CCPU *cpu); + void execute(CCPU *cpu); protected: /** register number */ @@ -171,6 +289,33 @@ class CInstructionMul unsigned m_regidx3; }; +/*----------------------------------------------------------------------------*/ + +template +void CInstructionMul::compile(std::list& params) +{ + if (params.size() != 3) + throw std::runtime_error("Invalid paramater count - must be 3"); + m_regidx1 = super::parseRegister(params.front()); + params.pop_front(); + m_regidx2 = super::parseRegister(params.front()); + params.pop_front(); + m_regidx3 = super::parseRegister(params.front()); + params.pop_front(); +} + +/*----------------------------------------------------------------------------*/ + +template +void CInstructionMul::execute(CCPU *cpu) +{ + super::checkRegister(cpu, m_regidx1); + super::checkRegister(cpu, m_regidx2); + super::checkRegister(cpu, m_regidx3); + cpu->getRegisters()[ m_regidx1 ] = cpu->getRegisters()[ m_regidx2 ] + * cpu->getRegisters()[ m_regidx3 ]; +} + /*============================================================================*/ /** @@ -180,12 +325,15 @@ class CInstructionMul * Syntax: div R1, R2, R3 * (R1 = R2 / R3) */ +template class CInstructionDiv - : public CInstruction + : public CInstruction { + typedef CInstruction super; + public: CInstructionDiv() - : CInstruction("div") + : CInstruction("div") {} CInstructionDiv *factory() @@ -194,7 +342,7 @@ class CInstructionDiv } void compile(std::list& params); - void execute(CCPU *cpu); + void execute(CCPU *cpu); protected: /** register number */ @@ -205,6 +353,35 @@ class CInstructionDiv unsigned m_regidx3; }; +/*----------------------------------------------------------------------------*/ + +template +void CInstructionDiv::compile(std::list& params) +{ + if (params.size() != 3) + throw std::runtime_error("Invalid paramater count - must be 3"); + m_regidx1 = super::parseRegister(params.front()); + params.pop_front(); + m_regidx2 = super::parseRegister(params.front()); + params.pop_front(); + m_regidx3 = super::parseRegister(params.front()); + params.pop_front(); +} + +/*----------------------------------------------------------------------------*/ + +template +void CInstructionDiv::execute(CCPU *cpu) +{ + assert(cpu != NULL); + assert(cpu->getRegisters() != NULL); + super::checkRegister(cpu, m_regidx1); + super::checkRegister(cpu, m_regidx2); + super::checkRegister(cpu, m_regidx3); + cpu->getRegisters()[ m_regidx1 ] = cpu->getRegisters()[ m_regidx2 ] + / cpu->getRegisters()[ m_regidx3 ]; +} + /*============================================================================*/ /** @@ -214,12 +391,15 @@ class CInstructionDiv * Syntax: load R1, R2 * (R1 = memory[R2]) */ +template class CInstructionLoad - : public CInstruction + : public CInstruction { + typedef CInstruction super; + public: CInstructionLoad() - : CInstruction("load") + : CInstruction("load") {} CInstructionLoad *factory() @@ -228,7 +408,7 @@ class CInstructionLoad } void compile(std::list& params); - void execute(CCPU *cpu); + void execute(CCPU *cpu); protected: /** register number */ @@ -237,6 +417,33 @@ class CInstructionLoad unsigned m_regidx2; }; +/*----------------------------------------------------------------------------*/ + +template +void CInstructionLoad::compile(std::list& params) +{ + if (params.size() != 2) + throw std::runtime_error("Invalid paramater count - must be 2"); + m_regidx1 = super::parseRegister(params.front()); + params.pop_front(); + m_regidx2 = super::parseRegister(params.front()); + params.pop_front(); +} + +/*----------------------------------------------------------------------------*/ + +template +void CInstructionLoad::execute(CCPU *cpu) +{ + assert(cpu != NULL); + assert(cpu->getRegisters() != NULL); + assert(cpu->getMemory() != NULL); + super::checkRegister(cpu, m_regidx1); + super::checkRegister(cpu, m_regidx2); + T val(cpu->getRegisters()[ m_regidx2 ]); + cpu->getRegisters()[ m_regidx1 ] = (*cpu->getMemory())[ val ]; +} + /*============================================================================*/ /** @@ -246,12 +453,15 @@ class CInstructionLoad * Syntax: store R1, R2 * (memory[R2] = R1) */ +template class CInstructionStore - : public CInstruction + : public CInstruction { + typedef CInstruction super; + public: CInstructionStore() - : CInstruction("store") + : CInstruction("store") {} CInstructionStore *factory() @@ -260,7 +470,7 @@ class CInstructionStore } void compile(std::list& params); - void execute(CCPU *cpu); + void execute(CCPU *cpu); protected: /** register number */ @@ -269,6 +479,33 @@ class CInstructionStore unsigned m_regidx2; }; +/*----------------------------------------------------------------------------*/ + +template +void CInstructionStore::compile(std::list& params) +{ + if (params.size() != 2) + throw std::runtime_error("Invalid paramater count - must be 2"); + m_regidx1 = super::parseRegister(params.front()); + params.pop_front(); + m_regidx2 = super::parseRegister(params.front()); + params.pop_front(); +} + +/*----------------------------------------------------------------------------*/ + +template +void CInstructionStore::execute(CCPU *cpu) +{ + assert(cpu != NULL); + assert(cpu->getRegisters() != NULL); + assert(cpu->getMemory() != NULL); + super::checkRegister(cpu, m_regidx1); + super::checkRegister(cpu, m_regidx2); + T val(cpu->getRegisters()[ m_regidx2 ]); + (*cpu->getMemory())[ val ] = cpu->getRegisters()[ m_regidx1 ]; +} + /*============================================================================*/ /** @@ -278,12 +515,15 @@ class CInstructionStore * Syntax: test R1 * (R1 == 0: zeroflag: true, R1 < 0: signflag: true) */ +template class CInstructionTest - : public CInstruction + : public CInstruction { + typedef CInstruction super; + public: CInstructionTest() - : CInstruction("test") + : CInstruction("test") {} CInstructionTest *factory() @@ -292,13 +532,38 @@ class CInstructionTest } void compile(std::list& params); - void execute(CCPU *cpu); + void execute(CCPU *cpu); protected: /** register number */ unsigned m_regidx1; }; +/*----------------------------------------------------------------------------*/ + +template +void CInstructionTest::compile(std::list& params) +{ + if (params.size() != 1) + throw std::runtime_error("Invalid paramater count - must be 1"); + m_regidx1 = super::parseRegister(params.front()); + params.pop_front(); +} + +/*----------------------------------------------------------------------------*/ + +template +void CInstructionTest::execute(CCPU *cpu) +{ + assert(cpu != NULL); + assert(cpu->getRegisters() != NULL); + super::checkRegister(cpu, m_regidx1); + if (cpu->getRegisters()[ m_regidx1 ] == T(0)) + cpu->setFlagZero(true); + if (cpu->getRegisters()[ m_regidx1 ] < T(0)) + cpu->setFlagSign(true); +} + /*============================================================================*/ /** @@ -307,12 +572,15 @@ class CInstructionTest * Implementation of assembler command "label" * Syntax: label name: */ +template class CInstructionLabel - : public CInstruction + : public CInstruction { + typedef CInstruction super; + public: CInstructionLabel() - : CInstruction("label") + : CInstruction("label") {} CInstructionLabel *factory() @@ -323,7 +591,7 @@ class CInstructionLabel void compile(std::list& params) {} - void execute(CCPU *cpu) + void execute(CCPU *cpu) {} }; @@ -336,12 +604,15 @@ class CInstructionLabel * Syntax: jumpa labelname * (jump to labelname) */ +template class CInstructionJumpA - : public CInstruction + : public CInstruction { + typedef CInstruction super; + public: CInstructionJumpA() - : CInstruction("jumpa"), m_addr("") + : CInstruction("jumpa"), m_addr("") {} CInstructionJumpA *factory() @@ -350,13 +621,37 @@ class CInstructionJumpA } void compile(std::list& params); - void execute(CCPU *cpu); + void execute(CCPU *cpu); protected: /** labelname */ std::string m_addr; }; +/*----------------------------------------------------------------------------*/ + +template +void CInstructionJumpA::compile(std::list& params) +{ + if (params.size() != 1) + throw std::runtime_error("Invalid paramater count - must be 1"); + m_addr = params.front(); + params.pop_front(); +} + +/*----------------------------------------------------------------------------*/ + +template +void CInstructionJumpA::execute(CCPU *cpu) +{ + assert(cpu != NULL); + assert(cpu->getRegisters() != NULL); + assert(cpu->getProgram() != NULL); + if (m_addr.empty()) + throw std::runtime_error("Empty address"); + cpu->getRegisters()[ 0 ] = cpu->getProgram()->findLabel(m_addr); +} + /*============================================================================*/ /** @@ -366,12 +661,15 @@ class CInstructionJumpA * Syntax: jumpz labelname * (jump to labelname if zeroflag) */ +template class CInstructionJumpZ - : public CInstruction + : public CInstruction { + typedef CInstruction super; + public: CInstructionJumpZ() - : CInstruction("jumpz"), m_addr("") + : CInstruction("jumpz"), m_addr("") {} CInstructionJumpZ *factory() @@ -380,13 +678,39 @@ class CInstructionJumpZ } void compile(std::list& params); - void execute(CCPU *cpu); + void execute(CCPU *cpu); protected: /** labelname */ std::string m_addr; }; +/*----------------------------------------------------------------------------*/ + +template +void CInstructionJumpZ::compile(std::list& params) +{ + if (params.size() != 1) + throw std::runtime_error("Invalid paramater count - must be 1"); + m_addr = params.front(); + params.pop_front(); +} + +/*----------------------------------------------------------------------------*/ + +template +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 std::runtime_error("Empty address"); + cpu->getRegisters()[ 0 ] = cpu->getProgram()->findLabel(m_addr); +} + /*============================================================================*/ /** @@ -396,12 +720,15 @@ class CInstructionJumpZ * Syntax: jumps labelname * (jump to labelname if signflag) */ +template class CInstructionJumpS - : public CInstruction + : public CInstruction { + typedef CInstruction super; + public: CInstructionJumpS() - : CInstruction("jumps"), m_addr("") + : CInstruction("jumps"), m_addr("") {} CInstructionJumpS *factory() @@ -410,13 +737,39 @@ class CInstructionJumpS } void compile(std::list& params); - void execute(CCPU *cpu); + void execute(CCPU *cpu); protected: /** labelname */ std::string m_addr; }; +/*----------------------------------------------------------------------------*/ + +template +void CInstructionJumpS::compile(std::list& params) +{ + if (params.size() != 1) + throw std::runtime_error("Invalid paramater count - must be 1"); + m_addr = params.front(); + params.pop_front(); +} + +/*----------------------------------------------------------------------------*/ + +template +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 std::runtime_error("Empty address"); + cpu->getRegisters()[ 0 ] = cpu->getProgram()->findLabel(m_addr); +} + /*============================================================================*/ /** @@ -426,12 +779,16 @@ class CInstructionJumpS * Syntax: write DEV, R1 * (write R1 to DEV, which is a name of a display) */ +template class CInstructionWrite - : public CInstruction + : public CInstruction { + typedef CInstruction super; + typedef typename std::set *>::iterator setiterator; + public: CInstructionWrite() - : CInstruction("write"), m_dev("") + : CInstruction("write"), m_dev("") {} CInstructionWrite *factory() @@ -440,7 +797,7 @@ class CInstructionWrite } void compile(std::list& params); - void execute(CCPU *cpu); + void execute(CCPU *cpu); protected: /** register number */ @@ -449,6 +806,46 @@ class CInstructionWrite std::string m_dev; }; +/*----------------------------------------------------------------------------*/ + +template +void CInstructionWrite::compile(std::list& params) +{ + if (params.size() != 2) + throw std::runtime_error("Invalid paramater count - must be 2"); + m_dev = params.front(); + params.pop_front(); + m_regidx1 = super::parseRegister(params.front()); + params.pop_front(); +} + +/*----------------------------------------------------------------------------*/ + +template +void CInstructionWrite::execute(CCPU *cpu) +{ + assert(cpu != NULL); + assert(cpu->getRegisters() != NULL); + super::checkRegister(cpu, m_regidx1); + if (m_dev.empty()) + throw std::runtime_error("Empty device"); + + CDisplay *display = NULL; + std::set *> displays = cpu->getDisplays(); + for(setiterator it = displays.begin(); it != displays.end(); ++it) + { + if ((*it)->getName() == m_dev) + { + display = *it; + break; + } + } + if (display == NULL) + throw std::runtime_error("Unknown display"); + + display->display(cpu->getRegisters()[ m_regidx1 ]); +} + #endif /* vim: set et sw=2 ts=2: */ diff --git a/ue4/mycpu/mycpu.cpp b/ue4/mycpu/mycpu.cpp index b25e721..6c9f71a 100644 --- a/ue4/mycpu/mycpu.cpp +++ b/ue4/mycpu/mycpu.cpp @@ -6,7 +6,7 @@ * be executed in linear order (except jumps) afterwards. In order to * initialize the memory of the cpu before execution an optional * memoryfile can be passed as commandline option. - * @date 13.05.2009 + * @date 26.05.2009 * @par Exercise * 4 */ @@ -16,9 +16,10 @@ #include #include #include -#include "ccpu.h" +#include "cdat.h" #include "cmem.h" #include "cprogram.h" +#include "ccpu.h" using namespace std; namespace po = boost::program_options; @@ -47,6 +48,7 @@ int main(int argc, char* argv[]) po::options_description desc("Allowed options"); desc.add_options() ("help,h", "this help message") + ("format,f", po::value(), "format") ("compile,c", po::value(), "input programfile") ("memory,m", po::value(), "input memoryfile"); @@ -65,13 +67,13 @@ int main(int argc, char* argv[]) /* print usage upon request or missing params */ if (vm.count("help") || !vm.count("compile")) { - cout << "Usage: " << me << " -c [-m ]" << endl; + cout << "Usage: " << me << " [-f ] -c [-m ]" << endl; cout << desc << endl; return 0; } /* create memory and optionally initialize memory from file */ - CMem memory; + CMem > memory; if (vm.count("memory")) { string memoryfile(vm["memory"].as()); @@ -101,7 +103,7 @@ int main(int argc, char* argv[]) } /* create program instance */ - CProgram program; + CProgram > program; string programfile(vm["compile"].as()); ifstream file(programfile.c_str(), ios::in); if (!file.is_open()) @@ -131,7 +133,7 @@ int main(int argc, char* argv[]) /* create cpu and execute the program */ try { - CCPU cpu(256); + CCPU > cpu(256); cpu.setMemory(&memory); cpu.setProgram(&program); cpu.run(); -- cgit v1.2.3