Krolyxon
Commit 133f6f7

Branches

Tags

Refs →

bench51srccpu.rs

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