Krolyxon
Commit 3372e77

Branches

Tags

Refs →

bench51srccpu.rs

360 lines · 9.5 KB · Rust

1use crate::instructions::Instruction;
2use crate::memory::Memory;
3
4#[derive(Default, Debug)]
5#[allow(dead_code)]
6pub struct CPU {
7 pub a: u8,
8 pub b: u8,
9 pub c: u8,
10 pub d: u8,
11
12 pub pc: u16,
13 pub sp: u16,
14
15 pub zero: bool,
16 pub carry: bool,
17
18 pub halted: bool,
19}
20
21impl CPU {
22 pub fn debug_instr(&self, mem: &Memory) {
23 let opcode = mem.read(self.pc);
24
25 println!(
26 "PC={:04X} {:<3} | A={:02X} B={:02X} C={:02X} D={:02X} | Z={} C={}",
27 self.pc,
28 Instruction::opcode_name(opcode),
29 self.a,
30 self.b,
31 self.c,
32 self.d,
33 self.zero as u8,
34 self.carry as u8
35 );
36 }
37
38 pub fn step(&mut self, mem: &mut Memory) {
39 let opcode = mem.read(self.pc);
40 self.inc_pc();
41
42 match opcode {
43 x if x == Instruction::MOV_RI as u8 => self.mov_ri(mem),
44 x if x == Instruction::MOV_RR as u8 => self.mov_rr(mem),
45 x if x == Instruction::ADD_RR as u8 => self.add_rr(mem),
46 x if x == Instruction::ADD_RI as u8 => self.add_ri(mem),
47 x if x == Instruction::SUB_RR as u8 => self.sub_rr(mem),
48 x if x == Instruction::SUB_RI as u8 => self.sub_ri(mem),
49 x if x == Instruction::JMP as u8 => self.jmp(mem),
50 x if x == Instruction::JZ as u8 => self.jz(mem),
51 x if x == Instruction::JNZ as u8 => self.jnz(mem),
52 x if x == Instruction::CMP_RI as u8 => self.cmp_ri(mem),
53 x if x == Instruction::CMP_RR as u8 => self.cmp_rr(mem),
54 x if x == Instruction::MUL as u8 => self.mul(mem),
55 x if x == Instruction::DIV as u8 => self.div(mem),
56 x if x == Instruction::HLT as u8 => self.halt(),
57 _ => panic!("Unknown opcode {:02X}", opcode),
58 }
59 }
60
61 pub fn inc_pc(&mut self) {
62 self.pc += 1;
63 }
64
65 pub fn halt(&mut self) {
66 self.halted = true;
67 }
68
69 pub fn mov_ri(&mut self, mem: &Memory) {
70 let reg = mem.read(self.pc);
71 self.inc_pc();
72 let val = mem.read(self.pc);
73 self.inc_pc();
74
75 match reg {
76 0 => self.a = val,
77 1 => self.b = val,
78 2 => self.c = val,
79 3 => self.d = val,
80 _ => {}
81 }
82
83 self.zero = val == 0;
84 }
85
86 pub fn mov_rr(&mut self, mem: &Memory) {
87 let dest = mem.read(self.pc);
88 self.inc_pc();
89 let src= mem.read(self.pc);
90 self.inc_pc();
91
92 let val = self.get_reg(src);
93 self.set_reg(dest, val);
94
95 self.zero = val == 0;
96 }
97
98
99 pub fn add_rr(&mut self, mem: &Memory) {
100 let dest = mem.read(self.pc);
101 self.pc += 1;
102 let src = mem.read(self.pc);
103 self.pc += 1;
104
105 let (result, carry) = match (dest, src) {
106 (0, 0) => self.a.overflowing_add(self.a),
107 (0, 1) => self.a.overflowing_add(self.b),
108 (0, 2) => self.a.overflowing_add(self.c),
109 (0, 3) => self.a.overflowing_add(self.d),
110
111 (1, 0) => self.b.overflowing_add(self.a),
112 (1, 1) => self.b.overflowing_add(self.b),
113 (1, 2) => self.b.overflowing_add(self.c),
114 (1, 3) => self.b.overflowing_add(self.d),
115
116 (2, 0) => self.c.overflowing_add(self.a),
117 (2, 1) => self.c.overflowing_add(self.b),
118 (2, 2) => self.c.overflowing_add(self.c),
119 (2, 3) => self.c.overflowing_add(self.d),
120
121 (3, 0) => self.d.overflowing_add(self.a),
122 (3, 1) => self.d.overflowing_add(self.b),
123 (3, 2) => self.d.overflowing_add(self.c),
124 (3, 3) => self.d.overflowing_add(self.d),
125
126 _ => (0, false),
127 };
128
129 match dest {
130 0 => self.a = result,
131 1 => self.b = result,
132 2 => self.c = result,
133 3 => self.d = result,
134 _ => {}
135 }
136
137 self.zero = result == 0;
138 self.carry = carry;
139 }
140 pub fn add_ri(&mut self, mem: &Memory) {
141
142 let dest = mem.read(self.pc);
143 self.pc += 1;
144 let imm = mem.read(self.pc);
145 self.pc += 1;
146
147 let (result, carry) = match dest {
148 0 => self.a.overflowing_add(imm),
149 1 => self.b.overflowing_add(imm),
150 2 => self.c.overflowing_add(imm),
151 3 => self.d.overflowing_add(imm),
152 _ => (0, false),
153 };
154
155 match dest {
156 0 => self.a = result,
157 1 => self.b = result,
158 2 => self.c = result,
159 3 => self.d = result,
160 _ => {}
161 }
162
163 self.zero = result == 0;
164 self.carry = carry;
165 }
166
167
168 pub fn sub_rr(&mut self, mem: &Memory) {
169 let dest = mem.read(self.pc);
170 self.pc += 1;
171 let src = mem.read(self.pc);
172 self.pc += 1;
173
174 let (result, borrow) = match (dest, src) {
175 (0, 0) => self.a.overflowing_sub(self.a),
176 (0, 1) => self.a.overflowing_sub(self.b),
177 (0, 2) => self.a.overflowing_sub(self.c),
178 (0, 3) => self.a.overflowing_sub(self.d),
179
180 (1, 0) => self.b.overflowing_sub(self.a),
181 (1, 1) => self.b.overflowing_sub(self.b),
182 (1, 2) => self.b.overflowing_sub(self.c),
183 (1, 3) => self.b.overflowing_sub(self.d),
184
185 (2, 0) => self.c.overflowing_sub(self.a),
186 (2, 1) => self.c.overflowing_sub(self.b),
187 (2, 2) => self.c.overflowing_sub(self.c),
188 (2, 3) => self.c.overflowing_sub(self.d),
189
190 (3, 0) => self.d.overflowing_sub(self.a),
191 (3, 1) => self.d.overflowing_sub(self.b),
192 (3, 2) => self.d.overflowing_sub(self.c),
193 (3, 3) => self.d.overflowing_sub(self.d),
194
195 _ => (0, false),
196 };
197
198 match dest {
199 0 => self.a = result,
200 1 => self.b = result,
201 2 => self.c = result,
202 3 => self.d = result,
203 _ => {}
204 }
205
206 self.zero = result == 0;
207 self.carry = borrow;
208 }
209
210 pub fn sub_ri(&mut self, mem: &Memory) {
211 let dest = mem.read(self.pc);
212 self.pc += 1;
213 let imm = mem.read(self.pc);
214 self.pc += 1;
215
216 let (result, borrow) = match dest {
217 0 => self.a.overflowing_sub(imm),
218 1 => self.b.overflowing_sub(imm),
219 2 => self.c.overflowing_sub(imm),
220 3 => self.d.overflowing_sub(imm),
221 _ => (0, false),
222 };
223
224 match dest {
225 0 => self.a = result,
226 1 => self.b = result,
227 2 => self.c = result,
228 3 => self.d = result,
229 _ => {}
230 }
231
232 self.zero = result == 0;
233 self.carry = borrow;
234 }
235
236
237 pub fn jmp(&mut self, mem: &Memory) {
238 let low = mem.read(self.pc) as u16;
239 self.inc_pc();
240 let high = mem.read(self.pc) as u16;
241 self.inc_pc();
242
243 let addrs = (high << 8) | low;
244
245 self.pc = addrs;
246 }
247
248 pub fn jz(&mut self, mem: &Memory) {
249 let low = mem.read(self.pc) as u16;
250 self.inc_pc();
251 let high = mem.read(self.pc) as u16;
252 self.inc_pc();
253
254 let addrs = (high << 8) | low;
255
256 if self.zero {
257 self.pc = addrs;
258 }
259 }
260
261 pub fn jnz(&mut self, mem: &Memory) {
262 let low = mem.read(self.pc) as u16;
263 self.inc_pc();
264 let high = mem.read(self.pc) as u16;
265 self.inc_pc();
266
267 let addrs = (high << 8) | low;
268
269 if !self.zero {
270 self.pc = addrs;
271 }
272 }
273
274 pub fn cmp_rr(&mut self, mem: &Memory) {
275 let r1 = mem.read(self.pc);
276 self.inc_pc();
277 let r2 = mem.read(self.pc);
278 self.inc_pc();
279
280 let v1 = self.get_reg(r1);
281 let v2 = self.get_reg(r2);
282
283 let (result, borrow) = v1.overflowing_sub(v2);
284
285 self.zero = result == 0;
286 self.carry = borrow;
287 }
288
289 pub fn cmp_ri(&mut self, mem: &Memory) {
290 let r1 = mem.read(self.pc);
291 self.inc_pc();
292 let r2 = mem.read(self.pc);
293 self.inc_pc();
294
295 let v1 = self.get_reg(r1);
296
297 let (result, borrow) = v1.overflowing_sub(r2);
298
299 self.zero = result == 0;
300 self.carry = borrow;
301 }
302
303 pub fn mul(&mut self, mem: &Memory) {
304 let dest = mem.read(self.pc); self.inc_pc();
305 let src = mem.read(self.pc); self.inc_pc();
306
307 let lhs = self.get_reg(dest);
308 let rhs = self.get_reg(src);
309
310 let result16 = (lhs as u16) * (rhs as u16);
311 let result8 = (result16 & 0xFF) as u8;
312
313 self.set_reg(dest, result8);
314
315 self.zero = result8 == 0;
316 self.carry = result16 > 0xFF;
317 }
318
319 pub fn div(&mut self, mem: &Memory) {
320 let dest = mem.read(self.pc); self.inc_pc();
321 let src = mem.read(self.pc); self.inc_pc();
322
323 let lhs = self.get_reg(dest);
324 let rhs = self.get_reg(src);
325
326 if rhs == 0 {
327 panic!("Division by zero");
328 // OR: set halted = true
329 // OR: define a syscall/exception later
330 }
331
332 let result = lhs / rhs;
333
334 self.set_reg(dest, result);
335
336 self.zero = result == 0;
337 // carry unchanged
338 }
339
340 fn get_reg(&self, r: u8) -> u8 {
341 match r {
342 0 => self.a,
343 1 => self.b,
344 2 => self.c,
345 3 => self.d,
346 _ => panic!("Invalid Register"),
347 }
348 }
349
350 fn set_reg(&mut self, dest: u8, val: u8) {
351 match dest {
352 0 => self.a = val,
353 1 => self.b = val,
354 2 => self.c = val,
355 3 => self.d = val,
356 _ => panic!("Invalid register"),
357 }
358 }
359
360}