gte_w65c02s/
lib.rs

1#![allow(unused)]
2
3//! This crate is a cycle-accurate simulator for the WDC W65C02S, the most
4//! advanced direct descendent of that catalyst of the home computer
5//! revolution, the 6502.
6//!
7//! This crate accurately simulates all bus signals of the W65C02S except RDY,
8//! SOB, and BE, which can all be simulated by outside code. It is written in
9//! such a way that the unused bus logic usually gets optimized out. Make sure
10//! LTO is enabled in your `Cargo.toml` for a tremendous speedup:
11//!
12//! ```toml
13//! [profile.release]
14//! lto = true
15//! ```
16//!
17//! This crate does not depend on any other libraries, including the standard
18//! library.
19//!
20//! The W65C02S instruction set includes the original NMOS 6502 instructions,
21//! the additional instructions supported by all CMOS 6502s, the "Rockwell bit
22//! extensions" (`BBRx`/`BBSx`/`RMBx`/`SMBx`), and the `WAI` and `STP`
23//! instructions.
24//!
25//! The accuracy of this simulation has been tested on the [`65test` test
26//! suite](https://github.com/SolraBizna/65test), which contains over 4500
27//! tests. In every single test, the simulator's bus traffic is *exactly* the
28//! same as the real hardware—even down to the timing of IRQ and NMI responses.
29//! This means that this simulator is suitable for prototyping and simulation
30//! of real systems using the W65C02S processor, including systems based on the
31//! W65C134S MCU.
32//!
33//! To use it, you will need an instance of [`W65C02S`](struct.W65C02S.html)
34//! and an implementation of [`System`](trait.System.html). `W65C02S` simulates
35//! the CPU; `System` must simulate the hardware attached to the bus (memory,
36//! IO devices, et cetera).
37//!
38//! ```rust
39//! use w65c02s::*;
40//!
41//! pub fn main() {
42//!     let mut system = HelloWorldSystem::new();
43//!     let mut cpu = W65C02S::new();
44//!     while cpu.get_state() != State::Stopped { cpu.step(&mut system); }
45//! }
46//!
47//! /// A simple system with 64K of RAM, along with an output-only "serial
48//! /// port" mapped to $0000.
49//! struct HelloWorldSystem {
50//!     ram: [u8; 65536],
51//! }
52//!
53//! impl HelloWorldSystem {
54//!     pub fn new() -> HelloWorldSystem {
55//!         // initialize RAM with all 0xFFs
56//!         let mut ram = [0xFF; 65536];
57//!         // initialize the message
58//!         ram[0x0001..0x000F].copy_from_slice(b"Hello World!\n\0");
59//!         // initialize the program
60//!         ram[0x0200..0x020C].copy_from_slice(&[
61//!             op::LDX_IMM, 0,     //   LDX #0
62//!                                 // loop:
63//!             op::LDA_ZPX, 1,     //   LDA $01, X
64//!             op::BNE, 1,         //   BNE +
65//!             op::STP,            //   STP
66//!             op::STA_ZP, 0,      // + STA $00
67//!             op::INC_X,          //   INX
68//!             op::BRA, 0xF6,      //   BRA loop
69//!         ]);
70//!         // initialize the reset vector to point to $0200
71//!         ram[0xFFFC..0xFFFE].copy_from_slice(&[0x00, 0x02]);
72//!         HelloWorldSystem { ram }
73//!     }
74//! }
75//!
76//! impl System for HelloWorldSystem {
77//!     fn read(&mut self, _cpu: &mut W65C02S, addr: u16) -> u8 {
78//!         // all reads return RAM values directly
79//!         self.ram[addr as usize]
80//!     }
81//!     fn write(&mut self, _cpu: &mut W65C02S, addr: u16, value: u8) {
82//!         if addr == 0 {
83//!             // writing address $0000 outputs on an ASCII-only "serial port"
84//!             print!("{}", String::from_utf8_lossy(&[value]));
85//!         }
86//!         else {
87//!             // all other writes write to RAM
88//!             self.ram[addr as usize] = value
89//!         }
90//!     }
91//! }
92//! ```
93//!
94//! This simulator is based on the simulator in the original [ARS
95//! Emulator](https://github.com/SolraBizna/ars-emu).
96//!
97//! # License
98//!
99//! w65c02s is distributed under the zlib license. The complete text is as
100//! follows:
101//!
102//! > Copyright (c) 2019, Solra Bizna
103//! > 
104//! > This software is provided "as-is", without any express or implied
105//! > warranty. In no event will the author be held liable for any damages
106//! > arising from the use of this software.
107//! > 
108//! > Permission is granted to anyone to use this software for any purpose,
109//! > including commercial applications, and to alter it and redistribute it
110//! > freely, subject to the following restrictions:
111//! > 
112//! > 1. The origin of this software must not be misrepresented; you must not
113//! > claim that you wrote the original software. If you use this software in a
114//! > product, an acknowledgement in the product documentation would be
115//! > appreciated but is not required.
116//! > 2. Altered source versions must be plainly marked as such, and must not
117//! > be misrepresented as being the original software.
118//! > 3. This notice may not be removed or altered from any source
119//! > distribution.
120
121pub mod op;
122mod addressing_modes;
123mod instructions;
124
125use addressing_modes::*;
126
127pub static OPCODE_CYCLES: [i32; 256]= [ // was this worst case or...? who knows, who cares
128    7, 6, 2, 0, 5, 3, 5, 5, 2, 3, 4, 0, 7, 5, 7, 7,
129    3, 5, 5, 0, 5, 4, 6, 5, 1, 5, 4, 0, 7, 5, 7, 7,
130    6, 6, 2, 0, 3, 3, 5, 5, 3, 3, 4, 0, 5, 5, 7, 7,
131    2, 5, 5, 0, 4, 4, 6, 5, 1, 5, 4, 0, 5, 5, 7, 7,
132    5, 6, 2, 0, 2, 3, 5, 5, 2, 3, 4, 0, 4, 5, 7, 7,
133    3, 5, 5, 0, 3, 4, 6, 5, 1, 5, 2, 0, 9, 5, 7, 7,
134    5, 6, 2, 0, 3, 3, 5, 5, 3, 3, 4, 0, 7, 5, 7, 7,
135    2, 5, 5, 0, 4, 4, 6, 5, 1, 5, 2, 0, 7, 5, 7, 7,
136    3, 5, 2, 0, 3, 2, 3, 5, 4, 3, 1, 0, 5, 5, 5, 6,
137    3, 5, 4, 0, 4, 3, 4, 5, 1, 5, 1, 0, 5, 5, 6, 6,
138    3, 6, 3, 0, 3, 3, 3, 5, 1, 2, 1, 0, 5, 5, 5, 6,
139    2, 5, 5, 0, 4, 4, 4, 5, 1, 5, 1, 0, 5, 5, 5, 6,
140    3, 6, 2, 0, 3, 3, 5, 5, 4, 3, 4, 0, 5, 5, 7, 6,
141    3, 5, 5, 0, 3, 4, 6, 5, 1, 5, 2, 1, 4, 5, 8, 6,
142    3, 6, 2, 0, 3, 3, 5, 5, 4, 3, 1, 0, 5, 5, 7, 6,
143    2, 5, 5, 0, 3, 4, 6, 5, 1, 6, 3, 0, 4, 6, 8, 6,
144];
145
146/// Implements a system connected to a W65C02S's bus. Only `read` and `write`
147/// need be implemented for a simple system, but other systems may be more
148/// complicated; for instance, many 65C02-based microcontrollers have advanced
149/// interrupt vectoring logic that would require implementing `read_vector`.
150pub trait System {
151    /// Read an instruction opcode from the given address. VPB, MLB, and SYNC
152    /// are all HIGH.
153    fn read_opcode(&mut self, cpu: &mut W65C02S, addr: u16) -> u8 { self.read(cpu, addr) }
154    /// Read a byte of data from the given address. SYNC is LOW and VPB and MLB
155    /// are HIGH.
156    fn read(&mut self, cpu: &mut W65C02S, addr: u16) -> u8;
157    /// Read data from the given address as part of a Read-Modify-Write
158    /// instruction. SYNC and MLB are LOW, VPB is HIGH.
159    fn read_locked(&mut self, cpu: &mut W65C02S, addr: u16) -> u8 { self.read(cpu, addr) }
160    /// Second data read from the given address as part of a Read-Modify-Write
161    /// instruction. This data is ignored; this is an "idle cycle". SYNC and
162    /// MLB are LOW, VPB is HIGH. Indistinguishable from a locked data read on
163    /// real hardware, but the distinction may be useful for simulation.
164    fn read_locked_spurious(&mut self, cpu: &mut W65C02S, addr: u16) { self.read_locked(cpu, addr); }
165    /// Read part of an interrupt vector from the given address. VPB is LOW,
166    /// and SYNC and MLB are HIGH.
167    fn read_vector(&mut self, cpu: &mut W65C02S, addr: u16) -> u8 { self.read(cpu, addr) }
168    /// Write a byte of data to the given address. SYNC is LOW and VPB and MLB
169    /// are HIGH.
170    fn write(&mut self, cpu: &mut W65C02S, addr: u16, data: u8);
171    /// Push a byte of data onto the stack at the given address. SYNC is LOW
172    /// and VPB and MLB are HIGH. Indistinguishable from a normal data write
173    /// on real hardware, but the distinction may be useful for simulation.
174    fn write_stack(&mut self, cpu: &mut W65C02S, addr: u16, data: u8) { self.write(cpu, addr, data) }
175    /// Write a byte of data to the given address as the conclusion of a Read-
176    /// Modify-Write instruction. SYNC and MLB are LOW, VPB is HIGH.
177    fn write_locked(&mut self, cpu: &mut W65C02S, addr: u16, data: u8) { self.write(cpu, addr, data) }
178    /// Read an instruction opcode whose execution will be preempted by an
179    /// interrupt or a reset, or which follows a WAI or STP instruction that
180    /// has not yet been broken out of. VPB, MLB, and SYNC are all HIGH.
181    /// Indistinguishable from a normal opcode fetch on real hardware, but
182    /// the distinction may be useful for simulation.
183    fn read_opcode_spurious(&mut self, cpu: &mut W65C02S, addr: u16) { self.read_opcode(cpu, addr); }
184    /// Read an instruction operand from the given address. SYNC is LOW and VPB
185    /// and MLB are HIGH. Indistinguishable from an ordinary data read on real
186    /// hardware, but the distinction may be useful for simulation.
187    fn read_operand(&mut self, cpu: &mut W65C02S, addr: u16) -> u8 { self.read(cpu, addr) }
188    /// Read an instruction operand from the given address, except that the
189    /// instruction had an implied operand or was preempted by a reset. SYNC
190    /// is LOW and VPB and MLB are HIGH. Indistinguishable from an ordinary
191    /// data read on real hardware, but the distinction may be useful for
192    /// simulation.
193    fn read_operand_spurious(&mut self, cpu: &mut W65C02S, addr: u16) { self.read(cpu, addr); }
194    /// Read part of a pointer from the given address. SYNC is LOW and VPB and
195    /// MLB are HIGH. Indistinguishable from an ordinary data read on real
196    /// hardware, but the distinction may be useful for simulation.
197    fn read_pointer(&mut self, cpu: &mut W65C02S, addr: u16) -> u8 { self.read(cpu, addr) }
198    /// Pop a value from the stack at the given address. SYNC is LOW and VPB
199    /// and MLB are HIGH. Indistinguishable from an ordinary data read on real
200    /// hardware, but the distinction may be useful for simulation.
201    fn read_stack(&mut self, cpu: &mut W65C02S, addr: u16) -> u8 { self.read(cpu, addr) }
202    /// Spurious stack "read" that occurs during reset. SYNC is LOW and VPB
203    /// and MLB are HIGH. Indistinguishable from an ordinary data read on real
204    /// hardware, but the distinction may be useful for simulation.
205    fn read_stack_spurious(&mut self, cpu: &mut W65C02S, addr: u16) { self.read_stack(cpu, addr); }
206    /// Read a byte of data from the given address during an "internal
207    /// operation" cycle. SYNC is LOW and VPB and MLB are HIGH.
208    /// Indistinguishable from an ordinary data read on real hardware, but the
209    /// distinction may be useful for simulation.
210    fn read_spurious(&mut self, cpu: &mut W65C02S, addr: u16) { self.read(cpu, addr); }
211}
212
213/// Status register flag corresponding to the **C**arry bit.
214pub const P_C: u8 = 0x01;
215/// Status register flag corresponding to the **Z**ero bit.
216pub const P_Z: u8 = 0x02;
217/// Status register flag corresponding to the **I**nterrupt mask bit.
218pub const P_I: u8 = 0x04;
219/// Status register flag corresponding to the **D**ecimal mode bit.
220pub const P_D: u8 = 0x08;
221/// Status register flag corresponding to the **B**reak bit.
222pub const P_B: u8 = 0x10;
223/// Status register flag that is hardwired to 1, in spite of what the datasheet
224/// says.
225pub const P_1: u8 = 0x20;
226/// Status register flag corresponding to the o**V**erflow bit.
227pub const P_V: u8 = 0x40;
228/// Status register flag corresponding to the **N**egative bit.
229pub const P_N: u8 = 0x80;
230
231/// Address of the IRQ/BRK interrupt vector.
232pub const IRQ_VECTOR: u16 = 0xfffe;
233/// Address of the Reset interrupt vector.
234pub const RESET_VECTOR: u16 = 0xfffc;
235/// Address of the NMI interrupt vector.
236pub const NMI_VECTOR: u16 = 0xfffa;
237
238/// The CPU is in one of the given states between `step`s.
239#[derive(Clone,Copy,Debug,PartialEq,Eq)]
240pub enum State {
241    /// The CPU has just been reset. It will execute the reset sequence at the
242    /// next step. RDY is HIGH.
243    HasBeenReset,
244    /// The CPU is in its normal operating state. It will fetch an instruction
245    /// at the next step, and possibly handle an interrupt. RDY is HIGH.
246    Running,
247    /// The CPU has executed a `WAI` instruction and has not yet detected an
248    /// interrupt. RDY is LOW.
249    AwaitingInterrupt,
250    /// The CPU has executed a `STP` instruction. Only a reset will return it
251    /// to an executing state. RDY is LOW.
252    Stopped,
253}
254
255/// An instance of a W65C02S, encapsulating the entire runtime state of the
256/// processor itself. Not very useful without a `System` to go with it.
257#[derive(Copy,Clone,Debug,PartialEq,Eq)]
258pub struct W65C02S {
259    state: State, pc: u16,
260    a: u8, x: u8, y: u8, s: u8, p: u8,
261    irq: bool, irq_pending: bool,
262    nmi: bool, nmi_edge: bool, nmi_pending: bool,
263}
264
265impl W65C02S {
266    /// Creates a new `W65C02S` instance, initialized in a newly-reset state.
267    /// (Unlike a real W65C02S, most registers will be in the all-ones state at
268    /// this point.)
269    pub fn new() -> W65C02S {
270        W65C02S {
271            state: State::HasBeenReset,
272            pc: 0xFFFF,
273            a: 0xFF,
274            x: 0xFF,
275            y: 0xFF,
276            s: 0xFF,
277            p: P_1|P_I,
278            irq: false, irq_pending: false,
279            nmi: false, nmi_edge: false, nmi_pending: false,
280        }
281    }
282    /// Resets the CPU. Execution will flounder for a few cycles, then fetch
283    /// the reset vector and "start over".
284    #[inline(always)]
285    pub fn reset(&mut self) {
286        self.state = State::HasBeenReset;
287        self.s = 0;
288        self.p = P_1|P_I;
289    }
290    /// Get the current value of the **P**rogram **C**ounter, i.e. the next
291    /// instruction that will (probably) be executed.
292    #[inline(always)]
293    pub fn get_pc(&self) -> u16 { self.pc }
294    /// Internal function. Get the current value of the **P**rogram
295    /// **C**ounter. Increment the underlying value by one *after* reading it.
296    #[inline(always)]
297    fn read_pc_postincrement(&mut self) -> u16 {
298        let ret = self.pc;
299        self.pc = self.pc.wrapping_add(1);
300        ret
301    }
302    /// Overwrite the current value of the **P**rogram **C**ounter.
303    #[inline(always)]
304    pub fn set_pc(&mut self, pc: u16) { self.pc = pc }
305    /// Get the current value of the **A**ccumulator.
306    #[inline(always)]
307    pub fn get_a(&self) -> u8 { self.a }
308    /// Overwrite the current value of the **A**ccumulator.
309    #[inline(always)]
310    pub fn set_a(&mut self, a: u8) { self.a = a }
311    /// Get the current value of index register **X**.
312    #[inline(always)]
313    pub fn get_x(&self) -> u8 { self.x }
314    /// Overwrite the current value of index register **X**.
315    #[inline(always)]
316    pub fn set_x(&mut self, x: u8) { self.x = x }
317    /// Get the current value of index register **Y**.
318    #[inline(always)]
319    pub fn get_y(&self) -> u8 { self.y }
320    /// Overwrite the current value of index register **Y**.
321    #[inline(always)]
322    pub fn set_y(&mut self, y: u8) { self.y = y }
323    /// Get the current value of the **S**tack pointer. The next byte pushed
324    /// onto the stack will go into address `$01xx` where `xx` is this value.
325    #[inline(always)]
326    pub fn get_s(&self) -> u8 { self.s }
327    /// Overwrite the current value of the **S**tack pointer.
328    #[inline(always)]
329    pub fn set_s(&mut self, s: u8) { self.s = s }
330    /// Get the current value of the **P**rocessor status register. Use the
331    /// `P_*` constants to interpret the value.
332    #[inline(always)]
333    pub fn get_p(&self) -> u8 { self.p }
334    /// Overwrite the current value of the **P**rocessor status register.
335    /// Can't be used to change the hardwired 1 bit. You can use this to
336    /// implement SOB logic; when the SOB pin should transition to active, do
337    /// something like:
338    ///
339    /// ```rust
340    /// # use w65c02s::*;
341    /// # let mut cpu = W65C02S::new();
342    /// cpu.set_p(cpu.get_p() | P_V);
343    /// ```
344    #[inline(always)]
345    pub fn set_p(&mut self, p: u8) { self.p = p | P_1 }
346    /// Get the current operating state of the CPU. May return a stale value if
347    /// called during a `step`.
348    #[inline(always)]
349    pub fn get_state(&self) -> State { self.state }
350    /// Push a value onto the stack using the given `System`.
351    #[inline(always)]
352    pub fn push<S: System>(&mut self, system: &mut S, value: u8) {
353        system.write_stack(self, 0x100 | self.s as u16, value);
354        self.s = self.s.wrapping_sub(1);
355    }
356    /// Spurious push during reset.
357    #[inline(always)]
358    pub fn spurious_push<S: System>(&mut self, system: &mut S) {
359        // system.read_stack_spurious(self, 0x100 | self.s as u16);
360        self.s = self.s.wrapping_sub(1);
361    }
362    /// Pop a value from the stack using the given `System`.
363    #[inline(always)]
364    pub fn pop<S: System>(&mut self, system: &mut S) -> u8 {
365        self.s = self.s.wrapping_add(1);
366        system.read_stack(self, 0x100 | self.s as u16)
367    }
368    /// Spuriously read a value from the next stack slot, like happens during
369    /// a JSR or RTS or most pulls.
370    #[inline(always)]
371    pub fn spurious_stack_read<S: System>(&mut self, system: &mut S) {
372        // system.read_spurious(self, 0x100 | (self.s as u16));
373    }
374    /// Change the input on the `IRQB` pin. `false` means no interrupt pending.
375    /// `true` means some interrupt is pending. Note that `IRQB` is an active-
376    /// low pin and that the value you pass to this function is the *logical*
377    /// value and not the *electrical* one.
378    #[inline(always)]
379    pub fn set_irq(&mut self, irq: bool) { self.irq = irq }
380    /// Change the input on the NMIB pin. `false` means no NMI pending. A
381    /// transition from `false` to `true` triggers an NMI at the next `step`.
382    /// Note that `NMIB` is an active-low pin and that the value you pass to
383    /// this function is the *logical* value and not the *electrical* one.
384    ///
385    /// This crate does not accurately simulate extremely short NMI pulses, or
386    /// extremely rapid ones. If these conditions arise on real hardware, chaos
387    /// will ensue anyway.
388    #[inline(always)]
389    pub fn set_nmi(&mut self, nmi: bool) {
390        self.nmi_edge = self.nmi_edge || (!self.nmi_edge && nmi);
391        self.nmi = nmi;
392    }
393    /// Internal function. Updates the IRQ and NMI edge flags.
394    #[inline(always)]
395    fn check_irq_edge(&mut self) {
396        self.irq_pending = self.irq && (self.p & P_I) == 0;
397        self.nmi_pending = self.nmi_edge;
398    }
399    /// Set N and Z flags according to the argument value.
400    #[inline(always)]
401    fn nz_p(&mut self, v: u8) {
402        self.p = (self.p & 0x7F) | (v & 0x80);
403        if v == 0 { self.p |= P_Z; }
404        else { self.p &= !P_Z; }
405    }
406    /// Set N and Z flags according to the argument value, and the C flag
407    /// according to the argument.
408    #[inline(always)]
409    fn cnz_p(&mut self, c: bool, v: u8) {
410        self.p = (self.p & 0x7F) | (v & 0x80);
411        if v == 0 { self.p |= P_Z; }
412        else { self.p &= !P_Z; }
413        if c { self.p |= P_C; }
414        else { self.p &= !P_C; }
415    }
416    /// Step the processor once. This means executing an interrupt sequence,
417    /// fetching an instruction, or doing a spurious read, depending on the
418    /// current state of the processor. Returns the new state.
419    ///
420    /// Always executes at least one bus cycle. May execute more.
421    pub fn step<S: System>(&mut self, system: &mut S) -> i32 {
422        match self.state {
423            State::Stopped => /*system.read_operand_spurious(self, self.pc),*/return 1,
424            State::AwaitingInterrupt => {
425                if self.irq || self.nmi_edge {
426                    self.state = State::Running;
427                    // system.read_operand_spurious(self, self.pc);
428                }
429                self.check_irq_edge();
430                // system.read_operand_spurious(self, self.pc);
431
432                return 2;
433            },
434            State::HasBeenReset => {
435                // first, we spuriously read an opcode
436                // system.read_opcode_spurious(self, self.pc);
437                // second, we read ... the same byte, but with SYNC low
438                // system.read_operand_spurious(self, self.pc);
439                // three spurious pushes...
440                self.spurious_push(system);
441                self.spurious_push(system);
442                self.spurious_push(system);
443                // clear the D flag, set the I flag
444                self.p &= !P_D;
445                self.p |= P_I;
446                // read the reset vector, non-spuriously
447                self.pc = (self.pc & 0xFF00) | (system.read_vector(self, RESET_VECTOR) as u16);
448                self.pc = (self.pc & 0x00FF) | (system.read_vector(self, RESET_VECTOR+1) as u16) << 8;
449                // we are ready to be actually running!
450                self.state = State::Running;
451
452                return 7
453            },
454            State::Running => {
455                if self.nmi_pending {
456                    self.nmi_pending = false;
457                    self.nmi_edge = false;
458                    let opcode_addr = self.get_pc();
459                    // system.read_opcode_spurious(self, opcode_addr);
460                    // system.read_spurious(self, opcode_addr);
461                    self.push(system, (opcode_addr >> 8) as u8);
462                    self.push(system, opcode_addr as u8);
463                    self.push(system, self.p & !P_B);
464                    self.p &= !P_D;
465                    self.p |= P_I;
466                    self.pc = (self.pc & 0xFF00) | (system.read_vector(self, NMI_VECTOR) as u16);
467                    self.pc = (self.pc & 0x00FF) | (system.read_vector(self, NMI_VECTOR+1) as u16) << 8;
468                    return 7
469                }
470                else if self.irq_pending {
471                    self.irq_pending = false;
472                    let opcode_addr = self.get_pc();
473                    // system.read_opcode_spurious(self, opcode_addr);
474                    // system.read_spurious(self, opcode_addr);
475                    self.push(system, (opcode_addr >> 8) as u8);
476                    self.push(system, opcode_addr as u8);
477                    self.push(system, self.p);
478                    self.p &= !P_D;
479                    self.p |= P_I;
480                    self.pc = (self.pc & 0xFF00) | (system.read_vector(self, IRQ_VECTOR) as u16);
481                    self.pc = (self.pc & 0x00FF) | (system.read_vector(self, IRQ_VECTOR+1) as u16) << 8;
482                    return 7
483                }
484                else {
485                    // oh boy, we're running! oh boy oh boy!
486                    let opcode_addr = self.read_pc_postincrement();
487                    let opcode = system.read_opcode(self, opcode_addr);
488                    // oh boy OH JEEZ
489                    match opcode {
490                        0x00 => self.brk(system),
491                        0x01 => self.ora::<_, ZeroPageXIndirect, S>(system),
492                        0x02 => self.nop::<_, Immediate, S>(system),
493                        0x03 => self.nop::<_, FastImplied, S>(system),
494                        0x04 => self.tsb::<_, ZeroPage, S>(system),
495                        0x05 => self.ora::<_, ZeroPage, S>(system),
496                        0x06 => self.asl::<_, ZeroPage, S>(system),
497                        0x07 => self.rmb::<_, ZeroPage, S>(system, !0x01),
498                        0x08 => self.php(system),
499                        0x09 => self.ora::<_, Immediate, S>(system),
500                        0x0A => self.asl::<_, ImpliedA, S>(system),
501                        0x0B => self.nop::<_, FastImplied, S>(system),
502                        0x0C => self.tsb::<_, Absolute, S>(system),
503                        0x0D => self.ora::<_, Absolute, S>(system),
504                        0x0E => self.asl::<_, Absolute, S>(system),
505                        0x0F => self.bbr::<_, RelativeBitBranch, S>(system, 0x01),
506                        0x10 => self.branch::<_, Relative, S>(system, self.p & P_N == 0),
507                        0x11 => self.ora::<_, ZeroPageIndirectY, S>(system),
508                        0x12 => self.ora::<_, ZeroPageIndirect, S>(system),
509                        0x13 => self.nop::<_, FastImplied, S>(system),
510                        0x14 => self.trb::<_, ZeroPage, S>(system),
511                        0x15 => self.ora::<_, ZeroPageX, S>(system),
512                        0x16 => self.asl::<_, ZeroPageX, S>(system),
513                        0x17 => self.rmb::<_, ZeroPage, S>(system, !0x02),
514                        0x18 => self.clc(system),
515                        0x19 => self.ora::<_, AbsoluteY, S>(system),
516                        0x1A => self.inc::<_, ImpliedA, S>(system),
517                        0x1B => self.nop::<_, FastImplied, S>(system),
518                        0x1C => self.trb::<_, Absolute, S>(system),
519                        0x1D => self.ora::<_, AbsoluteX, S>(system),
520                        0x1E => self.asl::<_, AbsoluteX, S>(system),
521                        0x1F => self.bbr::<_, RelativeBitBranch, S>(system, 0x02),
522                        0x20 => self.jsr(system),
523                        0x21 => self.and::<_, ZeroPageXIndirect, S>(system),
524                        0x22 => self.nop::<_, Immediate, S>(system),
525                        0x23 => self.nop::<_, FastImplied, S>(system),
526                        0x24 => self.bit::<_, ZeroPage, S>(system),
527                        0x25 => self.and::<_, ZeroPage, S>(system),
528                        0x26 => self.rol::<_, ZeroPage, S>(system),
529                        0x27 => self.rmb::<_, ZeroPage, S>(system, !0x04),
530                        0x28 => self.plp(system),
531                        0x29 => self.and::<_, Immediate, S>(system),
532                        0x2A => self.rol::<_, ImpliedA, S>(system),
533                        0x2B => self.nop::<_, FastImplied, S>(system),
534                        0x2C => self.bit::<_, Absolute, S>(system),
535                        0x2D => self.and::<_, Absolute, S>(system),
536                        0x2E => self.rol::<_, Absolute, S>(system),
537                        0x2F => self.bbr::<_, RelativeBitBranch, S>(system, 0x04),
538                        0x30 => self.branch::<_, Relative, S>(system, self.p & P_N == P_N),
539                        0x31 => self.and::<_, ZeroPageIndirectY, S>(system),
540                        0x32 => self.and::<_, ZeroPageIndirect, S>(system),
541                        0x33 => self.nop::<_, FastImplied, S>(system),
542                        0x34 => self.bit::<_, ZeroPageX, S>(system),
543                        0x35 => self.and::<_, ZeroPageX, S>(system),
544                        0x36 => self.rol::<_, ZeroPageX, S>(system),
545                        0x37 => self.rmb::<_, ZeroPage, S>(system, !0x08),
546                        0x38 => self.sec(system),
547                        0x39 => self.and::<_, AbsoluteY, S>(system),
548                        0x3A => self.dec::<_, ImpliedA, S>(system),
549                        0x3B => self.nop::<_, FastImplied, S>(system),
550                        0x3C => self.bit::<_, AbsoluteX, S>(system),
551                        0x3D => self.and::<_, AbsoluteX, S>(system),
552                        0x3E => self.rol::<_, AbsoluteX, S>(system),
553                        0x3F => self.bbr::<_, RelativeBitBranch, S>(system, 0x08),
554                        0x40 => self.rti(system),
555                        0x41 => self.eor::<_, ZeroPageXIndirect, S>(system),
556                        0x42 => self.nop::<_, Immediate, S>(system),
557                        0x43 => self.nop::<_, FastImplied, S>(system),
558                        0x44 => self.nop::<_, ZeroPage, S>(system),
559                        0x45 => self.eor::<_, ZeroPage, S>(system),
560                        0x46 => self.lsr::<_, ZeroPage, S>(system),
561                        0x47 => self.rmb::<_, ZeroPage, S>(system, !0x10),
562                        0x48 => self.pha(system),
563                        0x49 => self.eor::<_, Immediate, S>(system),
564                        0x4A => self.lsr::<_, ImpliedA, S>(system),
565                        0x4B => self.nop::<_, FastImplied, S>(system),
566                        0x4C => self.jmp::<_, Absolute, S>(system),
567                        0x4D => self.eor::<_, Absolute, S>(system),
568                        0x4E => self.lsr::<_, Absolute, S>(system),
569                        0x4F => self.bbr::<_, RelativeBitBranch, S>(system, 0x10),
570                        0x50 => self.branch::<_, Relative, S>(system, self.p & P_V == 0),
571                        0x51 => self.eor::<_, ZeroPageIndirectY, S>(system),
572                        0x52 => self.eor::<_, ZeroPageIndirect, S>(system),
573                        0x53 => self.nop::<_, FastImplied, S>(system),
574                        0x54 => self.nop::<_, ZeroPageX, S>(system),
575                        0x55 => self.eor::<_, ZeroPageX, S>(system),
576                        0x56 => self.lsr::<_, ZeroPageX, S>(system),
577                        0x57 => self.rmb::<_, ZeroPage, S>(system, !0x20),
578                        0x58 => self.cli(system),
579                        0x59 => self.eor::<_, AbsoluteY, S>(system),
580                        0x5A => self.phy(system),
581                        0x5B => self.nop::<_, FastImplied, S>(system),
582                        0x5C => self.nop_5c::<_, Absolute, S>(system),
583                        0x5D => self.eor::<_, AbsoluteX, S>(system),
584                        0x5E => self.lsr::<_, AbsoluteX, S>(system),
585                        0x5F => self.bbr::<_, RelativeBitBranch, S>(system, 0x20),
586                        0x60 => self.rts(system),
587                        0x61 => self.adc::<_, ZeroPageXIndirect, S>(system),
588                        0x62 => self.nop::<_, Immediate, S>(system),
589                        0x63 => self.nop::<_, FastImplied, S>(system),
590                        0x64 => self.stz::<_, ZeroPage, S>(system),
591                        0x65 => self.adc::<_, ZeroPage, S>(system),
592                        0x66 => self.ror::<_, ZeroPage, S>(system),
593                        0x67 => self.rmb::<_, ZeroPage, S>(system, !0x40),
594                        0x68 => self.pla(system),
595                        0x69 => self.adc::<_, Immediate, S>(system),
596                        0x6A => self.ror::<_, ImpliedA, S>(system),
597                        0x6B => self.nop::<_, FastImplied, S>(system),
598                        0x6C => self.jmp::<_, AbsoluteIndirect, S>(system),
599                        0x6D => self.adc::<_, Absolute, S>(system),
600                        0x6E => self.ror::<_, Absolute, S>(system),
601                        0x6F => self.bbr::<_, RelativeBitBranch, S>(system, 0x40),
602                        0x70 => self.branch::<_, Relative, S>(system, self.p & P_V == P_V),
603                        0x71 => self.adc::<_, ZeroPageIndirectY, S>(system),
604                        0x72 => self.adc::<_, ZeroPageIndirect, S>(system),
605                        0x73 => self.nop::<_, FastImplied, S>(system),
606                        0x74 => self.stz::<_, ZeroPageX, S>(system),
607                        0x75 => self.adc::<_, ZeroPageX, S>(system),
608                        0x76 => self.ror::<_, ZeroPageX, S>(system),
609                        0x77 => self.rmb::<_, ZeroPage, S>(system, !0x80),
610                        0x78 => self.sei(system),
611                        0x79 => self.adc::<_, AbsoluteY, S>(system),
612                        0x7A => self.ply(system),
613                        0x7B => self.nop::<_, FastImplied, S>(system),
614                        0x7C => self.jmp::<_, AbsoluteXIndirect, S>(system),
615                        0x7D => self.adc::<_, AbsoluteX, S>(system),
616                        0x7E => self.ror::<_, AbsoluteX, S>(system),
617                        0x7F => self.bbr::<_, RelativeBitBranch, S>(system, 0x80),
618                        0x80 => self.branch::<_, Relative, S>(system, true),
619                        0x81 => self.sta::<_, ZeroPageXIndirect, S>(system),
620                        0x82 => self.nop::<_, Immediate, S>(system),
621                        0x83 => self.nop::<_, FastImplied, S>(system),
622                        0x84 => self.sty::<_, ZeroPage, S>(system),
623                        0x85 => self.sta::<_, ZeroPage, S>(system),
624                        0x86 => self.stx::<_, ZeroPage, S>(system),
625                        0x87 => self.smb::<_, ZeroPage, S>(system, 0x01),
626                        0x88 => self.dec::<_, ImpliedY, S>(system),
627                        0x89 => self.bit_i::<_, Immediate, S>(system),
628                        0x8A => self.txa(system),
629                        0x8B => self.nop::<_, FastImplied, S>(system),
630                        0x8C => self.sty::<_, Absolute, S>(system),
631                        0x8D => self.sta::<_, Absolute, S>(system),
632                        0x8E => self.stx::<_, Absolute, S>(system),
633                        0x8F => self.bbs::<_, RelativeBitBranch, S>(system, 0x01),
634                        0x90 => self.branch::<_, Relative, S>(system, self.p & P_C == 0),
635                        0x91 => self.sta::<_, ZeroPageIndirectYSlower, S>(system),
636                        0x92 => self.sta::<_, ZeroPageIndirect, S>(system),
637                        0x93 => self.nop::<_, FastImplied, S>(system),
638                        0x94 => self.sty::<_, ZeroPageX, S>(system),
639                        0x95 => self.sta::<_, ZeroPageX, S>(system),
640                        0x96 => self.stx::<_, ZeroPageY, S>(system),
641                        0x97 => self.smb::<_, ZeroPage, S>(system, 0x02),
642                        0x98 => self.tya(system),
643                        0x99 => self.sta::<_, AbsoluteYSlower, S>(system),
644                        0x9A => self.txs(system),
645                        0x9B => self.nop::<_, FastImplied, S>(system),
646                        0x9C => self.stz::<_, Absolute, S>(system),
647                        0x9D => self.sta::<_, AbsoluteXSlower, S>(system),
648                        0x9E => self.stz::<_, AbsoluteXSlower, S>(system),
649                        0x9F => self.bbs::<_, RelativeBitBranch, S>(system, 0x02),
650                        0xA0 => self.ldy::<_, Immediate, S>(system),
651                        0xA1 => self.lda::<_, ZeroPageXIndirect, S>(system),
652                        0xA2 => self.ldx::<_, Immediate, S>(system),
653                        0xA3 => self.nop::<_, FastImplied, S>(system),
654                        0xA4 => self.ldy::<_, ZeroPage, S>(system),
655                        0xA5 => self.lda::<_, ZeroPage, S>(system),
656                        0xA6 => self.ldx::<_, ZeroPage, S>(system),
657                        0xA7 => self.smb::<_, ZeroPage, S>(system, 0x04),
658                        0xA8 => self.tay(system),
659                        0xA9 => self.lda::<_, Immediate, S>(system),
660                        0xAA => self.tax(system),
661                        0xAB => self.nop::<_, FastImplied, S>(system),
662                        0xAC => self.ldy::<_, Absolute, S>(system),
663                        0xAD => self.lda::<_, Absolute, S>(system),
664                        0xAE => self.ldx::<_, Absolute, S>(system),
665                        0xAF => self.bbs::<_, RelativeBitBranch, S>(system, 0x04),
666                        0xB0 => self.branch::<_, Relative, S>(system, self.p & P_C == P_C),
667                        0xB1 => self.lda::<_, ZeroPageIndirectY, S>(system),
668                        0xB2 => self.lda::<_, ZeroPageIndirect, S>(system),
669                        0xB3 => self.nop::<_, FastImplied, S>(system),
670                        0xB4 => self.ldy::<_, ZeroPageX, S>(system),
671                        0xB5 => self.lda::<_, ZeroPageX, S>(system),
672                        0xB6 => self.ldx::<_, ZeroPageY, S>(system),
673                        0xB7 => self.smb::<_, ZeroPage, S>(system, 0x08),
674                        0xB8 => self.clv(system),
675                        0xB9 => self.lda::<_, AbsoluteY, S>(system),
676                        0xBA => self.tsx(system),
677                        0xBB => self.nop::<_, FastImplied, S>(system),
678                        0xBC => self.ldy::<_, AbsoluteX, S>(system),
679                        0xBD => self.lda::<_, AbsoluteX, S>(system),
680                        0xBE => self.ldx::<_, AbsoluteY, S>(system),
681                        0xBF => self.bbs::<_, RelativeBitBranch, S>(system, 0x08),
682                        0xC0 => self.cpy::<_, Immediate, S>(system),
683                        0xC1 => self.cmp::<_, ZeroPageXIndirect, S>(system),
684                        0xC2 => self.nop::<_, Immediate, S>(system),
685                        0xC3 => self.nop::<_, FastImplied, S>(system),
686                        0xC4 => self.cpy::<_, ZeroPage, S>(system),
687                        0xC5 => self.cmp::<_, ZeroPage, S>(system),
688                        0xC6 => self.dec::<_, ZeroPage, S>(system),
689                        0xC7 => self.smb::<_, ZeroPage, S>(system, 0x10),
690                        0xC8 => self.inc::<_, ImpliedY, S>(system),
691                        0xC9 => self.cmp::<_, Immediate, S>(system),
692                        0xCA => self.dec::<_, ImpliedX, S>(system),
693                        0xCB => self.wai(system),
694                        0xCC => self.cpy::<_, Absolute, S>(system),
695                        0xCD => self.cmp::<_, Absolute, S>(system),
696                        0xCE => self.dec::<_, Absolute, S>(system),
697                        0xCF => self.bbs::<_, RelativeBitBranch, S>(system, 0x10),
698                        0xD0 => self.branch::<_, Relative, S>(system, self.p & P_Z == 0),
699                        0xD1 => self.cmp::<_, ZeroPageIndirectY, S>(system),
700                        0xD2 => self.cmp::<_, ZeroPageIndirect, S>(system),
701                        0xD3 => self.nop::<_, FastImplied, S>(system),
702                        0xD4 => self.nop::<_, ZeroPageX, S>(system),
703                        0xD5 => self.cmp::<_, ZeroPageX, S>(system),
704                        0xD6 => self.dec::<_, ZeroPageX, S>(system),
705                        0xD7 => self.smb::<_, ZeroPage, S>(system, 0x20),
706                        0xD8 => self.cld(system),
707                        0xD9 => self.cmp::<_, AbsoluteY, S>(system),
708                        0xDA => self.phx(system),
709                        0xDB => self.stp(system),
710                        0xDC => self.nop::<_, Absolute, S>(system),
711                        0xDD => self.cmp::<_, AbsoluteX, S>(system),
712                        0xDE => self.dec::<_, AbsoluteXSlower, S>(system),
713                        0xDF => self.bbs::<_, RelativeBitBranch, S>(system, 0x20),
714                        0xE0 => self.cpx::<_, Immediate, S>(system),
715                        0xE1 => self.sbc::<_, ZeroPageXIndirect, S>(system),
716                        0xE2 => self.nop::<_, Immediate, S>(system),
717                        0xE3 => self.nop::<_, FastImplied, S>(system),
718                        0xE4 => self.cpx::<_, ZeroPage, S>(system),
719                        0xE5 => self.sbc::<_, ZeroPage, S>(system),
720                        0xE6 => self.inc::<_, ZeroPage, S>(system),
721                        0xE7 => self.smb::<_, ZeroPage, S>(system, 0x40),
722                        0xE8 => self.inc::<_, ImpliedX, S>(system),
723                        0xE9 => self.sbc::<_, Immediate, S>(system),
724                        0xEA => self.nop::<_, Implied, S>(system),
725                        0xEB => self.nop::<_, FastImplied, S>(system),
726                        0xEC => self.cpx::<_, Absolute, S>(system),
727                        0xED => self.sbc::<_, Absolute, S>(system),
728                        0xEE => self.inc::<_, Absolute, S>(system),
729                        0xEF => self.bbs::<_, RelativeBitBranch, S>(system, 0x40),
730                        0xF0 => self.branch::<_, Relative, S>(system, self.p & P_Z == P_Z),
731                        0xF1 => self.sbc::<_, ZeroPageIndirectY, S>(system),
732                        0xF2 => self.sbc::<_, ZeroPageIndirect, S>(system),
733                        0xF3 => self.nop::<_, FastImplied, S>(system),
734                        0xF4 => self.nop::<_, ZeroPageX, S>(system),
735                        0xF5 => self.sbc::<_, ZeroPageX, S>(system),
736                        0xF6 => self.inc::<_, ZeroPageX, S>(system),
737                        0xF7 => self.smb::<_, ZeroPage, S>(system, 0x80),
738                        0xF8 => self.sed(system),
739                        0xF9 => self.sbc::<_, AbsoluteY, S>(system),
740                        0xFA => self.plx(system),
741                        0xFB => self.nop::<_, FastImplied, S>(system),
742                        0xFC => self.nop::<_, Absolute, S>(system),
743                        0xFD => self.sbc::<_, AbsoluteX, S>(system),
744                        0xFE => self.inc::<_, AbsoluteXSlower, S>(system),
745                        0xFF => self.bbs::<_, RelativeBitBranch, S>(system, 0x80),
746                    }
747
748                    return OPCODE_CYCLES[opcode as usize];
749                }
750            },
751        }
752        1
753    }
754}
755