1use crate::bus::Bus;
16use crate::registers::Registers;
17
18mod opcodes;
19
20pub use opcodes::instruction_cycles;
21
22pub const VEC_RESET: u16 = 0xFFFE;
27pub const VEC_NMI: u16 = 0xFFFC;
28pub const VEC_SWI: u16 = 0xFFFA;
29pub const VEC_IRQ: u16 = 0xFFF8;
30pub const VEC_FIRQ: u16 = 0xFFF6;
31pub const VEC_SWI2: u16 = 0xFFF4;
32pub const VEC_SWI3: u16 = 0xFFF2;
33
34pub struct Cpu {
40 pub reg: Registers,
42 pub cycles: u64,
44 pub halted: bool,
46 pub illegal: bool,
48
49 nmi_armed: bool,
52 nmi_pending: bool,
54 firq_line: bool,
56 irq_line: bool,
58 cwai: bool,
60 sync: bool,
62}
63
64impl Cpu {
65 pub fn new() -> Self {
67 Self {
68 reg: Registers::new(),
69 cycles: 0,
70 halted: false,
71 illegal: false,
72 nmi_armed: false,
73 nmi_pending: false,
74 firq_line: false,
75 irq_line: false,
76 cwai: false,
77 sync: false,
78 }
79 }
80
81 pub fn reset(&mut self, bus: &mut impl Bus) {
83 self.reg = Registers::new();
84 self.reg.cc.set_irq_inhibit(true);
85 self.reg.cc.set_firq_inhibit(true);
86 self.reg.pc = bus.read_word(VEC_RESET);
87 self.cycles = 0;
88 self.halted = false;
89 self.illegal = false;
90 self.nmi_armed = false;
91 self.nmi_pending = false;
92 self.firq_line = false;
93 self.irq_line = false;
94 self.cwai = false;
95 self.sync = false;
96 }
97
98 pub fn set_irq(&mut self, active: bool) {
100 self.irq_line = active;
101 }
102
103 pub fn set_firq(&mut self, active: bool) {
105 self.firq_line = active;
106 }
107
108 pub fn trigger_nmi(&mut self) {
110 if self.nmi_armed {
111 self.nmi_pending = true;
112 }
113 }
114
115 pub fn step(&mut self, bus: &mut impl Bus) -> u64 {
118 if self.halted {
119 return 1;
120 }
121
122 let start_cycles = self.cycles;
123
124 if self.sync {
126 if self.nmi_pending || self.firq_line || self.irq_line {
127 self.sync = false;
128 } else {
129 self.cycles += 1;
130 return 1;
131 }
132 }
133
134 if self.check_interrupts(bus) {
136 return self.cycles - start_cycles;
137 }
138
139 let opcode = self.fetch_byte(bus);
141 self.execute(bus, opcode);
142
143 self.cycles - start_cycles
144 }
145
146 pub fn run(&mut self, bus: &mut impl Bus, cycle_budget: u64) -> u64 {
148 let start_cycles = self.cycles;
149 let target = self.cycles + cycle_budget;
150 while self.cycles < target && !self.halted {
151 self.step(bus);
152 }
153 self.cycles - start_cycles
154 }
155
156 fn check_interrupts(&mut self, bus: &mut impl Bus) -> bool {
159 if self.nmi_pending {
161 self.nmi_pending = false;
162 if !self.cwai {
163 self.reg.cc.set_entire(true);
164 self.push_entire_state(bus);
165 }
166 self.cwai = false;
167 self.reg.cc.set_irq_inhibit(true);
168 self.reg.cc.set_firq_inhibit(true);
169 self.reg.pc = bus.read_word(VEC_NMI);
170 self.cycles += 19;
171 return true;
172 }
173
174 if self.firq_line && !self.reg.cc.firq_inhibit() {
176 if !self.cwai {
177 self.reg.cc.set_entire(false);
178 self.push_word_s(bus, self.reg.pc);
179 self.push_byte_s(bus, self.reg.cc.to_byte());
180 }
181 self.cwai = false;
182 self.reg.cc.set_irq_inhibit(true);
183 self.reg.cc.set_firq_inhibit(true);
184 self.reg.pc = bus.read_word(VEC_FIRQ);
185 self.cycles += 10;
186 return true;
187 }
188
189 if self.irq_line && !self.reg.cc.irq_inhibit() {
191 if !self.cwai {
192 self.reg.cc.set_entire(true);
193 self.push_entire_state(bus);
194 }
195 self.cwai = false;
196 self.reg.cc.set_irq_inhibit(true);
197 self.reg.pc = bus.read_word(VEC_IRQ);
198 self.cycles += 19;
199 return true;
200 }
201
202 false
203 }
204
205 pub(super) fn push_byte_s(&mut self, bus: &mut impl Bus, val: u8) {
209 self.reg.s = self.reg.s.wrapping_sub(1);
210 bus.write(self.reg.s, val);
211 }
212
213 pub(super) fn push_word_s(&mut self, bus: &mut impl Bus, val: u16) {
215 self.push_byte_s(bus, val as u8); self.push_byte_s(bus, (val >> 8) as u8);
217 }
218
219 pub(super) fn pull_byte_s(&mut self, bus: &mut impl Bus) -> u8 {
221 let val = bus.read(self.reg.s);
222 self.reg.s = self.reg.s.wrapping_add(1);
223 val
224 }
225
226 pub(super) fn pull_word_s(&mut self, bus: &mut impl Bus) -> u16 {
228 let hi = self.pull_byte_s(bus) as u16;
229 let lo = self.pull_byte_s(bus) as u16;
230 (hi << 8) | lo
231 }
232
233 pub(super) fn push_byte_u(&mut self, bus: &mut impl Bus, val: u8) {
235 self.reg.u = self.reg.u.wrapping_sub(1);
236 bus.write(self.reg.u, val);
237 }
238
239 pub(super) fn push_word_u(&mut self, bus: &mut impl Bus, val: u16) {
241 self.push_byte_u(bus, val as u8);
242 self.push_byte_u(bus, (val >> 8) as u8);
243 }
244
245 pub(super) fn pull_byte_u(&mut self, bus: &mut impl Bus) -> u8 {
247 let val = bus.read(self.reg.u);
248 self.reg.u = self.reg.u.wrapping_add(1);
249 val
250 }
251
252 pub(super) fn pull_word_u(&mut self, bus: &mut impl Bus) -> u16 {
254 let hi = self.pull_byte_u(bus) as u16;
255 let lo = self.pull_byte_u(bus) as u16;
256 (hi << 8) | lo
257 }
258
259 pub(super) fn push_entire_state(&mut self, bus: &mut impl Bus) {
262 self.push_word_s(bus, self.reg.pc);
263 self.push_word_s(bus, self.reg.u);
264 self.push_word_s(bus, self.reg.y);
265 self.push_word_s(bus, self.reg.x);
266 self.push_byte_s(bus, self.reg.dp);
267 self.push_byte_s(bus, self.reg.b());
268 self.push_byte_s(bus, self.reg.a());
269 self.push_byte_s(bus, self.reg.cc.to_byte());
270 }
271
272 pub(super) fn fetch_byte(&mut self, bus: &mut impl Bus) -> u8 {
276 let val = bus.read(self.reg.pc);
277 self.reg.pc = self.reg.pc.wrapping_add(1);
278 val
279 }
280
281 pub(super) fn fetch_word(&mut self, bus: &mut impl Bus) -> u16 {
283 let hi = self.fetch_byte(bus) as u16;
284 let lo = self.fetch_byte(bus) as u16;
285 (hi << 8) | lo
286 }
287
288 pub(super) fn addr_direct(&mut self, bus: &mut impl Bus) -> u16 {
292 let lo = self.fetch_byte(bus) as u16;
293 ((self.reg.dp as u16) << 8) | lo
294 }
295
296 pub(super) fn addr_extended(&mut self, bus: &mut impl Bus) -> u16 {
298 self.fetch_word(bus)
299 }
300
301 pub(super) fn addr_indexed(&mut self, bus: &mut impl Bus) -> (u16, u8) {
303 crate::addressing::indexed(self, bus)
304 }
305
306 pub(super) fn addr_relative8(&mut self, bus: &mut impl Bus) -> u16 {
308 let offset = self.fetch_byte(bus) as i8 as i16 as u16;
309 self.reg.pc.wrapping_add(offset)
310 }
311
312 pub(super) fn addr_relative16(&mut self, bus: &mut impl Bus) -> u16 {
314 let offset = self.fetch_word(bus);
315 self.reg.pc.wrapping_add(offset)
316 }
317
318 pub(super) fn arm_nmi(&mut self) {
320 self.nmi_armed = true;
321 }
322}
323
324impl Default for Cpu {
325 fn default() -> Self {
326 Self::new()
327 }
328}
329
330impl fmt::Debug for Cpu {
331 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
332 write!(f, "{} cyc={}", self.reg, self.cycles)
333 }
334}
335
336use std::fmt;