Krolyxon
Commit 4d311de

Branches

Tags

Refs →

bench51srccpu.rs

182 lines · 4.9 KB · Rust

1use crate::instructions::Instruction;
2use crate::memory::Memory;
3
4#[derive(Default, Debug)]
5pub struct CPU {
6 pub a: u8,
7 pub b: u8,
8 pub c: u8,
9 pub d: u8,
10
11 pub pc: u16,
12 pub sp: u16,
13
14 pub zero: bool,
15 pub carry: bool,
16
17 pub halted: bool,
18}
19
20impl CPU {
21 pub fn step(&mut self, mem: &mut Memory) {
22 let opcode = mem.read(self.pc);
23 self.inc_pc();
24
25 match opcode {
26 x if x == Instruction::MOV as u8 => self.mov(mem),
27 x if x == Instruction::ADD as u8 => self.add(mem),
28 x if x == Instruction::SUB as u8 => self.sub(mem),
29 x if x == Instruction::JMP as u8 => self.jmp(mem),
30 x if x == Instruction::JZ as u8 => self.jz(mem),
31 x if x == Instruction::JNZ as u8 => self.jnz(mem),
32 x if x == Instruction::HLT as u8 => self.halt(),
33 _ => panic!("Unknown opcode {:02X}", opcode),
34 }
35 }
36
37 pub fn inc_pc(&mut self) {
38 self.pc += 1;
39 }
40
41 pub fn halt(&mut self) {
42 self.halted = true;
43 }
44
45 pub fn mov(&mut self, mem: &Memory) {
46 let reg = mem.read(self.pc);
47 self.inc_pc();
48 let val = mem.read(self.pc);
49 self.inc_pc();
50
51 match reg {
52 0 => self.a = val,
53 1 => self.b = val,
54 2 => self.c = val,
55 3 => self.d = val,
56 _ => {}
57 }
58
59 self.zero = val == 0;
60 }
61
62 pub fn add(&mut self, mem: &Memory) {
63 let dest = mem.read(self.pc);
64 self.pc += 1;
65 let src = mem.read(self.pc);
66 self.pc += 1;
67
68 let (result, carry) = match (dest, src) {
69 (0, 0) => self.a.overflowing_add(self.a),
70 (0, 1) => self.a.overflowing_add(self.b),
71 (0, 2) => self.a.overflowing_add(self.c),
72 (0, 3) => self.a.overflowing_add(self.d),
73
74 (1, 0) => self.b.overflowing_add(self.a),
75 (1, 1) => self.b.overflowing_add(self.b),
76 (1, 2) => self.b.overflowing_add(self.c),
77 (1, 3) => self.b.overflowing_add(self.d),
78
79 (2, 0) => self.c.overflowing_add(self.a),
80 (2, 1) => self.c.overflowing_add(self.b),
81 (2, 2) => self.c.overflowing_add(self.c),
82 (2, 3) => self.c.overflowing_add(self.d),
83
84 (3, 0) => self.d.overflowing_add(self.a),
85 (3, 1) => self.d.overflowing_add(self.b),
86 (3, 2) => self.d.overflowing_add(self.c),
87 (3, 3) => self.d.overflowing_add(self.d),
88
89 _ => (0, false),
90 };
91
92 match dest {
93 0 => self.a = result,
94 1 => self.b = result,
95 2 => self.c = result,
96 3 => self.d = result,
97 _ => {}
98 }
99
100 self.zero = result == 0;
101 self.carry = carry;
102 }
103
104 pub fn sub(&mut self, mem: &Memory) {
105 let dest = mem.read(self.pc);
106 self.pc += 1;
107 let src = mem.read(self.pc);
108 self.pc += 1;
109
110 let (result, borrow) = match (dest, src) {
111 (0, 0) => self.a.overflowing_sub(self.a),
112 (0, 1) => self.a.overflowing_sub(self.b),
113 (0, 2) => self.a.overflowing_sub(self.c),
114 (0, 3) => self.a.overflowing_sub(self.d),
115
116 (1, 0) => self.b.overflowing_sub(self.a),
117 (1, 1) => self.b.overflowing_sub(self.b),
118 (1, 2) => self.b.overflowing_sub(self.c),
119 (1, 3) => self.b.overflowing_sub(self.d),
120
121 (2, 0) => self.c.overflowing_sub(self.a),
122 (2, 1) => self.c.overflowing_sub(self.b),
123 (2, 2) => self.c.overflowing_sub(self.c),
124 (2, 3) => self.c.overflowing_sub(self.d),
125
126 (3, 0) => self.d.overflowing_sub(self.a),
127 (3, 1) => self.d.overflowing_sub(self.b),
128 (3, 2) => self.d.overflowing_sub(self.c),
129 (3, 3) => self.d.overflowing_sub(self.d),
130
131 _ => (0, false),
132 };
133
134 match dest {
135 0 => self.a = result,
136 1 => self.b = result,
137 2 => self.c = result,
138 3 => self.d = result,
139 _ => {}
140 }
141
142 self.zero = result == 0;
143 self.carry = borrow;
144 }
145
146 pub fn jmp(&mut self, mem: &Memory) {
147 let low = mem.read(self.pc) as u16;
148 self.inc_pc();
149 let high = mem.read(self.pc) as u16;
150 self.inc_pc();
151
152 let addrs = (high << 8) | low;
153
154 self.pc = addrs;
155 }
156
157 pub fn jz(&mut self, mem: &Memory) {
158 let low = mem.read(self.pc) as u16;
159 self.inc_pc();
160 let high = mem.read(self.pc) as u16;
161 self.inc_pc();
162
163 let addrs = (high << 8) | low;
164
165 if self.zero {
166 self.pc = addrs;
167 }
168 }
169
170 pub fn jnz(&mut self, mem: &Memory) {
171 let low = mem.read(self.pc) as u16;
172 self.inc_pc();
173 let high = mem.read(self.pc) as u16;
174 self.inc_pc();
175
176 let addrs = (high << 8) | low;
177
178 if !self.zero {
179 self.pc = addrs;
180 }
181 }
182}