sim: highlight for instr
[calu.git] / 3b_sim / ccpu.cpp
1 #include "ccpu.hpp"
2
3 /*              CDat m_pc, m_pc_next;
4                 CMem m_regfile, m_ram;
5 */
6
7 //void registerExtension() {};
8
9 const char* expression = "(;.*)|(r0)|(rX)|(r1[0-5])|(r[1-5])|(r[6-9])|(0x[a-fA-F0-9]+)|([-]?\\d+)";
10 const char* format = "(?1$&)"
11                                         //Return-Register: violett
12                                         "(?2\033[0m\033[35m$&\033[0m\\3:)"
13                                         // Callee-saved Register: rot
14                                         "(?4\033[0m\033[31m$&\033[0m\\3:)"
15                                         //Argument-Register: gruen
16                                         "(?5\033[0m\033[32m$&\033[0m\\3:)"
17                                         // Temporary Register: gelb
18                                         "(?6\033[0m\033[33m$&\033[0m\\3:)"
19                                         // Zahlenwerte: tuerkis
20                                         "(?7\033[0m\033[36m$&\033[0m\\3:)"
21                                         "(?8\033[0m\033[36m$&\033[0m\\3:)";
22
23
24 string CCpu::colorifyInstr(string instr)
25 {
26         boost::regex e;
27         e.assign(expression);
28         return boost::regex_replace(instr, e, format, boost::match_default | boost::format_all);
29 }
30
31
32 void CCpu::tick()
33 {
34         // signal extensions
35         // Todo
36
37         m_pc = m_pc_next;
38         m_pc_next += 4;
39         Iinstr* instr = this->getProg(m_pc);
40         if(instr == NULL) {
41                 throw string("Out of Instructions!");
42         }
43         if(this->conditionMet(instr->getCondition())) {
44                 cout << color(green,black) << "Executing: " << color(white,black) << colorifyInstr(instr->toString()) << endl;
45                 instr->execInstr();
46                 this->incPerfBy(instr->getClockCount());
47         }
48         else {
49                 cout << color(red,black) << "Didn't Execute " << color(white,black) << colorifyInstr(instr->toString()) << "; condition wasn't met" << endl;
50                 this->incPerf();
51         }
52
53 }
54
55 bool CCpu::conditionMet(short cond)
56 {
57         switch(cond) {
58                 case NOT_EQUAL:
59                         return !this->m_Z;
60                         break;
61                 case EQUAL:
62                         return this->m_Z;
63                         break;
64                 case NOT_OVERFLOW:
65                         return !this->m_O;
66                         break;
67                 case OVER_FLOW:
68                         return this->m_O;
69                         break;
70                 case NOT_CARRY:
71                         return !this->m_C;
72                         break;
73                 case CARRY:
74                         return this->m_C;
75                         break;
76                 case NOT_SIGNED:
77                         return !this->m_S;
78                         break;
79                 case SIGNED:
80                         return this->m_S;
81                         break;
82                 case ABOVE:
83                         return (!this->m_C && !this->m_Z);
84                         break;
85                 case BELOW_EQ:
86                         return (this->m_C || this->m_Z);
87                         break;
88                 case GREATER_EQ:
89                         return (this->m_S == this->m_O);
90                         break;
91                 case LESS:
92                         return (this->m_S != this->m_O);
93                         break;
94                 case GREATER:
95                         return (!this->m_Z && (this->m_S == this->m_O));
96                         break;
97                 case LESS_EQ:
98                         return (!this->m_Z || (this->m_S != this->m_O));
99                         break;
100                 case ALWAYS:
101                         return true;
102                         break;
103                 case NEVER:
104                         return false;
105                         break;
106                 default:
107                         cerr << "What did you do? more than 16 values in 5 bits?!" << endl;
108                         return false;
109         }
110
111 }
112
113 CDat CCpu::getNextPC() const
114 {
115         return m_pc_next;
116 }
117
118 CDat CCpu::getCurPC() const
119 {
120         return m_pc;
121 }
122
123 void CCpu::setNextPC(CDat val)
124 {
125         m_pc_next = val;
126 }
127
128 CDat CCpu::getFlags() const {
129         CDat psw = 0;
130         psw += (this->m_Z ? 1 : 0);
131         psw += (this->m_O ? 2 : 0);
132         psw += (this->m_C ? 4 : 0);
133         psw += (this->m_S ? 8 : 0);
134         return psw;
135 }
136
137 void CCpu::setFlags(CDat psw) {
138         this->m_Z = ((psw & 0x1) != 0);
139         this->m_O = ((psw & 0x2) != 0);
140         this->m_C = ((psw & 0x4) != 0);
141         this->m_S = ((psw & 0x8) != 0);
142 }
143
144 void CCpu::updateFlags(CDat val) {
145         this->m_Z = (val == 0);
146         this->m_S = ((val >> (BIT_LEN-1)) & 0x1);
147 /*      this->m_C = false;
148         this->m_O = false; */
149 }
150
151 void CCpu::updateFlags(CDatd val, CDat a, CDat b) {
152         this->m_Z = (val == 0);
153         this->m_S = ((val >> (BIT_LEN-1)) & 0x1);
154         this->m_C = ((val >> (BIT_LEN)) & 0x1);
155         bool a_31 = ((a >> (BIT_LEN-1)) & 0x1);
156         bool b_31 = ((b >> (BIT_LEN-1)) & 0x1);
157         bool val_31 = ((val >> (BIT_LEN-1)) & 0x1);
158         this->m_O = ((a_31 && b_31 && !val_31) || (!a_31 && !b_31 && val_31));
159 }
160
161 void CCpu::updateCarry(bool c)
162 {
163         this->m_C = c;
164 }
165
166 bool CCpu::getCarry()
167 {
168         return this->m_C;
169 }
170
171 void CCpu::updateFlags(bool z, bool o, bool c, bool s)
172 {
173         this->m_Z = z;
174         this->m_O = o;
175         this->m_C = c;
176         this->m_S = s;
177 }
178
179 CDat CCpu::getRegister(const int addr) const
180 {
181         return m_reg.getDirect(addr);
182 }
183
184 void CCpu::setRegister(const int addr, CDat data)
185 {
186         m_reg.setDirect(addr, data);
187 }
188
189 CDat CCpu::getRAM(const int addr) const
190 {
191         return m_ram.get(addr);
192 }
193 void CCpu::setRAM(const int addr, CDat data)
194 {
195         m_ram.set(addr, data);
196 }
197
198 void CCpu::setProg(int addr, Iinstr* instr)
199 {
200         m_prog.set(addr, instr);
201 }
202
203 Iinstr* CCpu::getProg(const int addr) const
204 {
205         return m_prog.get(addr);
206 }
207
208 int CCpu::getStack() const
209 {
210         return this->m_stack;
211 }
212
213 void CCpu::setStack(const int val)
214 {
215         this->m_stack = val;
216 }
217
218 CDat CCpu::getPerf() const
219 {
220         return this->m_perf;
221 }
222
223 void CCpu::setPerf(CDat val)
224 {
225         this->m_perf = val;
226 }
227
228 void CCpu::incPerf()
229 {
230         this->m_perf++;
231 }
232
233 void CCpu::incPerfBy(short inc)
234 {
235         this->m_perf += inc;
236 }
237
238
239 CCpu::CCpu(int regs, int ram, int prog) : m_Z(false), m_S(false), m_C(false), m_O(false), m_pc(0), m_pc_next(0), m_perf(0), m_reg(regs), m_ram(ram), m_prog(prog), m_stack(0)
240 {
241 }
242
243