From f67834dd18859ed333c88360f4141a99dc7db5dd Mon Sep 17 00:00:00 2001 From: manuel Date: Thu, 28 May 2009 19:22:52 +0200 Subject: push for me --- .hgignore | 1 + ue4/doxygen.conf | 1 - ue4/mycpu/Makefile | 4 +- ue4/mycpu/ccpu.h | 128 ++++++++++----- ue4/mycpu/cdat.h | 70 +++++--- ue4/mycpu/cdatn.h | 382 +++++++++++++++++++++++++++++++++++++++++++ ue4/mycpu/cdatset.h | 56 +++++-- ue4/mycpu/cdisplay.h | 12 +- ue4/mycpu/cinstruction.h | 91 ++++++++--- ue4/mycpu/cmem.h | 65 +++++--- ue4/mycpu/cprogram.h | 76 ++++++--- ue4/mycpu/displays.h | 10 +- ue4/mycpu/instructions.h | 157 +++++++++--------- ue4/mycpu/mycpu.cpp | 212 +++++++++++++----------- ue4/mycpu/test/test.sh | 11 +- ue4/mycpu/test/test1_args | 1 + ue4/mycpu/test/test2_args | 1 + ue4/mycpu/test/test2_memory | 1 + ue4/mycpu/test/test2_output | 19 +++ ue4/mycpu/test/test2_program | 13 ++ ue4/mycpu/test/test3_args | 1 + ue4/mycpu/test/test3_memory | 1 + ue4/mycpu/test/test3_output | 21 +++ ue4/mycpu/test/test3_program | 13 ++ 24 files changed, 1013 insertions(+), 334 deletions(-) create mode 100644 ue4/mycpu/cdatn.h create mode 100644 ue4/mycpu/test/test1_args create mode 100644 ue4/mycpu/test/test2_args create mode 100644 ue4/mycpu/test/test2_memory create mode 100644 ue4/mycpu/test/test2_output create mode 100644 ue4/mycpu/test/test2_program create mode 100644 ue4/mycpu/test/test3_args create mode 100644 ue4/mycpu/test/test3_memory create mode 100644 ue4/mycpu/test/test3_output create mode 100644 ue4/mycpu/test/test3_program diff --git a/.hgignore b/.hgignore index b96a5d0..3896220 100644 --- a/.hgignore +++ b/.hgignore @@ -11,3 +11,4 @@ ue2/imgsynth/test/*_out* ue2/imgsynth2/imgsynth2 ue2/imgsynth2/test/*_out* ue3/mycpu/mycpu +ue4/mycpu/mycpu diff --git a/ue4/doxygen.conf b/ue4/doxygen.conf index d8b9773..c7dd94a 100644 --- a/ue4/doxygen.conf +++ b/ue4/doxygen.conf @@ -190,7 +190,6 @@ ALIASES += "func=\par Functionname:\n" ALIASES += "method=\par Methodname:\n" ALIASES += "globalvars=\par Global variables used:\n" #ALIASES += "exceptions=\par Exceptions thrown:\n" -ALIASES += "conditions=\par Conditions:\n" # Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C # sources only. Doxygen will then generate output that is more tailored for C. diff --git a/ue4/mycpu/Makefile b/ue4/mycpu/Makefile index 9e6db7a..bf4ebc8 100644 --- a/ue4/mycpu/Makefile +++ b/ue4/mycpu/Makefile @@ -7,13 +7,13 @@ LD= $(CXX) DEBUGFLAGS= -DNDEBUG INCLUDE_PATH= -I/usr/local/include CXXFLAGS= -O -ansi -pedantic-errors -Wall -Wno-long-long $(INCLUDE_PATH) $(DEBUGFLAGS) +CXXFLAGS= -ansi -pedantic-errors -Wall -Wno-long-long $(INCLUDE_PATH) $(DEBUGFLAGS) LDFLAGS= LIBS= -L/usr/local/lib -lboost_program_options BIN= mycpu OBJS= mycpu.o -HEADERS= cdat.h cdatn.h cdatset.h cmem.h cinstruction.h instructions.h \ - cprogram.h cdisplay.h displays.h ccpu.h +HEADERS= cdat.h cdatset.h cdatn.h cmem.h cinstruction.h instructions.h cprogram.h cdisplay.h displays.h ccpu.h .SUFFIXES: .cpp .o diff --git a/ue4/mycpu/ccpu.h b/ue4/mycpu/ccpu.h index 545b870..7257a87 100644 --- a/ue4/mycpu/ccpu.h +++ b/ue4/mycpu/ccpu.h @@ -16,13 +16,37 @@ # include # include #endif -#include "cdat.h" + +/** + * @class CCPUError + * + * Exception thrown by implemententations of CCPU + */ +class CCPUError + : public std::invalid_argument +{ + public: + /** + * @method CCPUError + * @brief Default exception ctor + * @param what message to pass along + * @return - + * @globalvars none + * @exception none + * @pre none + * @post none + */ + CCPUError(const std::string& what) + : std::invalid_argument(what) + {} +}; + #include "cmem.h" #include "displays.h" #include "cprogram.h" /* forward declare CProgram */ -template , int width=0> +template class CProgram; /** @@ -31,7 +55,7 @@ class CProgram; * CPU implementation. Used as a container for memory and instructions. * Implements a run method to execute the program (= the instructions). */ -template, int width=0> +template class CCPU { typedef typename std::set *>::iterator displayiterator; @@ -44,9 +68,10 @@ class CCPU * @return - * @globalvars none * @exception none - * @conditions none + * @pre none + * @post none */ - CCPU(const unsigned cnt); + CCPU(const unsigned cnt, T& datatype); /** * @method ~CCPU @@ -55,7 +80,8 @@ class CCPU * @return - * @globalvars none * @exception none - * @conditions none + * @pre none + * @post none */ ~CCPU(); @@ -66,7 +92,8 @@ class CCPU * @return number of registers * @globalvars none * @exception none - * @conditions none + * @pre none + * @post none */ const unsigned getRegisterCount() const { @@ -75,14 +102,15 @@ class CCPU /** * @method getRegisters - * @brief get pointer to registers array + * @brief get reference to registers vector * @param - - * @return pointer to registers array + * @return reference to registers vector * @globalvars none * @exception none - * @conditions none + * @pre none + * @post none */ - T *getRegisters() const + std::vector &getRegisters() { return m_registers; } @@ -94,7 +122,8 @@ class CCPU * @return - * @globalvars none * @exception none - * @conditions none + * @pre none + * @post none */ void setMemory(CMem *memory) { @@ -108,7 +137,8 @@ class CCPU * @return pointer to memory * @globalvars none * @exception none - * @conditions none + * @pre none + * @post none */ CMem *getMemory() const { @@ -122,7 +152,8 @@ class CCPU * @return - * @globalvars none * @exception none - * @conditions none + * @pre none + * @post none */ void setProgram(const CProgram *program) { @@ -136,7 +167,8 @@ class CCPU * @return pointer to program * @globalvars none * @exception none - * @conditions none + * @pre none + * @post none */ const CProgram *getProgram() { @@ -150,7 +182,8 @@ class CCPU * @return reference to set of pointers to displays * @globalvars none * @exception none - * @conditions none + * @pre none + * @post none */ const std::set *>& getDisplays() { @@ -164,7 +197,8 @@ class CCPU * @return - * @globalvars none * @exception none - * @conditions none + * @pre none + * @post none */ void setFlagZero(const bool value) { @@ -178,7 +212,8 @@ class CCPU * @return value of zero flag * @globalvars none * @exception none - * @conditions none + * @pre none + * @post none */ const bool getFlagZero() { @@ -192,7 +227,8 @@ class CCPU * @return - * @globalvars none * @exception none - * @conditions none + * @pre none + * @post none */ void setFlagSign(const bool value) { @@ -206,7 +242,8 @@ class CCPU * @return value of sign flag * @globalvars none * @exception none - * @conditions none + * @pre none + * @post none */ const bool getFlagSign() { @@ -219,8 +256,9 @@ class CCPU * @param - * @return - * @globalvars none - * @exception std::runtime_error - * @conditions none + * @exception CCPUError + * @pre none + * @post none */ void run(); @@ -232,14 +270,16 @@ class CCPU * @return void * @globalvars none * @exception none - * @conditions none + * @pre none + * @post none */ void dumpRegisters(std::ostream& out); #endif private: /* members */ - T *m_registers; + T m_datatype; + std::vector m_registers; unsigned m_regcnt; CMem *m_memory; const CProgram *m_program; @@ -250,15 +290,10 @@ class CCPU /*----------------------------------------------------------------------------*/ -template -CCPU::CCPU(const unsigned cnt) - : m_regcnt(cnt), m_memory(NULL), m_program(NULL), m_flagzero(false), m_flagsign(false) +template +CCPU::CCPU(const unsigned cnt, T& datatype) + : m_datatype(datatype), m_registers(cnt, T(m_datatype) = 0), 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); @@ -266,13 +301,9 @@ CCPU::CCPU(const unsigned cnt) /*----------------------------------------------------------------------------*/ -template +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; @@ -280,15 +311,15 @@ CCPU::~CCPU() /*----------------------------------------------------------------------------*/ -template +template void CCPU::run() { if (m_memory == NULL) - throw std::runtime_error("CPU has no memory"); + throw CCPUError("CPU has no memory"); if (m_program == NULL) - throw std::runtime_error("CPU has no program to execute"); + throw CCPUError("CPU has no program to execute"); if (m_regcnt == 0) - throw std::runtime_error("CPU has no registers"); + throw CCPUError("CPU has no registers"); bool run = true; while(run) @@ -301,18 +332,25 @@ void CCPU::run() /* pc is out of bound */ if (pc > m_program->size()) - throw std::runtime_error("Programcounter is out of bound"); + throw CCPUError("Programcounter is out of bound"); /* execute instruction */ - (*m_program->at(pc))(this); - ++m_registers[0]; + try + { + (*m_program->at(pc))(this); + ++m_registers[0]; + } + catch(CInstructionError& ex) + { + throw CCPUError(ex.what()); + } } } /*----------------------------------------------------------------------------*/ #if DEBUG -template +template void CCPU::dumpRegisters(std::ostream& out) { out << "[REGISTER DUMP]" << std::endl; diff --git a/ue4/mycpu/cdat.h b/ue4/mycpu/cdat.h index ca9d745..a5f2ce0 100644 --- a/ue4/mycpu/cdat.h +++ b/ue4/mycpu/cdat.h @@ -18,7 +18,7 @@ */ template class CDat - : boost::operators > + : public boost::operators > { public: /** @@ -28,7 +28,8 @@ class CDat * @return - * @globalvars none * @exception bad_alloc - * @conditions none + * @pre none + * @post none */ CDat() {} @@ -40,9 +41,10 @@ class CDat * @return - * @globalvars none * @exception none - * @conditions none + * @pre none + * @post none */ - ~CDat() + virtual ~CDat() {} /** @@ -52,7 +54,8 @@ class CDat * @return - * @globalvars none * @exception none - * @conditions none + * @pre none + * @post none */ CDat(const CDat& other) : m_value(other.m_value) @@ -60,14 +63,15 @@ class CDat /** * @method CDat - * @brief Copy constructor for int + * @brief Copy constructor for T * @param newval new value for CDat * @return - * @globalvars none * @exception none - * @conditions none + * @pre none + * @post none */ - CDat(T newval) + CDat(const T newval) : m_value(newval) {} @@ -78,7 +82,8 @@ class CDat * @return value of CDat * @globalvars none * @exception none - * @conditions none + * @pre none + * @post none */ T getValue() const { @@ -92,7 +97,8 @@ class CDat * @return T * @globalvars none * @exception none - * @conditions none + * @pre none + * @post none */ operator T() { @@ -106,7 +112,8 @@ class CDat * @return true if cdat is less than object x * @globalvars none * @exception none - * @conditions none + * @pre none + * @post none */ bool operator<(const CDat& x) const { @@ -120,7 +127,8 @@ class CDat * @return true if cdat equals object x * @globalvars none * @exception none - * @conditions none + * @pre none + * @post none */ bool operator==(const CDat& x) const { @@ -134,7 +142,8 @@ class CDat * @return refecence to CDat * @globalvars none * @exception none - * @conditions none + * @pre none + * @post none */ CDat& operator+=(const CDat& x) { @@ -149,7 +158,8 @@ class CDat * @return refecence to CDat * @globalvars none * @exception none - * @conditions none + * @pre none + * @post none */ CDat& operator-=(const CDat& x) { @@ -164,7 +174,8 @@ class CDat * @return refecence to CDat * @globalvars none * @exception none - * @conditions none + * @pre none + * @post none */ CDat& operator*=(const CDat& x) { @@ -179,7 +190,8 @@ class CDat * @return refecence to CDat * @globalvars none * @exception none - * @conditions none + * @pre none + * @post none */ CDat& operator/=(const CDat& x) { @@ -194,7 +206,8 @@ class CDat * @return refecence to CDat * @globalvars none * @exception none - * @conditions none + * @pre none + * @post none */ CDat& operator%=(const CDat& x) { @@ -209,7 +222,8 @@ class CDat * @return refecence to CDat * @globalvars none * @exception none - * @conditions none + * @pre none + * @post none */ CDat& operator|=(const CDat& x) { @@ -224,7 +238,8 @@ class CDat * @return refecence to CDat * @globalvars none * @exception none - * @conditions none + * @pre none + * @post none */ CDat& operator&=(const CDat& x) { @@ -239,7 +254,8 @@ class CDat * @return refecence to CDat * @globalvars none * @exception none - * @conditions none + * @pre none + * @post none */ CDat& operator^=(const CDat& x) { @@ -254,7 +270,8 @@ class CDat * @return refecence to CDat * @globalvars none * @exception none - * @conditions none + * @pre none + * @post none */ CDat& operator++() { @@ -269,7 +286,8 @@ class CDat * @return refecence to CDat * @globalvars none * @exception none - * @conditions none + * @pre none + * @post none */ CDat& operator--() { @@ -285,7 +303,8 @@ class CDat * @return reference to outputstream * @globalvars none * @exception none - * @conditions none + * @pre none + * @post none */ friend std::ostream& operator<<(std::ostream& stream, CDat cdat) { @@ -301,7 +320,8 @@ class CDat * @return reference to inputstream * @globalvars none * @exception none - * @conditions none + * @pre none + * @post none */ friend std::istream& operator>>(std::istream & stream, CDat& cdat) { @@ -309,7 +329,7 @@ class CDat return stream; } - private: + protected: /* members */ T m_value; }; diff --git a/ue4/mycpu/cdatn.h b/ue4/mycpu/cdatn.h new file mode 100644 index 0000000..32d8d7b --- /dev/null +++ b/ue4/mycpu/cdatn.h @@ -0,0 +1,382 @@ +/** + * @module cdatn + * @author Guenther Neuwirth (0626638), Manuel Mausz (0728348) + * @brief Datatype template and datatype definition for CCPU and CMem + * @date 26.05.2009 + */ + +#ifndef CDATN_H +#define CDATN_H 1 + +#include +#include + +/** + * @class CDatN + * + * Datatype template for CCPU and CMem. + */ +class CDatN + : public boost::operators +{ + private: + /** + * @method CDatN + * @brief Default ctor + * @param - + * @return - + * @globalvars none + * @exception bad_alloc + * @pre none + * @post none + */ + CDatN() + {} + + public: + /** + * @method ~CDatN + * @brief Default dtor + * @param - + * @return - + * @globalvars none + * @exception none + * @pre none + * @post none + */ + virtual ~CDatN() + {} + + /** + * @method CDatN + * @brief Copy constructor for CDatN + * @param other reference to CDatN which will be copied + * @return - + * @globalvars none + * @exception none + * @pre none + * @post none + */ + CDatN(const CDatN& other) + : m_value(other.m_value), m_width(other.m_width) + {} + + /** + * @method CDatN + * @brief Copy constructor for int + * @param newval new value for CDatN + * @param width maximum width + * @return - + * @globalvars none + * @exception none + * @pre none + * @post none + */ + CDatN(const int newval, unsigned width = 31) + : m_value(((1 << width) - 1) & newval), m_width(width) + {} + + /** + * @method getValue + * @brief returns value of CDatN + * @param - + * @return value of CDatN + * @globalvars none + * @exception none + * @pre none + * @post none + */ + int getValue() const + { + return m_value; + } + + /** + * @method operator int + * @brief convert to int + * @param - + * @return int + * @globalvars none + * @exception none + * @pre none + * @post none + */ + operator int() + { + return m_value; + } + + /** + * @method operator< + * @brief implementation of operator < + * @param x reference to CDatN + * @return true if cdat is less than object x + * @globalvars none + * @exception none + * @pre none + * @post none + */ + bool operator<(const CDatN& x) const + { + return m_value < x.m_value; + } + + /** + * @method operator== + * @brief implementation of operator == + * @param x reference to CDatN + * @return true if cdat equals object x + * @globalvars none + * @exception none + * @pre none + * @post none + */ + bool operator==(const CDatN& x) const + { + return m_value == x.m_value; + } + + /** + * @method operator= + * @brief implementation of operator = + * @param x reference to int + * @return refecence to int + * @globalvars none + * @exception none + * @pre none + * @post none + */ + CDatN &operator=(const int& newval) + { + m_value = newval; + align(); + return *this; + } + + /** + * @method operator+= + * @brief implementation of operator += + * @param x reference to CDatN + * @return refecence to CDatN + * @globalvars none + * @exception none + * @pre none + * @post none + */ + CDatN& operator+=(const CDatN& x) + { + m_value += x.m_value; + align(); + return *this; + } + + /** + * @method operator-= + * @brief implementation of operator -= + * @param x reference to CDatN + * @return refecence to CDatN + * @globalvars none + * @exception none + * @pre none + * @post none + */ + CDatN& operator-=(const CDatN& x) + { + m_value -= x.m_value; + align(); + return *this; + } + + /** + * @method operator*= + * @brief implementation of operator *= + * @param x reference to CDatN + * @return refecence to CDatN + * @globalvars none + * @exception none + * @pre none + * @post none + */ + CDatN& operator*=(const CDatN& x) + { + m_value *= x.m_value; + align(); + return *this; + } + + /** + * @method operator/= + * @brief implementation of operator /= + * @param x reference to CDatN + * @return refecence to CDatN + * @globalvars none + * @exception none + * @pre none + * @post none + */ + CDatN& operator/=(const CDatN& x) + { + m_value /= x.m_value; + align(); + return *this; + } + + /** + * @method operator%= + * @brief implementation of operator %= + * @param x reference to CDatN + * @return refecence to CDatN + * @globalvars none + * @exception none + * @pre none + * @post none + */ + CDatN& operator%=(const CDatN& x) + { + m_value %= x.m_value; + align(); + return *this; + } + + /** + * @method operator|= + * @brief implementation of operator |= + * @param x reference to CDatN + * @return refecence to CDatN + * @globalvars none + * @exception none + * @pre none + * @post none + */ + CDatN& operator|=(const CDatN& x) + { + m_value |= x.m_value; + align(); + return *this; + } + + /** + * @method operator&= + * @brief implementation of operator &= + * @param x reference to CDatN + * @return refecence to CDatN + * @globalvars none + * @exception none + * @pre none + * @post none + */ + CDatN& operator&=(const CDatN& x) + { + m_value &= x.m_value; + align(); + return *this; + } + + /** + * @method operator^= + * @brief implementation of operator ^= + * @param x reference to CDatN + * @return refecence to CDatN + * @globalvars none + * @exception none + * @pre none + * @post none + */ + CDatN& operator^=(const CDatN& x) + { + m_value ^= x.m_value; + align(); + return *this; + } + + /** + * @method operator++ + * @brief implementation of operator ++ + * @param - + * @return refecence to CDatN + * @globalvars none + * @exception none + * @pre none + * @post none + */ + CDatN& operator++() + { + m_value++; + align(); + return *this; + } + + /** + * @method operator-- + * @brief implementation of operator -- + * @param - + * @return refecence to CDatN + * @globalvars none + * @exception none + * @pre none + * @post none + */ + CDatN& operator--() + { + m_value--; + return *this; + } + + /** + * @method operator<< + * @brief Shift/output operator for outputstream + * @param stream reference to outputstream + * @param cdat 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, CDatN cdat) + { + stream << cdat.m_value; + return stream; + } + + /** + * @method operator>> + * @brief Shift/read operator for inputstream + * @param stream reference to inputstream + * @param cdat reference to object which will be read from stream + * @return reference to inputstream + * @globalvars none + * @exception none + * @pre none + * @post none + */ + friend std::istream& operator>>(std::istream & stream, CDatN& cdat) + { + stream >> cdat.m_value; + cdat.align(); + return stream; + } + + protected: + /** + * @method align + * @brief aligns value by width + * @return - + * @globalvars none + * @exception none + * @pre none + * @post none + */ + inline void align() + { + m_value &= ((1 << m_width) - 1); + } + + /* members */ + int m_value; + unsigned m_width; +}; + +#endif + +/* vim: set et sw=2 ts=2: */ diff --git a/ue4/mycpu/cdatset.h b/ue4/mycpu/cdatset.h index 03e71f4..56a0630 100644 --- a/ue4/mycpu/cdatset.h +++ b/ue4/mycpu/cdatset.h @@ -1,5 +1,5 @@ /** - * @module cdat + * @module cdatset * @author Guenther Neuwirth (0626638), Manuel Mausz (0728348) * @brief Datatype template and datatype definition for CCPU and CMem * @date 26.05.2009 @@ -8,19 +8,45 @@ #ifndef CDATSET_H #define CDATSET_H 1 -#include #include +#include "cdat.h" /** - * @class CDat + * @class CDatSet * * Datatype template for CCPU and CMem. */ -template class CDatSet - : public CDat + : public CDat, public boost::operators { public: + /** + * @method CDatSet + * @brief Default ctor + * @param - + * @return - + * @globalvars none + * @exception bad_alloc + * @pre none + * @post none + */ + CDatSet() + {} + + /** + * @method CDatSet + * @brief Copy constructor for int + * @param newval new value for CDatSet + * @return - + * @globalvars none + * @exception none + * @pre none + * @post none + */ + CDatSet(const int newval) + : CDat(newval) + {} + /** * @method operator>> * @brief Shift/read operator for inputstream @@ -29,19 +55,23 @@ class CDatSet * @return reference to inputstream * @globalvars none * @exception none - * @conditions none + * @pre none + * @post none */ friend std::istream& operator>>(std::istream & stream, CDatSet& cdat) { - std::string s; - stream >> s; - cdat.m_value = s.size(); + unsigned count = 0; + while(stream.good() && !stream.eof()) + { + int val = stream.get(); + if (val != 'o') + break; + ++count; + } + stream.clear(); + cdat.m_value = count; return stream; } - - private: - /* members */ - T m_value; }; #endif diff --git a/ue4/mycpu/cdisplay.h b/ue4/mycpu/cdisplay.h index 8d15eb9..7108442 100644 --- a/ue4/mycpu/cdisplay.h +++ b/ue4/mycpu/cdisplay.h @@ -24,7 +24,8 @@ class CDisplay * @return - * @globalvars none * @exception none - * @conditions none + * @pre none + * @post none */ CDisplay(std::string name) : m_name(name) @@ -37,7 +38,8 @@ class CDisplay * @return - * @globalvars none * @exception none - * @conditions none + * @pre none + * @post none */ virtual ~CDisplay() {} @@ -49,7 +51,8 @@ class CDisplay * @return name of display * @globalvars none * @exception none - * @conditions none + * @pre none + * @post none */ virtual const std::string& getName() { @@ -63,7 +66,8 @@ class CDisplay * @return - * @globalvars none * @exception none - * @conditions none + * @pre none + * @post none */ virtual void display(const T &value) = 0; diff --git a/ue4/mycpu/cinstruction.h b/ue4/mycpu/cinstruction.h index a2e3743..85122b4 100644 --- a/ue4/mycpu/cinstruction.h +++ b/ue4/mycpu/cinstruction.h @@ -1,7 +1,7 @@ /** * @module cinstruction * @author Guenther Neuwirth (0626638), Manuel Mausz (0728348) - * @brief Abstract class for displays + * @brief Abstract class for instructions * @date 26.05.2009 */ @@ -11,21 +11,46 @@ #include #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 +template class CCPU; /** * @class CInstruction * - * Abstract class for displays + * Abstract class for instructions */ -template, int width=0> +template class CInstruction { public: @@ -36,7 +61,8 @@ class CInstruction * @return - * @globalvars none * @exception none - * @conditions none + * @pre none + * @post none */ CInstruction(std::string name) : m_name(name) @@ -49,7 +75,8 @@ class CInstruction * @return - * @globalvars none * @exception none - * @conditions none + * @pre none + * @post none */ virtual ~CInstruction() {} @@ -61,7 +88,8 @@ class CInstruction * @return true if instructionname is name * @globalvars none * @exception none - * @conditions none + * @pre none + * @post none */ virtual bool operator==(std::string& name) { @@ -74,8 +102,9 @@ class CInstruction * @param cpu pointer to cpu * @return - * @globalvars none - * @exception std::runtime_error - * @conditions none + * @exception CInstructionError + * @pre none + * @post none */ virtual CInstruction& operator()(CCPU *cpu) { @@ -90,7 +119,8 @@ class CInstruction * @return name of instruction * @globalvars none * @exception none - * @conditions none + * @pre none + * @post none */ virtual const std::string& getName() { @@ -104,7 +134,8 @@ class CInstruction * @return reference to outputstream * @globalvars none * @exception none - * @conditions none + * @pre none + * @post none */ virtual std::ostream& dump(std::ostream& stream) { @@ -120,7 +151,8 @@ class CInstruction * @return reference to outputstream * @globalvars none * @exception none - * @conditions none + * @pre none + * @post none */ friend std::ostream& operator<<(std::ostream& stream, CInstruction& instr) { @@ -133,8 +165,9 @@ class CInstruction * @param str register in assembler syntax * @return registernumber * @globalvars none - * @exception std::runtime_error - * @conditions none + * @exception CInstructionError + * @pre none + * @post none */ virtual const unsigned parseRegister(const std::string& str); @@ -146,8 +179,9 @@ class CInstruction * @param regidx registernumber * @return - * @globalvars none - * @exception std::runtime_error - * @conditions none + * @exception CInstructionError + * @pre none + * @post none */ virtual void checkRegister(CCPU *cpu, const unsigned regidx); @@ -158,7 +192,8 @@ class CInstruction * @return new instruction instance * @globalvars none * @exception none - * @conditions none + * @pre none + * @post none */ virtual CInstruction *factory() = 0; @@ -169,8 +204,9 @@ class CInstruction * @param params list of parameters of this instruction * @return - * @globalvars none - * @exception std::runtime_error - * @conditions none + * @exception CInstructionError + * @pre none + * @post none */ virtual void compile(std::list& params) = 0; @@ -180,8 +216,9 @@ class CInstruction * @param cpu pointer to cpu * @return - * @globalvars none - * @exception std::runtime_error - * @conditions none + * @exception CInstructionError + * @pre none + * @post none */ virtual void execute(CCPU *cpu) = 0; @@ -193,12 +230,12 @@ class CInstruction /*----------------------------------------------------------------------------*/ -template, int width=0> +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"); + throw CInstructionError("Invalid syntax of register"); try { @@ -206,7 +243,7 @@ const unsigned CInstruction::parseRegister(const std::string& str) } catch(boost::bad_lexical_cast& ex) { - throw std::runtime_error("Invalid syntax of register"); + throw CInstructionError("Invalid syntax of register"); } return reg; @@ -214,7 +251,7 @@ const unsigned CInstruction::parseRegister(const std::string& str) /*----------------------------------------------------------------------------*/ -template, int width=0> +template inline void CInstruction::checkRegister(CCPU *cpu, const unsigned regidx) { assert(cpu != NULL); @@ -222,7 +259,7 @@ inline void CInstruction::checkRegister(CCPU *cpu, const unsigned regidx) { std::stringstream sstr; sstr << "Register R" << regidx << " doesn't exist (out of bound)"; - throw std::runtime_error(sstr.str()); + throw CInstructionError(sstr.str()); } } diff --git a/ue4/mycpu/cmem.h b/ue4/mycpu/cmem.h index c6b8735..3f35a70 100644 --- a/ue4/mycpu/cmem.h +++ b/ue4/mycpu/cmem.h @@ -12,21 +12,43 @@ #include #include #include -#include -#include #ifdef DEBUG # include # include #endif +/** + * @class CMemError + * + * Exception thrown by implemententations of CMem + */ +class CMemError + : public std::invalid_argument +{ + public: + /** + * @method CMemError + * @brief Default exception ctor + * @param what message to pass along + * @return - + * @globalvars none + * @exception none + * @pre none + * @post none + */ + CMemError(const std::string& what) + : std::invalid_argument(what) + {} +}; + /** * @class CMem * * Extends std::vector template for use as memory for CCPU. */ -template, int width=0> +template class CMem - : public std::vector + : public std::vector { typedef std::vector super; typedef typename super::iterator iterator; @@ -39,13 +61,15 @@ class CMem * @method initialize * @brief initialize the vector with the content of istream. istream is * read per line. empty lines will add unitialized elements. - * @param in inputstream to read from + * @param in inputstream to read from + * @param datatype reference instance of datatype to copy from * @return void * @globalvars none - * @exception std::runtime_error - * @conditions none + * @exception CMemError + * @pre none + * @post none */ - void initialize(std::istream& in) + void initialize(std::istream& in, T& datatype) { if (!in.good()) return; @@ -56,24 +80,22 @@ class CMem { ++i; std::getline(in, line); - boost::algorithm::trim(line); - + /* skip last line if it's empty */ if (line.empty() && in.eof()) break; - T value; - try - { + T value(datatype); if (!line.empty()) { - value = boost::lexical_cast(line); - } - catch(boost::bad_lexical_cast& ex) - { - std::stringstream sstr; - sstr << "Unable to convert input (line " << i << "): " << ex.what(); - throw std::runtime_error(sstr.str()); + /* simple boost::lexical_cast replacement */ + std::stringstream interpreter; + if(!(interpreter << line && interpreter >> value && interpreter.get() == std::char_traits::eof())) + { + std::stringstream sstr; + sstr << "Unable to convert input (line " << i << ") to datatype"; + throw CMemError(sstr.str()); + } } push_back(value); @@ -88,7 +110,8 @@ class CMem * @return void * @globalvars none * @exception none - * @conditions none + * @pre none + * @post none */ void dump(std::ostream& out) { diff --git a/ue4/mycpu/cprogram.h b/ue4/mycpu/cprogram.h index d8f7d5e..6908db7 100644 --- a/ue4/mycpu/cprogram.h +++ b/ue4/mycpu/cprogram.h @@ -11,17 +11,43 @@ #include #include #include +#include #include #include #ifdef DEBUG # include # include #endif + +/** + * @class CProgramError + * + * Exception thrown by implemententations of CProgram + */ +class CProgramError + : public std::invalid_argument +{ + public: + /** + * @method CProgramError + * @brief Default exception ctor + * @param what message to pass along + * @return - + * @globalvars none + * @exception none + * @pre none + * @post none + */ + CProgramError(const std::string& what) + : std::invalid_argument(what) + {} +}; + #include "cinstruction.h" #include "instructions.h" /* forward declare CInstruction */ -template, int width=0> +template class CInstruction; /** @@ -30,9 +56,9 @@ class CInstruction; * CProgram extends std::vector and adds a method for parsing * programfile. This adds instances of CInstruction to CProgram itself. */ -template, int width=0> +template class CProgram - : public std::vector *> + : public std::vector *> { typedef typename std::set *>::iterator setiterator; typedef std::vector *> super; @@ -49,7 +75,8 @@ class CProgram * @return - * @globalvars none * @exception none - * @conditions none + * @pre none + * @post none */ CProgram(); @@ -60,7 +87,8 @@ class CProgram * @return - * @globalvars none * @exception none - * @conditions none + * @pre none + * @post none */ ~CProgram(); @@ -71,7 +99,8 @@ class CProgram * @return reference to labels map * @globalvars none * @exception none - * @conditions none + * @pre none + * @post none */ const std::map& getLabels() const { @@ -84,8 +113,9 @@ class CProgram * @param label name of label to search for * @return index of found label in program * @globalvars none - * @exception std::runtime_error - * @conditions none + * @exception CProgramError + * @pre none + * @post none */ unsigned findLabel(const std::string& label) const; @@ -95,8 +125,9 @@ class CProgram * @param in inputstream to read from * @return void * @globalvars none - * @exception std::runtime_error - * @conditions none + * @exception CProgramError + * @pre none + * @post none */ void compile(std::istream& in); @@ -108,7 +139,8 @@ class CProgram * @return void * @globalvars none * @exception none - * @conditions none + * @pre none + * @post none */ void dump(std::ostream& out); #endif @@ -122,7 +154,7 @@ class CProgram /*----------------------------------------------------------------------------*/ -template, int width=0> +template CProgram::CProgram() { m_instrset.insert(new CInstructionInc); @@ -143,7 +175,7 @@ CProgram::CProgram() /*----------------------------------------------------------------------------*/ -template, int width=0> +template CProgram::~CProgram() { /* free instruction set */ @@ -157,7 +189,7 @@ CProgram::~CProgram() /*----------------------------------------------------------------------------*/ -template, int width=0> +template void CProgram::compile(std::istream& in) { if (!in.good()) @@ -200,7 +232,7 @@ void CProgram::compile(std::istream& in) { std::stringstream sstr; sstr << "Unknown instruction '" << instrname << "' on line " << i << "."; - throw std::runtime_error(sstr.str()); + throw CProgramError(sstr.str()); } /* create instruction */ @@ -219,20 +251,20 @@ void CProgram::compile(std::istream& in) if (instrname == "label") { if (instrparams.size() != 1) - throw std::runtime_error("Invalid paramater count - must be 1"); + throw CInstructionError("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"); + throw CInstructionError("Label has invalid syntax"); m_labels[ label.substr(0, label.length() - 1) ] = size(); } instr->compile(instrparams); } - catch(std::runtime_error& ex) + catch(CInstructionError& ex) { std::stringstream sstr; sstr << "Unable to compile instruction '" << instrname << "' (line " << i << "): " << ex.what(); - throw std::runtime_error(sstr.str()); + throw CProgramError(sstr.str()); } push_back(instr); @@ -241,20 +273,20 @@ void CProgram::compile(std::istream& in) /*----------------------------------------------------------------------------*/ -template, int width=0> +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 + "'"); + throw CProgramError("Unknown label '" + label + "'"); return it->second; } /*----------------------------------------------------------------------------*/ #if DEBUG -template, int width=0> +template void CProgram::dump(std::ostream& out) { out << "[PROGRAM DUMP]" << std::endl; diff --git a/ue4/mycpu/displays.h b/ue4/mycpu/displays.h index 33d81bb..123547f 100644 --- a/ue4/mycpu/displays.h +++ b/ue4/mycpu/displays.h @@ -19,7 +19,7 @@ */ template class CDisplayWDEZ - : public CDisplay + : public CDisplay { public: CDisplayWDEZ() @@ -33,7 +33,8 @@ class CDisplayWDEZ * @return - * @globalvars none * @exception none - * @conditions none + * @pre none + * @post none */ void display(const T &value) { @@ -51,7 +52,7 @@ class CDisplayWDEZ */ template class CDisplayWHEX - : public CDisplay + : public CDisplay { public: CDisplayWHEX() @@ -65,7 +66,8 @@ class CDisplayWHEX * @return - * @globalvars none * @exception none - * @conditions none + * @pre none + * @post none */ void display(const T &value) { diff --git a/ue4/mycpu/instructions.h b/ue4/mycpu/instructions.h index 3f2fd51..fd547aa 100644 --- a/ue4/mycpu/instructions.h +++ b/ue4/mycpu/instructions.h @@ -19,9 +19,9 @@ * Syntax: inc R1 * (R1++) */ -template, int width=0> +template class CInstructionInc - : public CInstruction + : public CInstruction { typedef CInstruction super; @@ -45,22 +45,21 @@ class CInstructionInc /*----------------------------------------------------------------------------*/ -template, int width=0> +template void CInstructionInc::compile(std::list& params) { if (params.size() != 1) - throw std::runtime_error("Invalid paramater count - must be 1"); + throw CInstructionError("Invalid paramater count - must be 1"); m_regidx1 = super::parseRegister(params.front()); params.pop_front(); } /*----------------------------------------------------------------------------*/ -template, int width=0> +template void CInstructionInc::execute(CCPU *cpu) { assert(cpu != NULL); - assert(cpu->getRegisters() != NULL); super::checkRegister(cpu, m_regidx1); cpu->getRegisters()[ m_regidx1 ]++; } @@ -74,7 +73,7 @@ void CInstructionInc::execute(CCPU *cpu) * Syntax: dec R1 * (R1--) */ -template, int width=0> +template class CInstructionDec : public CInstruction { @@ -100,22 +99,21 @@ class CInstructionDec /*----------------------------------------------------------------------------*/ -template, int width=0> +template void CInstructionDec::compile(std::list& params) { if (params.size() != 1) - throw std::runtime_error("Invalid paramater count - must be 1"); + throw CInstructionError("Invalid paramater count - must be 1"); m_regidx1 = super::parseRegister(params.front()); params.pop_front(); } /*----------------------------------------------------------------------------*/ -template, int width=0> +template void CInstructionDec::execute(CCPU *cpu) { assert(cpu != NULL); - assert(cpu->getRegisters() != NULL); super::checkRegister(cpu, m_regidx1); cpu->getRegisters()[ m_regidx1 ]--; } @@ -129,7 +127,7 @@ void CInstructionDec::execute(CCPU *cpu) * Syntax: add R1, R2, R3 * (R1 = R2 + R3) */ -template, int width=0> +template class CInstructionAdd : public CInstruction { @@ -159,11 +157,11 @@ class CInstructionAdd /*----------------------------------------------------------------------------*/ -template, int width=0> +template void CInstructionAdd::compile(std::list& params) { if (params.size() != 3) - throw std::runtime_error("Invalid paramater count - must be 3"); + throw CInstructionError("Invalid paramater count - must be 3"); m_regidx1 = super::parseRegister(params.front()); params.pop_front(); m_regidx2 = super::parseRegister(params.front()); @@ -174,11 +172,10 @@ void CInstructionAdd::compile(std::list& params) /*----------------------------------------------------------------------------*/ -template, int width=0> +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); @@ -195,7 +192,7 @@ void CInstructionAdd::execute(CCPU *cpu) * Syntax: sub R1, R2, R3 * (R1 = R2 - R3) */ -template, int width=0> +template class CInstructionSub : public CInstruction { @@ -225,11 +222,11 @@ class CInstructionSub /*----------------------------------------------------------------------------*/ -template, int width=0> +template void CInstructionSub::compile(std::list& params) { if (params.size() != 3) - throw std::runtime_error("Invalid paramater count - must be 3"); + throw CInstructionError("Invalid paramater count - must be 3"); m_regidx1 = super::parseRegister(params.front()); params.pop_front(); m_regidx2 = super::parseRegister(params.front()); @@ -240,11 +237,10 @@ void CInstructionSub::compile(std::list& params) /*----------------------------------------------------------------------------*/ -template, int width=0> +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); @@ -261,7 +257,7 @@ void CInstructionSub::execute(CCPU *cpu) * Syntax: mul R1, R2, R3 * (R1 = R2 * R3) */ -template, int width=0> +template class CInstructionMul : public CInstruction { @@ -291,11 +287,11 @@ class CInstructionMul /*----------------------------------------------------------------------------*/ -template, int width=0> +template void CInstructionMul::compile(std::list& params) { if (params.size() != 3) - throw std::runtime_error("Invalid paramater count - must be 3"); + throw CInstructionError("Invalid paramater count - must be 3"); m_regidx1 = super::parseRegister(params.front()); params.pop_front(); m_regidx2 = super::parseRegister(params.front()); @@ -306,7 +302,7 @@ void CInstructionMul::compile(std::list& params) /*----------------------------------------------------------------------------*/ -template, int width=0> +template void CInstructionMul::execute(CCPU *cpu) { super::checkRegister(cpu, m_regidx1); @@ -325,7 +321,7 @@ void CInstructionMul::execute(CCPU *cpu) * Syntax: div R1, R2, R3 * (R1 = R2 / R3) */ -template, int width=0> +template class CInstructionDiv : public CInstruction { @@ -355,11 +351,11 @@ class CInstructionDiv /*----------------------------------------------------------------------------*/ -template, int width=0> +template void CInstructionDiv::compile(std::list& params) { if (params.size() != 3) - throw std::runtime_error("Invalid paramater count - must be 3"); + throw CInstructionError("Invalid paramater count - must be 3"); m_regidx1 = super::parseRegister(params.front()); params.pop_front(); m_regidx2 = super::parseRegister(params.front()); @@ -370,11 +366,10 @@ void CInstructionDiv::compile(std::list& params) /*----------------------------------------------------------------------------*/ -template, int width=0> +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); @@ -391,7 +386,7 @@ void CInstructionDiv::execute(CCPU *cpu) * Syntax: load R1, R2 * (R1 = memory[R2]) */ -template, int width=0> +template class CInstructionLoad : public CInstruction { @@ -419,11 +414,11 @@ class CInstructionLoad /*----------------------------------------------------------------------------*/ -template, int width=0> +template void CInstructionLoad::compile(std::list& params) { if (params.size() != 2) - throw std::runtime_error("Invalid paramater count - must be 2"); + throw CInstructionError("Invalid paramater count - must be 2"); m_regidx1 = super::parseRegister(params.front()); params.pop_front(); m_regidx2 = super::parseRegister(params.front()); @@ -432,11 +427,10 @@ void CInstructionLoad::compile(std::list& params) /*----------------------------------------------------------------------------*/ -template, int width=0> +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); @@ -453,7 +447,7 @@ void CInstructionLoad::execute(CCPU *cpu) * Syntax: store R1, R2 * (memory[R2] = R1) */ -template, int width=0> +template class CInstructionStore : public CInstruction { @@ -481,11 +475,11 @@ class CInstructionStore /*----------------------------------------------------------------------------*/ -template, int width=0> +template void CInstructionStore::compile(std::list& params) { if (params.size() != 2) - throw std::runtime_error("Invalid paramater count - must be 2"); + throw CInstructionError("Invalid paramater count - must be 2"); m_regidx1 = super::parseRegister(params.front()); params.pop_front(); m_regidx2 = super::parseRegister(params.front()); @@ -494,11 +488,10 @@ void CInstructionStore::compile(std::list& params) /*----------------------------------------------------------------------------*/ -template, int width=0> +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); @@ -515,7 +508,7 @@ void CInstructionStore::execute(CCPU *cpu) * Syntax: test R1 * (R1 == 0: zeroflag: true, R1 < 0: signflag: true) */ -template, int width=0> +template class CInstructionTest : public CInstruction { @@ -541,22 +534,21 @@ class CInstructionTest /*----------------------------------------------------------------------------*/ -template, int width=0> +template void CInstructionTest::compile(std::list& params) { if (params.size() != 1) - throw std::runtime_error("Invalid paramater count - must be 1"); + throw CInstructionError("Invalid paramater count - must be 1"); m_regidx1 = super::parseRegister(params.front()); params.pop_front(); } /*----------------------------------------------------------------------------*/ -template, int width=0> +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); @@ -572,7 +564,7 @@ void CInstructionTest::execute(CCPU *cpu) * Implementation of assembler command "label" * Syntax: label name: */ -template, int width=0> +template class CInstructionLabel : public CInstruction { @@ -604,7 +596,7 @@ class CInstructionLabel * Syntax: jumpa labelname * (jump to labelname) */ -template, int width=0> +template class CInstructionJumpA : public CInstruction { @@ -630,26 +622,32 @@ class CInstructionJumpA /*----------------------------------------------------------------------------*/ -template, int width=0> +template void CInstructionJumpA::compile(std::list& params) { if (params.size() != 1) - throw std::runtime_error("Invalid paramater count - must be 1"); + throw CInstructionError("Invalid paramater count - must be 1"); m_addr = params.front(); params.pop_front(); } /*----------------------------------------------------------------------------*/ -template, int width=0> +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); + throw CInstructionError("Empty address"); + try + { + cpu->getRegisters()[ 0 ] = cpu->getProgram()->findLabel(m_addr); + } + catch(CProgramError& ex) + { + throw CInstructionError(ex.what()); + } } /*============================================================================*/ @@ -661,7 +659,7 @@ void CInstructionJumpA::execute(CCPU *cpu) * Syntax: jumpz labelname * (jump to labelname if zeroflag) */ -template, int width=0> +template class CInstructionJumpZ : public CInstruction { @@ -687,28 +685,34 @@ class CInstructionJumpZ /*----------------------------------------------------------------------------*/ -template, int width=0> +template void CInstructionJumpZ::compile(std::list& params) { if (params.size() != 1) - throw std::runtime_error("Invalid paramater count - must be 1"); + throw CInstructionError("Invalid paramater count - must be 1"); m_addr = params.front(); params.pop_front(); } /*----------------------------------------------------------------------------*/ -template, int width=0> +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); + throw CInstructionError("Empty address"); + try + { + cpu->getRegisters()[ 0 ] = cpu->getProgram()->findLabel(m_addr); + } + catch(CProgramError& ex) + { + throw CInstructionError(ex.what()); + } } /*============================================================================*/ @@ -720,7 +724,7 @@ void CInstructionJumpZ::execute(CCPU *cpu) * Syntax: jumps labelname * (jump to labelname if signflag) */ -template, int width=0> +template class CInstructionJumpS : public CInstruction { @@ -746,28 +750,34 @@ class CInstructionJumpS /*----------------------------------------------------------------------------*/ -template, int width=0> +template void CInstructionJumpS::compile(std::list& params) { if (params.size() != 1) - throw std::runtime_error("Invalid paramater count - must be 1"); + throw CInstructionError("Invalid paramater count - must be 1"); m_addr = params.front(); params.pop_front(); } /*----------------------------------------------------------------------------*/ -template, int width=0> +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); + throw CInstructionError("Empty address"); + try + { + cpu->getRegisters()[ 0 ] = cpu->getProgram()->findLabel(m_addr); + } + catch(CProgramError& ex) + { + throw CInstructionError(ex.what()); + } } /*============================================================================*/ @@ -779,7 +789,7 @@ void CInstructionJumpS::execute(CCPU *cpu) * Syntax: write DEV, R1 * (write R1 to DEV, which is a name of a display) */ -template, int width=0> +template class CInstructionWrite : public CInstruction { @@ -808,11 +818,11 @@ class CInstructionWrite /*----------------------------------------------------------------------------*/ -template, int width=0> +template void CInstructionWrite::compile(std::list& params) { if (params.size() != 2) - throw std::runtime_error("Invalid paramater count - must be 2"); + throw CInstructionError("Invalid paramater count - must be 2"); m_dev = params.front(); params.pop_front(); m_regidx1 = super::parseRegister(params.front()); @@ -821,14 +831,13 @@ void CInstructionWrite::compile(std::list& params) /*----------------------------------------------------------------------------*/ -template, int width=0> +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"); + throw CInstructionError("Empty device"); CDisplay *display = NULL; std::set *> displays = cpu->getDisplays(); @@ -841,7 +850,7 @@ void CInstructionWrite::execute(CCPU *cpu) } } if (display == NULL) - throw std::runtime_error("Unknown display"); + throw CInstructionError("Unknown display"); display->display(cpu->getRegisters()[ m_regidx1 ]); } diff --git a/ue4/mycpu/mycpu.cpp b/ue4/mycpu/mycpu.cpp index 2d73177..ac4498a 100644 --- a/ue4/mycpu/mycpu.cpp +++ b/ue4/mycpu/mycpu.cpp @@ -12,20 +12,100 @@ */ #include +#include #include #include #include #include #include "cdat.h" -#include "cdatn.h" #include "cdatset.h" +#include "cdatn.h" +#include "ccpu.h" #include "cmem.h" #include "cprogram.h" -#include "ccpu.h" + +#define REGISTERS 256 using namespace std; namespace po = boost::program_options; +/* TODO */ +template +void cpu_run(string& me, po::variables_map& vm, unsigned registers, T& datatype) +{ + CMem memory; + /* optionally initialize memory from file */ + if (vm.count("memory")) + { + string memoryfile(vm["memory"].as()); + ifstream file(memoryfile.c_str(), ios::in); + if (!file.is_open()) + throw runtime_error("Unable to open memoryfile '" + memoryfile + "' for reading."); + + try + { + memory.initialize(file, datatype); + file.close(); + } + catch(CMemError& ex) + { + file.close(); + std::stringstream sstr; + sstr << "Error while reading from memoryfile:" << endl << " " << ex.what(); + throw runtime_error(sstr.str()); + } + +#if DEBUG + memory.dump(cerr); +#endif + } + + /* create program instance */ + CProgram program; + string programfile(vm["compile"].as()); + ifstream file(programfile.c_str(), ios::in); + if (!file.is_open()) + throw runtime_error("Unable to open programfile '" + programfile + "' for reading."); + + try + { + program.compile(file); + file.close(); + } + catch(CProgramError& ex) + { + file.close(); + std::stringstream sstr; + sstr << "Error while compiling programfile:" << endl << " " << ex.what(); + throw runtime_error(sstr.str()); + } + +#if DEBUG + program.dump(cerr); +#endif + + /* execute the program */ + CCPU cpu(registers, datatype); + try + { + cpu.setMemory(&memory); + cpu.setProgram(&program); + cpu.run(); +#if DEBUG + //cpu.dumpRegisters(cerr); +#endif + } + catch(CCPUError& ex) + { + std::stringstream sstr; + sstr << "Error while executing program:" << endl << " " << ex.what(); +#if DEBUG + memory.dump(cerr); +#endif + throw runtime_error(sstr.str()); + } +} + /** * @func main * @brief program entry point @@ -34,7 +114,8 @@ namespace po = boost::program_options; * @return 0 on success, not 0 otherwise * @globalvars none * @exception none - * @conditions none + * @pre none + * @post none * * parse commandline options, create and initialize memory, * create cprogram instance, which parses the programfile and @@ -50,7 +131,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") + ("format,f", po::value(), "input format") ("compile,c", po::value(), "input programfile") ("memory,m", po::value(), "input memoryfile"); @@ -64,6 +145,7 @@ int main(int argc, char* argv[]) catch(po::error& ex) { cerr << me << ": Error: " << ex.what() << endl; + return 1; } /* print usage upon request or missing params */ @@ -74,107 +156,49 @@ int main(int argc, char* argv[]) return 0; } - /* create memory and optionally initialize memory from file */ - - CMem *memory = NULL; - if (vm.count("format")) + /* create memory, program and cpu from templates */ + try { - string format(vm["format"].as()); - if(format == "s") - memory = new CMem >(); - else + if (vm.count("format")) { - try + string format(vm["format"].as()); + if (format == "s") { - int bc = boost::lexical_cast(format); - if (bc > 1 && bc < 33) - memory = new CMem >(); - } - catch(boost::bad_lexical_cast& ex) + CDatSet datatype(0); + cpu_run(me, vm, REGISTERS, datatype); + } + else { - std::stringstream sstr; - sstr << "Illegal format: (" << format << "): " << ex.what(); - throw std::runtime_error(sstr.str()); + unsigned bc; + try + { + bc = boost::lexical_cast(format); + } + catch(boost::bad_lexical_cast& ex) + { + cerr << me << ": Paramater 'format' has invalid or unknown format." << endl; + return 1; + } + + if (bc < 2 || bc > 31) + { + cerr << me << ": Paramater 'format' must be inbetween 2 and 32." << endl; + return 1; + } + + CDatN datatype(0, bc); + cpu_run(me, vm, REGISTERS, datatype); } } - } - else - - - if (vm.count("memory")) - { - string memoryfile(vm["memory"].as()); - ifstream file(memoryfile.c_str(), ios::in); - if (!file.is_open()) - { - cerr << me << ": Unable to open memoryfile '" << memoryfile << "' for reading." << endl; - return 1; - } - - try - { - memory->initialize(file); - file.close(); - } - catch(runtime_error& ex) + else { - file.close(); - cerr << me << ": Error while reading from memoryfile:" << endl - << " " << ex.what() << endl; - return 1; + CDat datatype(0); + cpu_run >(me, vm, REGISTERS, datatype); } - -#if DEBUG - memory->dump(cerr); -#endif - } - - /* create program instance */ - CProgram > program; - string programfile(vm["compile"].as()); - ifstream file(programfile.c_str(), ios::in); - if (!file.is_open()) - { - cerr << me << ": Unable to open programfile '" << programfile << "' for reading." << endl; - return 1; - } - - try - { - program.compile(file); - file.close(); - } - catch(runtime_error& ex) - { - file.close(); - cerr << me << ": Error while compiling programfile:" << endl - << " " << ex.what() << endl; - return 1; - } - -#if DEBUG - program.dump(cerr); -#endif - - - /* create cpu and execute the program */ - try - { - CCPU > cpu(256); - cpu.setMemory(memory); - cpu.setProgram(&program); - cpu.run(); -#if DEBUG - //cpu.dumpRegisters(cerr); -#endif } catch(runtime_error& ex) { - cerr << me << ": Error while executing program:" << endl - << " " << ex.what() << endl; -#if DEBUG - memory->dump(cerr); -#endif + cerr << me << ": " << ex.what() << endl; return 1; } diff --git a/ue4/mycpu/test/test.sh b/ue4/mycpu/test/test.sh index ff1076c..43ddb9a 100755 --- a/ue4/mycpu/test/test.sh +++ b/ue4/mycpu/test/test.sh @@ -10,13 +10,20 @@ do programfile="$input" args="-c $programfile" + argsfile="${input/_program/_args}" memoryfile="${input/_program/_memory}" reffile="${input/_program/_output}" - if [ -e "$memoryfile" ] + + if [ ! -e "$argsfile" ] then - args+=" -m $memoryfile" + echo " ERROR: argsfile $argsfile doesn't exist" + exit 1 fi + args=$(cat "$argsfile") + args=${args/\#program\#/$input} + args=${args/\#memory\#/$memoryfile} + if [ ! -e "$reffile" ] then echo " ERROR: reference file $reffile doesn't exist" diff --git a/ue4/mycpu/test/test1_args b/ue4/mycpu/test/test1_args new file mode 100644 index 0000000..c494f4e --- /dev/null +++ b/ue4/mycpu/test/test1_args @@ -0,0 +1 @@ +-c #program# -m #memory# diff --git a/ue4/mycpu/test/test2_args b/ue4/mycpu/test/test2_args new file mode 100644 index 0000000..1ef5766 --- /dev/null +++ b/ue4/mycpu/test/test2_args @@ -0,0 +1 @@ +-f s -c #program# -m #memory# diff --git a/ue4/mycpu/test/test2_memory b/ue4/mycpu/test/test2_memory new file mode 100644 index 0000000..bd9648e --- /dev/null +++ b/ue4/mycpu/test/test2_memory @@ -0,0 +1 @@ +oooooooooooooooooooo diff --git a/ue4/mycpu/test/test2_output b/ue4/mycpu/test/test2_output new file mode 100644 index 0000000..ac30dc2 --- /dev/null +++ b/ue4/mycpu/test/test2_output @@ -0,0 +1,19 @@ +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 diff --git a/ue4/mycpu/test/test2_program b/ue4/mycpu/test/test2_program new file mode 100644 index 0000000..ae5e9d2 --- /dev/null +++ b/ue4/mycpu/test/test2_program @@ -0,0 +1,13 @@ +# set R2 = 10 +LOAD R2, R1 + +# start of loop +label Loop: +inc R3 +sub R4, R3, R2 +test R4 +jumpz EndLoop +write WDEZ, R3 +jumpa Loop + +label EndLoop: diff --git a/ue4/mycpu/test/test3_args b/ue4/mycpu/test/test3_args new file mode 100644 index 0000000..098d137 --- /dev/null +++ b/ue4/mycpu/test/test3_args @@ -0,0 +1 @@ +-f 5 -c #program# -m #memory# diff --git a/ue4/mycpu/test/test3_memory b/ue4/mycpu/test/test3_memory new file mode 100644 index 0000000..fa8f08c --- /dev/null +++ b/ue4/mycpu/test/test3_memory @@ -0,0 +1 @@ +150 diff --git a/ue4/mycpu/test/test3_output b/ue4/mycpu/test/test3_output new file mode 100644 index 0000000..d4de868 --- /dev/null +++ b/ue4/mycpu/test/test3_output @@ -0,0 +1,21 @@ +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 diff --git a/ue4/mycpu/test/test3_program b/ue4/mycpu/test/test3_program new file mode 100644 index 0000000..ae5e9d2 --- /dev/null +++ b/ue4/mycpu/test/test3_program @@ -0,0 +1,13 @@ +# set R2 = 10 +LOAD R2, R1 + +# start of loop +label Loop: +inc R3 +sub R4, R3, R2 +test R4 +jumpz EndLoop +write WDEZ, R3 +jumpa Loop + +label EndLoop: -- cgit v1.2.3