Krolyxon
Commit 68d8540

Branches

Tags

Refs →

bench51srccpu.rs

322 lines · 8.4 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::HLT as u8 => self.halt(),
55 _ => panic!("Unknown opcode {:02X}", opcode),
56 }
57 }
58
59 pub fn inc_pc(&mut self) {
60 self.pc += 1;
61 }
62
63 pub fn halt(&mut self) {
64 self.halted = true;
65 }
66
67 pub fn mov_ri(&mut self, mem: &Memory) {
68 let reg = mem.read(self.pc);
69 self.inc_pc();
70 let val = mem.read(self.pc);
71 self.inc_pc();
72
73 match reg {
74 0 => self.a = val,
75 1 => self.b = val,
76 2 => self.c = val,
77 3 => self.d = val,
78 _ => {}
79 }
80
81 self.zero = val == 0;
82 }
83
84 pub fn mov_rr(&mut self, mem: &Memory) {
85 let dest = mem.read(self.pc);
86 self.inc_pc();
87 let src= mem.read(self.pc);
88 self.inc_pc();
89
90 let val = self.get_reg(src);
91 self.set_reg(dest, val);
92
93 self.zero = val == 0;
94 }
95
96
97 pub fn add_rr(&mut self, mem: &Memory) {
98 let dest = mem.read(self.pc);
99 self.pc += 1;
100 let src = mem.read(self.pc);
101 self.pc += 1;
102
103 let (result, carry) = match (dest, src) {
104 (0, 0) => self.a.overflowing_add(self.a),
105 (0, 1) => self.a.overflowing_add(self.b),
106 (0, 2) => self.a.overflowing_add(self.c),
107 (0, 3) => self.a.overflowing_add(self.d),
108
109 (1, 0) => self.b.overflowing_add(self.a),
110 (1, 1) => self.b.overflowing_add(self.b),
111 (1, 2) => self.b.overflowing_add(self.c),
112 (1, 3) => self.b.overflowing_add(self.d),
113
114 (2, 0) => self.c.overflowing_add(self.a),
115 (2, 1) => self.c.overflowing_add(self.b),
116 (2, 2) => self.c.overflowing_add(self.c),
117 (2, 3) => self.c.overflowing_add(self.d),
118
119 (3, 0) => self.d.overflowing_add(self.a),
120 (3, 1) => self.d.overflowing_add(self.b),
121 (3, 2) => self.d.overflowing_add(self.c),
122 (3, 3) => self.d.overflowing_add(self.d),
123
124 _ => (0, false),
125 };
126
127 match dest {
128 0 => self.a = result,
129 1 => self.b = result,
130 2 => self.c = result,
131 3 => self.d = result,
132 _ => {}
133 }
134
135 self.zero = result == 0;
136 self.carry = carry;
137 }
138 pub fn add_ri(&mut self, mem: &Memory) {
139
140 let dest = mem.read(self.pc);
141 self.pc += 1;
142 let imm = mem.read(self.pc);
143 self.pc += 1;
144
145 let (result, carry) = match dest {
146 0 => self.a.overflowing_add(imm),
147 1 => self.b.overflowing_add(imm),
148 2 => self.c.overflowing_add(imm),
149 3 => self.d.overflowing_add(imm),
150 _ => (0, false),
151 };
152
153 match dest {
154 0 => self.a = result,
155 1 => self.b = result,
156 2 => self.c = result,
157 3 => self.d = result,
158 _ => {}
159 }
160
161 self.zero = result == 0;
162 self.carry = carry;
163 }
164
165
166 pub fn sub_rr(&mut self, mem: &Memory) {
167 let dest = mem.read(self.pc);
168 self.pc += 1;
169 let src = mem.read(self.pc);
170 self.pc += 1;
171
172 let (result, borrow) = match (dest, src) {
173 (0, 0) => self.a.overflowing_sub(self.a),
174 (0, 1) => self.a.overflowing_sub(self.b),
175 (0, 2) => self.a.overflowing_sub(self.c),
176 (0, 3) => self.a.overflowing_sub(self.d),
177
178 (1, 0) => self.b.overflowing_sub(self.a),
179 (1, 1) => self.b.overflowing_sub(self.b),
180 (1, 2) => self.b.overflowing_sub(self.c),
181 (1, 3) => self.b.overflowing_sub(self.d),
182
183 (2, 0) => self.c.overflowing_sub(self.a),
184 (2, 1) => self.c.overflowing_sub(self.b),
185 (2, 2) => self.c.overflowing_sub(self.c),
186 (2, 3) => self.c.overflowing_sub(self.d),
187
188 (3, 0) => self.d.overflowing_sub(self.a),
189 (3, 1) => self.d.overflowing_sub(self.b),
190 (3, 2) => self.d.overflowing_sub(self.c),
191 (3, 3) => self.d.overflowing_sub(self.d),
192
193 _ => (0, false),
194 };
195
196 match dest {
197 0 => self.a = result,
198 1 => self.b = result,
199 2 => self.c = result,
200 3 => self.d = result,
201 _ => {}
202 }
203
204 self.zero = result == 0;
205 self.carry = borrow;
206 }
207
208 pub fn sub_ri(&mut self, mem: &Memory) {
209 let dest = mem.read(self.pc);
210 self.pc += 1;
211 let imm = mem.read(self.pc);
212 self.pc += 1;
213
214 let (result, borrow) = match dest {
215 0 => self.a.overflowing_sub(imm),
216 1 => self.b.overflowing_sub(imm),
217 2 => self.c.overflowing_sub(imm),
218 3 => self.d.overflowing_sub(imm),
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
235 pub fn jmp(&mut self, mem: &Memory) {
236 let low = mem.read(self.pc) as u16;
237 self.inc_pc();
238 let high = mem.read(self.pc) as u16;
239 self.inc_pc();
240
241 let addrs = (high << 8) | low;
242
243 self.pc = addrs;
244 }
245
246 pub fn jz(&mut self, mem: &Memory) {
247 let low = mem.read(self.pc) as u16;
248 self.inc_pc();
249 let high = mem.read(self.pc) as u16;
250 self.inc_pc();
251
252 let addrs = (high << 8) | low;
253
254 if self.zero {
255 self.pc = addrs;
256 }
257 }
258
259 pub fn jnz(&mut self, mem: &Memory) {
260 let low = mem.read(self.pc) as u16;
261 self.inc_pc();
262 let high = mem.read(self.pc) as u16;
263 self.inc_pc();
264
265 let addrs = (high << 8) | low;
266
267 if !self.zero {
268 self.pc = addrs;
269 }
270 }
271
272 pub fn cmp_rr(&mut self, mem: &Memory) {
273 let r1 = mem.read(self.pc);
274 self.inc_pc();
275 let r2 = mem.read(self.pc);
276 self.inc_pc();
277
278 let v1 = self.get_reg(r1);
279 let v2 = self.get_reg(r2);
280
281 let (result, borrow) = v1.overflowing_sub(v2);
282
283 self.zero = result == 0;
284 self.carry = borrow;
285 }
286
287 pub fn cmp_ri(&mut self, mem: &Memory) {
288 let r1 = mem.read(self.pc);
289 self.inc_pc();
290 let r2 = mem.read(self.pc);
291 self.inc_pc();
292
293 let v1 = self.get_reg(r1);
294
295 let (result, borrow) = v1.overflowing_sub(r2);
296
297 self.zero = result == 0;
298 self.carry = borrow;
299 }
300
301
302 fn get_reg(&self, r: u8) -> u8 {
303 match r {
304 0 => self.a,
305 1 => self.b,
306 2 => self.c,
307 3 => self.d,
308 _ => 0,
309 }
310 }
311
312 fn set_reg(&mut self, dest: u8, val: u8) {
313 match dest {
314 0 => self.a = val,
315 1 => self.b = val,
316 2 => self.c = val,
317 3 => self.d = val,
318 _ => {},
319 }
320 }
321
322}