Krolyxon
Commit 4251847

Branches

Tags

Refs →

bench51srccpu.rs

424 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 pub fn halt(&mut self) {
93 self.halted = true;
94 }
95
96 pub fn mov_ri(&mut self, mem: &Memory) {
97 let reg = mem.read(self.pc);
98 self.inc_pc();
99 let val = mem.read(self.pc);
100 self.inc_pc();
101
102 match reg {
103 0 => self.a = val,
104 1 => self.b = val,
105 2 => self.c = val,
106 3 => self.d = val,
107 _ => {}
108 }
109
110 self.zero = val == 0;
111 }
112
113 pub fn mov_rr(&mut self, mem: &Memory) {
114 let dest = mem.read(self.pc);
115 self.inc_pc();
116 let src = mem.read(self.pc);
117 self.inc_pc();
118
119 let val = self.get_reg(src);
120 self.set_reg(dest, val);
121
122 self.zero = val == 0;
123 }
124
125 pub fn add_rr(&mut self, mem: &Memory) {
126 let dest = mem.read(self.pc);
127 self.pc += 1;
128 let src = mem.read(self.pc);
129 self.pc += 1;
130
131 let (result, carry) = match (dest, src) {
132 (0, 0) => self.a.overflowing_add(self.a),
133 (0, 1) => self.a.overflowing_add(self.b),
134 (0, 2) => self.a.overflowing_add(self.c),
135 (0, 3) => self.a.overflowing_add(self.d),
136
137 (1, 0) => self.b.overflowing_add(self.a),
138 (1, 1) => self.b.overflowing_add(self.b),
139 (1, 2) => self.b.overflowing_add(self.c),
140 (1, 3) => self.b.overflowing_add(self.d),
141
142 (2, 0) => self.c.overflowing_add(self.a),
143 (2, 1) => self.c.overflowing_add(self.b),
144 (2, 2) => self.c.overflowing_add(self.c),
145 (2, 3) => self.c.overflowing_add(self.d),
146
147 (3, 0) => self.d.overflowing_add(self.a),
148 (3, 1) => self.d.overflowing_add(self.b),
149 (3, 2) => self.d.overflowing_add(self.c),
150 (3, 3) => self.d.overflowing_add(self.d),
151
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 pub fn add_ri(&mut self, mem: &Memory) {
167 let dest = mem.read(self.pc);
168 self.pc += 1;
169 let imm = mem.read(self.pc);
170 self.pc += 1;
171
172 let (result, carry) = match dest {
173 0 => self.a.overflowing_add(imm),
174 1 => self.b.overflowing_add(imm),
175 2 => self.c.overflowing_add(imm),
176 3 => self.d.overflowing_add(imm),
177 _ => (0, false),
178 };
179
180 match dest {
181 0 => self.a = result,
182 1 => self.b = result,
183 2 => self.c = result,
184 3 => self.d = result,
185 _ => {}
186 }
187
188 self.zero = result == 0;
189 self.carry = carry;
190 }
191
192 pub fn sub_rr(&mut self, mem: &Memory) {
193 let dest = mem.read(self.pc);
194 self.pc += 1;
195 let src = mem.read(self.pc);
196 self.pc += 1;
197
198 let (result, borrow) = match (dest, src) {
199 (0, 0) => self.a.overflowing_sub(self.a),
200 (0, 1) => self.a.overflowing_sub(self.b),
201 (0, 2) => self.a.overflowing_sub(self.c),
202 (0, 3) => self.a.overflowing_sub(self.d),
203
204 (1, 0) => self.b.overflowing_sub(self.a),
205 (1, 1) => self.b.overflowing_sub(self.b),
206 (1, 2) => self.b.overflowing_sub(self.c),
207 (1, 3) => self.b.overflowing_sub(self.d),
208
209 (2, 0) => self.c.overflowing_sub(self.a),
210 (2, 1) => self.c.overflowing_sub(self.b),
211 (2, 2) => self.c.overflowing_sub(self.c),
212 (2, 3) => self.c.overflowing_sub(self.d),
213
214 (3, 0) => self.d.overflowing_sub(self.a),
215 (3, 1) => self.d.overflowing_sub(self.b),
216 (3, 2) => self.d.overflowing_sub(self.c),
217 (3, 3) => self.d.overflowing_sub(self.d),
218
219 _ => (0, false),
220 };
221
222 match dest {
223 0 => self.a = result,
224 1 => self.b = result,
225 2 => self.c = result,
226 3 => self.d = result,
227 _ => {}
228 }
229
230 self.zero = result == 0;
231 self.carry = borrow;
232 }
233
234 pub fn sub_ri(&mut self, mem: &Memory) {
235 let dest = mem.read(self.pc);
236 self.pc += 1;
237 let imm = mem.read(self.pc);
238 self.pc += 1;
239
240 let (result, borrow) = match dest {
241 0 => self.a.overflowing_sub(imm),
242 1 => self.b.overflowing_sub(imm),
243 2 => self.c.overflowing_sub(imm),
244 3 => self.d.overflowing_sub(imm),
245 _ => (0, false),
246 };
247
248 match dest {
249 0 => self.a = result,
250 1 => self.b = result,
251 2 => self.c = result,
252 3 => self.d = result,
253 _ => {}
254 }
255
256 self.zero = result == 0;
257 self.carry = borrow;
258 }
259
260 pub fn jmp(&mut self, mem: &Memory) {
261 let low = mem.read(self.pc) as u16;
262 self.inc_pc();
263 let high = mem.read(self.pc) as u16;
264 self.inc_pc();
265
266 let addrs = (high << 8) | low;
267
268 self.pc = addrs;
269 }
270
271 pub fn jz(&mut self, mem: &Memory) {
272 let low = mem.read(self.pc) as u16;
273 self.inc_pc();
274 let high = mem.read(self.pc) as u16;
275 self.inc_pc();
276
277 let addrs = (high << 8) | low;
278
279 if self.zero {
280 self.pc = addrs;
281 }
282 }
283
284 pub fn jnz(&mut self, mem: &Memory) {
285 let low = mem.read(self.pc) as u16;
286 self.inc_pc();
287 let high = mem.read(self.pc) as u16;
288 self.inc_pc();
289
290 let addrs = (high << 8) | low;
291
292 if !self.zero {
293 self.pc = addrs;
294 }
295 }
296
297 pub fn cmp_rr(&mut self, mem: &Memory) {
298 let r1 = mem.read(self.pc);
299 self.inc_pc();
300 let r2 = mem.read(self.pc);
301 self.inc_pc();
302
303 let v1 = self.get_reg(r1);
304 let v2 = self.get_reg(r2);
305
306 let (result, borrow) = v1.overflowing_sub(v2);
307
308 self.zero = result == 0;
309 self.carry = borrow;
310 }
311
312 pub fn cmp_ri(&mut self, mem: &Memory) {
313 let r1 = mem.read(self.pc);
314 self.inc_pc();
315 let r2 = mem.read(self.pc);
316 self.inc_pc();
317
318 let v1 = self.get_reg(r1);
319
320 let (result, borrow) = v1.overflowing_sub(r2);
321
322 self.zero = result == 0;
323 self.carry = borrow;
324 }
325
326 pub fn mul(&mut self, mem: &Memory) {
327 let dest = mem.read(self.pc);
328 self.inc_pc();
329 let src = mem.read(self.pc);
330 self.inc_pc();
331
332 let lhs = self.get_reg(dest);
333 let rhs = self.get_reg(src);
334
335 let result16 = (lhs as u16) * (rhs as u16);
336 let result8 = (result16 & 0xFF) as u8;
337
338 self.set_reg(dest, result8);
339
340 self.zero = result8 == 0;
341 self.carry = result16 > 0xFF;
342 }
343
344 pub fn div(&mut self, mem: &Memory) {
345 let dest = mem.read(self.pc);
346 self.inc_pc();
347 let src = mem.read(self.pc);
348 self.inc_pc();
349
350 let lhs = self.get_reg(dest);
351 let rhs = self.get_reg(src);
352
353 if rhs == 0 {
354 panic!("Division by zero");
355 // OR: set halted = true
356 // OR: define a syscall/exception later
357 }
358
359 let result = lhs / rhs;
360
361 self.set_reg(dest, result);
362
363 self.zero = result == 0;
364 // carry unchanged
365 }
366
367 pub fn call(&mut self, mem: &mut Memory) {
368 let low = mem.read(self.pc) as u16;
369 self.inc_pc();
370 let high = mem.read(self.pc) as u16;
371 self.inc_pc();
372 let addr = (high << 8) | low;
373
374 let return_addr = self.pc;
375
376 self.push16(mem, return_addr);
377 self.pc = addr;
378 }
379
380 pub fn ret(&mut self, mem: &mut Memory) {
381 let addr = self.pop16(mem);
382 self.pc = addr;
383 }
384
385 pub fn syscall(&mut self, mem: &Memory) {
386 let num = mem.read(self.pc);
387 self.pc = self.pc.wrapping_add(1);
388 match num {
389 0 => {
390 // exit
391 self.halted = true;
392 }
393 1 => {
394 // print A as number
395 println!("{}", self.a);
396 }
397 2 => {
398 // print A as ASCII char
399 print!("{}", self.a as char);
400 }
401 _ => panic!("Unknown syscall {}", num),
402 }
403 }
404
405 fn get_reg(&self, r: u8) -> u8 {
406 match r {
407 0 => self.a,
408 1 => self.b,
409 2 => self.c,
410 3 => self.d,
411 _ => panic!("Invalid Register"),
412 }
413 }
414
415 fn set_reg(&mut self, dest: u8, val: u8) {
416 match dest {
417 0 => self.a = val,
418 1 => self.b = val,
419 2 => self.c = val,
420 3 => self.d = val,
421 _ => panic!("Invalid register"),
422 }
423 }
424}