mos6502_model/
machine.rs

1use crate::addressing_mode::*;
2use crate::instruction::*;
3pub use crate::{address, status, Address};
4use crate::{opcode, UnknownOpcode};
5#[cfg(feature = "serialize")]
6use serde::{Deserialize, Serialize};
7
8#[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
9#[derive(Debug, Clone)]
10pub struct Cpu {
11    pub pc: Address,
12    pub sp: u8,
13    pub acc: u8,
14    pub x: u8,
15    pub y: u8,
16    pub status: StatusRegister,
17}
18
19impl Cpu {
20    pub fn new() -> Self {
21        Self {
22            pc: 0,
23            sp: 0xff,
24            acc: 0,
25            x: 0,
26            y: 0,
27            status: StatusRegister::new(),
28        }
29    }
30    pub fn retrieve_nmi_return_address_during_nmi<MRO: MemoryReadOnly>(
31        &self,
32        memory: &MRO,
33    ) -> Option<Address> {
34        if self.pc == memory.read_u16_le_read_only(crate::interrupt_vector::NMI_LO) {
35            let lo = memory.read_u8_stack_read_only(self.sp.wrapping_add(2));
36            let hi = memory.read_u8_stack_read_only(self.sp.wrapping_add(3));
37            Some(address::from_u8_lo_hi(lo, hi))
38        } else {
39            None
40        }
41    }
42    pub fn nmi<M: Memory>(&mut self, memory: &mut M) {
43        self.push_stack_u8(memory, address::hi(self.pc));
44        self.push_stack_u8(memory, address::lo(self.pc));
45        self.push_stack_u8(memory, self.status.masked_with_brk_and_expansion());
46        self.pc = memory.read_u16_le(crate::interrupt_vector::NMI_LO);
47    }
48    pub fn push_stack_u8<M: Memory>(&mut self, memory: &mut M, value: u8) {
49        memory.write_u8_stack(self.sp, value);
50        self.sp = self.sp.wrapping_sub(1);
51    }
52    pub fn pop_stack_u8<M: Memory>(&mut self, memory: &mut M) -> u8 {
53        self.sp = self.sp.wrapping_add(1);
54        memory.read_u8_stack(self.sp)
55    }
56    pub fn start<M: Memory>(&mut self, memory: &mut M) {
57        self.pc = memory.read_u16_le(crate::interrupt_vector::START_LO);
58    }
59    pub fn run_for_cycles<M: Memory>(
60        &mut self,
61        memory: &mut M,
62        num_cycles: usize,
63    ) -> Result<usize, UnknownOpcode> {
64        let mut cycle_count = 0;
65        while cycle_count < num_cycles {
66            cycle_count += self.step(memory)? as usize;
67        }
68        Ok(cycle_count)
69    }
70    pub fn step<M: Memory>(&mut self, memory: &mut M) -> Result<u8, UnknownOpcode> {
71        let opcode = memory.read_u8(self.pc);
72        let cycles = match opcode {
73            opcode::adc::ABSOLUTE => adc::interpret(Absolute, self, memory),
74            opcode::adc::ABSOLUTE_X_INDEXED => adc::interpret(AbsoluteXIndexed, self, memory),
75            opcode::adc::ABSOLUTE_Y_INDEXED => adc::interpret(AbsoluteYIndexed, self, memory),
76            opcode::adc::IMMEDIATE => adc::interpret(Immediate, self, memory),
77            opcode::adc::INDIRECT_Y_INDEXED => adc::interpret(IndirectYIndexed, self, memory),
78            opcode::adc::X_INDEXED_INDIRECT => adc::interpret(XIndexedIndirect, self, memory),
79            opcode::adc::ZERO_PAGE => adc::interpret(ZeroPage, self, memory),
80            opcode::adc::ZERO_PAGE_X_INDEXED => adc::interpret(ZeroPageXIndexed, self, memory),
81            opcode::ahx::unofficial0::ABSOLUTE_Y_INDEXED => {
82                ahx::interpret(AbsoluteYIndexed, self, memory)
83            }
84            opcode::ahx::unofficial0::INDIRECT_Y_INDEXED => {
85                ahx::interpret(IndirectYIndexed, self, memory)
86            }
87            opcode::alr::unofficial0::IMMEDIATE => alr::interpret(self, memory),
88            opcode::arr::unofficial0::IMMEDIATE => arr::interpret(self, memory),
89            opcode::anc::unofficial0::IMMEDIATE => anc::interpret(self, memory),
90            opcode::anc::unofficial1::IMMEDIATE => anc::interpret(self, memory),
91            opcode::and::ABSOLUTE => and::interpret(Absolute, self, memory),
92            opcode::and::ABSOLUTE_X_INDEXED => and::interpret(AbsoluteXIndexed, self, memory),
93            opcode::and::ABSOLUTE_Y_INDEXED => and::interpret(AbsoluteYIndexed, self, memory),
94            opcode::and::IMMEDIATE => and::interpret(Immediate, self, memory),
95            opcode::and::INDIRECT_Y_INDEXED => and::interpret(IndirectYIndexed, self, memory),
96            opcode::and::X_INDEXED_INDIRECT => and::interpret(XIndexedIndirect, self, memory),
97            opcode::and::ZERO_PAGE => and::interpret(ZeroPage, self, memory),
98            opcode::and::ZERO_PAGE_X_INDEXED => and::interpret(ZeroPageXIndexed, self, memory),
99            opcode::asl::ABSOLUTE => asl::interpret(Absolute, self, memory),
100            opcode::asl::ABSOLUTE_X_INDEXED => asl::interpret(AbsoluteXIndexed, self, memory),
101            opcode::asl::ACCUMULATOR => asl::interpret_acc(self),
102            opcode::asl::ZERO_PAGE => asl::interpret(ZeroPage, self, memory),
103            opcode::asl::ZERO_PAGE_X_INDEXED => asl::interpret(ZeroPageXIndexed, self, memory),
104            opcode::axs::unofficial0::IMMEDIATE => axs::interpret(self, memory),
105            opcode::bcc::RELATIVE => bcc::interpret(self, memory),
106            opcode::bcs::RELATIVE => bcs::interpret(self, memory),
107            opcode::beq::RELATIVE => beq::interpret(self, memory),
108            opcode::bmi::RELATIVE => bmi::interpret(self, memory),
109            opcode::bne::RELATIVE => bne::interpret(self, memory),
110            opcode::bpl::RELATIVE => bpl::interpret(self, memory),
111            opcode::bvc::RELATIVE => bvc::interpret(self, memory),
112            opcode::bvs::RELATIVE => bvs::interpret(self, memory),
113            opcode::bit::ABSOLUTE => bit::interpret(Absolute, self, memory),
114            opcode::bit::ZERO_PAGE => bit::interpret(ZeroPage, self, memory),
115            opcode::brk::IMPLIED => brk::interpret(self, memory),
116            opcode::clc::IMPLIED => clc::interpret(self),
117            opcode::cld::IMPLIED => cld::interpret(self),
118            opcode::cli::IMPLIED => cli::interpret(self),
119            opcode::clv::IMPLIED => clv::interpret(self),
120            opcode::cmp::ABSOLUTE => cmp::interpret(Absolute, self, memory),
121            opcode::cmp::ABSOLUTE_X_INDEXED => cmp::interpret(AbsoluteXIndexed, self, memory),
122            opcode::cmp::ABSOLUTE_Y_INDEXED => cmp::interpret(AbsoluteYIndexed, self, memory),
123            opcode::cmp::IMMEDIATE => cmp::interpret(Immediate, self, memory),
124            opcode::cmp::INDIRECT_Y_INDEXED => cmp::interpret(IndirectYIndexed, self, memory),
125            opcode::cmp::X_INDEXED_INDIRECT => cmp::interpret(XIndexedIndirect, self, memory),
126            opcode::cmp::ZERO_PAGE => cmp::interpret(ZeroPage, self, memory),
127            opcode::cmp::ZERO_PAGE_X_INDEXED => cmp::interpret(ZeroPageXIndexed, self, memory),
128            opcode::cpx::ABSOLUTE => cpx::interpret(Absolute, self, memory),
129            opcode::cpx::IMMEDIATE => cpx::interpret(Immediate, self, memory),
130            opcode::cpx::ZERO_PAGE => cpx::interpret(ZeroPage, self, memory),
131            opcode::cpy::ABSOLUTE => cpy::interpret(Absolute, self, memory),
132            opcode::cpy::IMMEDIATE => cpy::interpret(Immediate, self, memory),
133            opcode::cpy::ZERO_PAGE => cpy::interpret(ZeroPage, self, memory),
134            opcode::dcp::unofficial0::X_INDEXED_INDIRECT => {
135                dcp::interpret(XIndexedIndirect, self, memory)
136            }
137            opcode::dcp::unofficial0::ZERO_PAGE => dcp::interpret(ZeroPage, self, memory),
138            opcode::dcp::unofficial0::ABSOLUTE => dcp::interpret(Absolute, self, memory),
139            opcode::dcp::unofficial0::INDIRECT_Y_INDEXED => {
140                dcp::interpret(IndirectYIndexed, self, memory)
141            }
142            opcode::dcp::unofficial0::ZERO_PAGE_X_INDEXED => {
143                dcp::interpret(ZeroPageXIndexed, self, memory)
144            }
145            opcode::dcp::unofficial0::ABSOLUTE_X_INDEXED => {
146                dcp::interpret(AbsoluteXIndexed, self, memory)
147            }
148            opcode::dcp::unofficial0::ABSOLUTE_Y_INDEXED => {
149                dcp::interpret(AbsoluteYIndexed, self, memory)
150            }
151            opcode::dec::ABSOLUTE => dec::interpret(Absolute, self, memory),
152            opcode::dec::ABSOLUTE_X_INDEXED => dec::interpret(AbsoluteXIndexed, self, memory),
153            opcode::dec::ZERO_PAGE => dec::interpret(ZeroPage, self, memory),
154            opcode::dec::ZERO_PAGE_X_INDEXED => dec::interpret(ZeroPageXIndexed, self, memory),
155            opcode::dex::IMPLIED => dex::interpret(self),
156            opcode::dey::IMPLIED => dey::interpret(self),
157            opcode::eor::ABSOLUTE => eor::interpret(Absolute, self, memory),
158            opcode::eor::ABSOLUTE_X_INDEXED => eor::interpret(AbsoluteXIndexed, self, memory),
159            opcode::eor::ABSOLUTE_Y_INDEXED => eor::interpret(AbsoluteYIndexed, self, memory),
160            opcode::eor::IMMEDIATE => eor::interpret(Immediate, self, memory),
161            opcode::eor::INDIRECT_Y_INDEXED => eor::interpret(IndirectYIndexed, self, memory),
162            opcode::eor::X_INDEXED_INDIRECT => eor::interpret(XIndexedIndirect, self, memory),
163            opcode::eor::ZERO_PAGE => eor::interpret(ZeroPage, self, memory),
164            opcode::eor::ZERO_PAGE_X_INDEXED => eor::interpret(ZeroPageXIndexed, self, memory),
165            opcode::ign::unofficial0::ABSOLUTE => ign::interpret(Absolute, self, memory),
166            opcode::ign::unofficial0::ABSOLUTE_X_INDEXED => {
167                ign::interpret(AbsoluteXIndexed, self, memory)
168            }
169            opcode::ign::unofficial0::ZERO_PAGE => ign::interpret(ZeroPage, self, memory),
170            opcode::ign::unofficial0::ZERO_PAGE_X_INDEXED => {
171                ign::interpret(ZeroPageXIndexed, self, memory)
172            }
173            opcode::ign::unofficial1::ABSOLUTE_X_INDEXED => {
174                ign::interpret(AbsoluteXIndexed, self, memory)
175            }
176            opcode::ign::unofficial1::ZERO_PAGE => ign::interpret(ZeroPage, self, memory),
177            opcode::ign::unofficial1::ZERO_PAGE_X_INDEXED => {
178                ign::interpret(ZeroPageXIndexed, self, memory)
179            }
180            opcode::ign::unofficial2::ABSOLUTE_X_INDEXED => {
181                ign::interpret(AbsoluteXIndexed, self, memory)
182            }
183            opcode::ign::unofficial2::ZERO_PAGE => ign::interpret(ZeroPage, self, memory),
184            opcode::ign::unofficial2::ZERO_PAGE_X_INDEXED => {
185                ign::interpret(ZeroPageXIndexed, self, memory)
186            }
187            opcode::ign::unofficial3::ABSOLUTE_X_INDEXED => {
188                ign::interpret(AbsoluteXIndexed, self, memory)
189            }
190            opcode::ign::unofficial3::ZERO_PAGE_X_INDEXED => {
191                ign::interpret(ZeroPageXIndexed, self, memory)
192            }
193            opcode::ign::unofficial4::ABSOLUTE_X_INDEXED => {
194                ign::interpret(AbsoluteXIndexed, self, memory)
195            }
196            opcode::ign::unofficial4::ZERO_PAGE_X_INDEXED => {
197                ign::interpret(ZeroPageXIndexed, self, memory)
198            }
199            opcode::ign::unofficial5::ABSOLUTE_X_INDEXED => {
200                ign::interpret(AbsoluteXIndexed, self, memory)
201            }
202            opcode::ign::unofficial5::ZERO_PAGE_X_INDEXED => {
203                ign::interpret(ZeroPageXIndexed, self, memory)
204            }
205            opcode::inc::ABSOLUTE => inc::interpret(Absolute, self, memory),
206            opcode::inc::ABSOLUTE_X_INDEXED => inc::interpret(AbsoluteXIndexed, self, memory),
207            opcode::inc::ZERO_PAGE => inc::interpret(ZeroPage, self, memory),
208            opcode::inc::ZERO_PAGE_X_INDEXED => inc::interpret(ZeroPageXIndexed, self, memory),
209            opcode::inx::IMPLIED => inx::interpret(self),
210            opcode::iny::IMPLIED => iny::interpret(self),
211            opcode::isc::unofficial0::X_INDEXED_INDIRECT => {
212                isc::interpret(XIndexedIndirect, self, memory)
213            }
214            opcode::isc::unofficial0::ZERO_PAGE => isc::interpret(ZeroPage, self, memory),
215            opcode::isc::unofficial0::ABSOLUTE => isc::interpret(Absolute, self, memory),
216            opcode::isc::unofficial0::INDIRECT_Y_INDEXED => {
217                isc::interpret(IndirectYIndexed, self, memory)
218            }
219            opcode::isc::unofficial0::ZERO_PAGE_X_INDEXED => {
220                isc::interpret(ZeroPageXIndexed, self, memory)
221            }
222            opcode::isc::unofficial0::ABSOLUTE_X_INDEXED => {
223                isc::interpret(AbsoluteXIndexed, self, memory)
224            }
225            opcode::isc::unofficial0::ABSOLUTE_Y_INDEXED => {
226                isc::interpret(AbsoluteYIndexed, self, memory)
227            }
228            opcode::jmp::ABSOLUTE => jmp::interpret(Absolute, self, memory),
229            opcode::jmp::INDIRECT => jmp::interpret(Indirect, self, memory),
230            opcode::jsr::ABSOLUTE => jsr::interpret(Absolute, self, memory),
231            opcode::lax::unofficial0::ABSOLUTE => lax::interpret(Absolute, self, memory),
232            opcode::lax::unofficial0::ABSOLUTE_Y_INDEXED => {
233                lax::interpret(AbsoluteYIndexed, self, memory)
234            }
235            opcode::lax::unofficial0::IMMEDIATE => lax::interpret(Immediate, self, memory),
236            opcode::lax::unofficial0::X_INDEXED_INDIRECT => {
237                lax::interpret(XIndexedIndirect, self, memory)
238            }
239            opcode::lax::unofficial0::INDIRECT_Y_INDEXED => {
240                lax::interpret(IndirectYIndexed, self, memory)
241            }
242            opcode::lax::unofficial0::ZERO_PAGE => lax::interpret(ZeroPage, self, memory),
243            opcode::lax::unofficial0::ZERO_PAGE_Y_INDEXED => {
244                lax::interpret(ZeroPageYIndexed, self, memory)
245            }
246            opcode::lda::ABSOLUTE => lda::interpret(Absolute, self, memory),
247            opcode::lda::ABSOLUTE_X_INDEXED => lda::interpret(AbsoluteXIndexed, self, memory),
248            opcode::lda::ABSOLUTE_Y_INDEXED => lda::interpret(AbsoluteYIndexed, self, memory),
249            opcode::lda::IMMEDIATE => lda::interpret(Immediate, self, memory),
250            opcode::lda::INDIRECT_Y_INDEXED => lda::interpret(IndirectYIndexed, self, memory),
251            opcode::lda::X_INDEXED_INDIRECT => lda::interpret(XIndexedIndirect, self, memory),
252            opcode::lda::ZERO_PAGE => lda::interpret(ZeroPage, self, memory),
253            opcode::lda::ZERO_PAGE_X_INDEXED => lda::interpret(ZeroPageXIndexed, self, memory),
254            opcode::ldx::ABSOLUTE => ldx::interpret(Absolute, self, memory),
255            opcode::ldx::ABSOLUTE_Y_INDEXED => ldx::interpret(AbsoluteYIndexed, self, memory),
256            opcode::ldx::IMMEDIATE => ldx::interpret(Immediate, self, memory),
257            opcode::ldx::ZERO_PAGE => ldx::interpret(ZeroPage, self, memory),
258            opcode::ldx::ZERO_PAGE_Y_INDEXED => ldx::interpret(ZeroPageYIndexed, self, memory),
259            opcode::ldy::ABSOLUTE => ldy::interpret(Absolute, self, memory),
260            opcode::ldy::ABSOLUTE_X_INDEXED => ldy::interpret(AbsoluteXIndexed, self, memory),
261            opcode::ldy::IMMEDIATE => ldy::interpret(Immediate, self, memory),
262            opcode::ldy::ZERO_PAGE => ldy::interpret(ZeroPage, self, memory),
263            opcode::ldy::ZERO_PAGE_X_INDEXED => ldy::interpret(ZeroPageXIndexed, self, memory),
264            opcode::lsr::ABSOLUTE => lsr::interpret(Absolute, self, memory),
265            opcode::lsr::ABSOLUTE_X_INDEXED => lsr::interpret(AbsoluteXIndexed, self, memory),
266            opcode::lsr::ACCUMULATOR => lsr::interpret_acc(self),
267            opcode::lsr::ZERO_PAGE => lsr::interpret(ZeroPage, self, memory),
268            opcode::lsr::ZERO_PAGE_X_INDEXED => lsr::interpret(ZeroPageXIndexed, self, memory),
269            opcode::nop::IMPLIED => nop::interpret(self),
270            opcode::nop::unofficial0::IMPLIED => nop::interpret(self),
271            opcode::nop::unofficial1::IMPLIED => nop::interpret(self),
272            opcode::nop::unofficial2::IMPLIED => nop::interpret(self),
273            opcode::nop::unofficial3::IMPLIED => nop::interpret(self),
274            opcode::nop::unofficial4::IMPLIED => nop::interpret(self),
275            opcode::nop::unofficial5::IMPLIED => nop::interpret(self),
276            opcode::ora::ABSOLUTE => ora::interpret(Absolute, self, memory),
277            opcode::ora::ABSOLUTE_X_INDEXED => ora::interpret(AbsoluteXIndexed, self, memory),
278            opcode::ora::ABSOLUTE_Y_INDEXED => ora::interpret(AbsoluteYIndexed, self, memory),
279            opcode::ora::IMMEDIATE => ora::interpret(Immediate, self, memory),
280            opcode::ora::INDIRECT_Y_INDEXED => ora::interpret(IndirectYIndexed, self, memory),
281            opcode::ora::X_INDEXED_INDIRECT => ora::interpret(XIndexedIndirect, self, memory),
282            opcode::ora::ZERO_PAGE => ora::interpret(ZeroPage, self, memory),
283            opcode::ora::ZERO_PAGE_X_INDEXED => ora::interpret(ZeroPageXIndexed, self, memory),
284            opcode::pha::IMPLIED => pha::interpret(self, memory),
285            opcode::php::IMPLIED => php::interpret(self, memory),
286            opcode::pla::IMPLIED => pla::interpret(self, memory),
287            opcode::plp::IMPLIED => plp::interpret(self, memory),
288            opcode::rla::unofficial0::X_INDEXED_INDIRECT => {
289                rla::interpret(XIndexedIndirect, self, memory)
290            }
291            opcode::rla::unofficial0::ZERO_PAGE => rla::interpret(ZeroPage, self, memory),
292            opcode::rla::unofficial0::ABSOLUTE => rla::interpret(Absolute, self, memory),
293            opcode::rla::unofficial0::INDIRECT_Y_INDEXED => {
294                rla::interpret(IndirectYIndexed, self, memory)
295            }
296            opcode::rla::unofficial0::ZERO_PAGE_X_INDEXED => {
297                rla::interpret(ZeroPageXIndexed, self, memory)
298            }
299            opcode::rla::unofficial0::ABSOLUTE_X_INDEXED => {
300                rla::interpret(AbsoluteXIndexed, self, memory)
301            }
302            opcode::rla::unofficial0::ABSOLUTE_Y_INDEXED => {
303                rla::interpret(AbsoluteYIndexed, self, memory)
304            }
305            opcode::rol::ABSOLUTE => rol::interpret(Absolute, self, memory),
306            opcode::rol::ABSOLUTE_X_INDEXED => rol::interpret(AbsoluteXIndexed, self, memory),
307            opcode::rol::ACCUMULATOR => rol::interpret_acc(self),
308            opcode::rol::ZERO_PAGE => rol::interpret(ZeroPage, self, memory),
309            opcode::rol::ZERO_PAGE_X_INDEXED => rol::interpret(ZeroPageXIndexed, self, memory),
310            opcode::ror::ABSOLUTE => ror::interpret(Absolute, self, memory),
311            opcode::ror::ABSOLUTE_X_INDEXED => ror::interpret(AbsoluteXIndexed, self, memory),
312            opcode::ror::ACCUMULATOR => ror::interpret_acc(self),
313            opcode::ror::ZERO_PAGE => ror::interpret(ZeroPage, self, memory),
314            opcode::ror::ZERO_PAGE_X_INDEXED => ror::interpret(ZeroPageXIndexed, self, memory),
315            opcode::rra::unofficial0::X_INDEXED_INDIRECT => {
316                rra::interpret(XIndexedIndirect, self, memory)
317            }
318            opcode::rra::unofficial0::ZERO_PAGE => rra::interpret(ZeroPage, self, memory),
319            opcode::rra::unofficial0::ABSOLUTE => rra::interpret(Absolute, self, memory),
320            opcode::rra::unofficial0::INDIRECT_Y_INDEXED => {
321                rra::interpret(IndirectYIndexed, self, memory)
322            }
323            opcode::rra::unofficial0::ZERO_PAGE_X_INDEXED => {
324                rra::interpret(ZeroPageXIndexed, self, memory)
325            }
326            opcode::rra::unofficial0::ABSOLUTE_X_INDEXED => {
327                rra::interpret(AbsoluteXIndexed, self, memory)
328            }
329            opcode::rra::unofficial0::ABSOLUTE_Y_INDEXED => {
330                rra::interpret(AbsoluteYIndexed, self, memory)
331            }
332            opcode::rti::IMPLIED => rti::interpret(self, memory),
333            opcode::rts::IMPLIED => rts::interpret(self, memory),
334            opcode::sax::unofficial0::X_INDEXED_INDIRECT => {
335                sax::interpret(XIndexedIndirect, self, memory)
336            }
337            opcode::sax::unofficial0::ZERO_PAGE => sax::interpret(ZeroPage, self, memory),
338            opcode::sax::unofficial0::ABSOLUTE => sax::interpret(Absolute, self, memory),
339            opcode::sax::unofficial0::ZERO_PAGE_Y_INDEXED => {
340                sax::interpret(ZeroPageYIndexed, self, memory)
341            }
342            opcode::sbc::ABSOLUTE => sbc::interpret(Absolute, self, memory),
343            opcode::sbc::ABSOLUTE_X_INDEXED => sbc::interpret(AbsoluteXIndexed, self, memory),
344            opcode::sbc::ABSOLUTE_Y_INDEXED => sbc::interpret(AbsoluteYIndexed, self, memory),
345            opcode::sbc::IMMEDIATE => sbc::interpret(Immediate, self, memory),
346            opcode::sbc::INDIRECT_Y_INDEXED => sbc::interpret(IndirectYIndexed, self, memory),
347            opcode::sbc::X_INDEXED_INDIRECT => sbc::interpret(XIndexedIndirect, self, memory),
348            opcode::sbc::ZERO_PAGE => sbc::interpret(ZeroPage, self, memory),
349            opcode::sbc::ZERO_PAGE_X_INDEXED => sbc::interpret(ZeroPageXIndexed, self, memory),
350            opcode::sbc::unofficial0::IMMEDIATE => sbc::interpret(Immediate, self, memory),
351            opcode::sec::IMPLIED => sec::interpret(self),
352            opcode::sed::IMPLIED => sed::interpret(self),
353            opcode::sei::IMPLIED => sei::interpret(self),
354            opcode::skb::unofficial0::IMMEDIATE => skb::interpret(self, memory),
355            opcode::skb::unofficial1::IMMEDIATE => skb::interpret(self, memory),
356            opcode::skb::unofficial2::IMMEDIATE => skb::interpret(self, memory),
357            opcode::skb::unofficial3::IMMEDIATE => skb::interpret(self, memory),
358            opcode::skb::unofficial4::IMMEDIATE => skb::interpret(self, memory),
359            opcode::slo::unofficial0::X_INDEXED_INDIRECT => {
360                slo::interpret(XIndexedIndirect, self, memory)
361            }
362            opcode::slo::unofficial0::ZERO_PAGE => slo::interpret(ZeroPage, self, memory),
363            opcode::slo::unofficial0::ABSOLUTE => slo::interpret(Absolute, self, memory),
364            opcode::slo::unofficial0::INDIRECT_Y_INDEXED => {
365                slo::interpret(IndirectYIndexed, self, memory)
366            }
367            opcode::slo::unofficial0::ZERO_PAGE_X_INDEXED => {
368                slo::interpret(ZeroPageXIndexed, self, memory)
369            }
370            opcode::slo::unofficial0::ABSOLUTE_X_INDEXED => {
371                slo::interpret(AbsoluteXIndexed, self, memory)
372            }
373            opcode::slo::unofficial0::ABSOLUTE_Y_INDEXED => {
374                slo::interpret(AbsoluteYIndexed, self, memory)
375            }
376            opcode::sre::unofficial0::X_INDEXED_INDIRECT => {
377                sre::interpret(XIndexedIndirect, self, memory)
378            }
379            opcode::sre::unofficial0::ZERO_PAGE => sre::interpret(ZeroPage, self, memory),
380            opcode::sre::unofficial0::ABSOLUTE => sre::interpret(Absolute, self, memory),
381            opcode::sre::unofficial0::INDIRECT_Y_INDEXED => {
382                sre::interpret(IndirectYIndexed, self, memory)
383            }
384            opcode::sre::unofficial0::ZERO_PAGE_X_INDEXED => {
385                sre::interpret(ZeroPageXIndexed, self, memory)
386            }
387            opcode::sre::unofficial0::ABSOLUTE_X_INDEXED => {
388                sre::interpret(AbsoluteXIndexed, self, memory)
389            }
390            opcode::sre::unofficial0::ABSOLUTE_Y_INDEXED => {
391                sre::interpret(AbsoluteYIndexed, self, memory)
392            }
393            opcode::sta::ABSOLUTE => sta::interpret(Absolute, self, memory),
394            opcode::sta::ABSOLUTE_X_INDEXED => sta::interpret(AbsoluteXIndexed, self, memory),
395            opcode::sta::ABSOLUTE_Y_INDEXED => sta::interpret(AbsoluteYIndexed, self, memory),
396            opcode::sta::INDIRECT_Y_INDEXED => sta::interpret(IndirectYIndexed, self, memory),
397            opcode::sta::X_INDEXED_INDIRECT => sta::interpret(XIndexedIndirect, self, memory),
398            opcode::sta::ZERO_PAGE => sta::interpret(ZeroPage, self, memory),
399            opcode::sta::ZERO_PAGE_X_INDEXED => sta::interpret(ZeroPageXIndexed, self, memory),
400            opcode::stx::ABSOLUTE => stx::interpret(Absolute, self, memory),
401            opcode::stx::ZERO_PAGE => stx::interpret(ZeroPage, self, memory),
402            opcode::stx::ZERO_PAGE_Y_INDEXED => stx::interpret(ZeroPageYIndexed, self, memory),
403            opcode::sty::ABSOLUTE => sty::interpret(Absolute, self, memory),
404            opcode::sty::ZERO_PAGE => sty::interpret(ZeroPage, self, memory),
405            opcode::sty::ZERO_PAGE_X_INDEXED => sty::interpret(ZeroPageXIndexed, self, memory),
406            opcode::sxa::unofficial0::ABSOLUTE_Y_INDEXED => sxa::interpret(self, memory),
407            opcode::sya::unofficial0::ABSOLUTE_X_INDEXED => sya::interpret(self, memory),
408            opcode::tax::IMPLIED => tax::interpret(self),
409            opcode::tay::IMPLIED => tay::interpret(self),
410            opcode::tsx::IMPLIED => tsx::interpret(self),
411            opcode::txa::IMPLIED => txa::interpret(self),
412            opcode::txs::IMPLIED => txs::interpret(self),
413            opcode::tya::IMPLIED => tya::interpret(self),
414            _ => return Err(UnknownOpcode(opcode)),
415        };
416        Ok(cycles)
417    }
418}
419
420const STACK_ADDRESS_HI: u8 = 0x01;
421pub trait Memory {
422    fn read_u8(&mut self, address: Address) -> u8;
423    fn read_u16_le(&mut self, address: Address) -> u16 {
424        let lo = self.read_u8(address);
425        let hi = self.read_u8(address.wrapping_add(1));
426        ((hi as u16) << 8) | lo as u16
427    }
428    fn read_u8_zero_page(&mut self, address: u8) -> u8 {
429        self.read_u8(address as Address)
430    }
431    fn read_u16_le_zero_page(&mut self, address: u8) -> u16 {
432        let lo = self.read_u8_zero_page(address);
433        let hi = self.read_u8_zero_page(address.wrapping_add(1));
434        ((hi as u16) << 8) | lo as u16
435    }
436    fn read_u8_stack(&mut self, stack_pointer: u8) -> u8 {
437        self.read_u8(address::from_u8_lo_hi(stack_pointer, STACK_ADDRESS_HI))
438    }
439    fn write_u8(&mut self, address: Address, data: u8);
440    fn write_u8_zero_page(&mut self, address: u8, data: u8) {
441        self.write_u8(address as Address, data);
442    }
443    fn write_u8_stack(&mut self, stack_pointer: u8, data: u8) {
444        self.write_u8(
445            address::from_u8_lo_hi(stack_pointer, STACK_ADDRESS_HI),
446            data,
447        );
448    }
449}
450
451/// View of memory which never changed by reading, for use in debugging and testing
452pub trait MemoryReadOnly {
453    fn read_u8_read_only(&self, address: Address) -> u8;
454    fn read_u16_le_read_only(&self, address: Address) -> u16 {
455        let lo = self.read_u8_read_only(address);
456        let hi = self.read_u8_read_only(address + 1);
457        ((hi as u16) << 8) | lo as u16
458    }
459    fn read_u8_stack_read_only(&self, stack_pointer: u8) -> u8 {
460        self.read_u8_read_only(address::from_u8_lo_hi(stack_pointer, STACK_ADDRESS_HI))
461    }
462}
463
464pub use status::Register as StatusRegister;