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