summaryrefslogtreecommitdiffstats
path: root/ue3/mycpu
diff options
context:
space:
mode:
authormanuel <manuel@nc8430.lan>2009-05-14 18:58:48 +0200
committermanuel <manuel@nc8430.lan>2009-05-14 18:58:48 +0200
commit53b68ac658569dea3f5a26745dacf2a9aca0b266 (patch)
tree269af83394e84e2a7142dde87fb15dce413aa5c9 /ue3/mycpu
parentddf63e2765a6b225d18c59321595e69e1a126e0c (diff)
parent3563c6dfd0f5f102cb748ecc6ad318601990515e (diff)
downloadooprog-53b68ac658569dea3f5a26745dacf2a9aca0b266.tar.gz
ooprog-53b68ac658569dea3f5a26745dacf2a9aca0b266.tar.bz2
ooprog-53b68ac658569dea3f5a26745dacf2a9aca0b266.zip
trying merging cpu-mm with default branch
Diffstat (limited to 'ue3/mycpu')
-rw-r--r--ue3/mycpu/Makefile6
-rw-r--r--ue3/mycpu/ccpu.cpp125
-rw-r--r--ue3/mycpu/ccpu.h235
-rw-r--r--ue3/mycpu/cdat.h67
-rw-r--r--ue3/mycpu/cdisplay.h85
-rw-r--r--ue3/mycpu/cinstruction.cpp132
-rw-r--r--ue3/mycpu/cinstruction.h306
-rw-r--r--ue3/mycpu/cmem.cpp124
-rw-r--r--ue3/mycpu/cmem.h133
-rw-r--r--ue3/mycpu/cprogram.cpp186
-rw-r--r--ue3/mycpu/cprogram.h112
-rw-r--r--ue3/mycpu/displays.h76
-rw-r--r--ue3/mycpu/instructions.cpp341
-rw-r--r--ue3/mycpu/instructions.h454
-rw-r--r--ue3/mycpu/mycpu.cpp127
-rwxr-xr-xue3/mycpu/test/test.sh42
-rw-r--r--ue3/mycpu/test/test1_memory1
-rw-r--r--ue3/mycpu/test/test1_output19
-rw-r--r--ue3/mycpu/test/test1_program13
-rw-r--r--ue3/mycpu/test/test_prog15
-rw-r--r--ue3/mycpu/test/test_prog_mem6
21 files changed, 1863 insertions, 742 deletions
diff --git a/ue3/mycpu/Makefile b/ue3/mycpu/Makefile
index 76b6244..eec8b47 100644
--- a/ue3/mycpu/Makefile
+++ b/ue3/mycpu/Makefile
@@ -6,13 +6,13 @@ CXX= g++
6LD= $(CXX) 6LD= $(CXX)
7DEBUGFLAGS= -DNDEBUG 7DEBUGFLAGS= -DNDEBUG
8INCLUDE_PATH= -I/usr/local/include 8INCLUDE_PATH= -I/usr/local/include
9CXXFLAGS= -O -ansi -pedantic-errors -Wall $(INCLUDE_PATH) $(DEBUGFLAGS) 9CXXFLAGS= -O -ansi -pedantic-errors -Wall -Wno-long-long $(INCLUDE_PATH) $(DEBUGFLAGS)
10LDFLAGS= 10LDFLAGS=
11LIBS= -L/usr/local/lib -lboost_program_options 11LIBS= -L/usr/local/lib -lboost_program_options
12 12
13BIN= mycpu 13BIN= mycpu
14OBJS= mycpu.o ccpu.o cprogram.o cmem.o cinstruction.o 14OBJS= cinstruction.o instructions.o cprogram.o ccpu.o mycpu.o
15HEADERS= cdat.h ccpu.h cprogram.h cmem.h cinstruction.h 15HEADERS= cdat.h cmem.h cinstruction.h instructions.h cprogram.h cdisplay.h displays.h ccpu.h
16 16
17.SUFFIXES: .cpp .o 17.SUFFIXES: .cpp .o
18 18
diff --git a/ue3/mycpu/ccpu.cpp b/ue3/mycpu/ccpu.cpp
index 978f1f7..af86200 100644
--- a/ue3/mycpu/ccpu.cpp
+++ b/ue3/mycpu/ccpu.cpp
@@ -1,76 +1,89 @@
1/** 1/**
2 * @module ccpu 2 * @module ccpu
3 * @author Guenther Neuwirth (0626638), Manuel Mausz (0728348) 3 * @author Guenther Neuwirth (0626638), Manuel Mausz (0728348)
4 * @brief class for processing a program 4 * @brief CPU implementation. Used as a container for memory and instructions.
5 * @date 11.05.2009 5 * Implements an run method to execute the program (= the instructions).
6 * @date 10.05.2009
6 */ 7 */
7 8
8#include <fstream> 9#ifdef DEBUG
9#include <boost/tokenizer.hpp> 10# include <iostream>
10#include <boost/algorithm/string.hpp> 11# include <iomanip>
11 12#endif
12#include "ccpu.h" 13#include "ccpu.h"
13#include "cinstruction.h" 14#include "displays.h"
14#include "cprogram.h"
15#include "cmem.h"
16
17 15
18using namespace std; 16using namespace std;
19using namespace boost;
20 17
21CCPU::CCPU(const std::string& progfile, const std::string& memfile) 18CCPU::CCPU(const unsigned cnt)
22 : m_program(progfile), m_memory(memfile) 19 : m_regcnt(cnt), m_memory(NULL), m_program(NULL), m_flagzero(false), m_flagsign(false)
23{ 20{
24 f_zero = false; 21 /* create registers */
25 f_sign = false; 22 m_registers = new CDat[cnt];
26 m_instrHandler["inc"] = new CInc(); 23 for(unsigned i = 0; i < cnt; ++i)
27 m_instrHandler["dec"] = new CDec(); 24 m_registers[i] = 0;
28 m_instrHandler["add"] = new CAdd(); 25
29 m_instrHandler["sub"] = new CSub(); 26 /* create displays */
30 m_instrHandler["mul"] = new CMul(); 27 m_displays.insert(new CDisplayWDEZ);
31 m_instrHandler["div"] = new CDiv(); 28 m_displays.insert(new CDisplayWHEX);
32 m_instrHandler["load"] = new CLoad();
33 m_instrHandler["store"] = new CStore();
34 m_instrHandler["test"] = new CTest(f_zero, f_sign);
35 m_instrHandler["label"] = new CLabel();
36 m_instrHandler["jumpa"] = new CJumpa(m_program.getJumpAddrs());
37 m_instrHandler["jumpz"] = new CJumpz(f_zero, f_sign, m_program.getJumpAddrs());
38 m_instrHandler["jumps"] = new CJumps(f_zero, f_sign, m_program.getJumpAddrs());
39 m_instrHandler["write"] = new CWrite();
40} 29}
41 30
31/*----------------------------------------------------------------------------*/
32
42CCPU::~CCPU() 33CCPU::~CCPU()
43{ 34{
44 std::map<std::string, CInstruction *>::iterator it; 35 /* delete registers */
45 for (it = m_instrHandler.begin(); it != m_instrHandler.end(); it++) 36 delete[] m_registers;
46 delete (*it).second ; 37 m_registers = NULL;
38
39 /* delete displays */
40 std::set<CDisplay *>::iterator it;
41 for (it = m_displays.begin() ; it != m_displays.end(); ++it)
42 delete *it;
47} 43}
48void CCPU::proceed() 44
45/*----------------------------------------------------------------------------*/
46
47void CCPU::run()
49{ 48{
50 49 if (m_memory == NULL)
51 while (m_memory.getRegister("R0") < m_program.getMaxProgramCount()) 50 throw runtime_error("CPU has no memory");
52 { 51 if (m_program == NULL)
53 std::vector<std::string>& i_list = m_program.getInstruction( 52 throw runtime_error("CPU has no program to execute");
54 m_memory.getRegister("R0") 53 if (m_regcnt == 0)
55 ); 54 throw runtime_error("CPU has no registers");
56 55
57 56 bool run = true;
58 57 while(run)
59 m_instrHandler[i_list[0]]->exec(m_memory, i_list); 58 {
60/* for(int i = 0; i < (int)i_list.size(); i++) 59 unsigned pc = static_cast<unsigned>(m_registers[0]);
61 cout << i_list[i] << " "; 60
62 if (i_list[0] == "load") 61 /* end of the program reached */
63 { 62 if (pc == m_program->size())
64 63 break;
65 cout << m_memory.getRegister(i_list[1])<<" "<<m_memory.getRegister("R255")<<endl; 64
66 break; 65 /* pc is out of bound */
67 }*/ 66 if (pc > m_program->size())
68 m_memory.getRegister("R0")++; 67 throw runtime_error("Programcounter is out of bound");
69// cout << m_memory.getRegister("R0")<<endl; 68
70 // cout<<endl; 69 /* execute instruction */
71 } 70 (*m_program->at(pc))(this);
72 71 ++m_registers[0];
72 }
73} 73}
74 74
75/*----------------------------------------------------------------------------*/
75 76
77#if DEBUG
78void CCPU::dumpRegisters(std::ostream& out)
79{
80 out << "[REGISTER DUMP]" << endl;
81 for(unsigned i = 0; i < getRegisterCount(); ++i)
82 {
83 out << "[" << std::setw(4) << std::setfill('0') << i << "] "
84 << m_registers[i] << endl;
85 }
86}
87#endif
76 88
89/* vim: set et sw=2 ts=2: */
diff --git a/ue3/mycpu/ccpu.h b/ue3/mycpu/ccpu.h
index 68a4b8d..6849623 100644
--- a/ue3/mycpu/ccpu.h
+++ b/ue3/mycpu/ccpu.h
@@ -1,50 +1,43 @@
1/** 1/**
2 * @module ccpu 2 * @module ccpu
3 * @author Guenther Neuwirth (0626638), Manuel Mausz (0728348) 3 * @author Guenther Neuwirth (0626638), Manuel Mausz (0728348)
4 * @brief class for parsing simple scriptfiles 4 * @brief CPU implementation. Used as a container for memory and instructions.
5 * @date 17.04.2009 5 * Implements a run method to execute the program (= the instructions).
6 * @date 10.05.2009
6 */ 7 */
7 8
8#ifndef CCPU_H 9#ifndef CCPU_H
9#define CCPU_H 10#define CCPU_H 1
10 11
11#include <stdexcept> 12#include <iostream>
12#include <string> 13#include <set>
13#include <vector> 14#include "cdat.h"
14
15#include "cprogram.h"
16#include "cmem.h" 15#include "cmem.h"
17#include "cinstruction.h" 16#include "cprogram.h"
17#include "cdisplay.h"
18
18/** 19/**
19 * @class CCPU 20 * @class CCPU
20 * 21 *
21 * Parses a simple line based scriptfile with some limitations: 22 * CPU implementation. Used as a container for memory and instructions.
22 * first function (starting a block) must be a read-command, 23 * Implements a run method to execute the program (= the instructions).
23 * last must be a write-command (ending this block).
24 *
25 * read- and write-commands have hard coded parameters, number#1 being a filetype.
26 * Classes handling certain filetypes must be of type CFile.
27 * Custom functions will be passed to CFile::callFunc().
28 *
29 * On error ParserError will be thrown.
30 */ 24 */
31class CCPU 25class CCPU
32{ 26{
33 public: 27 public:
34
35
36 /** 28 /**
37 * @method CScriptparser 29 * @method CCPU
38 * @brief Default ctor 30 * @brief Default ctor
39 * @param scriptfile filename of script to parse 31 * @param cnt number of registers to allocate for this cpu
40 * @return - 32 * @return -
41 * @globalvars none 33 * @globalvars none
42 * @exception bad_alloc 34 * @exception none
43 * @conditions none 35 * @conditions none
44 */ 36 */
45 CCPU(const std::string& progfile, const std::string& memfile); 37 CCPU(const unsigned cnt);
38
46 /** 39 /**
47 * @method ~CScriptparser 40 * @method ~CCPU
48 * @brief Default dtor 41 * @brief Default dtor
49 * @param - 42 * @param -
50 * @return - 43 * @return -
@@ -54,21 +47,193 @@ class CCPU
54 */ 47 */
55 ~CCPU(); 48 ~CCPU();
56 49
50 /**
51 * @method getRegisterCount
52 * @brief get number of registers
53 * @param -
54 * @return number of registers
55 * @globalvars none
56 * @exception none
57 * @conditions none
58 */
59 const unsigned getRegisterCount() const
60 {
61 return m_regcnt;
62 }
63
64 /**
65 * @method getRegisters
66 * @brief get pointer to registers array
67 * @param -
68 * @return pointer to registers array
69 * @globalvars none
70 * @exception none
71 * @conditions none
72 */
73 CDat *getRegisters() const
74 {
75 return m_registers;
76 }
77
78 /**
79 * @method setMemory
80 * @brief set memory of cpu
81 * @param memory pointer to memory
82 * @return -
83 * @globalvars none
84 * @exception none
85 * @conditions none
86 */
87 void setMemory(CMem *memory)
88 {
89 m_memory = memory;
90 }
91
92 /**
93 * @method getMemory
94 * @brief get pointer to memory
95 * @param -
96 * @return pointer to memory
97 * @globalvars none
98 * @exception none
99 * @conditions none
100 */
101 CMem *getMemory() const
102 {
103 return m_memory;
104 }
105
106 /**
107 * @method setProgram
108 * @brief set program to execute
109 * @param program pointer to program
110 * @return -
111 * @globalvars none
112 * @exception none
113 * @conditions none
114 */
115 void setProgram(const CProgram *program)
116 {
117 m_program = program;
118 }
119
120 /**
121 * @method getProgram
122 * @brief get pointer to program
123 * @param -
124 * @return pointer to program
125 * @globalvars none
126 * @exception none
127 * @conditions none
128 */
129 const CProgram *getProgram()
130 {
131 return m_program;
132 }
133
134 /**
135 * @method getDisplays
136 * @brief get set of pointers to displays
137 * @param -
138 * @return reference to set of pointers to displays
139 * @globalvars none
140 * @exception none
141 * @conditions none
142 */
143 const std::set<CDisplay *>& getDisplays()
144 {
145 return m_displays;
146 }
57 147
58 void proceed(); 148 /**
59 149 * @method setFlagZero
150 * @brief set zero flag
151 * @param value new value of zero flag
152 * @return -
153 * @globalvars none
154 * @exception none
155 * @conditions none
156 */
157 void setFlagZero(const bool value)
158 {
159 m_flagzero = value;
160 }
161
162 /**
163 * @method getFlagZero
164 * @brief get value of zero flag
165 * @param -
166 * @return value of zero flag
167 * @globalvars none
168 * @exception none
169 * @conditions none
170 */
171 const bool getFlagZero()
172 {
173 return m_flagzero;
174 }
60 175
176 /**
177 * @method setFlagSign
178 * @brief set sign flag
179 * @param value new value of sign flag
180 * @return -
181 * @globalvars none
182 * @exception none
183 * @conditions none
184 */
185 void setFlagSign(const bool value)
186 {
187 m_flagsign = value;
188 }
189
190 /**
191 * @method getFlagSign
192 * @brief get value of sign flag
193 * @param -
194 * @return value of sign flag
195 * @globalvars none
196 * @exception none
197 * @conditions none
198 */
199 const bool getFlagSign()
200 {
201 return m_flagsign;
202 }
203
204 /**
205 * @method run
206 * @brief execute current program
207 * @param -
208 * @return -
209 * @globalvars none
210 * @exception std::runtime_error
211 * @conditions none
212 */
213 void run();
214
215#if DEBUG
216 /**
217 * @method dumpRegisters
218 * @brief dump content of registers to outputstream
219 * @param out outputstream to write to
220 * @return void
221 * @globalvars none
222 * @exception none
223 * @conditions none
224 */
225 void dumpRegisters(std::ostream& out);
226#endif
61 227
62 void execInstruction( CInstruction& instr, std::vector<std::string>& i_list);
63 private: 228 private:
64 /* members */ 229 /* members */
65 230 CDat *m_registers;
66 CProgram m_program; 231 unsigned m_regcnt;
67 CMem m_memory; 232 CMem *m_memory;
68 std::map<std::string, CInstruction *> m_instrHandler; 233 const CProgram *m_program;
69 bool f_zero, f_sign; 234 std::set<CDisplay *> m_displays;
70 // std::string m_memfiler; 235 bool m_flagzero;
71 236 bool m_flagsign;
72}; 237};
73 238
74#endif 239#endif
diff --git a/ue3/mycpu/cdat.h b/ue3/mycpu/cdat.h
index 3fda572..a533fae 100644
--- a/ue3/mycpu/cdat.h
+++ b/ue3/mycpu/cdat.h
@@ -1,12 +1,12 @@
1/** 1/**
2 * @module cdat 2 * @module cdat
3 * @author Guenther Neuwirth (0626638), Manuel Mausz (0728348) 3 * @author Guenther Neuwirth (0626638), Manuel Mausz (0728348)
4 * @brief Datatype template for mycpu 4 * @brief Datatype template and datatype definition for CCPU and CMem
5 * @date 10.05.2009 5 * @date 10.05.2009
6 */ 6 */
7 7
8#ifndef CDATT_H 8#ifndef CDAT_H
9#define CDATT_H 9#define CDAT_H 1
10 10
11#include <boost/operators.hpp> 11#include <boost/operators.hpp>
12#include <iostream> 12#include <iostream>
@@ -14,7 +14,7 @@
14/** 14/**
15 * @class CDatT 15 * @class CDatT
16 * 16 *
17 * Datatype template for mycpu. 17 * Datatype template for CCPU and CMem.
18 */ 18 */
19template <class T> 19template <class T>
20class CDatT 20class CDatT
@@ -72,7 +72,7 @@ class CDatT
72 {} 72 {}
73 73
74 /** 74 /**
75 * @method value 75 * @method getValue
76 * @brief returns value of CDatT 76 * @brief returns value of CDatT
77 * @param - 77 * @param -
78 * @return value of CDatT 78 * @return value of CDatT
@@ -80,7 +80,21 @@ class CDatT
80 * @exception none 80 * @exception none
81 * @conditions none 81 * @conditions none
82 */ 82 */
83 T value() const 83 T getValue() const
84 {
85 return m_value;
86 }
87
88 /**
89 * @method operator T
90 * @brief convert to T
91 * @param -
92 * @return T
93 * @globalvars none
94 * @exception none
95 * @conditions none
96 */
97 operator T()
84 { 98 {
85 return m_value; 99 return m_value;
86 } 100 }
@@ -88,7 +102,7 @@ class CDatT
88 /** 102 /**
89 * @method operator< 103 * @method operator<
90 * @brief implementation of operator < 104 * @brief implementation of operator <
91 * @param reference to CDatT 105 * @param x reference to CDatT
92 * @return true if cdat is less than object x 106 * @return true if cdat is less than object x
93 * @globalvars none 107 * @globalvars none
94 * @exception none 108 * @exception none
@@ -102,7 +116,7 @@ class CDatT
102 /** 116 /**
103 * @method operator== 117 * @method operator==
104 * @brief implementation of operator == 118 * @brief implementation of operator ==
105 * @param reference to CDatT 119 * @param x reference to CDatT
106 * @return true if cdat equals object x 120 * @return true if cdat equals object x
107 * @globalvars none 121 * @globalvars none
108 * @exception none 122 * @exception none
@@ -116,7 +130,7 @@ class CDatT
116 /** 130 /**
117 * @method operator+= 131 * @method operator+=
118 * @brief implementation of operator += 132 * @brief implementation of operator +=
119 * @param reference to CDatT 133 * @param x reference to CDatT
120 * @return refecence to CDatT 134 * @return refecence to CDatT
121 * @globalvars none 135 * @globalvars none
122 * @exception none 136 * @exception none
@@ -131,7 +145,7 @@ class CDatT
131 /** 145 /**
132 * @method operator-= 146 * @method operator-=
133 * @brief implementation of operator -= 147 * @brief implementation of operator -=
134 * @param reference to CDatT 148 * @param x reference to CDatT
135 * @return refecence to CDatT 149 * @return refecence to CDatT
136 * @globalvars none 150 * @globalvars none
137 * @exception none 151 * @exception none
@@ -146,7 +160,7 @@ class CDatT
146 /** 160 /**
147 * @method operator*= 161 * @method operator*=
148 * @brief implementation of operator *= 162 * @brief implementation of operator *=
149 * @param reference to CDatT 163 * @param x reference to CDatT
150 * @return refecence to CDatT 164 * @return refecence to CDatT
151 * @globalvars none 165 * @globalvars none
152 * @exception none 166 * @exception none
@@ -161,7 +175,7 @@ class CDatT
161 /** 175 /**
162 * @method operator/= 176 * @method operator/=
163 * @brief implementation of operator /= 177 * @brief implementation of operator /=
164 * @param reference to CDatT 178 * @param x reference to CDatT
165 * @return refecence to CDatT 179 * @return refecence to CDatT
166 * @globalvars none 180 * @globalvars none
167 * @exception none 181 * @exception none
@@ -176,7 +190,7 @@ class CDatT
176 /** 190 /**
177 * @method operator%= 191 * @method operator%=
178 * @brief implementation of operator %= 192 * @brief implementation of operator %=
179 * @param reference to CDatT 193 * @param x reference to CDatT
180 * @return refecence to CDatT 194 * @return refecence to CDatT
181 * @globalvars none 195 * @globalvars none
182 * @exception none 196 * @exception none
@@ -191,7 +205,7 @@ class CDatT
191 /** 205 /**
192 * @method operator|= 206 * @method operator|=
193 * @brief implementation of operator |= 207 * @brief implementation of operator |=
194 * @param reference to CDatT 208 * @param x reference to CDatT
195 * @return refecence to CDatT 209 * @return refecence to CDatT
196 * @globalvars none 210 * @globalvars none
197 * @exception none 211 * @exception none
@@ -206,7 +220,7 @@ class CDatT
206 /** 220 /**
207 * @method operator&= 221 * @method operator&=
208 * @brief implementation of operator &= 222 * @brief implementation of operator &=
209 * @param reference to CDatT 223 * @param x reference to CDatT
210 * @return refecence to CDatT 224 * @return refecence to CDatT
211 * @globalvars none 225 * @globalvars none
212 * @exception none 226 * @exception none
@@ -221,7 +235,7 @@ class CDatT
221 /** 235 /**
222 * @method operator^= 236 * @method operator^=
223 * @brief implementation of operator ^= 237 * @brief implementation of operator ^=
224 * @param reference to CDatT 238 * @param x reference to CDatT
225 * @return refecence to CDatT 239 * @return refecence to CDatT
226 * @globalvars none 240 * @globalvars none
227 * @exception none 241 * @exception none
@@ -295,27 +309,16 @@ class CDatT
295 return stream; 309 return stream;
296 } 310 }
297 311
298 /**
299 * @method getTypeValue
300 * @brief returns value as type T
301 * @param -
302 * @return m_value
303 * @globalvars none
304 * @exception none
305 * @conditions none
306 */
307 T& getTypeValue()
308 {
309 return m_value;
310 }
311
312 private: 312 private:
313 /* members */ 313 /* members */
314 T m_value; 314 T m_value;
315}; 315};
316 316
317 317/**
318/** define CDat */ 318 * @class CDat
319 *
320 * Datatype for CCPU and CMem
321 */
319typedef CDatT<int> CDat; 322typedef CDatT<int> CDat;
320 323
321#endif 324#endif
diff --git a/ue3/mycpu/cdisplay.h b/ue3/mycpu/cdisplay.h
new file mode 100644
index 0000000..82776ee
--- /dev/null
+++ b/ue3/mycpu/cdisplay.h
@@ -0,0 +1,85 @@
1/**
2 * @module cdisplay
3 * @author Guenther Neuwirth (0626638), Manuel Mausz (0728348)
4 * @brief Abstract template class for displays
5 * @date 10.05.2009
6 */
7
8#ifndef CDISPLAY_H
9#define CDISPLAY_H 1
10
11/**
12 * @class CDisplayT
13 *
14 * Abstract template class for displays
15 */
16template <class T>
17class CDisplayT
18{
19 public:
20 /**
21 * @method CDisplayT
22 * @brief Default ctor
23 * @param name name of display
24 * @return -
25 * @globalvars none
26 * @exception none
27 * @conditions none
28 */
29 CDisplayT(std::string name)
30 : m_name(name)
31 {}
32
33 /**
34 * @method ~CDisplayT
35 * @brief Default dtor
36 * @param -
37 * @return -
38 * @globalvars none
39 * @exception none
40 * @conditions none
41 */
42 virtual ~CDisplayT()
43 {}
44
45 /**
46 * @method getName
47 * @brief returns name of display
48 * @param -
49 * @return name of display
50 * @globalvars none
51 * @exception none
52 * @conditions none
53 */
54 virtual const std::string& getName()
55 {
56 return m_name;
57 }
58
59 /**
60 * @method display
61 * @brief prints value to display
62 * @param value value to display
63 * @return -
64 * @globalvars none
65 * @exception none
66 * @conditions none
67 */
68 virtual void display(const T &value) = 0;
69
70 protected:
71 /* members */
72 /** name of display */
73 std::string m_name;
74};
75
76/**
77 * @class CDisplay
78 *
79 * Memory definition for CCPU
80 */
81typedef CDisplayT<CDat> CDisplay;
82
83#endif
84
85/* vim: set et sw=2 ts=2: */
diff --git a/ue3/mycpu/cinstruction.cpp b/ue3/mycpu/cinstruction.cpp
index 12c5c74..a766015 100644
--- a/ue3/mycpu/cinstruction.cpp
+++ b/ue3/mycpu/cinstruction.cpp
@@ -1,110 +1,48 @@
1#include <iostream> 1/**
2 * @module cinstruction
3 * @author Guenther Neuwirth (0626638), Manuel Mausz (0728348)
4 * @brief Abstract class for displays
5 * @date 13.05.2009
6 */
7
2#include <sstream> 8#include <sstream>
3#include <vector> 9#include <stdexcept>
4#include <map> 10#include <boost/lexical_cast.hpp>
11#include <assert.h>
5#include "cinstruction.h" 12#include "cinstruction.h"
6#include "cmem.h" 13#include "ccpu.h"
7using namespace std;
8
9void CInc::exec(CMem& mem, vector<string>& instr)
10{
11 mem.getRegister(instr[1])++;
12}
13
14
15void CDec::exec(CMem& mem, vector<string>& instr)
16{
17 mem.getRegister(instr[1])--;
18}
19
20
21void CAdd::exec(CMem& mem, vector<string>& instr)
22{
23 mem.getRegister(instr[1]) = mem.getRegister(instr[2]) +
24 mem.getRegister(instr[3]);
25}
26
27
28void CSub::exec(CMem& mem, vector<string>& instr)
29{
30 mem.getRegister(instr[1]) = mem.getRegister(instr[2]) -
31 mem.getRegister(instr[3]);
32
33}
34
35
36void CMul::exec(CMem& mem, vector<string>& instr)
37{
38 mem.getRegister(instr[1]) = mem.getRegister(instr[2]) *
39 mem.getRegister(instr[3]);
40}
41
42
43void CDiv::exec(CMem& mem, vector<string>& instr)
44{
45 mem.getRegister(instr[1]) = mem.getRegister(instr[2]) /
46 mem.getRegister(instr[3]);
47}
48
49
50void CLoad::exec(CMem& mem, vector<string>& instr)
51{
52 istringstream stmp (mem.getMemAt(instr[2]));
53 stmp >> mem.getRegister(instr[1]);
54
55}
56
57
58void CStore::exec(CMem& mem, vector<string>& instr)
59{
60 mem.setMemAt(instr[2], mem.getRegister(instr[1]));
61}
62
63
64void CTest::exec(CMem& mem, vector<string>& instr)
65{
66 if(mem.getRegister(instr[1]) == 0)
67 f_zero = true;
68 else
69 f_zero = false;
70
71 if(mem.getRegister(instr[1]) < 0)
72 f_sign = true;
73 else
74 f_sign = false;
75
76}
77
78
79
80
81
82void CJumpa::exec(CMem& mem, vector<string>& instr)
83{
84 mem.getRegister("R0") = (int) m_jumpaddr[instr[1]];
85}
86 14
15using namespace std;
87 16
88void CJumpz::exec(CMem& mem, vector<string>& instr) 17const unsigned CInstruction::parseRegister(const std::string& str)
89{ 18{
90 if(f_zero) 19 unsigned reg;
91 mem.getRegister("R0") = (int) m_jumpaddr[instr[1]]; 20 if (str.length() < 2 || str[0] != 'r')
92} 21 throw runtime_error("Invalid syntax of register");
93 22
23 try
24 {
25 reg = boost::lexical_cast<unsigned>(str.substr(1));
26 }
27 catch(boost::bad_lexical_cast& ex)
28 {
29 throw runtime_error("Invalid syntax of register");
30 }
94 31
95void CJumps::exec(CMem& mem, vector<string>& instr) 32 return reg;
96{
97 if(f_sign)
98 mem.getRegister("R0") = (int) m_jumpaddr[instr[1]];
99} 33}
100 34
35/*----------------------------------------------------------------------------*/
101 36
102void CWrite::exec(CMem& mem, vector<string>& instr) 37inline void CInstruction::checkRegister(CCPU *cpu, const unsigned regidx)
103{ 38{
104 39 assert(cpu != NULL);
105 if(instr[1] == "WDEZ") 40 if (regidx >= cpu->getRegisterCount())
106 cout << mem.getRegister(instr[2]) << endl; 41 {
107 else if (instr[1] == "WHEX") 42 stringstream sstr;
108 cout << hex << mem.getRegister(instr[2]) << endl; 43 sstr << "Register R" << regidx << " doesn't exist (out of bound)";
44 throw runtime_error(sstr.str());
45 }
109} 46}
110 47
48/* vim: set et sw=2 ts=2: */
diff --git a/ue3/mycpu/cinstruction.h b/ue3/mycpu/cinstruction.h
index 7d929a5..4cc69de 100644
--- a/ue3/mycpu/cinstruction.h
+++ b/ue3/mycpu/cinstruction.h
@@ -1,39 +1,38 @@
1/** 1/**
2 * @module cinstruction 2 * @module cinstruction
3 * @author Guenther Neuwirth (0626638), Manuel Mausz (0728348) 3 * @author Guenther Neuwirth (0626638), Manuel Mausz (0728348)
4 * @brief abstract class cpu instructions 4 * @brief Abstract class for displays
5 * @date 17.04.2009 5 * @date 13.05.2009
6 */ 6 */
7 7
8#ifndef CINSTRUCTION_H 8#ifndef CINSTRUCTION_H
9#define CINSTRUCTION_H 9#define CINSTRUCTION_H 1
10#include <map>
11#include <vector>
12#include "cmem.h"
13 10
11#include <iostream>
12#include <list>
13
14/* forward declare CCPU */
15class CCPU;
14 16
15
16/** 17/**
17 * @class CInstruction 18 * @class CInstruction
18 * 19 *
19 * Parses a simple line based scriptfile with some limitations: 20 * Abstract class for displays
20 * first function (starting a block) must be a read-command,
21 * last must be a write-command (ending this block).
22 *
23 * read- and write-commands have hard coded parameters, number#1 being a filetype.
24 * Classes handling certain filetypes must be of type CFile.
25 * Custom functions will be passed to CFile::callFunc().
26 *
27 * On error ParserError will be thrown.
28 */ 21 */
29class CInstruction 22class CInstruction
30{ 23{
31 public: 24 public:
32 25 /**
33 CInstruction() 26 * @method CInstruction
34 {} 27 * @brief Default ctor
35 CInstruction(std::map<std::string, unsigned int>& jumpaddr) 28 * @param name name of instruction
36 : m_jumpaddr(jumpaddr) 29 * @return -
30 * @globalvars none
31 * @exception none
32 * @conditions none
33 */
34 CInstruction(std::string name)
35 : m_name(name)
37 {} 36 {}
38 37
39 /** 38 /**
@@ -47,157 +46,144 @@ class CInstruction
47 */ 46 */
48 virtual ~CInstruction() 47 virtual ~CInstruction()
49 {} 48 {}
50
51
52 virtual void exec(CMem& mem, std::vector<std::string>& instr) = 0;
53
54 protected:
55 std::map<std::string, unsigned int> m_jumpaddr;
56
57
58};
59
60
61
62
63class CFlagInstruction : public CInstruction
64{
65 public:
66 public:
67 CFlagInstruction(bool& zero, bool& sign)
68 : f_zero(zero), f_sign(sign)
69 {}
70 CFlagInstruction(bool& zero, bool& sign, std::map<std::string, unsigned int>& jumpaddr)
71 : CInstruction::CInstruction(jumpaddr), f_zero(zero), f_sign(sign)
72 {}
73 virtual void exec(CMem& mem, std::vector<std::string>& instr) = 0;
74
75 protected:
76 bool &f_zero, &f_sign;
77
78};
79
80
81
82class CInc : public CInstruction
83{
84 public:
85 void exec(CMem& mem, std::vector<std::string>& instr);
86};
87
88
89class CDec : public CInstruction
90{
91 public:
92 void exec(CMem& mem, std::vector<std::string>& instr);
93};
94
95
96
97class CAdd : public CInstruction
98{
99 public:
100 void exec(CMem& mem, std::vector<std::string>& instr);
101};
102
103
104
105class CSub : public CInstruction
106{
107 public:
108 void exec(CMem& mem, std::vector<std::string>& instr);
109};
110
111
112
113class CMul : public CInstruction
114{
115 public:
116 void exec(CMem& mem, std::vector<std::string>& instr);
117};
118
119
120
121class CDiv : public CInstruction
122{
123 public:
124 void exec(CMem& mem, std::vector<std::string>& instr);
125};
126
127
128
129class CLoad : public CInstruction
130{
131 public:
132 void exec(CMem& mem, std::vector<std::string>& instr);
133};
134
135
136
137class CStore : public CInstruction
138{
139 public:
140 void exec(CMem& mem, std::vector<std::string>& instr);
141};
142
143class CTest : public CFlagInstruction
144{
145 public:
146 CTest(bool& zero, bool& sign)
147 : CFlagInstruction::CFlagInstruction(zero, sign)
148 {}
149
150 void exec(CMem& mem, std::vector<std::string>& instr);
151};
152 49
50 /**
51 * @method operator==
52 * @brief implementation of operator ==
53 * @param name reference to std::string
54 * @return true if instructionname is name
55 * @globalvars none
56 * @exception none
57 * @conditions none
58 */
59 virtual bool operator==(std::string& name)
60 {
61 return name == m_name;
62 }
153 63
154class CLabel : public CInstruction 64 /**
155{ 65 * @method operator()
156 public: 66 * @brief implementation of operator (CCPU)
157 void exec(CMem& mem, std::vector<std::string>& instr) 67 * @param cpu pointer to cpu
158 {} 68 * @return -
159 69 * @globalvars none
160}; 70 * @exception std::runtime_error
161 71 * @conditions none
72 */
73 virtual CInstruction& operator()(CCPU *cpu)
74 {
75 execute(cpu);
76 return *this;
77 }
162 78
163class CJumpa : public CInstruction 79 /**
164{ 80 * @method getName
165 public: 81 * @brief returns instruction name
166 CJumpa(std::map<std::string, unsigned int>& jumpaddr) 82 * @param -
167 : CInstruction::CInstruction(jumpaddr) 83 * @return name of instruction
168 {} 84 * @globalvars none
169 void exec(CMem& mem, std::vector<std::string>& instr); 85 * @exception none
86 * @conditions none
87 */
88 virtual const std::string& getName()
89 {
90 return m_name;
91 }
170 92
171}; 93 /**
94 * @method dump
95 * @brief dumps information about instruction to outputstream
96 * @param stream outputstream
97 * @return reference to outputstream
98 * @globalvars none
99 * @exception none
100 * @conditions none
101 */
102 virtual std::ostream& dump(std::ostream& stream)
103 {
104 stream << m_name;
105 return stream;
106 }
172 107
108 /**
109 * @method operator<<
110 * @brief Shift/output operator for outputstream
111 * @param stream reference to outputstream
112 * @param instr object which will be printed to stream
113 * @return reference to outputstream
114 * @globalvars none
115 * @exception none
116 * @conditions none
117 */
118 friend std::ostream& operator<<(std::ostream& stream, CInstruction& instr)
119 {
120 return instr.dump(stream);
121 }
173 122
174class CJumpz : public CFlagInstruction 123 /**
175{ 124 * @method parseRegister
176 125 * @brief parses register syntax Rx (e.g. "R1")
177 public: 126 * @param str register in assembler syntax
178 CJumpz(bool& zero, bool& sign, std::map<std::string, unsigned int>& jumpaddr) 127 * @return registernumber
179 : CFlagInstruction::CFlagInstruction(zero, sign, jumpaddr) 128 * @globalvars none
180 {} 129 * @exception std::runtime_error
181 void exec(CMem& mem, std::vector<std::string>& instr); 130 * @conditions none
182}; 131 */
132 virtual const unsigned parseRegister(const std::string& str);
183 133
134 /**
135 * @method checkRegister
136 * @brief performs a register boundary check
137 * does the register exist in cpu?
138 * @param cpu pointer to cpu
139 * @param regidx registernumber
140 * @return -
141 * @globalvars none
142 * @exception std::runtime_error
143 * @conditions none
144 */
145 virtual void checkRegister(CCPU *cpu, const unsigned regidx);
184 146
185class CJumps : public CFlagInstruction 147 /**
186{ 148 * @method factory
187 public: 149 * @brief creates a new instance of this instruction
188 CJumps(bool& zero ,bool& sign, std::map<std::string, unsigned int>& jumpaddr) 150 * @param -
189 : CFlagInstruction::CFlagInstruction(zero, sign, jumpaddr) 151 * @return new instruction instance
190 {} 152 * @globalvars none
191 void exec(CMem& mem, std::vector<std::string>& instr); 153 * @exception none
192}; 154 * @conditions none
155 */
156 virtual CInstruction *factory() = 0;
193 157
158 /**
159 * @method compile
160 * @brief parses instruction parameters and prepares the
161 * instruction for executing
162 * @param params list of parameters of this instruction
163 * @return -
164 * @globalvars none
165 * @exception std::runtime_error
166 * @conditions none
167 */
168 virtual void compile(std::list<std::string>& params) = 0;
194 169
170 /**
171 * @method execute
172 * @brief executes the instruction
173 * @param cpu pointer to cpu
174 * @return -
175 * @globalvars none
176 * @exception std::runtime_error
177 * @conditions none
178 */
179 virtual void execute(CCPU *cpu) = 0;
195 180
196class CWrite : public CInstruction 181 protected:
197{ 182 /* members */
198 public: 183 /** name of instruction */
199 void exec(CMem& mem, std::vector<std::string>& instr); 184 std::string m_name;
200}; 185};
201 186
202#endif 187#endif
188
203/* vim: set et sw=2 ts=2: */ 189/* vim: set et sw=2 ts=2: */
diff --git a/ue3/mycpu/cmem.cpp b/ue3/mycpu/cmem.cpp
deleted file mode 100644
index 165747b..0000000
--- a/ue3/mycpu/cmem.cpp
+++ /dev/null
@@ -1,124 +0,0 @@
1/**
2 * @module cprogram
3 * @author Guenther Neuwirth (0626638), Manuel Mausz (0728348)
4 * @brief class for parsing and saving a program
5 * @date 11.05.2009
6 */
7
8#include <fstream>
9#include <sstream>
10#include <string>
11#include <boost/tokenizer.hpp>
12#include <boost/algorithm/string.hpp>
13#include "cdat.h"
14#include "cmem.h"
15
16
17
18using namespace std;
19using namespace boost;
20
21CMem::CMem(const std::string& memfile) :
22 m_memfile(memfile)
23{
24
25 dump(std::cout);
26
27}
28
29/*----------------------------------------------------------------------------*/
30
31CMem::~CMem()
32{
33
34}
35
36/*----------------------------------------------------------------------------*/
37
38CDat& CMem::getRegister(const string reg)
39{
40
41 unsigned int regnr = getRegNr(reg);
42
43 // if (regnr >= MAX_REGISTER )
44
45 if (regnr >= m_registers.size())
46 {
47 for ( int i = m_registers.size(); i <= (int)regnr; i++)
48 m_registers.push_back(CDat((int)0));
49 return m_registers[m_registers.size() - 1];
50 }
51
52 return m_registers[regnr];
53}
54
55/*----------------------------------------------------------------------------*/
56
57string CMem::getMemAt(const std::string addr)
58{
59 int pos = getRegister(addr).getTypeValue();
60 /* open and read mem */
61 ifstream file(m_memfile.c_str(), ios::in);
62 string cur_line;
63 for (int i = 0; i <= pos; i++)
64 getline(file, cur_line);
65
66 file.close();
67 if (cur_line.empty())
68 return "";
69 trim(cur_line);
70 return cur_line;
71}
72void CMem::setMemAt(const std::string addr, const CDat& value)
73{
74 unsigned int pos = getRegister(addr).getTypeValue();
75 /* open and read mem */
76 ifstream ifile(m_memfile.c_str() );
77 vector<string> tmp;
78 unsigned int i = 0;
79 while (ifile.good())
80 {
81 string cur_line;
82 getline(ifile, cur_line);
83 if(!cur_line.empty())
84 tmp.push_back(cur_line);
85 i++;
86 }
87 ifile.close();
88 cout << tmp.size()<<"sasa"<<pos<<" "<<endl;
89
90 ofstream ofile(m_memfile.c_str(), fstream::trunc);
91 i = 0;
92 while (ofile.good() && i < tmp.size())
93 {
94 if (i != pos)
95 ofile << tmp[i] << endl;
96 else
97 ofile << value << endl;
98 cout << tmp[i]<< endl;
99 i++;
100 }
101 ofile.close();
102}
103/*----------------------------------------------------------------------------*/
104
105unsigned int CMem::getRegNr(const std::string reg)
106{
107 istringstream stmp (
108 reg.substr(reg.find_first_of("R") + 1, reg.size())
109 );
110
111 unsigned int regnr;
112 stmp >> regnr;
113 return regnr;
114}
115
116/*----------------------------------------------------------------------------*/
117
118#ifdef DEBUG
119void CMem::dump(std::ostream& out)
120{
121 out << endl << "Memory file:" << endl << m_memfile << endl;
122 out << endl << "Memory file content:" << endl;
123}
124#endif
diff --git a/ue3/mycpu/cmem.h b/ue3/mycpu/cmem.h
index 356c9c0..5045c34 100644
--- a/ue3/mycpu/cmem.h
+++ b/ue3/mycpu/cmem.h
@@ -1,92 +1,109 @@
1/** 1/**
2 * @module cmem 2 * @module cmem
3 * @author Guenther Neuwirth (0626638), Manuel Mausz (0728348) 3 * @author Guenther Neuwirth (0626638), Manuel Mausz (0728348)
4 * @brief class for providing 256 registers. 4 * @brief Memory template and memory definition for CCPU
5 * @date 11.05.2009 5 * @date 10.05.2009
6 */ 6 */
7 7
8#ifndef CMEM_H 8#ifndef CMEM_H
9#define CMEM_H 9#define CMEM_H 1
10 10
11#include <vector>
12#include <istream>
13#include <sstream>
11#include <stdexcept> 14#include <stdexcept>
12#include <string> 15#include <boost/lexical_cast.hpp>
13
14#include <set>
15#ifdef DEBUG 16#ifdef DEBUG
16# include <iostream> 17# include <iostream>
18# include <iomanip>
17#endif 19#endif
18 #include "cdat.h" 20#include "cdat.h"
19
20 21
21#define MAX_REGISTER 256;
22/** 22/**
23 * @class CMem 23 * @class CVectorMem
24 * 24 *
25 * Parses a simple line based scriptfile with some limitations: 25 * Extends std::vector template for use as memory for CCPU.
26 * first function (starting a block) must be a read-command,
27 * last must be a write-command (ending this block).
28 *
29 * read- and write-commands have hard coded parameters, number#1 being a filetype.
30 * Classes handling certain filetypes must be of type CFile.
31 * Custom functions will be passed to CFile::callFunc().
32 *
33 * On error ParserError will be thrown.
34 */ 26 */
35class CMem 27template <class T, class Allocator=std::allocator<T> >
28class CVectorMem
29 : public std::vector<T, Allocator>
36{ 30{
37 public: 31 public:
32 using std::vector<T, Allocator>::size;
33 using std::vector<T, Allocator>::at;
38 34
39 /** 35 /**
40 * @method CMem 36 * @method initialize
41 * @brief Default ctor 37 * @brief initialize the vector with the content of istream. istream is
42 * @param memoryfile filename 38 * read per line. empty lines will add unitialized elements.
43 * @return - 39 * @param in inputstream to read from
40 * @return void
44 * @globalvars none 41 * @globalvars none
45 * @exception bad_alloc 42 * @exception std::runtime_error
46 * @conditions none 43 * @conditions none
47 */ 44 */
48 CMem(const std::string& memfile); 45 void initialize(std::istream& in)
46 {
47 if (!in.good())
48 return;
49
50 std::string line;
51 unsigned i = 0;
52 while (!in.eof() && in.good())
53 {
54 ++i;
55 std::getline(in, line);
49 56
57 /* skip last line if it's empty */
58 if (line.empty() && in.eof())
59 break;
60
61 T value;
62 try
63 {
64 if (!line.empty())
65 value = boost::lexical_cast<T>(line);
66 }
67 catch(boost::bad_lexical_cast& ex)
68 {
69 std::stringstream sstr;
70 sstr << "Unable to convert input (line " << i << "): " << ex.what();
71 throw std::runtime_error(sstr.str());
72 }
73
74 push_back(value);
75 }
76 }
77
78#if DEBUG
50 /** 79 /**
51 * @method ~CMem 80 * @method dump
52 * @brief Default dtor 81 * @brief dumps contents of vector to outputstream
53 * @param - 82 * @param out outputstream to write to
54 * @return - 83 * @return void
55 * @globalvars none 84 * @globalvars none
56 * @exception none 85 * @exception none
57 * @conditions none 86 * @conditions none
58 */ 87 */
59 ~CMem(); 88 void dump(std::ostream& out)
60 89 {
61 CDat& getRegister(const std::string reg); 90 out << "[MEMORY DUMP]" << std::endl;
62 91 for(unsigned i = 0; i < size(); ++i)
63 std::string getMemAt(const std::string addr); 92 {
64 93 out << "[" << std::setw(4) << std::setfill('0') << i << "] "
65 void setMemAt(const std::string addr, const CDat& value); 94 << at(i) << std::endl;
66 95 }
67#ifdef DEBUG 96 }
68 /**
69 * @method dump
70 * @brief Dumps the resgister contnent to ostream
71 * @param out output stream
72 * @return -
73 * @globalvars
74 * @exception
75 * @conditions
76 */
77 void dump(std::ostream& out);
78#endif 97#endif
79
80
81 private:
82
83 unsigned int getRegNr(const std::string reg);
84
85 /* members */
86 std::string m_memfile;
87 std::vector<CDat> m_registers;
88}; 98};
89 99
100/**
101 * @class CMem
102 *
103 * Memory definition for CCPU
104 */
105typedef CVectorMem<CDat> CMem;
106
90#endif 107#endif
91 108
92/* vim: set et sw=2 ts=2: */ 109/* vim: set et sw=2 ts=2: */
diff --git a/ue3/mycpu/cprogram.cpp b/ue3/mycpu/cprogram.cpp
index 9297b6e..3fcf734 100644
--- a/ue3/mycpu/cprogram.cpp
+++ b/ue3/mycpu/cprogram.cpp
@@ -1,109 +1,161 @@
1/** 1/**
2 * @module cprogram 2 * @module cprogram
3 * @author Guenther Neuwirth (0626638), Manuel Mausz (0728348) 3 * @author Guenther Neuwirth (0626638), Manuel Mausz (0728348)
4 * @brief class for parsing and saving a program 4 * @brief CProgram extends std::vector and adds a method for parsing programfile
5 * @date 11.05.2009 5 * @date 12.05.2009
6 */ 6 */
7 7
8#include <fstream>
9#include <vector>
10#include <string>
11#include <boost/tokenizer.hpp>
12#include <boost/algorithm/string.hpp> 8#include <boost/algorithm/string.hpp>
13#include <boost/algorithm/string/split.hpp> 9#include <boost/algorithm/string/split.hpp>
10#ifdef DEBUG
11# include <iostream>
12# include <iomanip>
13#endif
14#include "cprogram.h" 14#include "cprogram.h"
15 15#include "instructions.h"
16
17 16
18using namespace std; 17using namespace std;
19using namespace boost;
20 18
21CProgram::CProgram(const std::string& progfile) : 19CProgram::CProgram()
22 m_programfile(progfile)
23{ 20{
24 parse(); 21 m_instrset.insert(new CInstructionInc);
25 dump(std::cout); 22 m_instrset.insert(new CInstructionDec);
26 23 m_instrset.insert(new CInstructionAdd);
24 m_instrset.insert(new CInstructionSub);
25 m_instrset.insert(new CInstructionMul);
26 m_instrset.insert(new CInstructionDiv);
27 m_instrset.insert(new CInstructionLoad);
28 m_instrset.insert(new CInstructionStore);
29 m_instrset.insert(new CInstructionTest);
30 m_instrset.insert(new CInstructionLabel);
31 m_instrset.insert(new CInstructionJumpA);
32 m_instrset.insert(new CInstructionJumpZ);
33 m_instrset.insert(new CInstructionJumpS);
34 m_instrset.insert(new CInstructionWrite);
27} 35}
28 36
29/*----------------------------------------------------------------------------*/ 37/*----------------------------------------------------------------------------*/
30 38
31CProgram::~CProgram() 39CProgram::~CProgram()
32{ 40{
33 41 /* free instruction set */
42 set<CInstruction *>::iterator it;
43 for (it = m_instrset.begin(); it != m_instrset.end(); ++it)
44 delete *it;
45
46 /* free instruction */
47 for (iterator it = begin(); it != end(); ++it)
48 delete *it;
34} 49}
35 50
36
37
38/*----------------------------------------------------------------------------*/ 51/*----------------------------------------------------------------------------*/
39 52
40void CProgram::parse() 53void CProgram::compile(std::istream& in)
41{ 54{
42 /* open and read file */ 55 if (!in.good())
43 ifstream file(m_programfile.c_str(), ios::in); 56 return;
44 // if (!file) 57
45 // throw ParserError("Unable to open scriptfile '" + m_scriptfile + "'."); 58 string line;
46 59 unsigned i = 0;
47 int cur_line_nr = 0; 60 while (!in.eof() && in.good())
48
49 while (!file.eof() && file.good())
50 { 61 {
51 string cur_line; 62 ++i;
52 63
53 /* read file per line */ 64 /* read stream per line */
54 getline(file, cur_line); 65 getline(in, line);
55 if (cur_line.empty()) 66 if (line.empty())
56 continue; 67 continue;
57 68
58 trim(cur_line); 69 boost::trim(line);
70 boost::to_lower(line);
59 71
60 /* ignore comments */ 72 /* ignore comments */
61 if (cur_line.find_first_of('#') == 0) 73 if (line.find_first_of('#') == 0)
62 continue; 74 continue;
63 75
64 /*remove commas from current line */ 76 /* get instruction name */
65 unsigned int pos; 77 size_t pos = line.find_first_of(' ');
66 while (( pos = cur_line.find_first_of(",") ) != string::npos) 78 string instrname(line.substr(0, pos));
67 cur_line.erase(pos, 1); 79
68 80 /* search and create instruction */
69 /* add source line*/ 81 CInstruction *instrptr = NULL;
70 m_progsource.push_back(vector<string>()); 82 set<CInstruction *>::iterator it;
71 algorithm::split( m_progsource.back(), cur_line, is_any_of(" \t")); 83 for (it = m_instrset.begin(); it != m_instrset.end(); ++it)
72 84 {
73 /* jump addr as line number */ 85 if (*(*it) == instrname)
74 if(m_progsource[cur_line_nr][0] == "label") 86 {
75 { 87 instrptr = *it;
76 int size = m_progsource[cur_line_nr][01].size() - 1; 88 break;
77 string label(m_progsource[cur_line_nr][01].substr(0, size)); 89 }
78 m_jumpaddr[label] = cur_line_nr; 90 }
79 } 91 if (instrptr == NULL)
80 92 {
81 cur_line_nr++; 93 stringstream sstr;
94 sstr << "Unknown instruction '" << instrname << "' on line " << i << ".";
95 throw runtime_error(sstr.str());
96 }
97
98 /* create instruction */
99 CInstruction *instr = instrptr->factory();
100
101 /* parse instruction parameters */
102 string params = (pos == string::npos) ? "" : line.substr(pos + 1);
103 boost::trim(params);
104 list<string> instrparams;
105 boost::split(instrparams, params, boost::is_any_of(", \t"), boost::token_compress_on);
106
107 /* let instruction parse the parameters. catch+throw exception */
108 try
109 {
110 /* handle label instruction ourself, but still add a dummy instruction */
111 if (instrname == "label")
112 {
113 if (instrparams.size() != 1)
114 throw runtime_error("Invalid paramater count - must be 1");
115 string label(instrparams.front());
116 if (label.length() < 2 || label[ label.length() - 1] != ':')
117 throw runtime_error("Label has invalid syntax");
118 m_labels[ label.substr(0, label.length() - 1) ] = size();
119 }
120 instr->compile(instrparams);
121 }
122 catch(runtime_error& ex)
123 {
124 stringstream sstr;
125 sstr << "Unable to compile instruction '" << instrname
126 << "' (line " << i << "): " << ex.what();
127 throw runtime_error(sstr.str());
128 }
129
130 push_back(instr);
82 } 131 }
83 file.close(); 132}
133
134/*----------------------------------------------------------------------------*/
84 135
136unsigned CProgram::findLabel(const std::string& label) const
137{
138 map<string, unsigned>::const_iterator it;
139 it = m_labels.find(label);
140 if (it == m_labels.end())
141 throw runtime_error("Unknown label '" + label + "'");
142 return it->second;
85} 143}
86 144
87/*----------------------------------------------------------------------------*/ 145/*----------------------------------------------------------------------------*/
88 146
89#ifdef DEBUG 147#if DEBUG
90void CProgram::dump(std::ostream& out) 148void CProgram::dump(std::ostream& out)
91{ 149{
92 150 out << "[PROGRAM DUMP]" << endl;
93 out << endl << "Program file:" << endl << m_programfile << endl; 151 unsigned i = 0;
94 152 for(iterator it = begin(); it < end(); ++it)
95 out << endl << "Program source:" << endl;
96 for (int i = 0; i < (int) m_progsource.size();i++)
97 { 153 {
98 for(int x = 0; x < (int) m_progsource[i].size();x++) 154 out << "[" << std::setw(4) << std::setfill('0') << i << "] "
99 out << m_progsource[i][x] << " "; 155 << *(*it) << endl;
100 out << std::endl; 156 ++i;
101 } 157 }
102
103 out << endl << "Jump addresses:" << endl;
104 map<string, unsigned int>::iterator it;
105 for (it = m_jumpaddr.begin(); it != m_jumpaddr.end(); it++)
106 out << (*it).first << " " << (*it).second << endl;
107
108} 158}
109#endif 159#endif
160
161/* vim: set et sw=2 ts=2: */
diff --git a/ue3/mycpu/cprogram.h b/ue3/mycpu/cprogram.h
index 25d0ce2..27e7647 100644
--- a/ue3/mycpu/cprogram.h
+++ b/ue3/mycpu/cprogram.h
@@ -1,51 +1,41 @@
1/** 1/**
2 * @module cprogram 2 * @module cprogram
3 * @author Guenther Neuwirth (0626638), Manuel Mausz (0728348) 3 * @author Guenther Neuwirth (0626638), Manuel Mausz (0728348)
4 * @brief class for parsing and saving the program instuctions. 4 * @brief CProgram extends std::vector and adds a method for parsing programfile
5 * @date 17.04.2009 5 * @date 10.05.2009
6 */ 6 */
7 7
8#ifndef CPROGRAM_H 8#ifndef CPROGRAM_H
9#define CPROGRAM_H 9#define CPROGRAM_H 1
10 10
11#include <stdexcept>
12#include <string>
13#include <vector> 11#include <vector>
12#include <set>
14#include <map> 13#include <map>
15#ifdef DEBUG 14#include "cinstruction.h"
16# include <iostream> 15
17#endif
18#include "cdat.h"
19/** 16/**
20 * @class CProgram 17 * @class CProgram
21 * 18 *
22 * Parses a simple line based scriptfile with some limitations: 19 * CProgram extends std::vector and adds a method for parsing
23 * first function (starting a block) must be a read-command, 20 * programfile. This adds instances of CInstruction to CProgram itself.
24 * last must be a write-command (ending this block).
25 *
26 * read- and write-commands have hard coded parameters, number#1 being a filetype.
27 * Classes handling certain filetypes must be of type CFile.
28 * Custom functions will be passed to CFile::callFunc().
29 *
30 * On error ParserError will be thrown.
31 */ 21 */
32class CProgram 22class CProgram
23 : public std::vector<CInstruction *>
33{ 24{
34 public: 25 public:
35
36 /** 26 /**
37 * @method CProgram 27 * @method CProgram
38 * @brief Default ctor 28 * @brief Default ctor
39 * @param programfile filename 29 * @param -
40 * @return - 30 * @return -
41 * @globalvars none 31 * @globalvars none
42 * @exception bad_alloc 32 * @exception none
43 * @conditions none 33 * @conditions none
44 */ 34 */
45 CProgram(const std::string& progfile); 35 CProgram();
46 36
47 /** 37 /**
48 * @method ~CScriptparser 38 * @method ~CProgram
49 * @brief Default dtor 39 * @brief Default dtor
50 * @param - 40 * @param -
51 * @return - 41 * @return -
@@ -55,50 +45,60 @@ class CProgram
55 */ 45 */
56 ~CProgram(); 46 ~CProgram();
57 47
58 CDat getMaxProgramCount() 48 /**
59 { 49 * @method getLabels
60 return CDat(m_progsource.size()); 50 * @brief get reference to labels map
61 } 51 * @param -
62 52 * @return reference to labels map
63 std::vector<std::string>& getInstruction(CDat linenr) 53 * @globalvars none
64 { 54 * @exception none
65 return m_progsource[linenr.getTypeValue()]; 55 * @conditions none
66 } 56 */
67 57 const std::map<std::string, unsigned>& getLabels() const
68 std::map<std::string, unsigned int>& getJumpAddrs()
69 { 58 {
70 return m_jumpaddr; 59 return m_labels;
71 } 60 }
72#ifdef DEBUG 61
73 /** 62 /**
74 * @method dump 63 * @method findLabel
75 * @brief Dumps the program source to ostream 64 * @brief search for label
76 * @param out output stream 65 * @param label name of label to search for
77 * @return - 66 * @return index of found label in program
78 * @globalvars 67 * @globalvars none
79 * @exception 68 * @exception std::runtime_error
80 * @conditions 69 * @conditions none
81 */ 70 */
82 void dump(std::ostream& out); 71 unsigned findLabel(const std::string& label) const;
83#endif
84 72
85 protected:
86 /** 73 /**
87 * @method parse 74 * @method compile
88 * @brief parse the program file 75 * @brief create instructions from parsing stream
89 * @param - 76 * @param in inputstream to read from
90 * @return - 77 * @return void
78 * @globalvars none
79 * @exception std::runtime_error
80 * @conditions none
81 */
82 void compile(std::istream& in);
83
84#if DEBUG
85 /**
86 * @method dump
87 * @brief dumps contents to outputstream
88 * @param out outputstream to write to
89 * @return void
91 * @globalvars none 90 * @globalvars none
92 * @exception ParserError 91 * @exception none
93 * @conditions none 92 * @conditions none
94 */ 93 */
95 void parse(); 94 void dump(std::ostream& out);
96 95#endif
96
97 private: 97 private:
98 /* members */ 98 /* members */
99 std::string m_programfile; 99 /** set of known instructions */
100 std::vector<std::vector<std::string> > m_progsource; 100 std::set<CInstruction *> m_instrset;
101 std::map<std::string, unsigned int> m_jumpaddr; 101 std::map<std::string, unsigned> m_labels;
102}; 102};
103 103
104#endif 104#endif
diff --git a/ue3/mycpu/displays.h b/ue3/mycpu/displays.h
new file mode 100644
index 0000000..d4f3f36
--- /dev/null
+++ b/ue3/mycpu/displays.h
@@ -0,0 +1,76 @@
1/**
2 * @module displays
3 * @author Guenther Neuwirth (0626638), Manuel Mausz (0728348)
4 * @brief Implementations of CDisplay
5 * @date 10.05.2009
6 */
7
8#ifndef DISPLAYS_H
9#define DISPLAYS_H 1
10
11#include <iomanip>
12#include "cdisplay.h"
13
14/**
15 * @class CDisplayWDEZ
16 *
17 * Implementation of CDisplay
18 * Prints CDat to stdout as decimal
19 */
20class CDisplayWDEZ
21 : public CDisplay
22{
23 public:
24 CDisplayWDEZ()
25 : CDisplay("wdez")
26 {}
27
28 /**
29 * @method display
30 * @brief prints value to display
31 * @param value value to display
32 * @return -
33 * @globalvars none
34 * @exception none
35 * @conditions none
36 */
37 void display(const CDat &value)
38 {
39 std::cout << std::dec << value << std::endl;
40 }
41};
42
43/*============================================================================*/
44
45/**
46 * @class CDisplayWHEX
47 *
48 * Implementation of CDisplay
49 * Prints CDat to stdout as decimal
50 */
51class CDisplayWHEX
52 : public CDisplay
53{
54 public:
55 CDisplayWHEX()
56 : CDisplay("whex")
57 {}
58
59 /**
60 * @method display
61 * @brief prints value to display
62 * @param value value to display
63 * @return -
64 * @globalvars none
65 * @exception none
66 * @conditions none
67 */
68 void display(const CDat &value)
69 {
70 std::cout << std::hex << value << std::endl;
71 }
72};
73
74#endif
75
76/* vim: set et sw=2 ts=2: */
diff --git a/ue3/mycpu/instructions.cpp b/ue3/mycpu/instructions.cpp
new file mode 100644
index 0000000..ef9e944
--- /dev/null
+++ b/ue3/mycpu/instructions.cpp
@@ -0,0 +1,341 @@
1/**
2 * @module instructions
3 * @author Guenther Neuwirth (0626638), Manuel Mausz (0728348)
4 * @brief Implementations of CInstruction
5 * @date 10.05.2009
6 */
7
8#include <map>
9#include <assert.h>
10#include "instructions.h"
11
12using namespace std;
13
14void CInstructionInc::compile(std::list<std::string>& params)
15{
16 if (params.size() != 1)
17 throw runtime_error("Invalid paramater count - must be 1");
18 m_regidx1 = parseRegister(params.front());
19 params.pop_front();
20}
21
22/*----------------------------------------------------------------------------*/
23
24void CInstructionInc::execute(CCPU *cpu)
25{
26 assert(cpu != NULL);
27 assert(cpu->getRegisters() != NULL);
28 checkRegister(cpu, m_regidx1);
29 cpu->getRegisters()[ m_regidx1 ]++;
30}
31
32/*============================================================================*/
33
34void CInstructionDec::compile(std::list<std::string>& params)
35{
36 if (params.size() != 1)
37 throw runtime_error("Invalid paramater count - must be 1");
38 m_regidx1 = parseRegister(params.front());
39 params.pop_front();
40}
41
42/*----------------------------------------------------------------------------*/
43
44void CInstructionDec::execute(CCPU *cpu)
45{
46 assert(cpu != NULL);
47 assert(cpu->getRegisters() != NULL);
48 checkRegister(cpu, m_regidx1);
49 cpu->getRegisters()[ m_regidx1 ]--;
50}
51
52/*============================================================================*/
53
54void CInstructionAdd::compile(std::list<std::string>& params)
55{
56 if (params.size() != 3)
57 throw runtime_error("Invalid paramater count - must be 3");
58 m_regidx1 = parseRegister(params.front());
59 params.pop_front();
60 m_regidx2 = parseRegister(params.front());
61 params.pop_front();
62 m_regidx3 = parseRegister(params.front());
63 params.pop_front();
64}
65
66/*----------------------------------------------------------------------------*/
67
68void CInstructionAdd::execute(CCPU *cpu)
69{
70 assert(cpu != NULL);
71 assert(cpu->getRegisters() != NULL);
72 checkRegister(cpu, m_regidx1);
73 checkRegister(cpu, m_regidx2);
74 checkRegister(cpu, m_regidx3);
75 cpu->getRegisters()[ m_regidx1 ] = cpu->getRegisters()[ m_regidx2 ]
76 + cpu->getRegisters()[ m_regidx3 ];
77}
78
79/*============================================================================*/
80
81void CInstructionSub::compile(std::list<std::string>& params)
82{
83 if (params.size() != 3)
84 throw runtime_error("Invalid paramater count - must be 3");
85 m_regidx1 = parseRegister(params.front());
86 params.pop_front();
87 m_regidx2 = parseRegister(params.front());
88 params.pop_front();
89 m_regidx3 = parseRegister(params.front());
90 params.pop_front();
91}
92
93/*----------------------------------------------------------------------------*/
94
95void CInstructionSub::execute(CCPU *cpu)
96{
97 assert(cpu != NULL);
98 assert(cpu->getRegisters() != NULL);
99 checkRegister(cpu, m_regidx1);
100 checkRegister(cpu, m_regidx2);
101 checkRegister(cpu, m_regidx3);
102 cpu->getRegisters()[ m_regidx1 ] = cpu->getRegisters()[ m_regidx2 ]
103 - cpu->getRegisters()[ m_regidx3 ];
104}
105
106/*============================================================================*/
107
108void CInstructionMul::compile(std::list<std::string>& params)
109{
110 if (params.size() != 3)
111 throw runtime_error("Invalid paramater count - must be 3");
112 m_regidx1 = parseRegister(params.front());
113 params.pop_front();
114 m_regidx2 = parseRegister(params.front());
115 params.pop_front();
116 m_regidx3 = parseRegister(params.front());
117 params.pop_front();
118}
119
120/*----------------------------------------------------------------------------*/
121
122void CInstructionMul::execute(CCPU *cpu)
123{
124 checkRegister(cpu, m_regidx1);
125 checkRegister(cpu, m_regidx2);
126 checkRegister(cpu, m_regidx3);
127 cpu->getRegisters()[ m_regidx1 ] = cpu->getRegisters()[ m_regidx2 ]
128 * cpu->getRegisters()[ m_regidx3 ];
129}
130
131/*============================================================================*/
132
133void CInstructionDiv::compile(std::list<std::string>& params)
134{
135 if (params.size() != 3)
136 throw runtime_error("Invalid paramater count - must be 3");
137 m_regidx1 = parseRegister(params.front());
138 params.pop_front();
139 m_regidx2 = parseRegister(params.front());
140 params.pop_front();
141 m_regidx3 = parseRegister(params.front());
142 params.pop_front();
143}
144
145/*----------------------------------------------------------------------------*/
146
147void CInstructionDiv::execute(CCPU *cpu)
148{
149 assert(cpu != NULL);
150 assert(cpu->getRegisters() != NULL);
151 checkRegister(cpu, m_regidx1);
152 checkRegister(cpu, m_regidx2);
153 checkRegister(cpu, m_regidx3);
154 cpu->getRegisters()[ m_regidx1 ] = cpu->getRegisters()[ m_regidx2 ]
155 / cpu->getRegisters()[ m_regidx3 ];
156}
157
158/*============================================================================*/
159
160void CInstructionLoad::compile(std::list<std::string>& params)
161{
162 if (params.size() != 2)
163 throw runtime_error("Invalid paramater count - must be 2");
164 m_regidx1 = parseRegister(params.front());
165 params.pop_front();
166 m_regidx2 = parseRegister(params.front());
167 params.pop_front();
168}
169
170/*----------------------------------------------------------------------------*/
171
172void CInstructionLoad::execute(CCPU *cpu)
173{
174 assert(cpu != NULL);
175 assert(cpu->getRegisters() != NULL);
176 assert(cpu->getMemory() != NULL);
177 checkRegister(cpu, m_regidx1);
178 checkRegister(cpu, m_regidx2);
179 CDat val(cpu->getRegisters()[ m_regidx2 ]);
180 cpu->getRegisters()[ m_regidx1 ] = (*cpu->getMemory())[ val ];
181}
182
183/*============================================================================*/
184
185void CInstructionStore::compile(std::list<std::string>& params)
186{
187 if (params.size() != 2)
188 throw runtime_error("Invalid paramater count - must be 2");
189 m_regidx1 = parseRegister(params.front());
190 params.pop_front();
191 m_regidx2 = parseRegister(params.front());
192 params.pop_front();
193}
194
195/*----------------------------------------------------------------------------*/
196
197void CInstructionStore::execute(CCPU *cpu)
198{
199 assert(cpu != NULL);
200 assert(cpu->getRegisters() != NULL);
201 assert(cpu->getMemory() != NULL);
202 checkRegister(cpu, m_regidx1);
203 checkRegister(cpu, m_regidx2);
204 CDat val(cpu->getRegisters()[ m_regidx2 ]);
205 (*cpu->getMemory())[ val ] = cpu->getRegisters()[ m_regidx1 ];
206}
207
208/*============================================================================*/
209
210void CInstructionTest::compile(std::list<std::string>& params)
211{
212 if (params.size() != 1)
213 throw runtime_error("Invalid paramater count - must be 1");
214 m_regidx1 = parseRegister(params.front());
215 params.pop_front();
216}
217
218/*----------------------------------------------------------------------------*/
219
220void CInstructionTest::execute(CCPU *cpu)
221{
222 assert(cpu != NULL);
223 assert(cpu->getRegisters() != NULL);
224 checkRegister(cpu, m_regidx1);
225 if (cpu->getRegisters()[ m_regidx1 ] == CDat(0))
226 cpu->setFlagZero(true);
227 if (cpu->getRegisters()[ m_regidx1 ] < CDat(0))
228 cpu->setFlagSign(true);
229}
230
231/*============================================================================*/
232
233void CInstructionJumpA::compile(std::list<std::string>& params)
234{
235 if (params.size() != 1)
236 throw runtime_error("Invalid paramater count - must be 1");
237 m_addr = params.front();
238 params.pop_front();
239}
240
241/*----------------------------------------------------------------------------*/
242
243void CInstructionJumpA::execute(CCPU *cpu)
244{
245 assert(cpu != NULL);
246 assert(cpu->getRegisters() != NULL);
247 assert(cpu->getProgram() != NULL);
248 if (m_addr.empty())
249 throw runtime_error("Empty address");
250 cpu->getRegisters()[ 0 ] = cpu->getProgram()->findLabel(m_addr);
251}
252
253/*============================================================================*/
254
255void CInstructionJumpZ::compile(std::list<std::string>& params)
256{
257 if (params.size() != 1)
258 throw runtime_error("Invalid paramater count - must be 1");
259 m_addr = params.front();
260 params.pop_front();
261}
262
263/*----------------------------------------------------------------------------*/
264
265void CInstructionJumpZ::execute(CCPU *cpu)
266{
267 assert(cpu != NULL);
268 assert(cpu->getRegisters() != NULL);
269 assert(cpu->getProgram() != NULL);
270 if (!cpu->getFlagZero())
271 return;
272 if (m_addr.empty())
273 throw runtime_error("Empty address");
274 cpu->getRegisters()[ 0 ] = cpu->getProgram()->findLabel(m_addr);
275}
276
277/*============================================================================*/
278
279void CInstructionJumpS::compile(std::list<std::string>& params)
280{
281 if (params.size() != 1)
282 throw runtime_error("Invalid paramater count - must be 1");
283 m_addr = params.front();
284 params.pop_front();
285}
286
287/*----------------------------------------------------------------------------*/
288
289void CInstructionJumpS::execute(CCPU *cpu)
290{
291 assert(cpu != NULL);
292 assert(cpu->getRegisters() != NULL);
293 assert(cpu->getProgram() != NULL);
294 if (!cpu->getFlagSign())
295 return;
296 if (m_addr.empty())
297 throw runtime_error("Empty address");
298 cpu->getRegisters()[ 0 ] = cpu->getProgram()->findLabel(m_addr);
299}
300
301/*============================================================================*/
302
303void CInstructionWrite::compile(std::list<std::string>& params)
304{
305 if (params.size() != 2)
306 throw runtime_error("Invalid paramater count - must be 2");
307 m_dev = params.front();
308 params.pop_front();
309 m_regidx1 = parseRegister(params.front());
310 params.pop_front();
311}
312
313/*----------------------------------------------------------------------------*/
314
315void CInstructionWrite::execute(CCPU *cpu)
316{
317 assert(cpu != NULL);
318 assert(cpu->getRegisters() != NULL);
319 checkRegister(cpu, m_regidx1);
320 if (m_dev.empty())
321 throw runtime_error("Empty device");
322
323 CDisplay *display = NULL;
324 std::set<CDisplay *> displays = cpu->getDisplays();
325 std::set<CDisplay *>::iterator it;
326 for(it = displays.begin(); it != displays.end(); ++it)
327 {
328 if ((*it)->getName() == m_dev)
329 {
330 display = *it;
331 break;
332 }
333 }
334 if (display == NULL)
335 throw runtime_error("Unknown display");
336
337 display->display(cpu->getRegisters()[ m_regidx1 ]);
338}
339
340
341/* vim: set et sw=2 ts=2: */
diff --git a/ue3/mycpu/instructions.h b/ue3/mycpu/instructions.h
new file mode 100644
index 0000000..4c36562
--- /dev/null
+++ b/ue3/mycpu/instructions.h
@@ -0,0 +1,454 @@
1/**
2 * @module instructions
3 * @author Guenther Neuwirth (0626638), Manuel Mausz (0728348)
4 * @brief Implementations of CInstruction
5 * @date 10.05.2009
6 */
7
8#ifndef INSTRUCTIONS_H
9#define INSTRUCTIONS_H 1
10
11#include "cinstruction.h"
12#include "ccpu.h"
13
14/**
15 * @class CInstructionInc
16 *
17 * Implementation of assembler command "inc"
18 * Syntax: inc R1
19 * (R1++)
20 */
21class CInstructionInc
22 : public CInstruction
23{
24 public:
25 CInstructionInc()
26 : CInstruction("inc")
27 {}
28
29 CInstructionInc *factory()
30 {
31 return new CInstructionInc;
32 }
33
34 void compile(std::list<std::string>& params);
35 void execute(CCPU *cpu);
36
37 protected:
38 /** register number */
39 unsigned m_regidx1;
40};
41
42/*============================================================================*/
43
44/**
45 * @class CInstructionDec
46 *
47 * Implementation of assembler command "dec"
48 * Syntax: dec R1
49 * (R1--)
50 */
51class CInstructionDec
52 : public CInstruction
53{
54 public:
55 CInstructionDec()
56 : CInstruction("dec")
57 {}
58
59 CInstructionDec *factory()
60 {
61 return new CInstructionDec;
62 }
63
64 void compile(std::list<std::string>& params);
65 void execute(CCPU *cpu);
66
67 protected:
68 /** register number */
69 unsigned m_regidx1;
70};
71
72/*============================================================================*/
73
74/**
75 * @class CInstructionAdd
76 *
77 * Implementation of assembler command "add"
78 * Syntax: add R1, R2, R3
79 * (R1 = R2 + R3)
80 */
81class CInstructionAdd
82 : public CInstruction
83{
84 public:
85 CInstructionAdd()
86 : CInstruction("add")
87 {}
88
89 CInstructionAdd *factory()
90 {
91 return new CInstructionAdd;
92 }
93
94 void compile(std::list<std::string>& params);
95 void execute(CCPU *cpu);
96
97 protected:
98 /** register number */
99 unsigned m_regidx1;
100 /** register number */
101 unsigned m_regidx2;
102 /** register number */
103 unsigned m_regidx3;
104};
105
106/*============================================================================*/
107
108/**
109 * @class CInstructionSub
110 *
111 * Implementation of assembler command "sub"
112 * Syntax: sub R1, R2, R3
113 * (R1 = R2 - R3)
114 */
115class CInstructionSub
116 : public CInstruction
117{
118 public:
119 CInstructionSub()
120 : CInstruction("sub")
121 {}
122
123 CInstructionSub *factory()
124 {
125 return new CInstructionSub;
126 }
127
128 void compile(std::list<std::string>& params);
129 void execute(CCPU *cpu);
130
131 protected:
132 /** register number */
133 unsigned m_regidx1;
134 /** register number */
135 unsigned m_regidx2;
136 /** register number */
137 unsigned m_regidx3;
138};
139
140/*============================================================================*/
141
142/**
143 * @class CInstructionMul
144 *
145 * Implementation of assembler command "mul"
146 * Syntax: mul R1, R2, R3
147 * (R1 = R2 * R3)
148 */
149class CInstructionMul
150 : public CInstruction
151{
152 public:
153 CInstructionMul()
154 : CInstruction("mul")
155 {}
156
157 CInstructionMul *factory()
158 {
159 return new CInstructionMul;
160 }
161
162 void compile(std::list<std::string>& params);
163 void execute(CCPU *cpu);
164
165 protected:
166 /** register number */
167 unsigned m_regidx1;
168 /** register number */
169 unsigned m_regidx2;
170 /** register number */
171 unsigned m_regidx3;
172};
173
174/*============================================================================*/
175
176/**
177 * @class CInstructionDiv
178 *
179 * Implementation of assembler command "div"
180 * Syntax: div R1, R2, R3
181 * (R1 = R2 / R3)
182 */
183class CInstructionDiv
184 : public CInstruction
185{
186 public:
187 CInstructionDiv()
188 : CInstruction("div")
189 {}
190
191 CInstructionDiv *factory()
192 {
193 return new CInstructionDiv;
194 }
195
196 void compile(std::list<std::string>& params);
197 void execute(CCPU *cpu);
198
199 protected:
200 /** register number */
201 unsigned m_regidx1;
202 /** register number */
203 unsigned m_regidx2;
204 /** register number */
205 unsigned m_regidx3;
206};
207
208/*============================================================================*/
209
210/**
211 * @class CInstructionLoad
212 *
213 * Implementation of assembler command "load"
214 * Syntax: load R1, R2
215 * (R1 = memory[R2])
216 */
217class CInstructionLoad
218 : public CInstruction
219{
220 public:
221 CInstructionLoad()
222 : CInstruction("load")
223 {}
224
225 CInstructionLoad *factory()
226 {
227 return new CInstructionLoad;
228 }
229
230 void compile(std::list<std::string>& params);
231 void execute(CCPU *cpu);
232
233 protected:
234 /** register number */
235 unsigned m_regidx1;
236 /** register number */
237 unsigned m_regidx2;
238};
239
240/*============================================================================*/
241
242/**
243 * @class CInstructionStore
244 *
245 * Implementation of assembler command "store"
246 * Syntax: store R1, R2
247 * (memory[R2] = R1)
248 */
249class CInstructionStore
250 : public CInstruction
251{
252 public:
253 CInstructionStore()
254 : CInstruction("store")
255 {}
256
257 CInstructionStore *factory()
258 {
259 return new CInstructionStore;
260 }
261
262 void compile(std::list<std::string>& params);
263 void execute(CCPU *cpu);
264
265 protected:
266 /** register number */
267 unsigned m_regidx1;
268 /** register number */
269 unsigned m_regidx2;
270};
271
272/*============================================================================*/
273
274/**
275 * @class CInstructionTest
276 *
277 * Implementation of assembler command "test"
278 * Syntax: test R1
279 * (R1 == 0: zeroflag: true, R1 < 0: signflag: true)
280 */
281class CInstructionTest
282 : public CInstruction
283{
284 public:
285 CInstructionTest()
286 : CInstruction("test")
287 {}
288
289 CInstructionTest *factory()
290 {
291 return new CInstructionTest;
292 }
293
294 void compile(std::list<std::string>& params);
295 void execute(CCPU *cpu);
296
297 protected:
298 /** register number */
299 unsigned m_regidx1;
300};
301
302/*============================================================================*/
303
304/**
305 * @class CInstructionLabel
306 *
307 * Implementation of assembler command "label"
308 * Syntax: label name:
309 */
310class CInstructionLabel
311 : public CInstruction
312{
313 public:
314 CInstructionLabel()
315 : CInstruction("label")
316 {}
317
318 CInstructionLabel *factory()
319 {
320 return new CInstructionLabel;
321 }
322
323 void compile(std::list<std::string>& params)
324 {}
325
326 void execute(CCPU *cpu)
327 {}
328};
329
330/*============================================================================*/
331
332/**
333 * @class CInstructionJumpA
334 *
335 * Implementation of assembler command "jumpa"
336 * Syntax: jumpa labelname
337 * (jump to labelname)
338 */
339class CInstructionJumpA
340 : public CInstruction
341{
342 public:
343 CInstructionJumpA()
344 : CInstruction("jumpa"), m_addr("")
345 {}
346
347 CInstructionJumpA *factory()
348 {
349 return new CInstructionJumpA;
350 }
351
352 void compile(std::list<std::string>& params);
353 void execute(CCPU *cpu);
354
355 protected:
356 /** labelname */
357 std::string m_addr;
358};
359
360/*============================================================================*/
361
362/**
363 * @class CInstructionJumpZ
364 *
365 * Implementation of assembler command "jumpz"
366 * Syntax: jumpz labelname
367 * (jump to labelname if zeroflag)
368 */
369class CInstructionJumpZ
370 : public CInstruction
371{
372 public:
373 CInstructionJumpZ()
374 : CInstruction("jumpz"), m_addr("")
375 {}
376
377 CInstructionJumpZ *factory()
378 {
379 return new CInstructionJumpZ;
380 }
381
382 void compile(std::list<std::string>& params);
383 void execute(CCPU *cpu);
384
385 protected:
386 /** labelname */
387 std::string m_addr;
388};
389
390/*============================================================================*/
391
392/**
393 * @class CInstructionJumpS
394 *
395 * Implementation of assembler command "jumps"
396 * Syntax: jumps labelname
397 * (jump to labelname if signflag)
398 */
399class CInstructionJumpS
400 : public CInstruction
401{
402 public:
403 CInstructionJumpS()
404 : CInstruction("jumps"), m_addr("")
405 {}
406
407 CInstructionJumpS *factory()
408 {
409 return new CInstructionJumpS;
410 }
411
412 void compile(std::list<std::string>& params);
413 void execute(CCPU *cpu);
414
415 protected:
416 /** labelname */
417 std::string m_addr;
418};
419
420/*============================================================================*/
421
422/**
423 * @class CInstructionWrite
424 *
425 * Implementation of assembler command "write"
426 * Syntax: write DEV, R1
427 * (write R1 to DEV, which is a name of a display)
428 */
429class CInstructionWrite
430 : public CInstruction
431{
432 public:
433 CInstructionWrite()
434 : CInstruction("write"), m_dev("")
435 {}
436
437 CInstructionWrite *factory()
438 {
439 return new CInstructionWrite;
440 }
441
442 void compile(std::list<std::string>& params);
443 void execute(CCPU *cpu);
444
445 protected:
446 /** register number */
447 unsigned m_regidx1;
448 /** device name */
449 std::string m_dev;
450};
451
452#endif
453
454/* vim: set et sw=2 ts=2: */
diff --git a/ue3/mycpu/mycpu.cpp b/ue3/mycpu/mycpu.cpp
index af6fe08..b25e721 100644
--- a/ue3/mycpu/mycpu.cpp
+++ b/ue3/mycpu/mycpu.cpp
@@ -1,17 +1,24 @@
1/** 1/**
2 * @module mycpu 2 * @module mycpu
3 * @author Guenther Neuwirth (0626638), Manuel Mausz (0728348) 3 * @author Guenther Neuwirth (0626638), Manuel Mausz (0728348)
4 * @brief mycpu reads a program file and optional a memory file given as 4 * @brief mycpu executes a programfile (in simple assembler) by parsing the
5 * commandline option. 5 * programfile first. This creates a vector of instructions, which will
6 * On error (e.g. unknown function) the program will terminate 6 * be executed in linear order (except jumps) afterwards. In order to
7 * @date 11.05.2009 7 * initialize the memory of the cpu before execution an optional
8 * memoryfile can be passed as commandline option.
9 * @date 13.05.2009
8 * @par Exercise 10 * @par Exercise
9 * 3 11 * 4
10 */ 12 */
11 13
12#include <iostream>
13#include <boost/program_options.hpp> 14#include <boost/program_options.hpp>
15#include <iostream>
16#include <fstream>
17#include <stdexcept>
18#include <stdlib.h>
14#include "ccpu.h" 19#include "ccpu.h"
20#include "cmem.h"
21#include "cprogram.h"
15 22
16using namespace std; 23using namespace std;
17namespace po = boost::program_options; 24namespace po = boost::program_options;
@@ -26,8 +33,10 @@ namespace po = boost::program_options;
26 * @exception none 33 * @exception none
27 * @conditions none 34 * @conditions none
28 * 35 *
29 * setup commandline options, parse them and pass scriptfile to scriptparser 36 * parse commandline options, create and initialize memory,
30 * instance. On error print error message to stderr. 37 * create cprogram instance, which parses the programfile and
38 * execute CCPU::run()
39 * On error print error message to stderr.
31 * Unknown commandline options will print a usage message. 40 * Unknown commandline options will print a usage message.
32 */ 41 */
33int main(int argc, char* argv[]) 42int main(int argc, char* argv[])
@@ -37,9 +46,9 @@ int main(int argc, char* argv[])
37 /* define commandline options */ 46 /* define commandline options */
38 po::options_description desc("Allowed options"); 47 po::options_description desc("Allowed options");
39 desc.add_options() 48 desc.add_options()
40 ("help,h", "this help message") 49 ("help,h", "this help message")
41 ("progfile,c", po::value<string>(), "program file") 50 ("compile,c", po::value<string>(), "input programfile")
42 ("memfile,m", po::value<string>(), "memory file"); 51 ("memory,m", po::value<string>(), "input memoryfile");
43 52
44 /* parse commandline options */ 53 /* parse commandline options */
45 po::variables_map vm; 54 po::variables_map vm;
@@ -50,43 +59,95 @@ int main(int argc, char* argv[])
50 } 59 }
51 catch(po::error& ex) 60 catch(po::error& ex)
52 { 61 {
53 cerr << "Error: " << ex.what() << endl; 62 cerr << me << ": Error: " << ex.what() << endl;
54 } 63 }
55 64
56 /* print usage upon request or missing params */ 65 /* print usage upon request or missing params */
57 if (vm.count("help") || !vm.count("progfile")) 66 if (vm.count("help") || !vm.count("compile"))
58 { 67 {
59 cout << "Usage: " << me << " -c <programfile> [ -m <memoryfile>]" << endl; 68 cout << "Usage: " << me << " -c <programfile> [-m <memoryfile>]" << endl;
60 cout << desc << endl; 69 cout << desc << endl;
61 if ( vm.count("help")) 70 return 0;
62 return 0; 71 }
72
73 /* create memory and optionally initialize memory from file */
74 CMem memory;
75 if (vm.count("memory"))
76 {
77 string memoryfile(vm["memory"].as<string>());
78 ifstream file(memoryfile.c_str(), ios::in);
79 if (!file.is_open())
80 {
81 cerr << me << ": Unable to open memoryfile '" << memoryfile << "' for reading." << endl;
82 return 1;
83 }
84
85 try
86 {
87 memory.initialize(file);
88 file.close();
89 }
90 catch(runtime_error& ex)
91 {
92 file.close();
93 cerr << me << ": Error while reading from memoryfile:" << endl
94 << " " << ex.what() << endl;
95 return 1;
96 }
97
98#if DEBUG
99 memory.dump(cerr);
100#endif
101 }
102
103 /* create program instance */
104 CProgram program;
105 string programfile(vm["compile"].as<string>());
106 ifstream file(programfile.c_str(), ios::in);
107 if (!file.is_open())
108 {
109 cerr << me << ": Unable to open programfile '" << programfile << "' for reading." << endl;
63 return 1; 110 return 1;
64 } 111 }
65 112
66 string memfile("");
67 if (vm.count("memfile"))
68 memfile = vm["memfile"].as<string>();
69
70 CCPU cpu(vm["progfile"].as<string>(), memfile);
71 cpu.proceed();
72
73/* CScriptparser parser(vm["c"].as<string>());
74 try 113 try
75 { 114 {
76 parser.parse(); 115 program.compile(file);
116 file.close();
77 } 117 }
78 catch(CScriptparser::ParserError& ex) 118 catch(runtime_error& ex)
79 { 119 {
80 cerr << me << ": Error while processing scriptfile: " << ex.what() << endl; 120 file.close();
81 if (!ex.getLine().empty()) 121 cerr << me << ": Error while compiling programfile:" << endl
82 cerr << "Scriptline: '" << ex.getLine() << "'" << endl; 122 << " " << ex.what() << endl;
83 return 1; 123 return 1;
84 } 124 }
85 catch(exception& ex) 125
126#if DEBUG
127 program.dump(cerr);
128#endif
129
130
131 /* create cpu and execute the program */
132 try
133 {
134 CCPU cpu(256);
135 cpu.setMemory(&memory);
136 cpu.setProgram(&program);
137 cpu.run();
138#if DEBUG
139 //cpu.dumpRegisters(cerr);
140#endif
141 }
142 catch(runtime_error& ex)
86 { 143 {
87 cerr << me << ": Unexpected exception: " << ex.what() << endl; 144 cerr << me << ": Error while executing program:" << endl
145 << " " << ex.what() << endl;
146#if DEBUG
147 memory.dump(cerr);
148#endif
88 return 1; 149 return 1;
89 }*/ 150 }
90 151
91 return 0; 152 return 0;
92} 153}
diff --git a/ue3/mycpu/test/test.sh b/ue3/mycpu/test/test.sh
new file mode 100755
index 0000000..ff1076c
--- /dev/null
+++ b/ue3/mycpu/test/test.sh
@@ -0,0 +1,42 @@
1#!/bin/bash
2
3binary="./mycpu"
4tmpfile="test/tmpfile"
5inputs=( $(ls test/* | grep _program | sort -n) )
6
7for input in ${inputs[@]}
8do
9 echo "Testing $input ..."
10
11 programfile="$input"
12 args="-c $programfile"
13 memoryfile="${input/_program/_memory}"
14 reffile="${input/_program/_output}"
15 if [ -e "$memoryfile" ]
16 then
17 args+=" -m $memoryfile"
18 fi
19
20 if [ ! -e "$reffile" ]
21 then
22 echo " ERROR: reference file $reffile doesn't exist"
23 exit 1
24 fi
25
26 rm -rf "$tmpfile"
27 echo " Executing $binary $args ..."
28 $binary $args > $tmpfile
29
30 md5_1=$(md5sum < "$reffile")
31 md5_2=$(md5sum < "$tmpfile")
32 if [ "$md5_1" != "$md5_2" ]
33 then
34 echo " ERROR: output and $reffile differ"
35 diff -Naur "$reffile" "$tmpfile"
36 rm -rf "$tmpfile"
37 exit 1
38 else
39 echo " SUCCESS"
40 fi
41 rm -rf "$tmpfile"
42done
diff --git a/ue3/mycpu/test/test1_memory b/ue3/mycpu/test/test1_memory
new file mode 100644
index 0000000..209e3ef
--- /dev/null
+++ b/ue3/mycpu/test/test1_memory
@@ -0,0 +1 @@
20
diff --git a/ue3/mycpu/test/test1_output b/ue3/mycpu/test/test1_output
new file mode 100644
index 0000000..ac30dc2
--- /dev/null
+++ b/ue3/mycpu/test/test1_output
@@ -0,0 +1,19 @@
11
22
33
44
55
66
77
88
99
1010
1111
1212
1313
1414
1515
1616
1717
1818
1919
diff --git a/ue3/mycpu/test/test1_program b/ue3/mycpu/test/test1_program
new file mode 100644
index 0000000..ae5e9d2
--- /dev/null
+++ b/ue3/mycpu/test/test1_program
@@ -0,0 +1,13 @@
1# set R2 = 10
2LOAD R2, R1
3
4# start of loop
5label Loop:
6inc R3
7sub R4, R3, R2
8test R4
9jumpz EndLoop
10write WDEZ, R3
11jumpa Loop
12
13label EndLoop:
diff --git a/ue3/mycpu/test/test_prog b/ue3/mycpu/test/test_prog
deleted file mode 100644
index b50575b..0000000
--- a/ue3/mycpu/test/test_prog
+++ /dev/null
@@ -1,15 +0,0 @@
1# set R2 = 10
2
3load R2, R1
4
5# start of loop
6label Loop:
7inc R3
8sub R4, R3, R2
9test R4
10jumpz EndLoop
11write WDEZ, R3
12store R3, R1
13jumpa Loop
14
15label EndLoop:
diff --git a/ue3/mycpu/test/test_prog_mem b/ue3/mycpu/test/test_prog_mem
deleted file mode 100644
index 8c3e80f..0000000
--- a/ue3/mycpu/test/test_prog_mem
+++ /dev/null
@@ -1,6 +0,0 @@
19
23
34
45
54
63