Krolyxon
Commit 5d34df5

Branches

Tags

Refs →

bench51srccpu.rs

426 lines · 11.2 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 fn push16(&mut self, mem: &mut Memory, val: u16) {
23 self.dec_sp();
24 mem.write(self.sp, (val >> 8) as u8); // high
25 self.dec_sp();
26 mem.write(self.sp, (val & 0xFF) as u8); // low
27 }
28
29 fn pop16(&mut self, mem: &mut Memory) -> u16 {
30 let low = mem.read(self.sp) as u16;
31 self.inc_sp();
32 let high = mem.read(self.sp) as u16;
33 self.inc_sp();
34
35 (high << 8) | low
36 }
37
38 pub fn debug_instr(&self, mem: &Memory) {
39 let opcode = mem.read(self.pc);
40
41 println!(
42 "PC={:04X} {:<3} | A={:02X} B={:02X} C={:02X} D={:02X} | Z={} C={}",
43 self.pc,
44 Instruction::opcode_name(opcode),
45 self.a,
46 self.b,
47 self.c,
48 self.d,
49 self.zero as u8,
50 self.carry as u8
51 );
52 }
53
54 pub fn step(&mut self, mem: &mut Memory) {
55 let opcode = mem.read(self.pc);
56 self.inc_pc();
57
58 match opcode {
59 x if x == Instruction::MOV_RI as u8 => self.mov_ri(mem),
60 x if x == Instruction::MOV_RR as u8 => self.mov_rr(mem),
61 x if x == Instruction::ADD_RR as u8 => self.add_rr(mem),
62 x if x == Instruction::ADD_RI as u8 => self.add_ri(mem),
63 x if x == Instruction::SUB_RR as u8 => self.sub_rr(mem),
64 x if x == Instruction::SUB_RI as u8 => self.sub_ri(mem),
65 x if x == Instruction::JMP as u8 => self.jmp(mem),
66 x if x == Instruction::JZ as u8 => self.jz(mem),
67 x if x == Instruction::JNZ as u8 => self.jnz(mem),
68 x if x == Instruction::CMP_RI as u8 => self.cmp_ri(mem),
69 x if x == Instruction::CMP_RR as u8 => self.cmp_rr(mem),
70 x if x == Instruction::MUL as u8 => self.mul(mem),
71 x if x == Instruction::DIV as u8 => self.div(mem),
72 x if x == Instruction::CALL as u8 => self.call(mem),
73 x if x == Instruction::RET as u8 => self.ret(mem),
74 x if x == Instruction::SYS as u8 => self.syscall(mem),
75 x if x == Instruction::HLT as u8 => self.halt(),
76 _ => panic!("Unknown opcode {:02X}", opcode),
77 }
78 }
79
80 pub fn inc_pc(&mut self) {
81 self.pc += 1;
82 }
83
84 pub fn inc_sp(&mut self) {
85 self.sp = self.sp.wrapping_add(1);
86 }
87
88 pub fn dec_sp(&mut self) {
89 self.sp = self.sp.wrapping_sub(1);
90 }
91
92
93 pub fn halt(&mut self) {
94 self.halted = true;
95 }
96
97 pub fn mov_ri(&mut self, mem: &Memory) {
98 let reg = mem.read(self.pc);
99 self.inc_pc();
100 let val = mem.read(self.pc);
101 self.inc_pc();
102
103 match reg {
104 0 => self.a = val,
105 1 => self.b = val,
106 2 => self.c = val,
107 3 => self.d = val,
108 _ => {}
109 }
110
111 self.zero = val == 0;
112 }
113
114 pub fn mov_rr(&mut self, mem: &Memory) {
115 let dest = mem.read(self.pc);
116 self.inc_pc();
117 let src= mem.read(self.pc);
118 self.inc_pc();
119
120 let val = self.get_reg(src);
121 self.set_reg(dest, val);
122
123 self.zero = val == 0;
124 }
125
126
127 pub fn add_rr(&mut self, mem: &Memory) {
128 let dest = mem.read(self.pc);
129 self.pc += 1;
130 let src = mem.read(self.pc);
131 self.pc += 1;
132
133 let (result, carry) = match (dest, src) {
134 (0, 0) => self.a.overflowing_add(self.a),
135 (0, 1) => self.a.overflowing_add(self.b),
136 (0, 2) => self.a.overflowing_add(self.c),
137 (0, 3) => self.a.overflowing_add(self.d),
138
139 (1, 0) => self.b.overflowing_add(self.a),
140 (1, 1) => self.b.overflowing_add(self.b),
141 (1, 2) => self.b.overflowing_add(self.c),
142 (1, 3) => self.b.overflowing_add(self.d),
143
144 (2, 0) => self.c.overflowing_add(self.a),
145 (2, 1) => self.c.overflowing_add(self.b),
146 (2, 2) => self.c.overflowing_add(self.c),
147 (2, 3) => self.c.overflowing_add(self.d),
148
149 (3, 0) => self.d.overflowing_add(self.a),
150 (3, 1) => self.d.overflowing_add(self.b),
151 (3, 2) => self.d.overflowing_add(self.c),
152 (3, 3) => self.d.overflowing_add(self.d),
153
154 _ => (0, false),
155 };
156
157 match dest {
158 0 => self.a = result,
159 1 => self.b = result,
160 2 => self.c = result,
161 3 => self.d = result,
162 _ => {}
163 }
164
165 self.zero = result == 0;
166 self.carry = carry;
167 }
168 pub fn add_ri(&mut self, mem: &Memory) {
169
170 let dest = mem.read(self.pc);
171 self.pc += 1;
172 let imm = mem.read(self.pc);
173 self.pc += 1;
174
175 let (result, carry) = match dest {
176 0 => self.a.overflowing_add(imm),
177 1 => self.b.overflowing_add(imm),
178 2 => self.c.overflowing_add(imm),
179 3 => self.d.overflowing_add(imm),
180 _ => (0, false),
181 };
182
183 match dest {
184 0 => self.a = result,
185 1 => self.b = result,
186 2 => self.c = result,
187 3 => self.d = result,
188 _ => {}
189 }
190
191 self.zero = result == 0;
192 self.carry = carry;
193 }
194
195
196 pub fn sub_rr(&mut self, mem: &Memory) {
197 let dest = mem.read(self.pc);
198 self.pc += 1;
199 let src = mem.read(self.pc);
200 self.pc += 1;
201
202 let (result, borrow) = match (dest, src) {
203 (0, 0) => self.a.overflowing_sub(self.a),
204 (0, 1) => self.a.overflowing_sub(self.b),
205 (0, 2) => self.a.overflowing_sub(self.c),
206 (0, 3) => self.a.overflowing_sub(self.d),
207
208 (1, 0) => self.b.overflowing_sub(self.a),
209 (1, 1) => self.b.overflowing_sub(self.b),
210 (1, 2) => self.b.overflowing_sub(self.c),
211 (1, 3) => self.b.overflowing_sub(self.d),
212
213 (2, 0) => self.c.overflowing_sub(self.a),
214 (2, 1) => self.c.overflowing_sub(self.b),
215 (2, 2) => self.c.overflowing_sub(self.c),
216 (2, 3) => self.c.overflowing_sub(self.d),
217
218 (3, 0) => self.d.overflowing_sub(self.a),
219 (3, 1) => self.d.overflowing_sub(self.b),
220 (3, 2) => self.d.overflowing_sub(self.c),
221 (3, 3) => self.d.overflowing_sub(self.d),
222
223 _ => (0, false),
224 };
225
226 match dest {
227 0 => self.a = result,
228 1 => self.b = result,
229 2 => self.c = result,
230 3 => self.d = result,
231 _ => {}
232 }
233
234 self.zero = result == 0;
235 self.carry = borrow;
236 }
237
238 pub fn sub_ri(&mut self, mem: &Memory) {
239 let dest = mem.read(self.pc);
240 self.pc += 1;
241 let imm = mem.read(self.pc);
242 self.pc += 1;
243
244 let (result, borrow) = match dest {
245 0 => self.a.overflowing_sub(imm),
246 1 => self.b.overflowing_sub(imm),
247 2 => self.c.overflowing_sub(imm),
248 3 => self.d.overflowing_sub(imm),
249 _ => (0, false),
250 };
251
252 match dest {
253 0 => self.a = result,
254 1 => self.b = result,
255 2 => self.c = result,
256 3 => self.d = result,
257 _ => {}
258 }
259
260 self.zero = result == 0;
261 self.carry = borrow;
262 }
263
264
265 pub fn jmp(&mut self, mem: &Memory) {
266 let low = mem.read(self.pc) as u16;
267 self.inc_pc();
268 let high = mem.read(self.pc) as u16;
269 self.inc_pc();
270
271 let addrs = (high << 8) | low;
272
273 self.pc = addrs;
274 }
275
276 pub fn jz(&mut self, mem: &Memory) {
277 let low = mem.read(self.pc) as u16;
278 self.inc_pc();
279 let high = mem.read(self.pc) as u16;
280 self.inc_pc();
281
282 let addrs = (high << 8) | low;
283
284 if self.zero {
285 self.pc = addrs;
286 }
287 }
288
289 pub fn jnz(&mut self, mem: &Memory) {
290 let low = mem.read(self.pc) as u16;
291 self.inc_pc();
292 let high = mem.read(self.pc) as u16;
293 self.inc_pc();
294
295 let addrs = (high << 8) | low;
296
297 if !self.zero {
298 self.pc = addrs;
299 }
300 }
301
302 pub fn cmp_rr(&mut self, mem: &Memory) {
303 let r1 = mem.read(self.pc);
304 self.inc_pc();
305 let r2 = mem.read(self.pc);
306 self.inc_pc();
307
308 let v1 = self.get_reg(r1);
309 let v2 = self.get_reg(r2);
310
311 let (result, borrow) = v1.overflowing_sub(v2);
312
313 self.zero = result == 0;
314 self.carry = borrow;
315 }
316
317 pub fn cmp_ri(&mut self, mem: &Memory) {
318 let r1 = mem.read(self.pc);
319 self.inc_pc();
320 let r2 = mem.read(self.pc);
321 self.inc_pc();
322
323 let v1 = self.get_reg(r1);
324
325 let (result, borrow) = v1.overflowing_sub(r2);
326
327 self.zero = result == 0;
328 self.carry = borrow;
329 }
330
331 pub fn mul(&mut self, mem: &Memory) {
332 let dest = mem.read(self.pc); self.inc_pc();
333 let src = mem.read(self.pc); self.inc_pc();
334
335 let lhs = self.get_reg(dest);
336 let rhs = self.get_reg(src);
337
338 let result16 = (lhs as u16) * (rhs as u16);
339 let result8 = (result16 & 0xFF) as u8;
340
341 self.set_reg(dest, result8);
342
343 self.zero = result8 == 0;
344 self.carry = result16 > 0xFF;
345 }
346
347 pub fn div(&mut self, mem: &Memory) {
348 let dest = mem.read(self.pc); self.inc_pc();
349 let src = mem.read(self.pc); self.inc_pc();
350
351 let lhs = self.get_reg(dest);
352 let rhs = self.get_reg(src);
353
354 if rhs == 0 {
355 panic!("Division by zero");
356 // OR: set halted = true
357 // OR: define a syscall/exception later
358 }
359
360 let result = lhs / rhs;
361
362 self.set_reg(dest, result);
363
364 self.zero = result == 0;
365 // carry unchanged
366 }
367
368 pub fn call(&mut self, mem: &mut Memory ) {
369 let low = mem.read(self.pc) as u16; self.inc_pc();
370 let high = mem.read(self.pc) as u16; self.inc_pc();
371 let addr = (high << 8) | low;
372
373 let return_addr = self.pc;
374
375 self.push16(mem, return_addr);
376 self.pc = addr;
377
378 }
379
380 pub fn ret(&mut self, mem: &mut Memory) {
381 let addr = self.pop16(mem);
382 self.pc = addr;
383 }
384
385
386 pub fn syscall(&mut self, mem: &Memory) {
387 let num = mem.read(self.pc);
388 self.pc = self.pc.wrapping_add(1);
389 match num {
390 0 => {
391 // exit
392 self.halted = true;
393 }
394 1 => {
395 // print A as number
396 println!("{}", self.a);
397 }
398 2 => {
399 // print A as ASCII char
400 print!("{}", self.a as char);
401 }
402 _ => panic!("Unknown syscall {}", num),
403 }
404 }
405
406 fn get_reg(&self, r: u8) -> u8 {
407 match r {
408 0 => self.a,
409 1 => self.b,
410 2 => self.c,
411 3 => self.d,
412 _ => panic!("Invalid Register"),
413 }
414 }
415
416 fn set_reg(&mut self, dest: u8, val: u8) {
417 match dest {
418 0 => self.a = val,
419 1 => self.b = val,
420 2 => self.c = val,
421 3 => self.d = val,
422 _ => panic!("Invalid register"),
423 }
424 }
425
426}