Krolyxon
Commit 8d47920

Branches

Tags

Refs →

bench51srccpu.rs

200 lines · 5.3 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
23 pub fn debug_instr(&self, mem: &Memory) {
24 let opcode = mem.read(self.pc);
25
26 println!(
27 "PC={:04X} {:<3} | A={:02X} B={:02X} C={:02X} D={:02X} | Z={} C={}",
28 self.pc,
29 Instruction::opcode_name(opcode),
30 self.a,
31 self.b,
32 self.c,
33 self.d,
34 self.zero as u8,
35 self.carry as u8
36 );
37 }
38
39 pub fn step(&mut self, mem: &mut Memory) {
40 let opcode = mem.read(self.pc);
41 self.inc_pc();
42
43 match opcode {
44 x if x == Instruction::MOV as u8 => self.mov(mem),
45 x if x == Instruction::ADD as u8 => self.add(mem),
46 x if x == Instruction::SUB as u8 => self.sub(mem),
47 x if x == Instruction::JMP as u8 => self.jmp(mem),
48 x if x == Instruction::JZ as u8 => self.jz(mem),
49 x if x == Instruction::JNZ as u8 => self.jnz(mem),
50 x if x == Instruction::HLT as u8 => self.halt(),
51 _ => panic!("Unknown opcode {:02X}", opcode),
52 }
53 }
54
55 pub fn inc_pc(&mut self) {
56 self.pc += 1;
57 }
58
59 pub fn halt(&mut self) {
60 self.halted = true;
61 }
62
63 pub fn mov(&mut self, mem: &Memory) {
64 let reg = mem.read(self.pc);
65 self.inc_pc();
66 let val = mem.read(self.pc);
67 self.inc_pc();
68
69 match reg {
70 0 => self.a = val,
71 1 => self.b = val,
72 2 => self.c = val,
73 3 => self.d = val,
74 _ => {}
75 }
76
77 self.zero = val == 0;
78 }
79
80 pub fn add(&mut self, mem: &Memory) {
81 let dest = mem.read(self.pc);
82 self.pc += 1;
83 let src = mem.read(self.pc);
84 self.pc += 1;
85
86 let (result, carry) = match (dest, src) {
87 (0, 0) => self.a.overflowing_add(self.a),
88 (0, 1) => self.a.overflowing_add(self.b),
89 (0, 2) => self.a.overflowing_add(self.c),
90 (0, 3) => self.a.overflowing_add(self.d),
91
92 (1, 0) => self.b.overflowing_add(self.a),
93 (1, 1) => self.b.overflowing_add(self.b),
94 (1, 2) => self.b.overflowing_add(self.c),
95 (1, 3) => self.b.overflowing_add(self.d),
96
97 (2, 0) => self.c.overflowing_add(self.a),
98 (2, 1) => self.c.overflowing_add(self.b),
99 (2, 2) => self.c.overflowing_add(self.c),
100 (2, 3) => self.c.overflowing_add(self.d),
101
102 (3, 0) => self.d.overflowing_add(self.a),
103 (3, 1) => self.d.overflowing_add(self.b),
104 (3, 2) => self.d.overflowing_add(self.c),
105 (3, 3) => self.d.overflowing_add(self.d),
106
107 _ => (0, false),
108 };
109
110 match dest {
111 0 => self.a = result,
112 1 => self.b = result,
113 2 => self.c = result,
114 3 => self.d = result,
115 _ => {}
116 }
117
118 self.zero = result == 0;
119 self.carry = carry;
120 }
121
122 pub fn sub(&mut self, mem: &Memory) {
123 let dest = mem.read(self.pc);
124 self.pc += 1;
125 let src = mem.read(self.pc);
126 self.pc += 1;
127
128 let (result, borrow) = match (dest, src) {
129 (0, 0) => self.a.overflowing_sub(self.a),
130 (0, 1) => self.a.overflowing_sub(self.b),
131 (0, 2) => self.a.overflowing_sub(self.c),
132 (0, 3) => self.a.overflowing_sub(self.d),
133
134 (1, 0) => self.b.overflowing_sub(self.a),
135 (1, 1) => self.b.overflowing_sub(self.b),
136 (1, 2) => self.b.overflowing_sub(self.c),
137 (1, 3) => self.b.overflowing_sub(self.d),
138
139 (2, 0) => self.c.overflowing_sub(self.a),
140 (2, 1) => self.c.overflowing_sub(self.b),
141 (2, 2) => self.c.overflowing_sub(self.c),
142 (2, 3) => self.c.overflowing_sub(self.d),
143
144 (3, 0) => self.d.overflowing_sub(self.a),
145 (3, 1) => self.d.overflowing_sub(self.b),
146 (3, 2) => self.d.overflowing_sub(self.c),
147 (3, 3) => self.d.overflowing_sub(self.d),
148
149 _ => (0, false),
150 };
151
152 match dest {
153 0 => self.a = result,
154 1 => self.b = result,
155 2 => self.c = result,
156 3 => self.d = result,
157 _ => {}
158 }
159
160 self.zero = result == 0;
161 self.carry = borrow;
162 }
163
164 pub fn jmp(&mut self, mem: &Memory) {
165 let low = mem.read(self.pc) as u16;
166 self.inc_pc();
167 let high = mem.read(self.pc) as u16;
168 self.inc_pc();
169
170 let addrs = (high << 8) | low;
171
172 self.pc = addrs;
173 }
174
175 pub fn jz(&mut self, mem: &Memory) {
176 let low = mem.read(self.pc) as u16;
177 self.inc_pc();
178 let high = mem.read(self.pc) as u16;
179 self.inc_pc();
180
181 let addrs = (high << 8) | low;
182
183 if self.zero {
184 self.pc = addrs;
185 }
186 }
187
188 pub fn jnz(&mut self, mem: &Memory) {
189 let low = mem.read(self.pc) as u16;
190 self.inc_pc();
191 let high = mem.read(self.pc) as u16;
192 self.inc_pc();
193
194 let addrs = (high << 8) | low;
195
196 if !self.zero {
197 self.pc = addrs;
198 }
199 }
200}