5f533ce42c546860fd22e9f99d63ae77d371f2b8
[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 void CCpu::tick()
10 {
11         // signal extensions
12         // Todo
13
14         m_pc = m_pc_next;
15         m_pc_next += 4;
16         Iinstr* instr = this->getProg(m_pc);
17         if(instr == NULL) {
18                 throw string("Out of Instructions!");
19         }
20         this->incPerf();
21         if(this->conditionMet(instr->getCondition())) {
22                 cout << "Executing: " << instr->toString() << endl;
23                 instr->execInstr();
24         }
25         else {
26                 cout << "Didn't Execute " << instr->toString() << "; condition wasn't met" << endl;
27         }
28
29 }
30
31 bool CCpu::conditionMet(short cond)
32 {
33         switch(cond) {
34                 case NOT_EQUAL:
35                         return !this->m_Z;
36                         break;
37                 case EQUAL:
38                         return this->m_Z;
39                         break;
40                 case NOT_OVERFLOW:
41                         return !this->m_O;
42                         break;
43                 case OVER_FLOW:
44                         return this->m_O;
45                         break;
46                 case NOT_CARRY:
47                         return !this->m_C;
48                         break;
49                 case CARRY:
50                         return this->m_C;
51                         break;
52                 case NOT_SIGNED:
53                         return !this->m_S;
54                         break;
55                 case SIGNED:
56                         return this->m_S;
57                         break;
58                 case ABOVE:
59                         return (!this->m_C && !this->m_Z);
60                         break;
61                 case BELOW_EQ:
62                         return (this->m_C || this->m_Z);
63                         break;
64                 case GREATER_EQ:
65                         return (this->m_S == this->m_O);
66                         break;
67                 case LESS:
68                         return (this->m_S != this->m_O);
69                         break;
70                 case GREATER:
71                         return (!this->m_Z && (this->m_S == this->m_O));
72                         break;
73                 case LESS_EQ:
74                         return (!this->m_Z || (this->m_S != this->m_O));
75                         break;
76                 case ALWAYS:
77                         return true;
78                         break;
79                 case NEVER:
80                         return false;
81                         break;
82                 default:
83                         cerr << "What did you do? more than 16 values in 5 bits?!" << endl;
84                         return false;
85         }
86
87 }
88
89 CDat CCpu::getNextPC() const
90 {
91         return m_pc_next;
92 }
93
94 CDat CCpu::getCurPC() const
95 {
96         return m_pc;
97 }
98
99 void CCpu::setNextPC(CDat val)
100 {
101         m_pc_next = val;
102 }
103
104 CDat CCpu::getFlags() const {
105         CDat psw = 0;
106         psw += (this->m_Z ? 1 : 0);
107         psw += (this->m_O ? 2 : 0);
108         psw += (this->m_C ? 4 : 0);
109         psw += (this->m_S ? 8 : 0);
110         return psw;
111 }
112
113 void CCpu::setFlags(CDat psw) {
114         this->m_Z = ((psw & 0x1) != 0);
115         this->m_O = ((psw & 0x2) != 0);
116         this->m_C = ((psw & 0x4) != 0);
117         this->m_S = ((psw & 0x8) != 0);
118 }
119
120 void CCpu::updateFlags(CDat val) {
121         this->m_Z = (val == 0);
122         this->m_S = ((val >> (BIT_LEN-1)) & 0x1);
123 /*      this->m_C = false;
124         this->m_O = false; */
125 }
126
127 void CCpu::updateFlags(CDatd val, CDat a, CDat b) {
128         this->m_Z = (val == 0);
129         this->m_S = ((val >> (BIT_LEN-1)) & 0x1);
130         this->m_C = ((val >> (BIT_LEN)) & 0x1);
131         bool a_31 = ((a >> (BIT_LEN-1)) & 0x1);
132         bool b_31 = ((b >> (BIT_LEN-1)) & 0x1);
133         bool val_31 = ((val >> (BIT_LEN-1)) & 0x1);
134         this->m_O = ((a_31 && b_31 && !val_31) || (!a_31 && !b_31 && val_31));
135 }
136
137 void CCpu::updateCarry(bool c)
138 {
139         this->m_C = c;
140 }
141
142 bool CCpu::getCarry()
143 {
144         return this->m_C;
145 }
146
147 void CCpu::updateFlags(bool z, bool o, bool c, bool s)
148 {
149         this->m_Z = z;
150         this->m_O = o;
151         this->m_C = c;
152         this->m_S = s;
153 }
154
155 CDat CCpu::getRegister(const int addr) const
156 {
157         return m_reg.getDirect(addr);
158 }
159
160 void CCpu::setRegister(const int addr, CDat data)
161 {
162         m_reg.setDirect(addr, data);
163 }
164
165 CDat CCpu::getRAM(const int addr) const
166 {
167         return m_ram.get(addr);
168 }
169 void CCpu::setRAM(const int addr, CDat data)
170 {
171         m_ram.set(addr, data);
172 }
173
174 void CCpu::setProg(int addr, Iinstr* instr)
175 {
176         m_prog.set(addr, instr);
177 }
178
179 Iinstr* CCpu::getProg(const int addr) const
180 {
181         return m_prog.get(addr);
182 }
183
184 int CCpu::getStack() const
185 {
186         return this->m_stack;
187 }
188
189 void CCpu::setStack(const int val)
190 {
191         this->m_stack = val;
192 }
193
194 CDat CCpu::getPerf() const
195 {
196         return this->m_perf;
197 }
198
199 void CCpu::setPerf(CDat val)
200 {
201         this->m_perf = val;
202 }
203
204 void CCpu::incPerf()
205 {
206         this->m_perf++;
207 }
208
209
210 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)
211 {
212 }
213
214