summaryrefslogtreecommitdiffstats
path: root/ue4/mycpu
diff options
context:
space:
mode:
authormanuel <manuel@nc8430.lan>2009-05-26 14:49:37 +0200
committermanuel <manuel@nc8430.lan>2009-05-26 14:49:37 +0200
commit1a60d0c2a8eeef3b39ef276f0f3552552a1519b1 (patch)
tree038e7ea34e7093f959372885869234b90734331e /ue4/mycpu
parent1b2db0dfe36f134850965276ba62700dba02da4d (diff)
downloadooprog-1a60d0c2a8eeef3b39ef276f0f3552552a1519b1.tar.gz
ooprog-1a60d0c2a8eeef3b39ef276f0f3552552a1519b1.tar.bz2
ooprog-1a60d0c2a8eeef3b39ef276f0f3552552a1519b1.zip
adding ue4 (copy from ue3)
Diffstat (limited to 'ue4/mycpu')
-rw-r--r--ue4/mycpu/Makefile40
-rw-r--r--ue4/mycpu/ccpu.cpp89
-rw-r--r--ue4/mycpu/ccpu.h241
-rw-r--r--ue4/mycpu/cdat.h326
-rw-r--r--ue4/mycpu/cdisplay.h85
-rw-r--r--ue4/mycpu/cinstruction.cpp48
-rw-r--r--ue4/mycpu/cinstruction.h189
-rw-r--r--ue4/mycpu/cmem.h109
-rw-r--r--ue4/mycpu/cprogram.cpp161
-rw-r--r--ue4/mycpu/cprogram.h106
-rw-r--r--ue4/mycpu/displays.h76
-rw-r--r--ue4/mycpu/instructions.cpp341
-rw-r--r--ue4/mycpu/instructions.h454
-rw-r--r--ue4/mycpu/mycpu.cpp155
-rwxr-xr-xue4/mycpu/test/test.sh42
-rw-r--r--ue4/mycpu/test/test1_memory1
-rw-r--r--ue4/mycpu/test/test1_output19
-rw-r--r--ue4/mycpu/test/test1_program13
18 files changed, 2495 insertions, 0 deletions
diff --git a/ue4/mycpu/Makefile b/ue4/mycpu/Makefile
new file mode 100644
index 0000000..0dbb51a
--- /dev/null
+++ b/ue4/mycpu/Makefile
@@ -0,0 +1,40 @@
1# Makefile for mycpu
2# Author: Guenther Neuwirth (0626638), Manuel Mausz (0728348)
3# Created: 26.05.2009
4
5CXX= g++
6LD= $(CXX)
7DEBUGFLAGS= -DNDEBUG
8INCLUDE_PATH= -I/usr/local/include
9CXXFLAGS= -O -ansi -pedantic-errors -Wall -Wno-long-long $(INCLUDE_PATH) $(DEBUGFLAGS)
10LDFLAGS=
11LIBS= -L/usr/local/lib -lboost_program_options
12
13BIN= mycpu
14OBJS= cinstruction.o instructions.o cprogram.o ccpu.o mycpu.o
15HEADERS= cdat.h cmem.h cinstruction.h instructions.h cprogram.h cdisplay.h displays.h ccpu.h
16
17.SUFFIXES: .cpp .o
18
19all: $(BIN)
20
21.cpp.o:
22 $(CXX) $(CXXFLAGS) -c $< -o $@
23
24$(OBJS): $(HEADERS)
25
26$(BIN): $(OBJS)
27 $(LD) $(LDFLAGS) -o $@ $(OBJS) $(LIBS)
28
29debug:
30 @$(MAKE) all "DEBUGFLAGS=-DDEBUG -g"
31
32clean:
33 rm -f $(OBJS) $(BIN)
34
35run test: all
36 @./test/test.sh
37
38.PHONY: clean
39
40# vim600: noet sw=8 ts=8
diff --git a/ue4/mycpu/ccpu.cpp b/ue4/mycpu/ccpu.cpp
new file mode 100644
index 0000000..af86200
--- /dev/null
+++ b/ue4/mycpu/ccpu.cpp
@@ -0,0 +1,89 @@
1/**
2 * @module ccpu
3 * @author Guenther Neuwirth (0626638), Manuel Mausz (0728348)
4 * @brief CPU implementation. Used as a container for memory and instructions.
5 * Implements an run method to execute the program (= the instructions).
6 * @date 10.05.2009
7 */
8
9#ifdef DEBUG
10# include <iostream>
11# include <iomanip>
12#endif
13#include "ccpu.h"
14#include "displays.h"
15
16using namespace std;
17
18CCPU::CCPU(const unsigned cnt)
19 : m_regcnt(cnt), m_memory(NULL), m_program(NULL), m_flagzero(false), m_flagsign(false)
20{
21 /* create registers */
22 m_registers = new CDat[cnt];
23 for(unsigned i = 0; i < cnt; ++i)
24 m_registers[i] = 0;
25
26 /* create displays */
27 m_displays.insert(new CDisplayWDEZ);
28 m_displays.insert(new CDisplayWHEX);
29}
30
31/*----------------------------------------------------------------------------*/
32
33CCPU::~CCPU()
34{
35 /* delete registers */
36 delete[] m_registers;
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;
43}
44
45/*----------------------------------------------------------------------------*/
46
47void CCPU::run()
48{
49 if (m_memory == NULL)
50 throw runtime_error("CPU has no memory");
51 if (m_program == NULL)
52 throw runtime_error("CPU has no program to execute");
53 if (m_regcnt == 0)
54 throw runtime_error("CPU has no registers");
55
56 bool run = true;
57 while(run)
58 {
59 unsigned pc = static_cast<unsigned>(m_registers[0]);
60
61 /* end of the program reached */
62 if (pc == m_program->size())
63 break;
64
65 /* pc is out of bound */
66 if (pc > m_program->size())
67 throw runtime_error("Programcounter is out of bound");
68
69 /* execute instruction */
70 (*m_program->at(pc))(this);
71 ++m_registers[0];
72 }
73}
74
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
88
89/* vim: set et sw=2 ts=2: */
diff --git a/ue4/mycpu/ccpu.h b/ue4/mycpu/ccpu.h
new file mode 100644
index 0000000..6849623
--- /dev/null
+++ b/ue4/mycpu/ccpu.h
@@ -0,0 +1,241 @@
1/**
2 * @module ccpu
3 * @author Guenther Neuwirth (0626638), Manuel Mausz (0728348)
4 * @brief CPU implementation. Used as a container for memory and instructions.
5 * Implements a run method to execute the program (= the instructions).
6 * @date 10.05.2009
7 */
8
9#ifndef CCPU_H
10#define CCPU_H 1
11
12#include <iostream>
13#include <set>
14#include "cdat.h"
15#include "cmem.h"
16#include "cprogram.h"
17#include "cdisplay.h"
18
19/**
20 * @class CCPU
21 *
22 * CPU implementation. Used as a container for memory and instructions.
23 * Implements a run method to execute the program (= the instructions).
24 */
25class CCPU
26{
27 public:
28 /**
29 * @method CCPU
30 * @brief Default ctor
31 * @param cnt number of registers to allocate for this cpu
32 * @return -
33 * @globalvars none
34 * @exception none
35 * @conditions none
36 */
37 CCPU(const unsigned cnt);
38
39 /**
40 * @method ~CCPU
41 * @brief Default dtor
42 * @param -
43 * @return -
44 * @globalvars none
45 * @exception none
46 * @conditions none
47 */
48 ~CCPU();
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 }
147
148 /**
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 }
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
227
228 private:
229 /* members */
230 CDat *m_registers;
231 unsigned m_regcnt;
232 CMem *m_memory;
233 const CProgram *m_program;
234 std::set<CDisplay *> m_displays;
235 bool m_flagzero;
236 bool m_flagsign;
237};
238
239#endif
240
241/* vim: set et sw=2 ts=2: */
diff --git a/ue4/mycpu/cdat.h b/ue4/mycpu/cdat.h
new file mode 100644
index 0000000..a533fae
--- /dev/null
+++ b/ue4/mycpu/cdat.h
@@ -0,0 +1,326 @@
1/**
2 * @module cdat
3 * @author Guenther Neuwirth (0626638), Manuel Mausz (0728348)
4 * @brief Datatype template and datatype definition for CCPU and CMem
5 * @date 10.05.2009
6 */
7
8#ifndef CDAT_H
9#define CDAT_H 1
10
11#include <boost/operators.hpp>
12#include <iostream>
13
14/**
15 * @class CDatT
16 *
17 * Datatype template for CCPU and CMem.
18 */
19template <class T>
20class CDatT
21 : boost::operators<CDatT<T> >
22{
23 public:
24 /**
25 * @method CDatT
26 * @brief Default ctor
27 * @param -
28 * @return -
29 * @globalvars none
30 * @exception bad_alloc
31 * @conditions none
32 */
33 CDatT()
34 {}
35
36 /**
37 * @method ~CDatT
38 * @brief Default dtor
39 * @param -
40 * @return -
41 * @globalvars none
42 * @exception none
43 * @conditions none
44 */
45 ~CDatT()
46 {}
47
48 /**
49 * @method CDatT
50 * @brief Copy constructor for CDatT
51 * @param other reference to CDatT which will be copied
52 * @return -
53 * @globalvars none
54 * @exception none
55 * @conditions none
56 */
57 CDatT(const CDatT& other)
58 : m_value(other.m_value)
59 {}
60
61 /**
62 * @method CDatT
63 * @brief Copy constructor for int
64 * @param newval new value for CDatT
65 * @return -
66 * @globalvars none
67 * @exception none
68 * @conditions none
69 */
70 CDatT(T newval)
71 : m_value(newval)
72 {}
73
74 /**
75 * @method getValue
76 * @brief returns value of CDatT
77 * @param -
78 * @return value of CDatT
79 * @globalvars none
80 * @exception none
81 * @conditions none
82 */
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()
98 {
99 return m_value;
100 }
101
102 /**
103 * @method operator<
104 * @brief implementation of operator <
105 * @param x reference to CDatT
106 * @return true if cdat is less than object x
107 * @globalvars none
108 * @exception none
109 * @conditions none
110 */
111 bool operator<(const CDatT& x) const
112 {
113 return m_value < x.m_value;
114 }
115
116 /**
117 * @method operator==
118 * @brief implementation of operator ==
119 * @param x reference to CDatT
120 * @return true if cdat equals object x
121 * @globalvars none
122 * @exception none
123 * @conditions none
124 */
125 bool operator==(const CDatT& x) const
126 {
127 return m_value == x.m_value;
128 }
129
130 /**
131 * @method operator+=
132 * @brief implementation of operator +=
133 * @param x reference to CDatT
134 * @return refecence to CDatT
135 * @globalvars none
136 * @exception none
137 * @conditions none
138 */
139 CDatT& operator+=(const CDatT& x)
140 {
141 m_value += x.m_value;
142 return *this;
143 }
144
145 /**
146 * @method operator-=
147 * @brief implementation of operator -=
148 * @param x reference to CDatT
149 * @return refecence to CDatT
150 * @globalvars none
151 * @exception none
152 * @conditions none
153 */
154 CDatT& operator-=(const CDatT& x)
155 {
156 m_value -= x.m_value;
157 return *this;
158 }
159
160 /**
161 * @method operator*=
162 * @brief implementation of operator *=
163 * @param x reference to CDatT
164 * @return refecence to CDatT
165 * @globalvars none
166 * @exception none
167 * @conditions none
168 */
169 CDatT& operator*=(const CDatT& x)
170 {
171 m_value *= x.m_value;
172 return *this;
173 }
174
175 /**
176 * @method operator/=
177 * @brief implementation of operator /=
178 * @param x reference to CDatT
179 * @return refecence to CDatT
180 * @globalvars none
181 * @exception none
182 * @conditions none
183 */
184 CDatT& operator/=(const CDatT& x)
185 {
186 m_value /= x.m_value;
187 return *this;
188 }
189
190 /**
191 * @method operator%=
192 * @brief implementation of operator %=
193 * @param x reference to CDatT
194 * @return refecence to CDatT
195 * @globalvars none
196 * @exception none
197 * @conditions none
198 */
199 CDatT& operator%=(const CDatT& x)
200 {
201 m_value %= x.m_value;
202 return *this;
203 }
204
205 /**
206 * @method operator|=
207 * @brief implementation of operator |=
208 * @param x reference to CDatT
209 * @return refecence to CDatT
210 * @globalvars none
211 * @exception none
212 * @conditions none
213 */
214 CDatT& operator|=(const CDatT& x)
215 {
216 m_value |= x.m_value;
217 return *this;
218 }
219
220 /**
221 * @method operator&=
222 * @brief implementation of operator &=
223 * @param x reference to CDatT
224 * @return refecence to CDatT
225 * @globalvars none
226 * @exception none
227 * @conditions none
228 */
229 CDatT& operator&=(const CDatT& x)
230 {
231 m_value &= x.m_value;
232 return *this;
233 }
234
235 /**
236 * @method operator^=
237 * @brief implementation of operator ^=
238 * @param x reference to CDatT
239 * @return refecence to CDatT
240 * @globalvars none
241 * @exception none
242 * @conditions none
243 */
244 CDatT& operator^=(const CDatT& x)
245 {
246 m_value ^= x.m_value;
247 return *this;
248 }
249
250 /**
251 * @method operator++
252 * @brief implementation of operator ++
253 * @param -
254 * @return refecence to CDatT
255 * @globalvars none
256 * @exception none
257 * @conditions none
258 */
259 CDatT& operator++()
260 {
261 m_value++;
262 return *this;
263 }
264
265 /**
266 * @method operator--
267 * @brief implementation of operator --
268 * @param -
269 * @return refecence to CDatT
270 * @globalvars none
271 * @exception none
272 * @conditions none
273 */
274 CDatT& operator--()
275 {
276 m_value--;
277 return *this;
278 }
279
280 /**
281 * @method operator<<
282 * @brief Shift/output operator for outputstream
283 * @param stream reference to outputstream
284 * @param cdat object which will be printed to stream
285 * @return reference to outputstream
286 * @globalvars none
287 * @exception none
288 * @conditions none
289 */
290 friend std::ostream& operator<<(std::ostream& stream, CDatT cdat)
291 {
292 stream << cdat.m_value;
293 return stream;
294 }
295
296 /**
297 * @method operator>>
298 * @brief Shift/read operator for inputstream
299 * @param stream reference to inputstream
300 * @param cdat reference to object which will be read from stream
301 * @return reference to inputstream
302 * @globalvars none
303 * @exception none
304 * @conditions none
305 */
306 friend std::istream& operator>>(std::istream & stream, CDatT& cdat)
307 {
308 stream >> cdat.m_value;
309 return stream;
310 }
311
312 private:
313 /* members */
314 T m_value;
315};
316
317/**
318 * @class CDat
319 *
320 * Datatype for CCPU and CMem
321 */
322typedef CDatT<int> CDat;
323
324#endif
325
326/* vim: set et sw=2 ts=2: */
diff --git a/ue4/mycpu/cdisplay.h b/ue4/mycpu/cdisplay.h
new file mode 100644
index 0000000..82776ee
--- /dev/null
+++ b/ue4/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/ue4/mycpu/cinstruction.cpp b/ue4/mycpu/cinstruction.cpp
new file mode 100644
index 0000000..a766015
--- /dev/null
+++ b/ue4/mycpu/cinstruction.cpp
@@ -0,0 +1,48 @@
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
8#include <sstream>
9#include <stdexcept>
10#include <boost/lexical_cast.hpp>
11#include <assert.h>
12#include "cinstruction.h"
13#include "ccpu.h"
14
15using namespace std;
16
17const unsigned CInstruction::parseRegister(const std::string& str)
18{
19 unsigned reg;
20 if (str.length() < 2 || str[0] != 'r')
21 throw runtime_error("Invalid syntax of register");
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 }
31
32 return reg;
33}
34
35/*----------------------------------------------------------------------------*/
36
37inline void CInstruction::checkRegister(CCPU *cpu, const unsigned regidx)
38{
39 assert(cpu != NULL);
40 if (regidx >= cpu->getRegisterCount())
41 {
42 stringstream sstr;
43 sstr << "Register R" << regidx << " doesn't exist (out of bound)";
44 throw runtime_error(sstr.str());
45 }
46}
47
48/* vim: set et sw=2 ts=2: */
diff --git a/ue4/mycpu/cinstruction.h b/ue4/mycpu/cinstruction.h
new file mode 100644
index 0000000..4cc69de
--- /dev/null
+++ b/ue4/mycpu/cinstruction.h
@@ -0,0 +1,189 @@
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
8#ifndef CINSTRUCTION_H
9#define CINSTRUCTION_H 1
10
11#include <iostream>
12#include <list>
13
14/* forward declare CCPU */
15class CCPU;
16
17/**
18 * @class CInstruction
19 *
20 * Abstract class for displays
21 */
22class CInstruction
23{
24 public:
25 /**
26 * @method CInstruction
27 * @brief Default ctor
28 * @param name name of instruction
29 * @return -
30 * @globalvars none
31 * @exception none
32 * @conditions none
33 */
34 CInstruction(std::string name)
35 : m_name(name)
36 {}
37
38 /**
39 * @method ~CInstruction
40 * @brief Default dtor
41 * @param -
42 * @return -
43 * @globalvars none
44 * @exception none
45 * @conditions none
46 */
47 virtual ~CInstruction()
48 {}
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 }
63
64 /**
65 * @method operator()
66 * @brief implementation of operator (CCPU)
67 * @param cpu pointer to cpu
68 * @return -
69 * @globalvars none
70 * @exception std::runtime_error
71 * @conditions none
72 */
73 virtual CInstruction& operator()(CCPU *cpu)
74 {
75 execute(cpu);
76 return *this;
77 }
78
79 /**
80 * @method getName
81 * @brief returns instruction name
82 * @param -
83 * @return name of instruction
84 * @globalvars none
85 * @exception none
86 * @conditions none
87 */
88 virtual const std::string& getName()
89 {
90 return m_name;
91 }
92
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 }
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 }
122
123 /**
124 * @method parseRegister
125 * @brief parses register syntax Rx (e.g. "R1")
126 * @param str register in assembler syntax
127 * @return registernumber
128 * @globalvars none
129 * @exception std::runtime_error
130 * @conditions none
131 */
132 virtual const unsigned parseRegister(const std::string& str);
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);
146
147 /**
148 * @method factory
149 * @brief creates a new instance of this instruction
150 * @param -
151 * @return new instruction instance
152 * @globalvars none
153 * @exception none
154 * @conditions none
155 */
156 virtual CInstruction *factory() = 0;
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;
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;
180
181 protected:
182 /* members */
183 /** name of instruction */
184 std::string m_name;
185};
186
187#endif
188
189/* vim: set et sw=2 ts=2: */
diff --git a/ue4/mycpu/cmem.h b/ue4/mycpu/cmem.h
new file mode 100644
index 0000000..5045c34
--- /dev/null
+++ b/ue4/mycpu/cmem.h
@@ -0,0 +1,109 @@
1/**
2 * @module cmem
3 * @author Guenther Neuwirth (0626638), Manuel Mausz (0728348)
4 * @brief Memory template and memory definition for CCPU
5 * @date 10.05.2009
6 */
7
8#ifndef CMEM_H
9#define CMEM_H 1
10
11#include <vector>
12#include <istream>
13#include <sstream>
14#include <stdexcept>
15#include <boost/lexical_cast.hpp>
16#ifdef DEBUG
17# include <iostream>
18# include <iomanip>
19#endif
20#include "cdat.h"
21
22/**
23 * @class CVectorMem
24 *
25 * Extends std::vector template for use as memory for CCPU.
26 */
27template <class T, class Allocator=std::allocator<T> >
28class CVectorMem
29 : public std::vector<T, Allocator>
30{
31 public:
32 using std::vector<T, Allocator>::size;
33 using std::vector<T, Allocator>::at;
34
35 /**
36 * @method initialize
37 * @brief initialize the vector with the content of istream. istream is
38 * read per line. empty lines will add unitialized elements.
39 * @param in inputstream to read from
40 * @return void
41 * @globalvars none
42 * @exception std::runtime_error
43 * @conditions none
44 */
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);
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
79 /**
80 * @method dump
81 * @brief dumps contents of vector to outputstream
82 * @param out outputstream to write to
83 * @return void
84 * @globalvars none
85 * @exception none
86 * @conditions none
87 */
88 void dump(std::ostream& out)
89 {
90 out << "[MEMORY DUMP]" << std::endl;
91 for(unsigned i = 0; i < size(); ++i)
92 {
93 out << "[" << std::setw(4) << std::setfill('0') << i << "] "
94 << at(i) << std::endl;
95 }
96 }
97#endif
98};
99
100/**
101 * @class CMem
102 *
103 * Memory definition for CCPU
104 */
105typedef CVectorMem<CDat> CMem;
106
107#endif
108
109/* vim: set et sw=2 ts=2: */
diff --git a/ue4/mycpu/cprogram.cpp b/ue4/mycpu/cprogram.cpp
new file mode 100644
index 0000000..3fcf734
--- /dev/null
+++ b/ue4/mycpu/cprogram.cpp
@@ -0,0 +1,161 @@
1/**
2 * @module cprogram
3 * @author Guenther Neuwirth (0626638), Manuel Mausz (0728348)
4 * @brief CProgram extends std::vector and adds a method for parsing programfile
5 * @date 12.05.2009
6 */
7
8#include <boost/algorithm/string.hpp>
9#include <boost/algorithm/string/split.hpp>
10#ifdef DEBUG
11# include <iostream>
12# include <iomanip>
13#endif
14#include "cprogram.h"
15#include "instructions.h"
16
17using namespace std;
18
19CProgram::CProgram()
20{
21 m_instrset.insert(new CInstructionInc);
22 m_instrset.insert(new CInstructionDec);
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);
35}
36
37/*----------------------------------------------------------------------------*/
38
39CProgram::~CProgram()
40{
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;
49}
50
51/*----------------------------------------------------------------------------*/
52
53void CProgram::compile(std::istream& in)
54{
55 if (!in.good())
56 return;
57
58 string line;
59 unsigned i = 0;
60 while (!in.eof() && in.good())
61 {
62 ++i;
63
64 /* read stream per line */
65 getline(in, line);
66 if (line.empty())
67 continue;
68
69 boost::trim(line);
70 boost::to_lower(line);
71
72 /* ignore comments */
73 if (line.find_first_of('#') == 0)
74 continue;
75
76 /* get instruction name */
77 size_t pos = line.find_first_of(' ');
78 string instrname(line.substr(0, pos));
79
80 /* search and create instruction */
81 CInstruction *instrptr = NULL;
82 set<CInstruction *>::iterator it;
83 for (it = m_instrset.begin(); it != m_instrset.end(); ++it)
84 {
85 if (*(*it) == instrname)
86 {
87 instrptr = *it;
88 break;
89 }
90 }
91 if (instrptr == NULL)
92 {
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);
131 }
132}
133
134/*----------------------------------------------------------------------------*/
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;
143}
144
145/*----------------------------------------------------------------------------*/
146
147#if DEBUG
148void CProgram::dump(std::ostream& out)
149{
150 out << "[PROGRAM DUMP]" << endl;
151 unsigned i = 0;
152 for(iterator it = begin(); it < end(); ++it)
153 {
154 out << "[" << std::setw(4) << std::setfill('0') << i << "] "
155 << *(*it) << endl;
156 ++i;
157 }
158}
159#endif
160
161/* vim: set et sw=2 ts=2: */
diff --git a/ue4/mycpu/cprogram.h b/ue4/mycpu/cprogram.h
new file mode 100644
index 0000000..27e7647
--- /dev/null
+++ b/ue4/mycpu/cprogram.h
@@ -0,0 +1,106 @@
1/**
2 * @module cprogram
3 * @author Guenther Neuwirth (0626638), Manuel Mausz (0728348)
4 * @brief CProgram extends std::vector and adds a method for parsing programfile
5 * @date 10.05.2009
6 */
7
8#ifndef CPROGRAM_H
9#define CPROGRAM_H 1
10
11#include <vector>
12#include <set>
13#include <map>
14#include "cinstruction.h"
15
16/**
17 * @class CProgram
18 *
19 * CProgram extends std::vector and adds a method for parsing
20 * programfile. This adds instances of CInstruction to CProgram itself.
21 */
22class CProgram
23 : public std::vector<CInstruction *>
24{
25 public:
26 /**
27 * @method CProgram
28 * @brief Default ctor
29 * @param -
30 * @return -
31 * @globalvars none
32 * @exception none
33 * @conditions none
34 */
35 CProgram();
36
37 /**
38 * @method ~CProgram
39 * @brief Default dtor
40 * @param -
41 * @return -
42 * @globalvars none
43 * @exception none
44 * @conditions none
45 */
46 ~CProgram();
47
48 /**
49 * @method getLabels
50 * @brief get reference to labels map
51 * @param -
52 * @return reference to labels map
53 * @globalvars none
54 * @exception none
55 * @conditions none
56 */
57 const std::map<std::string, unsigned>& getLabels() const
58 {
59 return m_labels;
60 }
61
62 /**
63 * @method findLabel
64 * @brief search for label
65 * @param label name of label to search for
66 * @return index of found label in program
67 * @globalvars none
68 * @exception std::runtime_error
69 * @conditions none
70 */
71 unsigned findLabel(const std::string& label) const;
72
73 /**
74 * @method compile
75 * @brief create instructions from parsing stream
76 * @param in inputstream to read from
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
90 * @globalvars none
91 * @exception none
92 * @conditions none
93 */
94 void dump(std::ostream& out);
95#endif
96
97 private:
98 /* members */
99 /** set of known instructions */
100 std::set<CInstruction *> m_instrset;
101 std::map<std::string, unsigned> m_labels;
102};
103
104#endif
105
106/* vim: set et sw=2 ts=2: */
diff --git a/ue4/mycpu/displays.h b/ue4/mycpu/displays.h
new file mode 100644
index 0000000..d4f3f36
--- /dev/null
+++ b/ue4/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/ue4/mycpu/instructions.cpp b/ue4/mycpu/instructions.cpp
new file mode 100644
index 0000000..ef9e944
--- /dev/null
+++ b/ue4/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/ue4/mycpu/instructions.h b/ue4/mycpu/instructions.h
new file mode 100644
index 0000000..4c36562
--- /dev/null
+++ b/ue4/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/ue4/mycpu/mycpu.cpp b/ue4/mycpu/mycpu.cpp
new file mode 100644
index 0000000..b25e721
--- /dev/null
+++ b/ue4/mycpu/mycpu.cpp
@@ -0,0 +1,155 @@
1/**
2 * @module mycpu
3 * @author Guenther Neuwirth (0626638), Manuel Mausz (0728348)
4 * @brief mycpu executes a programfile (in simple assembler) by parsing the
5 * programfile first. This creates a vector of instructions, which will
6 * be executed in linear order (except jumps) afterwards. In order to
7 * initialize the memory of the cpu before execution an optional
8 * memoryfile can be passed as commandline option.
9 * @date 13.05.2009
10 * @par Exercise
11 * 4
12 */
13
14#include <boost/program_options.hpp>
15#include <iostream>
16#include <fstream>
17#include <stdexcept>
18#include <stdlib.h>
19#include "ccpu.h"
20#include "cmem.h"
21#include "cprogram.h"
22
23using namespace std;
24namespace po = boost::program_options;
25
26/**
27 * @func main
28 * @brief program entry point
29 * @param argc standard parameter of main
30 * @param argv standard parameter of main
31 * @return 0 on success, not 0 otherwise
32 * @globalvars none
33 * @exception none
34 * @conditions none
35 *
36 * parse commandline options, create and initialize memory,
37 * create cprogram instance, which parses the programfile and
38 * execute CCPU::run()
39 * On error print error message to stderr.
40 * Unknown commandline options will print a usage message.
41 */
42int main(int argc, char* argv[])
43{
44 string me(argv[0]);
45
46 /* define commandline options */
47 po::options_description desc("Allowed options");
48 desc.add_options()
49 ("help,h", "this help message")
50 ("compile,c", po::value<string>(), "input programfile")
51 ("memory,m", po::value<string>(), "input memoryfile");
52
53 /* parse commandline options */
54 po::variables_map vm;
55 try
56 {
57 po::store(po::parse_command_line(argc, argv, desc), vm);
58 po::notify(vm);
59 }
60 catch(po::error& ex)
61 {
62 cerr << me << ": Error: " << ex.what() << endl;
63 }
64
65 /* print usage upon request or missing params */
66 if (vm.count("help") || !vm.count("compile"))
67 {
68 cout << "Usage: " << me << " -c <programfile> [-m <memoryfile>]" << endl;
69 cout << desc << endl;
70 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;
110 return 1;
111 }
112
113 try
114 {
115 program.compile(file);
116 file.close();
117 }
118 catch(runtime_error& ex)
119 {
120 file.close();
121 cerr << me << ": Error while compiling programfile:" << endl
122 << " " << ex.what() << endl;
123 return 1;
124 }
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)
143 {
144 cerr << me << ": Error while executing program:" << endl
145 << " " << ex.what() << endl;
146#if DEBUG
147 memory.dump(cerr);
148#endif
149 return 1;
150 }
151
152 return 0;
153}
154
155/* vim: set et sw=2 ts=2: */
diff --git a/ue4/mycpu/test/test.sh b/ue4/mycpu/test/test.sh
new file mode 100755
index 0000000..ff1076c
--- /dev/null
+++ b/ue4/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/ue4/mycpu/test/test1_memory b/ue4/mycpu/test/test1_memory
new file mode 100644
index 0000000..209e3ef
--- /dev/null
+++ b/ue4/mycpu/test/test1_memory
@@ -0,0 +1 @@
20
diff --git a/ue4/mycpu/test/test1_output b/ue4/mycpu/test/test1_output
new file mode 100644
index 0000000..ac30dc2
--- /dev/null
+++ b/ue4/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/ue4/mycpu/test/test1_program b/ue4/mycpu/test/test1_program
new file mode 100644
index 0000000..ae5e9d2
--- /dev/null
+++ b/ue4/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: