nmos_6502/
lib.rs

1#![no_std]
2
3pub struct CentralProcessingUnit {
4    pub a: u8,
5    pub x: u8,
6    pub y: u8,
7    pub sp: u8,
8    pub pc: u16,
9    pub status: u8,
10    pub memory: [u8; 0x10000],
11}
12
13// Initialization
14#[allow(clippy::new_without_default)]
15impl CentralProcessingUnit {
16    pub const fn new() -> Self {
17        static ZEROED_MEMORY: [u8; 0x10000] = [0; 0x10000];
18
19        Self {
20            a: 0,
21            x: 0,
22            y: 0,
23            sp: 0xFD,
24            pc: 0,
25            status: Self::STATUS_FLAG_U | Self::STATUS_FLAG_I,
26            memory: ZEROED_MEMORY,
27        }
28    }
29
30    pub const fn new_with_memory(memory: [u8; 0x10000]) -> Self {
31        Self {
32            a: 0,
33            x: 0,
34            y: 0,
35            sp: 0xFD,
36            pc: ((memory[0xFFFD] as u16) << 8) | (memory[0xFFFC] as u16),
37            status: Self::STATUS_FLAG_U | Self::STATUS_FLAG_I,
38            memory,
39        }
40    }
41
42    pub const fn reset(&mut self) {
43        self.a = 0;
44        self.x = 0;
45        self.y = 0;
46        self.sp = 0xFD;
47        self.pc = self.read_word(0xFFFC);
48        self.status = Self::STATUS_FLAG_U | Self::STATUS_FLAG_I;
49    }
50}
51
52// Memory & Stack
53impl CentralProcessingUnit {
54    #[inline(always)]
55    const fn read_byte(&self, addr: u16) -> u8 {
56        self.memory[addr as usize]
57    }
58
59    #[inline(always)]
60    const fn write_byte(&mut self, addr: u16, value: u8) {
61        self.memory[addr as usize] = value;
62    }
63
64    #[inline(always)]
65    const fn read_word(&self, addr: u16) -> u16 {
66        ((self.read_byte(addr.wrapping_add(1)) as u16) << 8) | (self.read_byte(addr) as u16)
67    }
68
69    #[inline(always)]
70    const fn push(&mut self, value: u8) {
71        self.write_byte(0x0100 + self.sp as u16, value);
72        self.sp = self.sp.wrapping_sub(1);
73    }
74
75    #[inline(always)]
76    const fn pop(&mut self) -> u8 {
77        self.sp = self.sp.wrapping_add(1);
78        self.read_byte(0x0100 + self.sp as u16)
79    }
80}
81
82// Status Flags
83impl CentralProcessingUnit {
84    const STATUS_FLAG_C: u8 = 1 << 0;
85    const STATUS_FLAG_Z: u8 = 1 << 1;
86    const STATUS_FLAG_I: u8 = 1 << 2;
87    const STATUS_FLAG_D: u8 = 1 << 3;
88    const STATUS_FLAG_B: u8 = 1 << 4;
89    const STATUS_FLAG_U: u8 = 1 << 5;
90    const STATUS_FLAG_V: u8 = 1 << 6;
91    const STATUS_FLAG_N: u8 = 1 << 7;
92
93    #[inline(always)]
94    const fn set_flag(&mut self, flag: u8, state: bool) {
95        self.status ^= (self.status ^ (-(state as i8) as u8)) & flag;
96    }
97
98    #[inline(always)]
99    const fn get_flag(&self, flag: u8) -> bool {
100        self.status & flag != 0
101    }
102
103    #[inline(always)]
104    const fn update_zn(&mut self, result: u8) {
105        self.status ^= (self.status
106            ^ ((-((result == 0) as i8) as u8) & Self::STATUS_FLAG_Z
107                | (-(((result & 0x80) != 0) as i8) as u8) & Self::STATUS_FLAG_N))
108            & (Self::STATUS_FLAG_Z | Self::STATUS_FLAG_N);
109    }
110}
111
112// Addressing Modes
113impl CentralProcessingUnit {
114    const fn immediate(&mut self) -> u16 {
115        let addr = self.pc;
116        self.pc = self.pc.wrapping_add(1);
117
118        addr
119    }
120
121    const fn zeropage(&mut self) -> u16 {
122        let addr = self.read_byte(self.pc) as u16;
123        self.pc = self.pc.wrapping_add(1);
124
125        addr
126    }
127
128    const fn zeropage_x(&mut self) -> u16 {
129        let addr = self.read_byte(self.pc);
130        self.pc = self.pc.wrapping_add(1);
131
132        addr.wrapping_add(self.x) as u16
133    }
134
135    const fn zeropage_y(&mut self) -> u16 {
136        let addr = self.read_byte(self.pc);
137        self.pc = self.pc.wrapping_add(1);
138
139        addr.wrapping_add(self.y) as u16
140    }
141
142    const fn absolute(&mut self) -> u16 {
143        let addr = self.read_word(self.pc);
144        self.pc = self.pc.wrapping_add(2);
145
146        addr
147    }
148
149    const fn absolute_x(&mut self) -> u16 {
150        let addr = self.read_word(self.pc);
151        self.pc = self.pc.wrapping_add(2);
152
153        addr.wrapping_add(self.x as u16)
154    }
155
156    const fn absolute_y(&mut self) -> u16 {
157        let addr = self.read_word(self.pc);
158        self.pc = self.pc.wrapping_add(2);
159
160        addr.wrapping_add(self.y as u16)
161    }
162
163    const fn indirect(&mut self) -> u16 {
164        let addr = self.read_word(self.pc);
165        self.pc = self.pc.wrapping_add(2);
166
167        // I believe this is the correct behavior for the 6502 hardware bug.
168        (self.read_byte((addr & 0xFF00) | ((addr.wrapping_add(1)) & 0xFF)) as u16) << 8
169            | (self.read_byte(addr) as u16)
170    }
171
172    const fn indexed_indirect(&mut self) -> u16 {
173        let addr = self.read_byte(self.pc).wrapping_add(self.x) as u16;
174        self.pc = self.pc.wrapping_add(1);
175
176        ((self.read_byte(addr.wrapping_add(1)) as u16) << 8) | (self.read_byte(addr) as u16)
177    }
178
179    const fn indirect_indexed(&mut self) -> u16 {
180        let addr = self.read_byte(self.pc) as u16;
181        self.pc = self.pc.wrapping_add(1);
182
183        (((self.read_byte(addr.wrapping_add(1)) as u16) << 8) | (self.read_byte(addr) as u16))
184            .wrapping_add(self.y as u16)
185    }
186}
187
188// Arithmetic & Logic Instructions
189impl CentralProcessingUnit {
190    const fn adc(&mut self, value: u8) {
191        let sum = self.a as u16 + value as u16 + (self.status & Self::STATUS_FLAG_C) as u16;
192        let mut result = sum as u8;
193
194        if self.get_flag(Self::STATUS_FLAG_D) {
195            result =
196                result.wrapping_add(((result & 0x0F) > 9) as u8 * 0x06 + (sum > 0x99) as u8 * 0x60);
197
198            self.set_flag(Self::STATUS_FLAG_C, sum > 0x99);
199            self.set_flag(Self::STATUS_FLAG_V, false);
200        } else {
201            self.set_flag(Self::STATUS_FLAG_C, sum > 0xFF);
202            self.set_flag(
203                Self::STATUS_FLAG_V,
204                (!(self.a ^ value) & (self.a ^ result) & 0x80) != 0,
205            );
206        }
207
208        self.a = result;
209        self.update_zn(result);
210    }
211
212    const fn sbc(&mut self, value: u8) {
213        let original_carry = self.get_flag(Self::STATUS_FLAG_C);
214        self.set_flag(Self::STATUS_FLAG_C, true);
215        self.adc(value ^ 0xFF);
216        if !original_carry {
217            let (result, _) = self.a.overflowing_sub(1);
218            self.a = result;
219            self.update_zn(result);
220        }
221    }
222
223    const fn ora(&mut self, value: u8) {
224        self.a |= value;
225        self.update_zn(self.a);
226    }
227
228    const fn and(&mut self, value: u8) {
229        self.a &= value;
230        self.update_zn(self.a);
231    }
232
233    const fn eor(&mut self, value: u8) {
234        self.a ^= value;
235        self.update_zn(self.a);
236    }
237
238    const fn cmp(&mut self, reg: u8, value: u8) {
239        let result = reg.wrapping_sub(value);
240        self.set_flag(Self::STATUS_FLAG_C, reg >= value);
241        self.update_zn(result);
242    }
243
244    const fn bit(&mut self, value: u8) {
245        self.set_flag(Self::STATUS_FLAG_Z, (self.a & value) == 0);
246        self.set_flag(Self::STATUS_FLAG_N, value & 0x80 != 0);
247        self.set_flag(Self::STATUS_FLAG_V, value & 0x40 != 0);
248    }
249
250    const fn inc(&mut self, addr: u16) {
251        let result = self.read_byte(addr).wrapping_add(1);
252        self.write_byte(addr, result);
253        self.update_zn(result);
254    }
255
256    const fn dec(&mut self, addr: u16) {
257        let result = self.read_byte(addr).wrapping_sub(1);
258        self.write_byte(addr, result);
259        self.update_zn(result);
260    }
261}
262
263// Shifts & Rotates
264impl CentralProcessingUnit {
265    const fn asl_acc(&mut self) {
266        self.set_flag(Self::STATUS_FLAG_C, self.a & 0x80 != 0);
267        self.a <<= 1;
268        self.update_zn(self.a);
269    }
270
271    const fn asl_mem(&mut self, addr: u16) {
272        let value = self.read_byte(addr);
273        self.set_flag(Self::STATUS_FLAG_C, value & 0x80 != 0);
274        let result = value << 1;
275        self.write_byte(addr, result);
276        self.update_zn(result);
277    }
278
279    const fn lsr_acc(&mut self) {
280        self.set_flag(Self::STATUS_FLAG_C, self.a & 0x01 != 0);
281        self.a >>= 1;
282        self.update_zn(self.a);
283    }
284
285    const fn lsr_mem(&mut self, addr: u16) {
286        let value = self.read_byte(addr);
287        self.set_flag(Self::STATUS_FLAG_C, value & 0x01 != 0);
288        let result = value >> 1;
289        self.write_byte(addr, result);
290        self.update_zn(result);
291    }
292
293    const fn rol_acc(&mut self) {
294        let old = self.a;
295        let new_carry = old & 0x80 != 0;
296        self.a = (old << 1)
297            | if self.get_flag(Self::STATUS_FLAG_C) {
298                1
299            } else {
300                0
301            };
302        self.set_flag(Self::STATUS_FLAG_C, new_carry);
303        self.update_zn(self.a);
304    }
305
306    const fn rol_mem(&mut self, addr: u16) {
307        let value = self.read_byte(addr);
308        let new_carry = value & 0x80 != 0;
309        let result = (value << 1)
310            | if self.get_flag(Self::STATUS_FLAG_C) {
311                1
312            } else {
313                0
314            };
315        self.write_byte(addr, result);
316        self.set_flag(Self::STATUS_FLAG_C, new_carry);
317        self.update_zn(result);
318    }
319
320    const fn ror_acc(&mut self) {
321        let old = self.a;
322        let old_carry = if self.get_flag(Self::STATUS_FLAG_C) {
323            0x80
324        } else {
325            0
326        };
327        let new_carry = old & 0x01 != 0;
328        let result = (old >> 1) | old_carry;
329        self.a = result;
330        self.set_flag(Self::STATUS_FLAG_C, new_carry);
331        self.update_zn(result);
332    }
333
334    const fn ror_mem(&mut self, addr: u16) {
335        let value = self.read_byte(addr);
336        let old_carry = if self.get_flag(Self::STATUS_FLAG_C) {
337            0x80
338        } else {
339            0
340        };
341        let new_carry = value & 0x01 != 0;
342        let result = (value >> 1) | old_carry;
343        self.write_byte(addr, result);
344        self.set_flag(Self::STATUS_FLAG_C, new_carry);
345        self.update_zn(result);
346    }
347}
348
349// Control Flow
350impl CentralProcessingUnit {
351    const fn branch(&mut self, condition: bool) {
352        let offset = self.read_byte(self.pc) as i8;
353        self.pc = self.pc.wrapping_add(1);
354        if condition {
355            self.pc = self.pc.wrapping_add(offset as u16);
356        }
357    }
358}
359
360// Execution
361impl CentralProcessingUnit {
362    /// Execute one 6502 instruction
363    ///
364    /// # Supported instructions
365    /// - **System:**        `BRK`, `RTI`, `RTS`  
366    /// - **Jump/Call:**     `JSR`, `JMP` (absolute & indirect)  
367    /// - **Branches:**      `BPL`, `BMI`, `BVC`, `BVS`, `BCC`, `BCS`, `BNE`, `BEQ`  
368    /// - **Flag ops:**      `CLC`, `SEC`, `CLI`, `SEI`, `CLV`, `CLD`, `SED`  
369    /// - **Logical:**       `ORA`, `AND`, `EOR`, `BIT`  
370    /// - **Arithmetic:**    `ADC`, `SBC`, `INC`, `INX`, `INY`, `DEC`, `DEX`, `DEY`  
371    /// - **Compare:**       `CMP`, `CPX`, `CPY`  
372    /// - **Data xfer:**     `LDA`, `LDX`, `LDY`, `STA`, `STX`, `STY`  
373    /// - **Reg xfer:**      `TAX`, `TAY`, `TXA`, `TYA`, `TSX`, `TXS`  
374    /// - **Stack ops:**     `PHA`, `PLA`, `PHP`, `PLP`  
375    /// - **Shifts/Rots:**   `ASL`, `LSR`, `ROL`, `ROR` (acc & mem)  
376    /// - **Misc:**          `NOP`  
377    ///
378    /// # Illegal Opcodes
379    /// Currently all illegal opcodes are treated as `NOP` (no operation).
380    #[inline(always)]
381    pub const fn step(&mut self) {
382        let opcode = self.read_byte(self.pc);
383        self.pc = self.pc.wrapping_add(1);
384
385        //TODO: sort into order as its currently by instr type
386        match opcode {
387            // BRK
388            0x00 => {
389                self.pc = self.pc.wrapping_add(1);
390                self.push((self.pc >> 8) as u8);
391                self.push((self.pc & 0xFF) as u8);
392                self.set_flag(Self::STATUS_FLAG_B, true);
393                self.push(self.status);
394                self.set_flag(Self::STATUS_FLAG_I, true);
395                self.pc = self.read_word(0xFFFE);
396            }
397
398            // RTI
399            0x40 => {
400                self.status = self.pop();
401                self.status &= !(Self::STATUS_FLAG_B | Self::STATUS_FLAG_I);
402                self.status |= Self::STATUS_FLAG_U;
403                let lo = self.pop() as u16;
404                let hi = self.pop() as u16;
405                self.pc = (hi << 8) | lo;
406            }
407
408            // RTS
409            0x60 => {
410                let lo = self.pop() as u16;
411                let hi = self.pop() as u16;
412                self.pc = ((hi << 8) | lo).wrapping_add(1);
413            }
414
415            // JSR
416            0x20 => {
417                let addr = self.read_word(self.pc);
418                self.pc = self.pc.wrapping_add(2);
419                let ret = self.pc.wrapping_sub(1);
420                self.push((ret >> 8) as u8);
421                self.push((ret & 0xFF) as u8);
422                self.pc = addr;
423            }
424
425            // JMP abs
426            0x4C => self.pc = self.absolute(),
427
428            // JMP ind
429            0x6C => self.pc = self.indirect(),
430
431            // BPL
432            0x10 => self.branch(!self.get_flag(Self::STATUS_FLAG_N)),
433
434            // BMI
435            0x30 => self.branch(self.get_flag(Self::STATUS_FLAG_N)),
436
437            // BVC
438            0x50 => self.branch(!self.get_flag(Self::STATUS_FLAG_V)),
439
440            // BVS
441            0x70 => self.branch(self.get_flag(Self::STATUS_FLAG_V)),
442
443            // BCC
444            0x90 => self.branch(!self.get_flag(Self::STATUS_FLAG_C)),
445
446            // BCS
447            0xB0 => self.branch(self.get_flag(Self::STATUS_FLAG_C)),
448
449            // BNE
450            0xD0 => self.branch(!self.get_flag(Self::STATUS_FLAG_Z)),
451
452            // BEQ
453            0xF0 => self.branch(self.get_flag(Self::STATUS_FLAG_Z)),
454
455            // CLC
456            0x18 => self.set_flag(Self::STATUS_FLAG_C, false),
457
458            // SEC
459            0x38 => self.set_flag(Self::STATUS_FLAG_C, true),
460
461            // CLI
462            0x58 => self.set_flag(Self::STATUS_FLAG_I, false),
463
464            // SEI
465            0x78 => self.set_flag(Self::STATUS_FLAG_I, true),
466
467            // CLV
468            0xB8 => self.set_flag(Self::STATUS_FLAG_V, false),
469
470            // CLD
471            0xD8 => self.set_flag(Self::STATUS_FLAG_D, false),
472
473            // SED
474            0xF8 => self.set_flag(Self::STATUS_FLAG_D, true),
475
476            // ORA #imm
477            0x09 => {
478                let addr = self.immediate();
479                let v = self.read_byte(addr);
480
481                self.ora(v)
482            }
483
484            // ORA zp
485            0x05 => {
486                let addr = self.zeropage();
487                let v = self.read_byte(addr);
488
489                self.ora(v)
490            }
491
492            // ORA zp,X
493            0x15 => {
494                let addr = self.zeropage_x();
495                let v = self.read_byte(addr);
496
497                self.ora(v)
498            }
499
500            // ORA abs
501            0x0D => {
502                let addr = self.absolute();
503                let v = self.read_byte(addr);
504
505                self.ora(v)
506            }
507
508            // ORA abs,X
509            0x1D => {
510                let addr = self.absolute_x();
511                let v = self.read_byte(addr);
512
513                self.ora(v)
514            }
515
516            // ORA abs,Y
517            0x19 => {
518                let addr = self.absolute_y();
519                let v = self.read_byte(addr);
520
521                self.ora(v)
522            }
523
524            // ORA (zp,X)
525            0x01 => {
526                let addr = self.indexed_indirect();
527                let v = self.read_byte(addr);
528                self.ora(v)
529            }
530
531            // ORA (zp),Y
532            0x11 => {
533                let addr = self.indirect_indexed();
534                let v = self.read_byte(addr);
535                self.ora(v)
536            }
537
538            // AND #imm
539            0x29 => {
540                let addr = self.immediate();
541                let v = self.read_byte(addr);
542                self.and(v)
543            }
544
545            // AND zp
546            0x25 => {
547                let addr = self.zeropage();
548                let v = self.read_byte(addr);
549                self.and(v)
550            }
551
552            // AND zp,X
553            0x35 => {
554                let addr = self.zeropage_x();
555                let v = self.read_byte(addr);
556                self.and(v)
557            }
558
559            // AND abs
560            0x2D => {
561                let addr = self.absolute();
562                let v = self.read_byte(addr);
563                self.and(v)
564            }
565
566            // AND abs,X
567            0x3D => {
568                let addr = self.absolute_x();
569                let v = self.read_byte(addr);
570                self.and(v)
571            }
572
573            // AND abs,Y
574            0x39 => {
575                let addr = self.absolute_y();
576                let v = self.read_byte(addr);
577                self.and(v)
578            }
579
580            // AND (zp,X)
581            0x21 => {
582                let addr = self.indexed_indirect();
583                let v = self.read_byte(addr);
584                self.and(v)
585            }
586
587            // AND (zp),Y
588            0x31 => {
589                let addr = self.indirect_indexed();
590                let v = self.read_byte(addr);
591                self.and(v)
592            }
593
594            // EOR #imm
595            0x49 => {
596                let addr = self.immediate();
597                let v = self.read_byte(addr);
598                self.eor(v)
599            }
600
601            // EOR zp
602            0x45 => {
603                let addr = self.zeropage();
604                let v = self.read_byte(addr);
605                self.eor(v)
606            }
607
608            // EOR zp,X
609            0x55 => {
610                let addr = self.zeropage_x();
611                let v = self.read_byte(addr);
612                self.eor(v)
613            }
614
615            // EOR abs
616            0x4D => {
617                let addr = self.absolute();
618                let v = self.read_byte(addr);
619                self.eor(v)
620            }
621
622            // EOR abs,X
623            0x5D => {
624                let addr = self.absolute_x();
625                let v = self.read_byte(addr);
626                self.eor(v)
627            }
628
629            // EOR abs,Y
630            0x59 => {
631                let addr = self.absolute_y();
632                let v = self.read_byte(addr);
633                self.eor(v)
634            }
635
636            // EOR (zp,X)
637            0x41 => {
638                let addr = self.indexed_indirect();
639                let v = self.read_byte(addr);
640                self.eor(v)
641            }
642
643            // EOR (zp),Y
644            0x51 => {
645                let addr = self.indirect_indexed();
646                let v = self.read_byte(addr);
647                self.eor(v)
648            }
649
650            // BIT zp
651            0x24 => {
652                let addr = self.zeropage();
653                let v = self.read_byte(addr);
654                self.bit(v)
655            }
656
657            // BIT abs
658            0x2C => {
659                let addr = self.absolute();
660                let v = self.read_byte(addr);
661                self.bit(v)
662            }
663
664            // ADC #imm
665            0x69 => {
666                let addr = self.immediate();
667                let v = self.read_byte(addr);
668                self.adc(v)
669            }
670
671            // ADC zp
672            0x65 => {
673                let addr = self.zeropage();
674                let v = self.read_byte(addr);
675                self.adc(v)
676            }
677
678            // ADC zp,X
679            0x75 => {
680                let addr = self.zeropage_x();
681                let v = self.read_byte(addr);
682                self.adc(v)
683            }
684
685            // ADC abs
686            0x6D => {
687                let addr = self.absolute();
688                let v = self.read_byte(addr);
689                self.adc(v)
690            }
691
692            // ADC abs,X
693            0x7D => {
694                let addr = self.absolute_x();
695                let v = self.read_byte(addr);
696                self.adc(v)
697            }
698
699            // ADC abs,Y
700            0x79 => {
701                let addr = self.absolute_y();
702                let v = self.read_byte(addr);
703                self.adc(v)
704            }
705
706            // ADC (zp,X)
707            0x61 => {
708                let addr = self.indexed_indirect();
709                let v = self.read_byte(addr);
710                self.adc(v)
711            }
712
713            // ADC (zp),Y
714            0x71 => {
715                let addr = self.indirect_indexed();
716                let v = self.read_byte(addr);
717                self.adc(v)
718            }
719
720            // SBC #imm
721            0xE9 => {
722                let addr = self.immediate();
723                let v = self.read_byte(addr);
724                self.sbc(v)
725            }
726
727            // SBC zp
728            0xE5 => {
729                let addr = self.zeropage();
730                let v = self.read_byte(addr);
731                self.sbc(v)
732            }
733
734            // SBC zp,X
735            0xF5 => {
736                let addr = self.zeropage_x();
737                let v = self.read_byte(addr);
738                self.sbc(v)
739            }
740
741            // SBC abs
742            0xED => {
743                let addr = self.absolute();
744                let v = self.read_byte(addr);
745                self.sbc(v)
746            }
747
748            // SBC abs,X
749            0xFD => {
750                let addr = self.absolute_x();
751                let v = self.read_byte(addr);
752                self.sbc(v)
753            }
754
755            // SBC abs,Y
756            0xF9 => {
757                let addr = self.absolute_y();
758                let v = self.read_byte(addr);
759                self.sbc(v)
760            }
761
762            // SBC (zp,X)
763            0xE1 => {
764                let addr = self.indexed_indirect();
765                let v = self.read_byte(addr);
766                self.sbc(v)
767            }
768
769            // SBC (zp),Y
770            0xF1 => {
771                let addr = self.indirect_indexed();
772                let v = self.read_byte(addr);
773                self.sbc(v)
774            }
775
776            // INC zp
777            0xE6 => {
778                let addr = self.zeropage();
779                self.inc(addr)
780            }
781
782            // INC zp,X
783            0xF6 => {
784                let addr = self.zeropage_x();
785                self.inc(addr)
786            }
787
788            // INC abs
789            0xEE => {
790                let addr = self.absolute();
791                self.inc(addr)
792            }
793
794            // INC abs,X
795            0xFE => {
796                let addr = self.absolute_x();
797                self.inc(addr)
798            }
799
800            // DEC zp
801            0xC6 => {
802                let addr = self.zeropage();
803                self.dec(addr)
804            }
805
806            // DEC zp,X
807            0xD6 => {
808                let addr = self.zeropage_x();
809                self.dec(addr)
810            }
811
812            // DEC abs
813            0xCE => {
814                let addr = self.absolute();
815                self.dec(addr)
816            }
817
818            // DEC abs,X
819            0xDE => {
820                let addr = self.absolute_x();
821                self.dec(addr)
822            }
823
824            // CMP #imm
825            0xC9 => {
826                let addr = self.immediate();
827                self.cmp(self.a, self.read_byte(addr))
828            }
829
830            // CMP zp
831            0xC5 => {
832                let addr = self.zeropage();
833                self.cmp(self.a, self.read_byte(addr))
834            }
835
836            // CMP zp,X
837            0xD5 => {
838                let addr = self.zeropage_x();
839                self.cmp(self.a, self.read_byte(addr))
840            }
841
842            // CMP abs
843            0xCD => {
844                let addr = self.absolute();
845                self.cmp(self.a, self.read_byte(addr))
846            }
847
848            // CMP abs,X
849            0xDD => {
850                let addr = self.absolute_x();
851                self.cmp(self.a, self.read_byte(addr))
852            }
853
854            // CMP abs,Y
855            0xD9 => {
856                let addr = self.absolute_y();
857                self.cmp(self.a, self.read_byte(addr))
858            }
859
860            // CMP (zp,X)
861            0xC1 => {
862                let addr = self.indexed_indirect();
863                self.cmp(self.a, self.read_byte(addr))
864            }
865
866            // CMP (zp),Y
867            0xD1 => {
868                let addr = self.indirect_indexed();
869                self.cmp(self.a, self.read_byte(addr))
870            }
871
872            // CPX #imm
873            0xE0 => {
874                let addr = self.immediate();
875                self.cmp(self.x, self.read_byte(addr))
876            }
877
878            // CPX zp
879            0xE4 => {
880                let addr = self.zeropage();
881                self.cmp(self.x, self.read_byte(addr))
882            }
883
884            // CPX abs
885            0xEC => {
886                let addr = self.absolute();
887                self.cmp(self.x, self.read_byte(addr))
888            }
889
890            // CPY #imm
891            0xC0 => {
892                let addr = self.immediate();
893                self.cmp(self.y, self.read_byte(addr))
894            }
895
896            // CPY zp
897            0xC4 => {
898                let addr = self.zeropage();
899                self.cmp(self.y, self.read_byte(addr))
900            }
901
902            // CPY abs
903            0xCC => {
904                let addr = self.absolute();
905                self.cmp(self.y, self.read_byte(addr))
906            }
907
908            // LDA #imm
909            0xA9 => {
910                let addr = self.immediate();
911                let v = self.read_byte(addr);
912                self.a = v;
913                self.update_zn(v)
914            }
915
916            // LDA zp
917            0xA5 => {
918                let addr = self.zeropage();
919                let v = self.read_byte(addr);
920                self.a = v;
921                self.update_zn(v)
922            }
923
924            // LDA zp,X
925            0xB5 => {
926                let addr = self.zeropage_x();
927                let v = self.read_byte(addr);
928                self.a = v;
929                self.update_zn(v)
930            }
931
932            // LDA abs
933            0xAD => {
934                let addr = self.absolute();
935                let v = self.read_byte(addr);
936                self.a = v;
937                self.update_zn(v)
938            }
939
940            // LDA abs,X
941            0xBD => {
942                let addr = self.absolute_x();
943                let v = self.read_byte(addr);
944                self.a = v;
945                self.update_zn(v)
946            }
947
948            // LDA abs,Y
949            0xB9 => {
950                let addr = self.absolute_y();
951                let v = self.read_byte(addr);
952                self.a = v;
953                self.update_zn(v)
954            }
955
956            // LDA (zp,X)
957            0xA1 => {
958                let addr = self.indexed_indirect();
959                let v = self.read_byte(addr);
960                self.a = v;
961                self.update_zn(v)
962            }
963
964            // LDA (zp),Y
965            0xB1 => {
966                let addr = self.indirect_indexed();
967                let v = self.read_byte(addr);
968                self.a = v;
969                self.update_zn(v)
970            }
971
972            // LDX #imm
973            0xA2 => {
974                let addr = self.immediate();
975                let v = self.read_byte(addr);
976                self.x = v;
977                self.update_zn(v)
978            }
979
980            // LDX zp
981            0xA6 => {
982                let addr = self.zeropage();
983                let v = self.read_byte(addr);
984                self.x = v;
985                self.update_zn(v)
986            }
987
988            // LDX zp,Y
989            0xB6 => {
990                let addr = self.zeropage_y();
991                let v = self.read_byte(addr);
992                self.x = v;
993                self.update_zn(v)
994            }
995
996            // LDX abs
997            0xAE => {
998                let addr = self.absolute();
999                let v = self.read_byte(addr);
1000                self.x = v;
1001                self.update_zn(v)
1002            }
1003
1004            // LDX abs,Y
1005            0xBE => {
1006                let addr = self.absolute_y();
1007                let v = self.read_byte(addr);
1008                self.x = v;
1009                self.update_zn(v)
1010            }
1011
1012            // LDY #imm
1013            0xA0 => {
1014                let addr = self.immediate();
1015                let v = self.read_byte(addr);
1016                self.y = v;
1017                self.update_zn(v)
1018            }
1019
1020            // LDY zp
1021            0xA4 => {
1022                let addr = self.zeropage();
1023                let v = self.read_byte(addr);
1024                self.y = v;
1025                self.update_zn(v)
1026            }
1027
1028            // LDY zp,X
1029            0xB4 => {
1030                let addr = self.zeropage_x();
1031                let v = self.read_byte(addr);
1032                self.y = v;
1033                self.update_zn(v)
1034            }
1035
1036            // LDY abs
1037            0xAC => {
1038                let addr = self.absolute();
1039                let v = self.read_byte(addr);
1040                self.y = v;
1041                self.update_zn(v)
1042            }
1043
1044            // LDY abs,X
1045            0xBC => {
1046                let addr = self.absolute_x();
1047                let v = self.read_byte(addr);
1048                self.y = v;
1049                self.update_zn(v)
1050            }
1051
1052            // STA zp
1053            0x85 => {
1054                let addr = self.zeropage();
1055                self.write_byte(addr, self.a)
1056            }
1057
1058            // STA zp,X
1059            0x95 => {
1060                let addr = self.zeropage_x();
1061                self.write_byte(addr, self.a)
1062            }
1063
1064            // STA abs
1065            0x8D => {
1066                let addr = self.absolute();
1067                self.write_byte(addr, self.a)
1068            }
1069
1070            // STA abs,X
1071            0x9D => {
1072                let addr = self.absolute_x();
1073                self.write_byte(addr, self.a)
1074            }
1075
1076            // STA abs,Y
1077            0x99 => {
1078                let addr = self.absolute_y();
1079                self.write_byte(addr, self.a)
1080            }
1081
1082            // STA (zp,X)
1083            0x81 => {
1084                let addr = self.indexed_indirect();
1085                self.write_byte(addr, self.a)
1086            }
1087
1088            // STA (zp),Y
1089            0x91 => {
1090                let addr = self.indirect_indexed();
1091                self.write_byte(addr, self.a)
1092            }
1093
1094            // STX zp
1095            0x86 => {
1096                let addr = self.zeropage();
1097                self.write_byte(addr, self.x)
1098            }
1099
1100            // STX zp,Y
1101            0x96 => {
1102                let addr = self.zeropage_y();
1103                self.write_byte(addr, self.x)
1104            }
1105
1106            // STX abs
1107            0x8E => {
1108                let addr = self.absolute();
1109                self.write_byte(addr, self.x)
1110            }
1111
1112            // STY zp
1113            0x84 => {
1114                let addr = self.zeropage();
1115                self.write_byte(addr, self.y)
1116            }
1117
1118            // STY zp,X
1119            0x94 => {
1120                let addr = self.zeropage_x();
1121                self.write_byte(addr, self.y)
1122            }
1123
1124            // STY abs
1125            0x8C => {
1126                let addr = self.absolute();
1127                self.write_byte(addr, self.y)
1128            }
1129
1130            // TAX
1131            0xAA => {
1132                self.x = self.a;
1133                self.update_zn(self.x)
1134            }
1135
1136            // TAY
1137            0xA8 => {
1138                self.y = self.a;
1139                self.update_zn(self.y)
1140            }
1141
1142            // TXA
1143            0x8A => {
1144                self.a = self.x;
1145                self.update_zn(self.a)
1146            }
1147
1148            // TYA
1149            0x98 => {
1150                self.a = self.y;
1151                self.update_zn(self.a)
1152            }
1153
1154            // TSX
1155            0xBA => {
1156                self.x = self.sp;
1157                self.update_zn(self.x)
1158            }
1159
1160            // TXS
1161            0x9A => self.sp = self.x,
1162
1163            // PHA
1164            0x48 => self.push(self.a),
1165
1166            // PLA
1167            0x68 => {
1168                let v = self.pop();
1169                self.a = v;
1170                self.update_zn(v)
1171            }
1172
1173            // PHP
1174            0x08 => self.push(self.status | Self::STATUS_FLAG_B | Self::STATUS_FLAG_U),
1175
1176            // PLP
1177            0x28 => {
1178                self.status = self.pop();
1179                self.status |= Self::STATUS_FLAG_U
1180            }
1181
1182            // ASL A
1183            0x0A => self.asl_acc(),
1184
1185            // ASL zp
1186            0x06 => {
1187                let addr = self.zeropage();
1188                self.asl_mem(addr)
1189            }
1190
1191            // ASL zp,X
1192            0x16 => {
1193                let addr = self.zeropage_x();
1194                self.asl_mem(addr)
1195            }
1196
1197            // ASL abs
1198            0x0E => {
1199                let addr = self.absolute();
1200                self.asl_mem(addr)
1201            }
1202
1203            // ASL abs,X
1204            0x1E => {
1205                let addr = self.absolute_x();
1206                self.asl_mem(addr)
1207            }
1208
1209            // LSR A
1210            0x4A => self.lsr_acc(),
1211
1212            // LSR zp
1213            0x46 => {
1214                let addr = self.zeropage();
1215                self.lsr_mem(addr)
1216            }
1217
1218            // LSR zp,X
1219            0x56 => {
1220                let addr = self.zeropage_x();
1221                self.lsr_mem(addr)
1222            }
1223
1224            // LSR abs
1225            0x4E => {
1226                let addr = self.absolute();
1227                self.lsr_mem(addr)
1228            }
1229
1230            // LSR abs,X
1231            0x5E => {
1232                let addr = self.absolute_x();
1233                self.lsr_mem(addr)
1234            }
1235
1236            // ROL A
1237            0x2A => self.rol_acc(),
1238
1239            // ROL zp
1240            0x26 => {
1241                let addr = self.zeropage();
1242                self.rol_mem(addr)
1243            }
1244
1245            // ROL zp,X
1246            0x36 => {
1247                let addr = self.zeropage_x();
1248                self.rol_mem(addr)
1249            }
1250
1251            // ROL abs
1252            0x2E => {
1253                let addr = self.absolute();
1254                self.rol_mem(addr)
1255            }
1256
1257            // ROL abs,X
1258            0x3E => {
1259                let addr = self.absolute_x();
1260                self.rol_mem(addr)
1261            }
1262
1263            // ROR A
1264            0x6A => self.ror_acc(),
1265
1266            // ROR zp
1267            0x66 => {
1268                let addr = self.zeropage();
1269                self.ror_mem(addr)
1270            }
1271
1272            // ROR zp,X
1273            0x76 => {
1274                let addr = self.zeropage_x();
1275                self.ror_mem(addr)
1276            }
1277
1278            // ROR abs
1279            0x6E => {
1280                let addr = self.absolute();
1281                self.ror_mem(addr)
1282            }
1283
1284            // ROR abs,X
1285            0x7E => {
1286                let addr = self.absolute_x();
1287                self.ror_mem(addr)
1288            }
1289
1290            // NOP
1291            0xEA => {}
1292
1293            // Temp behavior for unimplemented opcodes
1294            _op => {}
1295        }
1296    }
1297}
1298
1299impl core::fmt::Debug for CentralProcessingUnit {
1300    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1301        writeln!(f, "6502 CPU State:")?;
1302        writeln!(f, "  PC     : {:#06X}", self.pc)?;
1303        writeln!(f, "  A      : {:#04X}", self.a)?;
1304        writeln!(f, "  X      : {:#04X}", self.x)?;
1305        writeln!(f, "  Y      : {:#04X}", self.y)?;
1306        writeln!(f, "  SP     : {:#04X}", self.sp)?;
1307        writeln!(f, "  STATUS : {:#04X}", self.status)?;
1308
1309        Ok(())
1310    }
1311}
1312
1313impl core::fmt::Display for CentralProcessingUnit {
1314    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1315        writeln!(f, "6502 CPU State:")?;
1316        writeln!(f, "  PC     : {:#06X}", self.pc)?;
1317        writeln!(f, "  A      : {:#04X}", self.a)?;
1318        writeln!(f, "  X      : {:#04X}", self.x)?;
1319        writeln!(f, "  Y      : {:#04X}", self.y)?;
1320        writeln!(f, "  SP     : {:#04X}", self.sp)?;
1321        writeln!(f, "  STATUS : {:#04X}", self.status)?;
1322
1323        Ok(())
1324    }
1325}