rustynes_cpu/
opcodes.rs

1//! Opcode definitions and lookup tables for the 6502 CPU.
2//!
3//! This module contains all 256 opcodes (151 official + 105 unofficial)
4//! with their mnemonics, addressing modes, base cycle counts, and page crossing penalties.
5
6use crate::addressing::AddressingMode;
7
8/// Opcode information structure.
9#[derive(Debug, Clone, Copy)]
10pub struct OpcodeInfo {
11    /// Instruction mnemonic (for debugging)
12    pub mnemonic: &'static str,
13    /// Addressing mode
14    pub addr_mode: AddressingMode,
15    /// Base cycle count
16    pub cycles: u8,
17    /// Whether this instruction can take an extra cycle on page crossing
18    pub page_cross_penalty: bool,
19    /// Whether this is an unofficial opcode
20    pub unofficial: bool,
21}
22
23/// Complete 256-entry opcode lookup table.
24///
25/// Indexed by opcode byte (0x00-0xFF). Includes both official and unofficial opcodes.
26pub const OPCODE_TABLE: [OpcodeInfo; 256] = [
27    // 0x00-0x0F
28    OpcodeInfo {
29        mnemonic: "BRK",
30        addr_mode: AddressingMode::Implied,
31        cycles: 7,
32        page_cross_penalty: false,
33
34        unofficial: false,
35    }, // 0x00
36    OpcodeInfo {
37        mnemonic: "ORA",
38        addr_mode: AddressingMode::IndexedIndirectX,
39        cycles: 6,
40        page_cross_penalty: false,
41
42        unofficial: false,
43    }, // 0x01
44    OpcodeInfo {
45        mnemonic: "JAM",
46        addr_mode: AddressingMode::Implied,
47        cycles: 0,
48        page_cross_penalty: false,
49
50        unofficial: true,
51    }, // 0x02 (unofficial)
52    OpcodeInfo {
53        mnemonic: "SLO",
54        addr_mode: AddressingMode::IndexedIndirectX,
55        cycles: 8,
56        page_cross_penalty: false,
57
58        unofficial: true,
59    }, // 0x03 (unofficial)
60    OpcodeInfo {
61        mnemonic: "NOP",
62        addr_mode: AddressingMode::ZeroPage,
63        cycles: 3,
64        page_cross_penalty: false,
65
66        unofficial: true,
67    }, // 0x04 (unofficial)
68    OpcodeInfo {
69        mnemonic: "ORA",
70        addr_mode: AddressingMode::ZeroPage,
71        cycles: 3,
72        page_cross_penalty: false,
73
74        unofficial: false,
75    }, // 0x05
76    OpcodeInfo {
77        mnemonic: "ASL",
78        addr_mode: AddressingMode::ZeroPage,
79        cycles: 5,
80        page_cross_penalty: false,
81
82        unofficial: false,
83    }, // 0x06
84    OpcodeInfo {
85        mnemonic: "SLO",
86        addr_mode: AddressingMode::ZeroPage,
87        cycles: 5,
88        page_cross_penalty: false,
89
90        unofficial: true,
91    }, // 0x07 (unofficial)
92    OpcodeInfo {
93        mnemonic: "PHP",
94        addr_mode: AddressingMode::Implied,
95        cycles: 3,
96        page_cross_penalty: false,
97
98        unofficial: false,
99    }, // 0x08
100    OpcodeInfo {
101        mnemonic: "ORA",
102        addr_mode: AddressingMode::Immediate,
103        cycles: 2,
104        page_cross_penalty: false,
105
106        unofficial: false,
107    }, // 0x09
108    OpcodeInfo {
109        mnemonic: "ASL",
110        addr_mode: AddressingMode::Accumulator,
111        cycles: 2,
112        page_cross_penalty: false,
113
114        unofficial: false,
115    }, // 0x0A
116    OpcodeInfo {
117        mnemonic: "ANC",
118        addr_mode: AddressingMode::Immediate,
119        cycles: 2,
120        page_cross_penalty: false,
121
122        unofficial: true,
123    }, // 0x0B (unofficial)
124    OpcodeInfo {
125        mnemonic: "NOP",
126        addr_mode: AddressingMode::Absolute,
127        cycles: 4,
128        page_cross_penalty: false,
129
130        unofficial: true,
131    }, // 0x0C (unofficial)
132    OpcodeInfo {
133        mnemonic: "ORA",
134        addr_mode: AddressingMode::Absolute,
135        cycles: 4,
136        page_cross_penalty: false,
137
138        unofficial: false,
139    }, // 0x0D
140    OpcodeInfo {
141        mnemonic: "ASL",
142        addr_mode: AddressingMode::Absolute,
143        cycles: 6,
144        page_cross_penalty: false,
145
146        unofficial: false,
147    }, // 0x0E
148    OpcodeInfo {
149        mnemonic: "SLO",
150        addr_mode: AddressingMode::Absolute,
151        cycles: 6,
152        page_cross_penalty: false,
153
154        unofficial: true,
155    }, // 0x0F (unofficial)
156    // 0x10-0x1F
157    OpcodeInfo {
158        mnemonic: "BPL",
159        addr_mode: AddressingMode::Relative,
160        cycles: 2,
161        page_cross_penalty: true,
162
163        unofficial: false,
164    }, // 0x10
165    OpcodeInfo {
166        mnemonic: "ORA",
167        addr_mode: AddressingMode::IndirectIndexedY,
168        cycles: 5,
169        page_cross_penalty: true,
170
171        unofficial: false,
172    }, // 0x11
173    OpcodeInfo {
174        mnemonic: "JAM",
175        addr_mode: AddressingMode::Implied,
176        cycles: 0,
177        page_cross_penalty: false,
178
179        unofficial: true,
180    }, // 0x12 (unofficial)
181    OpcodeInfo {
182        mnemonic: "SLO",
183        addr_mode: AddressingMode::IndirectIndexedY,
184        cycles: 8,
185        page_cross_penalty: false,
186
187        unofficial: true,
188    }, // 0x13 (unofficial)
189    OpcodeInfo {
190        mnemonic: "NOP",
191        addr_mode: AddressingMode::ZeroPageX,
192        cycles: 4,
193        page_cross_penalty: false,
194
195        unofficial: true,
196    }, // 0x14 (unofficial)
197    OpcodeInfo {
198        mnemonic: "ORA",
199        addr_mode: AddressingMode::ZeroPageX,
200        cycles: 4,
201        page_cross_penalty: false,
202
203        unofficial: false,
204    }, // 0x15
205    OpcodeInfo {
206        mnemonic: "ASL",
207        addr_mode: AddressingMode::ZeroPageX,
208        cycles: 6,
209        page_cross_penalty: false,
210
211        unofficial: false,
212    }, // 0x16
213    OpcodeInfo {
214        mnemonic: "SLO",
215        addr_mode: AddressingMode::ZeroPageX,
216        cycles: 6,
217        page_cross_penalty: false,
218
219        unofficial: true,
220    }, // 0x17 (unofficial)
221    OpcodeInfo {
222        mnemonic: "CLC",
223        addr_mode: AddressingMode::Implied,
224        cycles: 2,
225        page_cross_penalty: false,
226
227        unofficial: false,
228    }, // 0x18
229    OpcodeInfo {
230        mnemonic: "ORA",
231        addr_mode: AddressingMode::AbsoluteY,
232        cycles: 4,
233        page_cross_penalty: true,
234
235        unofficial: false,
236    }, // 0x19
237    OpcodeInfo {
238        mnemonic: "NOP",
239        addr_mode: AddressingMode::Implied,
240        cycles: 2,
241        page_cross_penalty: false,
242
243        unofficial: true,
244    }, // 0x1A (unofficial)
245    OpcodeInfo {
246        mnemonic: "SLO",
247        addr_mode: AddressingMode::AbsoluteY,
248        cycles: 7,
249        page_cross_penalty: false,
250
251        unofficial: true,
252    }, // 0x1B (unofficial)
253    OpcodeInfo {
254        mnemonic: "NOP",
255        addr_mode: AddressingMode::AbsoluteX,
256        cycles: 4,
257        page_cross_penalty: true,
258
259        unofficial: true,
260    }, // 0x1C (unofficial)
261    OpcodeInfo {
262        mnemonic: "ORA",
263        addr_mode: AddressingMode::AbsoluteX,
264        cycles: 4,
265        page_cross_penalty: true,
266
267        unofficial: false,
268    }, // 0x1D
269    OpcodeInfo {
270        mnemonic: "ASL",
271        addr_mode: AddressingMode::AbsoluteX,
272        cycles: 7,
273        page_cross_penalty: false,
274
275        unofficial: false,
276    }, // 0x1E
277    OpcodeInfo {
278        mnemonic: "SLO",
279        addr_mode: AddressingMode::AbsoluteX,
280        cycles: 7,
281        page_cross_penalty: false,
282
283        unofficial: true,
284    }, // 0x1F (unofficial)
285    // 0x20-0x2F
286    OpcodeInfo {
287        mnemonic: "JSR",
288        addr_mode: AddressingMode::Absolute,
289        cycles: 6,
290        page_cross_penalty: false,
291
292        unofficial: false,
293    }, // 0x20
294    OpcodeInfo {
295        mnemonic: "AND",
296        addr_mode: AddressingMode::IndexedIndirectX,
297        cycles: 6,
298        page_cross_penalty: false,
299
300        unofficial: false,
301    }, // 0x21
302    OpcodeInfo {
303        mnemonic: "JAM",
304        addr_mode: AddressingMode::Implied,
305        cycles: 0,
306        page_cross_penalty: false,
307
308        unofficial: true,
309    }, // 0x22 (unofficial)
310    OpcodeInfo {
311        mnemonic: "RLA",
312        addr_mode: AddressingMode::IndexedIndirectX,
313        cycles: 8,
314        page_cross_penalty: false,
315
316        unofficial: true,
317    }, // 0x23 (unofficial)
318    OpcodeInfo {
319        mnemonic: "BIT",
320        addr_mode: AddressingMode::ZeroPage,
321        cycles: 3,
322        page_cross_penalty: false,
323
324        unofficial: false,
325    }, // 0x24
326    OpcodeInfo {
327        mnemonic: "AND",
328        addr_mode: AddressingMode::ZeroPage,
329        cycles: 3,
330        page_cross_penalty: false,
331
332        unofficial: false,
333    }, // 0x25
334    OpcodeInfo {
335        mnemonic: "ROL",
336        addr_mode: AddressingMode::ZeroPage,
337        cycles: 5,
338        page_cross_penalty: false,
339
340        unofficial: false,
341    }, // 0x26
342    OpcodeInfo {
343        mnemonic: "RLA",
344        addr_mode: AddressingMode::ZeroPage,
345        cycles: 5,
346        page_cross_penalty: false,
347
348        unofficial: true,
349    }, // 0x27 (unofficial)
350    OpcodeInfo {
351        mnemonic: "PLP",
352        addr_mode: AddressingMode::Implied,
353        cycles: 4,
354        page_cross_penalty: false,
355
356        unofficial: false,
357    }, // 0x28
358    OpcodeInfo {
359        mnemonic: "AND",
360        addr_mode: AddressingMode::Immediate,
361        cycles: 2,
362        page_cross_penalty: false,
363
364        unofficial: false,
365    }, // 0x29
366    OpcodeInfo {
367        mnemonic: "ROL",
368        addr_mode: AddressingMode::Accumulator,
369        cycles: 2,
370        page_cross_penalty: false,
371
372        unofficial: false,
373    }, // 0x2A
374    OpcodeInfo {
375        mnemonic: "ANC",
376        addr_mode: AddressingMode::Immediate,
377        cycles: 2,
378        page_cross_penalty: false,
379
380        unofficial: true,
381    }, // 0x2B (unofficial)
382    OpcodeInfo {
383        mnemonic: "BIT",
384        addr_mode: AddressingMode::Absolute,
385        cycles: 4,
386        page_cross_penalty: false,
387
388        unofficial: false,
389    }, // 0x2C
390    OpcodeInfo {
391        mnemonic: "AND",
392        addr_mode: AddressingMode::Absolute,
393        cycles: 4,
394        page_cross_penalty: false,
395
396        unofficial: false,
397    }, // 0x2D
398    OpcodeInfo {
399        mnemonic: "ROL",
400        addr_mode: AddressingMode::Absolute,
401        cycles: 6,
402        page_cross_penalty: false,
403
404        unofficial: false,
405    }, // 0x2E
406    OpcodeInfo {
407        mnemonic: "RLA",
408        addr_mode: AddressingMode::Absolute,
409        cycles: 6,
410        page_cross_penalty: false,
411
412        unofficial: true,
413    }, // 0x2F (unofficial)
414    // 0x30-0x3F
415    OpcodeInfo {
416        mnemonic: "BMI",
417        addr_mode: AddressingMode::Relative,
418        cycles: 2,
419        page_cross_penalty: true,
420
421        unofficial: false,
422    }, // 0x30
423    OpcodeInfo {
424        mnemonic: "AND",
425        addr_mode: AddressingMode::IndirectIndexedY,
426        cycles: 5,
427        page_cross_penalty: true,
428
429        unofficial: false,
430    }, // 0x31
431    OpcodeInfo {
432        mnemonic: "JAM",
433        addr_mode: AddressingMode::Implied,
434        cycles: 0,
435        page_cross_penalty: false,
436
437        unofficial: true,
438    }, // 0x32 (unofficial)
439    OpcodeInfo {
440        mnemonic: "RLA",
441        addr_mode: AddressingMode::IndirectIndexedY,
442        cycles: 8,
443        page_cross_penalty: false,
444
445        unofficial: true,
446    }, // 0x33 (unofficial)
447    OpcodeInfo {
448        mnemonic: "NOP",
449        addr_mode: AddressingMode::ZeroPageX,
450        cycles: 4,
451        page_cross_penalty: false,
452
453        unofficial: true,
454    }, // 0x34 (unofficial)
455    OpcodeInfo {
456        mnemonic: "AND",
457        addr_mode: AddressingMode::ZeroPageX,
458        cycles: 4,
459        page_cross_penalty: false,
460
461        unofficial: false,
462    }, // 0x35
463    OpcodeInfo {
464        mnemonic: "ROL",
465        addr_mode: AddressingMode::ZeroPageX,
466        cycles: 6,
467        page_cross_penalty: false,
468
469        unofficial: false,
470    }, // 0x36
471    OpcodeInfo {
472        mnemonic: "RLA",
473        addr_mode: AddressingMode::ZeroPageX,
474        cycles: 6,
475        page_cross_penalty: false,
476
477        unofficial: true,
478    }, // 0x37 (unofficial)
479    OpcodeInfo {
480        mnemonic: "SEC",
481        addr_mode: AddressingMode::Implied,
482        cycles: 2,
483        page_cross_penalty: false,
484
485        unofficial: false,
486    }, // 0x38
487    OpcodeInfo {
488        mnemonic: "AND",
489        addr_mode: AddressingMode::AbsoluteY,
490        cycles: 4,
491        page_cross_penalty: true,
492
493        unofficial: false,
494    }, // 0x39
495    OpcodeInfo {
496        mnemonic: "NOP",
497        addr_mode: AddressingMode::Implied,
498        cycles: 2,
499        page_cross_penalty: false,
500
501        unofficial: true,
502    }, // 0x3A (unofficial)
503    OpcodeInfo {
504        mnemonic: "RLA",
505        addr_mode: AddressingMode::AbsoluteY,
506        cycles: 7,
507        page_cross_penalty: false,
508
509        unofficial: true,
510    }, // 0x3B (unofficial)
511    OpcodeInfo {
512        mnemonic: "NOP",
513        addr_mode: AddressingMode::AbsoluteX,
514        cycles: 4,
515        page_cross_penalty: true,
516
517        unofficial: true,
518    }, // 0x3C (unofficial)
519    OpcodeInfo {
520        mnemonic: "AND",
521        addr_mode: AddressingMode::AbsoluteX,
522        cycles: 4,
523        page_cross_penalty: true,
524
525        unofficial: false,
526    }, // 0x3D
527    OpcodeInfo {
528        mnemonic: "ROL",
529        addr_mode: AddressingMode::AbsoluteX,
530        cycles: 7,
531        page_cross_penalty: false,
532
533        unofficial: false,
534    }, // 0x3E
535    OpcodeInfo {
536        mnemonic: "RLA",
537        addr_mode: AddressingMode::AbsoluteX,
538        cycles: 7,
539        page_cross_penalty: false,
540
541        unofficial: true,
542    }, // 0x3F (unofficial)
543    // 0x40-0x4F
544    OpcodeInfo {
545        mnemonic: "RTI",
546        addr_mode: AddressingMode::Implied,
547        cycles: 6,
548        page_cross_penalty: false,
549
550        unofficial: false,
551    }, // 0x40
552    OpcodeInfo {
553        mnemonic: "EOR",
554        addr_mode: AddressingMode::IndexedIndirectX,
555        cycles: 6,
556        page_cross_penalty: false,
557
558        unofficial: false,
559    }, // 0x41
560    OpcodeInfo {
561        mnemonic: "JAM",
562        addr_mode: AddressingMode::Implied,
563        cycles: 0,
564        page_cross_penalty: false,
565
566        unofficial: true,
567    }, // 0x42 (unofficial)
568    OpcodeInfo {
569        mnemonic: "SRE",
570        addr_mode: AddressingMode::IndexedIndirectX,
571        cycles: 8,
572        page_cross_penalty: false,
573
574        unofficial: true,
575    }, // 0x43 (unofficial)
576    OpcodeInfo {
577        mnemonic: "NOP",
578        addr_mode: AddressingMode::ZeroPage,
579        cycles: 3,
580        page_cross_penalty: false,
581
582        unofficial: true,
583    }, // 0x44 (unofficial)
584    OpcodeInfo {
585        mnemonic: "EOR",
586        addr_mode: AddressingMode::ZeroPage,
587        cycles: 3,
588        page_cross_penalty: false,
589
590        unofficial: false,
591    }, // 0x45
592    OpcodeInfo {
593        mnemonic: "LSR",
594        addr_mode: AddressingMode::ZeroPage,
595        cycles: 5,
596        page_cross_penalty: false,
597
598        unofficial: false,
599    }, // 0x46
600    OpcodeInfo {
601        mnemonic: "SRE",
602        addr_mode: AddressingMode::ZeroPage,
603        cycles: 5,
604        page_cross_penalty: false,
605
606        unofficial: true,
607    }, // 0x47 (unofficial)
608    OpcodeInfo {
609        mnemonic: "PHA",
610        addr_mode: AddressingMode::Implied,
611        cycles: 3,
612        page_cross_penalty: false,
613
614        unofficial: false,
615    }, // 0x48
616    OpcodeInfo {
617        mnemonic: "EOR",
618        addr_mode: AddressingMode::Immediate,
619        cycles: 2,
620        page_cross_penalty: false,
621
622        unofficial: false,
623    }, // 0x49
624    OpcodeInfo {
625        mnemonic: "LSR",
626        addr_mode: AddressingMode::Accumulator,
627        cycles: 2,
628        page_cross_penalty: false,
629
630        unofficial: false,
631    }, // 0x4A
632    OpcodeInfo {
633        mnemonic: "ALR",
634        addr_mode: AddressingMode::Immediate,
635        cycles: 2,
636        page_cross_penalty: false,
637
638        unofficial: true,
639    }, // 0x4B (unofficial)
640    OpcodeInfo {
641        mnemonic: "JMP",
642        addr_mode: AddressingMode::Absolute,
643        cycles: 3,
644        page_cross_penalty: false,
645
646        unofficial: false,
647    }, // 0x4C
648    OpcodeInfo {
649        mnemonic: "EOR",
650        addr_mode: AddressingMode::Absolute,
651        cycles: 4,
652        page_cross_penalty: false,
653
654        unofficial: false,
655    }, // 0x4D
656    OpcodeInfo {
657        mnemonic: "LSR",
658        addr_mode: AddressingMode::Absolute,
659        cycles: 6,
660        page_cross_penalty: false,
661
662        unofficial: false,
663    }, // 0x4E
664    OpcodeInfo {
665        mnemonic: "SRE",
666        addr_mode: AddressingMode::Absolute,
667        cycles: 6,
668        page_cross_penalty: false,
669
670        unofficial: true,
671    }, // 0x4F (unofficial)
672    // 0x50-0x5F
673    OpcodeInfo {
674        mnemonic: "BVC",
675        addr_mode: AddressingMode::Relative,
676        cycles: 2,
677        page_cross_penalty: true,
678
679        unofficial: false,
680    }, // 0x50
681    OpcodeInfo {
682        mnemonic: "EOR",
683        addr_mode: AddressingMode::IndirectIndexedY,
684        cycles: 5,
685        page_cross_penalty: true,
686
687        unofficial: false,
688    }, // 0x51
689    OpcodeInfo {
690        mnemonic: "JAM",
691        addr_mode: AddressingMode::Implied,
692        cycles: 0,
693        page_cross_penalty: false,
694
695        unofficial: true,
696    }, // 0x52 (unofficial)
697    OpcodeInfo {
698        mnemonic: "SRE",
699        addr_mode: AddressingMode::IndirectIndexedY,
700        cycles: 8,
701        page_cross_penalty: false,
702
703        unofficial: true,
704    }, // 0x53 (unofficial)
705    OpcodeInfo {
706        mnemonic: "NOP",
707        addr_mode: AddressingMode::ZeroPageX,
708        cycles: 4,
709        page_cross_penalty: false,
710
711        unofficial: true,
712    }, // 0x54 (unofficial)
713    OpcodeInfo {
714        mnemonic: "EOR",
715        addr_mode: AddressingMode::ZeroPageX,
716        cycles: 4,
717        page_cross_penalty: false,
718
719        unofficial: false,
720    }, // 0x55
721    OpcodeInfo {
722        mnemonic: "LSR",
723        addr_mode: AddressingMode::ZeroPageX,
724        cycles: 6,
725        page_cross_penalty: false,
726
727        unofficial: false,
728    }, // 0x56
729    OpcodeInfo {
730        mnemonic: "SRE",
731        addr_mode: AddressingMode::ZeroPageX,
732        cycles: 6,
733        page_cross_penalty: false,
734
735        unofficial: true,
736    }, // 0x57 (unofficial)
737    OpcodeInfo {
738        mnemonic: "CLI",
739        addr_mode: AddressingMode::Implied,
740        cycles: 2,
741        page_cross_penalty: false,
742
743        unofficial: false,
744    }, // 0x58
745    OpcodeInfo {
746        mnemonic: "EOR",
747        addr_mode: AddressingMode::AbsoluteY,
748        cycles: 4,
749        page_cross_penalty: true,
750
751        unofficial: false,
752    }, // 0x59
753    OpcodeInfo {
754        mnemonic: "NOP",
755        addr_mode: AddressingMode::Implied,
756        cycles: 2,
757        page_cross_penalty: false,
758
759        unofficial: true,
760    }, // 0x5A (unofficial)
761    OpcodeInfo {
762        mnemonic: "SRE",
763        addr_mode: AddressingMode::AbsoluteY,
764        cycles: 7,
765        page_cross_penalty: false,
766
767        unofficial: true,
768    }, // 0x5B (unofficial)
769    OpcodeInfo {
770        mnemonic: "NOP",
771        addr_mode: AddressingMode::AbsoluteX,
772        cycles: 4,
773        page_cross_penalty: true,
774
775        unofficial: true,
776    }, // 0x5C (unofficial)
777    OpcodeInfo {
778        mnemonic: "EOR",
779        addr_mode: AddressingMode::AbsoluteX,
780        cycles: 4,
781        page_cross_penalty: true,
782
783        unofficial: false,
784    }, // 0x5D
785    OpcodeInfo {
786        mnemonic: "LSR",
787        addr_mode: AddressingMode::AbsoluteX,
788        cycles: 7,
789        page_cross_penalty: false,
790
791        unofficial: false,
792    }, // 0x5E
793    OpcodeInfo {
794        mnemonic: "SRE",
795        addr_mode: AddressingMode::AbsoluteX,
796        cycles: 7,
797        page_cross_penalty: false,
798
799        unofficial: true,
800    }, // 0x5F (unofficial)
801    // 0x60-0x6F
802    OpcodeInfo {
803        mnemonic: "RTS",
804        addr_mode: AddressingMode::Implied,
805        cycles: 6,
806        page_cross_penalty: false,
807
808        unofficial: false,
809    }, // 0x60
810    OpcodeInfo {
811        mnemonic: "ADC",
812        addr_mode: AddressingMode::IndexedIndirectX,
813        cycles: 6,
814        page_cross_penalty: false,
815
816        unofficial: false,
817    }, // 0x61
818    OpcodeInfo {
819        mnemonic: "JAM",
820        addr_mode: AddressingMode::Implied,
821        cycles: 0,
822        page_cross_penalty: false,
823
824        unofficial: true,
825    }, // 0x62 (unofficial)
826    OpcodeInfo {
827        mnemonic: "RRA",
828        addr_mode: AddressingMode::IndexedIndirectX,
829        cycles: 8,
830        page_cross_penalty: false,
831
832        unofficial: true,
833    }, // 0x63 (unofficial)
834    OpcodeInfo {
835        mnemonic: "NOP",
836        addr_mode: AddressingMode::ZeroPage,
837        cycles: 3,
838        page_cross_penalty: false,
839
840        unofficial: true,
841    }, // 0x64 (unofficial)
842    OpcodeInfo {
843        mnemonic: "ADC",
844        addr_mode: AddressingMode::ZeroPage,
845        cycles: 3,
846        page_cross_penalty: false,
847
848        unofficial: false,
849    }, // 0x65
850    OpcodeInfo {
851        mnemonic: "ROR",
852        addr_mode: AddressingMode::ZeroPage,
853        cycles: 5,
854        page_cross_penalty: false,
855
856        unofficial: false,
857    }, // 0x66
858    OpcodeInfo {
859        mnemonic: "RRA",
860        addr_mode: AddressingMode::ZeroPage,
861        cycles: 5,
862        page_cross_penalty: false,
863
864        unofficial: true,
865    }, // 0x67 (unofficial)
866    OpcodeInfo {
867        mnemonic: "PLA",
868        addr_mode: AddressingMode::Implied,
869        cycles: 4,
870        page_cross_penalty: false,
871
872        unofficial: false,
873    }, // 0x68
874    OpcodeInfo {
875        mnemonic: "ADC",
876        addr_mode: AddressingMode::Immediate,
877        cycles: 2,
878        page_cross_penalty: false,
879
880        unofficial: false,
881    }, // 0x69
882    OpcodeInfo {
883        mnemonic: "ROR",
884        addr_mode: AddressingMode::Accumulator,
885        cycles: 2,
886        page_cross_penalty: false,
887
888        unofficial: false,
889    }, // 0x6A
890    OpcodeInfo {
891        mnemonic: "ARR",
892        addr_mode: AddressingMode::Immediate,
893        cycles: 2,
894        page_cross_penalty: false,
895
896        unofficial: true,
897    }, // 0x6B (unofficial)
898    OpcodeInfo {
899        mnemonic: "JMP",
900        addr_mode: AddressingMode::Indirect,
901        cycles: 5,
902        page_cross_penalty: false,
903
904        unofficial: false,
905    }, // 0x6C
906    OpcodeInfo {
907        mnemonic: "ADC",
908        addr_mode: AddressingMode::Absolute,
909        cycles: 4,
910        page_cross_penalty: false,
911
912        unofficial: false,
913    }, // 0x6D
914    OpcodeInfo {
915        mnemonic: "ROR",
916        addr_mode: AddressingMode::Absolute,
917        cycles: 6,
918        page_cross_penalty: false,
919
920        unofficial: false,
921    }, // 0x6E
922    OpcodeInfo {
923        mnemonic: "RRA",
924        addr_mode: AddressingMode::Absolute,
925        cycles: 6,
926        page_cross_penalty: false,
927
928        unofficial: true,
929    }, // 0x6F (unofficial)
930    // 0x70-0x7F
931    OpcodeInfo {
932        mnemonic: "BVS",
933        addr_mode: AddressingMode::Relative,
934        cycles: 2,
935        page_cross_penalty: true,
936
937        unofficial: false,
938    }, // 0x70
939    OpcodeInfo {
940        mnemonic: "ADC",
941        addr_mode: AddressingMode::IndirectIndexedY,
942        cycles: 5,
943        page_cross_penalty: true,
944
945        unofficial: false,
946    }, // 0x71
947    OpcodeInfo {
948        mnemonic: "JAM",
949        addr_mode: AddressingMode::Implied,
950        cycles: 0,
951        page_cross_penalty: false,
952
953        unofficial: true,
954    }, // 0x72 (unofficial)
955    OpcodeInfo {
956        mnemonic: "RRA",
957        addr_mode: AddressingMode::IndirectIndexedY,
958        cycles: 8,
959        page_cross_penalty: false,
960
961        unofficial: true,
962    }, // 0x73 (unofficial)
963    OpcodeInfo {
964        mnemonic: "NOP",
965        addr_mode: AddressingMode::ZeroPageX,
966        cycles: 4,
967        page_cross_penalty: false,
968
969        unofficial: true,
970    }, // 0x74 (unofficial)
971    OpcodeInfo {
972        mnemonic: "ADC",
973        addr_mode: AddressingMode::ZeroPageX,
974        cycles: 4,
975        page_cross_penalty: false,
976
977        unofficial: false,
978    }, // 0x75
979    OpcodeInfo {
980        mnemonic: "ROR",
981        addr_mode: AddressingMode::ZeroPageX,
982        cycles: 6,
983        page_cross_penalty: false,
984
985        unofficial: false,
986    }, // 0x76
987    OpcodeInfo {
988        mnemonic: "RRA",
989        addr_mode: AddressingMode::ZeroPageX,
990        cycles: 6,
991        page_cross_penalty: false,
992
993        unofficial: true,
994    }, // 0x77 (unofficial)
995    OpcodeInfo {
996        mnemonic: "SEI",
997        addr_mode: AddressingMode::Implied,
998        cycles: 2,
999        page_cross_penalty: false,
1000
1001        unofficial: false,
1002    }, // 0x78
1003    OpcodeInfo {
1004        mnemonic: "ADC",
1005        addr_mode: AddressingMode::AbsoluteY,
1006        cycles: 4,
1007        page_cross_penalty: true,
1008
1009        unofficial: false,
1010    }, // 0x79
1011    OpcodeInfo {
1012        mnemonic: "NOP",
1013        addr_mode: AddressingMode::Implied,
1014        cycles: 2,
1015        page_cross_penalty: false,
1016
1017        unofficial: true,
1018    }, // 0x7A (unofficial)
1019    OpcodeInfo {
1020        mnemonic: "RRA",
1021        addr_mode: AddressingMode::AbsoluteY,
1022        cycles: 7,
1023        page_cross_penalty: false,
1024
1025        unofficial: true,
1026    }, // 0x7B (unofficial)
1027    OpcodeInfo {
1028        mnemonic: "NOP",
1029        addr_mode: AddressingMode::AbsoluteX,
1030        cycles: 4,
1031        page_cross_penalty: true,
1032
1033        unofficial: true,
1034    }, // 0x7C (unofficial)
1035    OpcodeInfo {
1036        mnemonic: "ADC",
1037        addr_mode: AddressingMode::AbsoluteX,
1038        cycles: 4,
1039        page_cross_penalty: true,
1040
1041        unofficial: false,
1042    }, // 0x7D
1043    OpcodeInfo {
1044        mnemonic: "ROR",
1045        addr_mode: AddressingMode::AbsoluteX,
1046        cycles: 7,
1047        page_cross_penalty: false,
1048
1049        unofficial: false,
1050    }, // 0x7E
1051    OpcodeInfo {
1052        mnemonic: "RRA",
1053        addr_mode: AddressingMode::AbsoluteX,
1054        cycles: 7,
1055        page_cross_penalty: false,
1056
1057        unofficial: true,
1058    }, // 0x7F (unofficial)
1059    // 0x80-0x8F
1060    OpcodeInfo {
1061        mnemonic: "NOP",
1062        addr_mode: AddressingMode::Immediate,
1063        cycles: 2,
1064        page_cross_penalty: false,
1065
1066        unofficial: true,
1067    }, // 0x80 (unofficial)
1068    OpcodeInfo {
1069        mnemonic: "STA",
1070        addr_mode: AddressingMode::IndexedIndirectX,
1071        cycles: 6,
1072        page_cross_penalty: false,
1073
1074        unofficial: false,
1075    }, // 0x81
1076    OpcodeInfo {
1077        mnemonic: "NOP",
1078        addr_mode: AddressingMode::Immediate,
1079        cycles: 2,
1080        page_cross_penalty: false,
1081
1082        unofficial: true,
1083    }, // 0x82 (unofficial)
1084    OpcodeInfo {
1085        mnemonic: "SAX",
1086        addr_mode: AddressingMode::IndexedIndirectX,
1087        cycles: 6,
1088        page_cross_penalty: false,
1089
1090        unofficial: true,
1091    }, // 0x83 (unofficial)
1092    OpcodeInfo {
1093        mnemonic: "STY",
1094        addr_mode: AddressingMode::ZeroPage,
1095        cycles: 3,
1096        page_cross_penalty: false,
1097
1098        unofficial: false,
1099    }, // 0x84
1100    OpcodeInfo {
1101        mnemonic: "STA",
1102        addr_mode: AddressingMode::ZeroPage,
1103        cycles: 3,
1104        page_cross_penalty: false,
1105
1106        unofficial: false,
1107    }, // 0x85
1108    OpcodeInfo {
1109        mnemonic: "STX",
1110        addr_mode: AddressingMode::ZeroPage,
1111        cycles: 3,
1112        page_cross_penalty: false,
1113
1114        unofficial: false,
1115    }, // 0x86
1116    OpcodeInfo {
1117        mnemonic: "SAX",
1118        addr_mode: AddressingMode::ZeroPage,
1119        cycles: 3,
1120        page_cross_penalty: false,
1121
1122        unofficial: true,
1123    }, // 0x87 (unofficial)
1124    OpcodeInfo {
1125        mnemonic: "DEY",
1126        addr_mode: AddressingMode::Implied,
1127        cycles: 2,
1128        page_cross_penalty: false,
1129
1130        unofficial: false,
1131    }, // 0x88
1132    OpcodeInfo {
1133        mnemonic: "NOP",
1134        addr_mode: AddressingMode::Immediate,
1135        cycles: 2,
1136        page_cross_penalty: false,
1137
1138        unofficial: true,
1139    }, // 0x89 (unofficial)
1140    OpcodeInfo {
1141        mnemonic: "TXA",
1142        addr_mode: AddressingMode::Implied,
1143        cycles: 2,
1144        page_cross_penalty: false,
1145
1146        unofficial: false,
1147    }, // 0x8A
1148    OpcodeInfo {
1149        mnemonic: "XAA",
1150        addr_mode: AddressingMode::Immediate,
1151        cycles: 2,
1152        page_cross_penalty: false,
1153
1154        unofficial: true,
1155    }, // 0x8B (unofficial, unstable)
1156    OpcodeInfo {
1157        mnemonic: "STY",
1158        addr_mode: AddressingMode::Absolute,
1159        cycles: 4,
1160        page_cross_penalty: false,
1161
1162        unofficial: false,
1163    }, // 0x8C
1164    OpcodeInfo {
1165        mnemonic: "STA",
1166        addr_mode: AddressingMode::Absolute,
1167        cycles: 4,
1168        page_cross_penalty: false,
1169
1170        unofficial: false,
1171    }, // 0x8D
1172    OpcodeInfo {
1173        mnemonic: "STX",
1174        addr_mode: AddressingMode::Absolute,
1175        cycles: 4,
1176        page_cross_penalty: false,
1177
1178        unofficial: false,
1179    }, // 0x8E
1180    OpcodeInfo {
1181        mnemonic: "SAX",
1182        addr_mode: AddressingMode::Absolute,
1183        cycles: 4,
1184        page_cross_penalty: false,
1185
1186        unofficial: true,
1187    }, // 0x8F (unofficial)
1188    // 0x90-0x9F
1189    OpcodeInfo {
1190        mnemonic: "BCC",
1191        addr_mode: AddressingMode::Relative,
1192        cycles: 2,
1193        page_cross_penalty: true,
1194
1195        unofficial: false,
1196    }, // 0x90
1197    OpcodeInfo {
1198        mnemonic: "STA",
1199        addr_mode: AddressingMode::IndirectIndexedY,
1200        cycles: 6,
1201        page_cross_penalty: false,
1202
1203        unofficial: false,
1204    }, // 0x91
1205    OpcodeInfo {
1206        mnemonic: "JAM",
1207        addr_mode: AddressingMode::Implied,
1208        cycles: 0,
1209        page_cross_penalty: false,
1210
1211        unofficial: true,
1212    }, // 0x92 (unofficial)
1213    OpcodeInfo {
1214        mnemonic: "SHA",
1215        addr_mode: AddressingMode::IndirectIndexedY,
1216        cycles: 6,
1217        page_cross_penalty: false,
1218
1219        unofficial: true,
1220    }, // 0x93 (unofficial, unstable)
1221    OpcodeInfo {
1222        mnemonic: "STY",
1223        addr_mode: AddressingMode::ZeroPageX,
1224        cycles: 4,
1225        page_cross_penalty: false,
1226
1227        unofficial: false,
1228    }, // 0x94
1229    OpcodeInfo {
1230        mnemonic: "STA",
1231        addr_mode: AddressingMode::ZeroPageX,
1232        cycles: 4,
1233        page_cross_penalty: false,
1234
1235        unofficial: false,
1236    }, // 0x95
1237    OpcodeInfo {
1238        mnemonic: "STX",
1239        addr_mode: AddressingMode::ZeroPageY,
1240        cycles: 4,
1241        page_cross_penalty: false,
1242
1243        unofficial: false,
1244    }, // 0x96
1245    OpcodeInfo {
1246        mnemonic: "SAX",
1247        addr_mode: AddressingMode::ZeroPageY,
1248        cycles: 4,
1249        page_cross_penalty: false,
1250
1251        unofficial: true,
1252    }, // 0x97 (unofficial)
1253    OpcodeInfo {
1254        mnemonic: "TYA",
1255        addr_mode: AddressingMode::Implied,
1256        cycles: 2,
1257        page_cross_penalty: false,
1258
1259        unofficial: false,
1260    }, // 0x98
1261    OpcodeInfo {
1262        mnemonic: "STA",
1263        addr_mode: AddressingMode::AbsoluteY,
1264        cycles: 5,
1265        page_cross_penalty: false,
1266
1267        unofficial: false,
1268    }, // 0x99
1269    OpcodeInfo {
1270        mnemonic: "TXS",
1271        addr_mode: AddressingMode::Implied,
1272        cycles: 2,
1273        page_cross_penalty: false,
1274
1275        unofficial: false,
1276    }, // 0x9A
1277    OpcodeInfo {
1278        mnemonic: "TAS",
1279        addr_mode: AddressingMode::AbsoluteY,
1280        cycles: 5,
1281        page_cross_penalty: false,
1282
1283        unofficial: true,
1284    }, // 0x9B (unofficial, unstable)
1285    OpcodeInfo {
1286        mnemonic: "SHY",
1287        addr_mode: AddressingMode::AbsoluteX,
1288        cycles: 5,
1289        page_cross_penalty: false,
1290
1291        unofficial: true,
1292    }, // 0x9C (unofficial, unstable)
1293    OpcodeInfo {
1294        mnemonic: "STA",
1295        addr_mode: AddressingMode::AbsoluteX,
1296        cycles: 5,
1297        page_cross_penalty: false,
1298
1299        unofficial: false,
1300    }, // 0x9D
1301    OpcodeInfo {
1302        mnemonic: "SHX",
1303        addr_mode: AddressingMode::AbsoluteY,
1304        cycles: 5,
1305        page_cross_penalty: false,
1306
1307        unofficial: true,
1308    }, // 0x9E (unofficial, unstable)
1309    OpcodeInfo {
1310        mnemonic: "SHA",
1311        addr_mode: AddressingMode::AbsoluteY,
1312        cycles: 5,
1313        page_cross_penalty: false,
1314
1315        unofficial: true,
1316    }, // 0x9F (unofficial, unstable)
1317    // 0xA0-0xAF
1318    OpcodeInfo {
1319        mnemonic: "LDY",
1320        addr_mode: AddressingMode::Immediate,
1321        cycles: 2,
1322        page_cross_penalty: false,
1323
1324        unofficial: false,
1325    }, // 0xA0
1326    OpcodeInfo {
1327        mnemonic: "LDA",
1328        addr_mode: AddressingMode::IndexedIndirectX,
1329        cycles: 6,
1330        page_cross_penalty: false,
1331
1332        unofficial: false,
1333    }, // 0xA1
1334    OpcodeInfo {
1335        mnemonic: "LDX",
1336        addr_mode: AddressingMode::Immediate,
1337        cycles: 2,
1338        page_cross_penalty: false,
1339
1340        unofficial: false,
1341    }, // 0xA2
1342    OpcodeInfo {
1343        mnemonic: "LAX",
1344        addr_mode: AddressingMode::IndexedIndirectX,
1345        cycles: 6,
1346        page_cross_penalty: false,
1347
1348        unofficial: true,
1349    }, // 0xA3 (unofficial)
1350    OpcodeInfo {
1351        mnemonic: "LDY",
1352        addr_mode: AddressingMode::ZeroPage,
1353        cycles: 3,
1354        page_cross_penalty: false,
1355
1356        unofficial: false,
1357    }, // 0xA4
1358    OpcodeInfo {
1359        mnemonic: "LDA",
1360        addr_mode: AddressingMode::ZeroPage,
1361        cycles: 3,
1362        page_cross_penalty: false,
1363
1364        unofficial: false,
1365    }, // 0xA5
1366    OpcodeInfo {
1367        mnemonic: "LDX",
1368        addr_mode: AddressingMode::ZeroPage,
1369        cycles: 3,
1370        page_cross_penalty: false,
1371
1372        unofficial: false,
1373    }, // 0xA6
1374    OpcodeInfo {
1375        mnemonic: "LAX",
1376        addr_mode: AddressingMode::ZeroPage,
1377        cycles: 3,
1378        page_cross_penalty: false,
1379
1380        unofficial: true,
1381    }, // 0xA7 (unofficial)
1382    OpcodeInfo {
1383        mnemonic: "TAY",
1384        addr_mode: AddressingMode::Implied,
1385        cycles: 2,
1386        page_cross_penalty: false,
1387
1388        unofficial: false,
1389    }, // 0xA8
1390    OpcodeInfo {
1391        mnemonic: "LDA",
1392        addr_mode: AddressingMode::Immediate,
1393        cycles: 2,
1394        page_cross_penalty: false,
1395
1396        unofficial: false,
1397    }, // 0xA9
1398    OpcodeInfo {
1399        mnemonic: "TAX",
1400        addr_mode: AddressingMode::Implied,
1401        cycles: 2,
1402        page_cross_penalty: false,
1403
1404        unofficial: false,
1405    }, // 0xAA
1406    OpcodeInfo {
1407        mnemonic: "LXA",
1408        addr_mode: AddressingMode::Immediate,
1409        cycles: 2,
1410        page_cross_penalty: false,
1411
1412        unofficial: true,
1413    }, // 0xAB (unofficial, unstable)
1414    OpcodeInfo {
1415        mnemonic: "LDY",
1416        addr_mode: AddressingMode::Absolute,
1417        cycles: 4,
1418        page_cross_penalty: false,
1419
1420        unofficial: false,
1421    }, // 0xAC
1422    OpcodeInfo {
1423        mnemonic: "LDA",
1424        addr_mode: AddressingMode::Absolute,
1425        cycles: 4,
1426        page_cross_penalty: false,
1427
1428        unofficial: false,
1429    }, // 0xAD
1430    OpcodeInfo {
1431        mnemonic: "LDX",
1432        addr_mode: AddressingMode::Absolute,
1433        cycles: 4,
1434        page_cross_penalty: false,
1435
1436        unofficial: false,
1437    }, // 0xAE
1438    OpcodeInfo {
1439        mnemonic: "LAX",
1440        addr_mode: AddressingMode::Absolute,
1441        cycles: 4,
1442        page_cross_penalty: false,
1443
1444        unofficial: true,
1445    }, // 0xAF (unofficial)
1446    // 0xB0-0xBF
1447    OpcodeInfo {
1448        mnemonic: "BCS",
1449        addr_mode: AddressingMode::Relative,
1450        cycles: 2,
1451        page_cross_penalty: true,
1452
1453        unofficial: false,
1454    }, // 0xB0
1455    OpcodeInfo {
1456        mnemonic: "LDA",
1457        addr_mode: AddressingMode::IndirectIndexedY,
1458        cycles: 5,
1459        page_cross_penalty: true,
1460
1461        unofficial: false,
1462    }, // 0xB1
1463    OpcodeInfo {
1464        mnemonic: "JAM",
1465        addr_mode: AddressingMode::Implied,
1466        cycles: 0,
1467        page_cross_penalty: false,
1468
1469        unofficial: true,
1470    }, // 0xB2 (unofficial)
1471    OpcodeInfo {
1472        mnemonic: "LAX",
1473        addr_mode: AddressingMode::IndirectIndexedY,
1474        cycles: 5,
1475        page_cross_penalty: true,
1476
1477        unofficial: true,
1478    }, // 0xB3 (unofficial)
1479    OpcodeInfo {
1480        mnemonic: "LDY",
1481        addr_mode: AddressingMode::ZeroPageX,
1482        cycles: 4,
1483        page_cross_penalty: false,
1484
1485        unofficial: false,
1486    }, // 0xB4
1487    OpcodeInfo {
1488        mnemonic: "LDA",
1489        addr_mode: AddressingMode::ZeroPageX,
1490        cycles: 4,
1491        page_cross_penalty: false,
1492
1493        unofficial: false,
1494    }, // 0xB5
1495    OpcodeInfo {
1496        mnemonic: "LDX",
1497        addr_mode: AddressingMode::ZeroPageY,
1498        cycles: 4,
1499        page_cross_penalty: false,
1500
1501        unofficial: false,
1502    }, // 0xB6
1503    OpcodeInfo {
1504        mnemonic: "LAX",
1505        addr_mode: AddressingMode::ZeroPageY,
1506        cycles: 4,
1507        page_cross_penalty: false,
1508
1509        unofficial: true,
1510    }, // 0xB7 (unofficial)
1511    OpcodeInfo {
1512        mnemonic: "CLV",
1513        addr_mode: AddressingMode::Implied,
1514        cycles: 2,
1515        page_cross_penalty: false,
1516
1517        unofficial: false,
1518    }, // 0xB8
1519    OpcodeInfo {
1520        mnemonic: "LDA",
1521        addr_mode: AddressingMode::AbsoluteY,
1522        cycles: 4,
1523        page_cross_penalty: true,
1524
1525        unofficial: false,
1526    }, // 0xB9
1527    OpcodeInfo {
1528        mnemonic: "TSX",
1529        addr_mode: AddressingMode::Implied,
1530        cycles: 2,
1531        page_cross_penalty: false,
1532
1533        unofficial: false,
1534    }, // 0xBA
1535    OpcodeInfo {
1536        mnemonic: "LAS",
1537        addr_mode: AddressingMode::AbsoluteY,
1538        cycles: 4,
1539        page_cross_penalty: true,
1540
1541        unofficial: true,
1542    }, // 0xBB (unofficial, unstable)
1543    OpcodeInfo {
1544        mnemonic: "LDY",
1545        addr_mode: AddressingMode::AbsoluteX,
1546        cycles: 4,
1547        page_cross_penalty: true,
1548
1549        unofficial: false,
1550    }, // 0xBC
1551    OpcodeInfo {
1552        mnemonic: "LDA",
1553        addr_mode: AddressingMode::AbsoluteX,
1554        cycles: 4,
1555        page_cross_penalty: true,
1556
1557        unofficial: false,
1558    }, // 0xBD
1559    OpcodeInfo {
1560        mnemonic: "LDX",
1561        addr_mode: AddressingMode::AbsoluteY,
1562        cycles: 4,
1563        page_cross_penalty: true,
1564
1565        unofficial: false,
1566    }, // 0xBE
1567    OpcodeInfo {
1568        mnemonic: "LAX",
1569        addr_mode: AddressingMode::AbsoluteY,
1570        cycles: 4,
1571        page_cross_penalty: true,
1572
1573        unofficial: true,
1574    }, // 0xBF (unofficial)
1575    // 0xC0-0xCF
1576    OpcodeInfo {
1577        mnemonic: "CPY",
1578        addr_mode: AddressingMode::Immediate,
1579        cycles: 2,
1580        page_cross_penalty: false,
1581
1582        unofficial: false,
1583    }, // 0xC0
1584    OpcodeInfo {
1585        mnemonic: "CMP",
1586        addr_mode: AddressingMode::IndexedIndirectX,
1587        cycles: 6,
1588        page_cross_penalty: false,
1589
1590        unofficial: false,
1591    }, // 0xC1
1592    OpcodeInfo {
1593        mnemonic: "NOP",
1594        addr_mode: AddressingMode::Immediate,
1595        cycles: 2,
1596        page_cross_penalty: false,
1597
1598        unofficial: true,
1599    }, // 0xC2 (unofficial)
1600    OpcodeInfo {
1601        mnemonic: "DCP",
1602        addr_mode: AddressingMode::IndexedIndirectX,
1603        cycles: 8,
1604        page_cross_penalty: false,
1605
1606        unofficial: true,
1607    }, // 0xC3 (unofficial)
1608    OpcodeInfo {
1609        mnemonic: "CPY",
1610        addr_mode: AddressingMode::ZeroPage,
1611        cycles: 3,
1612        page_cross_penalty: false,
1613
1614        unofficial: false,
1615    }, // 0xC4
1616    OpcodeInfo {
1617        mnemonic: "CMP",
1618        addr_mode: AddressingMode::ZeroPage,
1619        cycles: 3,
1620        page_cross_penalty: false,
1621
1622        unofficial: false,
1623    }, // 0xC5
1624    OpcodeInfo {
1625        mnemonic: "DEC",
1626        addr_mode: AddressingMode::ZeroPage,
1627        cycles: 5,
1628        page_cross_penalty: false,
1629
1630        unofficial: false,
1631    }, // 0xC6
1632    OpcodeInfo {
1633        mnemonic: "DCP",
1634        addr_mode: AddressingMode::ZeroPage,
1635        cycles: 5,
1636        page_cross_penalty: false,
1637
1638        unofficial: true,
1639    }, // 0xC7 (unofficial)
1640    OpcodeInfo {
1641        mnemonic: "INY",
1642        addr_mode: AddressingMode::Implied,
1643        cycles: 2,
1644        page_cross_penalty: false,
1645
1646        unofficial: false,
1647    }, // 0xC8
1648    OpcodeInfo {
1649        mnemonic: "CMP",
1650        addr_mode: AddressingMode::Immediate,
1651        cycles: 2,
1652        page_cross_penalty: false,
1653
1654        unofficial: false,
1655    }, // 0xC9
1656    OpcodeInfo {
1657        mnemonic: "DEX",
1658        addr_mode: AddressingMode::Implied,
1659        cycles: 2,
1660        page_cross_penalty: false,
1661
1662        unofficial: false,
1663    }, // 0xCA
1664    OpcodeInfo {
1665        mnemonic: "AXS",
1666        addr_mode: AddressingMode::Immediate,
1667        cycles: 2,
1668        page_cross_penalty: false,
1669
1670        unofficial: true,
1671    }, // 0xCB (unofficial)
1672    OpcodeInfo {
1673        mnemonic: "CPY",
1674        addr_mode: AddressingMode::Absolute,
1675        cycles: 4,
1676        page_cross_penalty: false,
1677
1678        unofficial: false,
1679    }, // 0xCC
1680    OpcodeInfo {
1681        mnemonic: "CMP",
1682        addr_mode: AddressingMode::Absolute,
1683        cycles: 4,
1684        page_cross_penalty: false,
1685
1686        unofficial: false,
1687    }, // 0xCD
1688    OpcodeInfo {
1689        mnemonic: "DEC",
1690        addr_mode: AddressingMode::Absolute,
1691        cycles: 6,
1692        page_cross_penalty: false,
1693
1694        unofficial: false,
1695    }, // 0xCE
1696    OpcodeInfo {
1697        mnemonic: "DCP",
1698        addr_mode: AddressingMode::Absolute,
1699        cycles: 6,
1700        page_cross_penalty: false,
1701
1702        unofficial: true,
1703    }, // 0xCF (unofficial)
1704    // 0xD0-0xDF
1705    OpcodeInfo {
1706        mnemonic: "BNE",
1707        addr_mode: AddressingMode::Relative,
1708        cycles: 2,
1709        page_cross_penalty: true,
1710
1711        unofficial: false,
1712    }, // 0xD0
1713    OpcodeInfo {
1714        mnemonic: "CMP",
1715        addr_mode: AddressingMode::IndirectIndexedY,
1716        cycles: 5,
1717        page_cross_penalty: true,
1718
1719        unofficial: false,
1720    }, // 0xD1
1721    OpcodeInfo {
1722        mnemonic: "JAM",
1723        addr_mode: AddressingMode::Implied,
1724        cycles: 0,
1725        page_cross_penalty: false,
1726
1727        unofficial: true,
1728    }, // 0xD2 (unofficial)
1729    OpcodeInfo {
1730        mnemonic: "DCP",
1731        addr_mode: AddressingMode::IndirectIndexedY,
1732        cycles: 8,
1733        page_cross_penalty: false,
1734
1735        unofficial: true,
1736    }, // 0xD3 (unofficial)
1737    OpcodeInfo {
1738        mnemonic: "NOP",
1739        addr_mode: AddressingMode::ZeroPageX,
1740        cycles: 4,
1741        page_cross_penalty: false,
1742
1743        unofficial: true,
1744    }, // 0xD4 (unofficial)
1745    OpcodeInfo {
1746        mnemonic: "CMP",
1747        addr_mode: AddressingMode::ZeroPageX,
1748        cycles: 4,
1749        page_cross_penalty: false,
1750
1751        unofficial: false,
1752    }, // 0xD5
1753    OpcodeInfo {
1754        mnemonic: "DEC",
1755        addr_mode: AddressingMode::ZeroPageX,
1756        cycles: 6,
1757        page_cross_penalty: false,
1758
1759        unofficial: false,
1760    }, // 0xD6
1761    OpcodeInfo {
1762        mnemonic: "DCP",
1763        addr_mode: AddressingMode::ZeroPageX,
1764        cycles: 6,
1765        page_cross_penalty: false,
1766
1767        unofficial: true,
1768    }, // 0xD7 (unofficial)
1769    OpcodeInfo {
1770        mnemonic: "CLD",
1771        addr_mode: AddressingMode::Implied,
1772        cycles: 2,
1773        page_cross_penalty: false,
1774
1775        unofficial: false,
1776    }, // 0xD8
1777    OpcodeInfo {
1778        mnemonic: "CMP",
1779        addr_mode: AddressingMode::AbsoluteY,
1780        cycles: 4,
1781        page_cross_penalty: true,
1782
1783        unofficial: false,
1784    }, // 0xD9
1785    OpcodeInfo {
1786        mnemonic: "NOP",
1787        addr_mode: AddressingMode::Implied,
1788        cycles: 2,
1789        page_cross_penalty: false,
1790
1791        unofficial: true,
1792    }, // 0xDA (unofficial)
1793    OpcodeInfo {
1794        mnemonic: "DCP",
1795        addr_mode: AddressingMode::AbsoluteY,
1796        cycles: 7,
1797        page_cross_penalty: false,
1798
1799        unofficial: true,
1800    }, // 0xDB (unofficial)
1801    OpcodeInfo {
1802        mnemonic: "NOP",
1803        addr_mode: AddressingMode::AbsoluteX,
1804        cycles: 4,
1805        page_cross_penalty: true,
1806
1807        unofficial: true,
1808    }, // 0xDC (unofficial)
1809    OpcodeInfo {
1810        mnemonic: "CMP",
1811        addr_mode: AddressingMode::AbsoluteX,
1812        cycles: 4,
1813        page_cross_penalty: true,
1814
1815        unofficial: false,
1816    }, // 0xDD
1817    OpcodeInfo {
1818        mnemonic: "DEC",
1819        addr_mode: AddressingMode::AbsoluteX,
1820        cycles: 7,
1821        page_cross_penalty: false,
1822
1823        unofficial: false,
1824    }, // 0xDE
1825    OpcodeInfo {
1826        mnemonic: "DCP",
1827        addr_mode: AddressingMode::AbsoluteX,
1828        cycles: 7,
1829        page_cross_penalty: false,
1830
1831        unofficial: true,
1832    }, // 0xDF (unofficial)
1833    // 0xE0-0xEF
1834    OpcodeInfo {
1835        mnemonic: "CPX",
1836        addr_mode: AddressingMode::Immediate,
1837        cycles: 2,
1838        page_cross_penalty: false,
1839
1840        unofficial: false,
1841    }, // 0xE0
1842    OpcodeInfo {
1843        mnemonic: "SBC",
1844        addr_mode: AddressingMode::IndexedIndirectX,
1845        cycles: 6,
1846        page_cross_penalty: false,
1847
1848        unofficial: false,
1849    }, // 0xE1
1850    OpcodeInfo {
1851        mnemonic: "NOP",
1852        addr_mode: AddressingMode::Immediate,
1853        cycles: 2,
1854        page_cross_penalty: false,
1855
1856        unofficial: true,
1857    }, // 0xE2 (unofficial)
1858    OpcodeInfo {
1859        mnemonic: "ISB",
1860        addr_mode: AddressingMode::IndexedIndirectX,
1861        cycles: 8,
1862        page_cross_penalty: false,
1863
1864        unofficial: true,
1865    }, // 0xE3 (unofficial)
1866    OpcodeInfo {
1867        mnemonic: "CPX",
1868        addr_mode: AddressingMode::ZeroPage,
1869        cycles: 3,
1870        page_cross_penalty: false,
1871
1872        unofficial: false,
1873    }, // 0xE4
1874    OpcodeInfo {
1875        mnemonic: "SBC",
1876        addr_mode: AddressingMode::ZeroPage,
1877        cycles: 3,
1878        page_cross_penalty: false,
1879
1880        unofficial: false,
1881    }, // 0xE5
1882    OpcodeInfo {
1883        mnemonic: "INC",
1884        addr_mode: AddressingMode::ZeroPage,
1885        cycles: 5,
1886        page_cross_penalty: false,
1887
1888        unofficial: false,
1889    }, // 0xE6
1890    OpcodeInfo {
1891        mnemonic: "ISB",
1892        addr_mode: AddressingMode::ZeroPage,
1893        cycles: 5,
1894        page_cross_penalty: false,
1895
1896        unofficial: true,
1897    }, // 0xE7 (unofficial)
1898    OpcodeInfo {
1899        mnemonic: "INX",
1900        addr_mode: AddressingMode::Implied,
1901        cycles: 2,
1902        page_cross_penalty: false,
1903
1904        unofficial: false,
1905    }, // 0xE8
1906    OpcodeInfo {
1907        mnemonic: "SBC",
1908        addr_mode: AddressingMode::Immediate,
1909        cycles: 2,
1910        page_cross_penalty: false,
1911
1912        unofficial: false,
1913    }, // 0xE9
1914    OpcodeInfo {
1915        mnemonic: "NOP",
1916        addr_mode: AddressingMode::Implied,
1917        cycles: 2,
1918        page_cross_penalty: false,
1919
1920        unofficial: false,
1921    }, // 0xEA
1922    OpcodeInfo {
1923        mnemonic: "SBC",
1924        addr_mode: AddressingMode::Immediate,
1925        cycles: 2,
1926        page_cross_penalty: false,
1927
1928        unofficial: true,
1929    }, // 0xEB (unofficial, same as 0xE9)
1930    OpcodeInfo {
1931        mnemonic: "CPX",
1932        addr_mode: AddressingMode::Absolute,
1933        cycles: 4,
1934        page_cross_penalty: false,
1935
1936        unofficial: false,
1937    }, // 0xEC
1938    OpcodeInfo {
1939        mnemonic: "SBC",
1940        addr_mode: AddressingMode::Absolute,
1941        cycles: 4,
1942        page_cross_penalty: false,
1943
1944        unofficial: false,
1945    }, // 0xED
1946    OpcodeInfo {
1947        mnemonic: "INC",
1948        addr_mode: AddressingMode::Absolute,
1949        cycles: 6,
1950        page_cross_penalty: false,
1951
1952        unofficial: false,
1953    }, // 0xEE
1954    OpcodeInfo {
1955        mnemonic: "ISB",
1956        addr_mode: AddressingMode::Absolute,
1957        cycles: 6,
1958        page_cross_penalty: false,
1959
1960        unofficial: true,
1961    }, // 0xEF (unofficial)
1962    // 0xF0-0xFF
1963    OpcodeInfo {
1964        mnemonic: "BEQ",
1965        addr_mode: AddressingMode::Relative,
1966        cycles: 2,
1967        page_cross_penalty: true,
1968
1969        unofficial: false,
1970    }, // 0xF0
1971    OpcodeInfo {
1972        mnemonic: "SBC",
1973        addr_mode: AddressingMode::IndirectIndexedY,
1974        cycles: 5,
1975        page_cross_penalty: true,
1976
1977        unofficial: false,
1978    }, // 0xF1
1979    OpcodeInfo {
1980        mnemonic: "JAM",
1981        addr_mode: AddressingMode::Implied,
1982        cycles: 0,
1983        page_cross_penalty: false,
1984
1985        unofficial: true,
1986    }, // 0xF2 (unofficial)
1987    OpcodeInfo {
1988        mnemonic: "ISB",
1989        addr_mode: AddressingMode::IndirectIndexedY,
1990        cycles: 8,
1991        page_cross_penalty: false,
1992
1993        unofficial: true,
1994    }, // 0xF3 (unofficial)
1995    OpcodeInfo {
1996        mnemonic: "NOP",
1997        addr_mode: AddressingMode::ZeroPageX,
1998        cycles: 4,
1999        page_cross_penalty: false,
2000
2001        unofficial: true,
2002    }, // 0xF4 (unofficial)
2003    OpcodeInfo {
2004        mnemonic: "SBC",
2005        addr_mode: AddressingMode::ZeroPageX,
2006        cycles: 4,
2007        page_cross_penalty: false,
2008
2009        unofficial: false,
2010    }, // 0xF5
2011    OpcodeInfo {
2012        mnemonic: "INC",
2013        addr_mode: AddressingMode::ZeroPageX,
2014        cycles: 6,
2015        page_cross_penalty: false,
2016
2017        unofficial: false,
2018    }, // 0xF6
2019    OpcodeInfo {
2020        mnemonic: "ISB",
2021        addr_mode: AddressingMode::ZeroPageX,
2022        cycles: 6,
2023        page_cross_penalty: false,
2024
2025        unofficial: true,
2026    }, // 0xF7 (unofficial)
2027    OpcodeInfo {
2028        mnemonic: "SED",
2029        addr_mode: AddressingMode::Implied,
2030        cycles: 2,
2031        page_cross_penalty: false,
2032
2033        unofficial: false,
2034    }, // 0xF8
2035    OpcodeInfo {
2036        mnemonic: "SBC",
2037        addr_mode: AddressingMode::AbsoluteY,
2038        cycles: 4,
2039        page_cross_penalty: true,
2040
2041        unofficial: false,
2042    }, // 0xF9
2043    OpcodeInfo {
2044        mnemonic: "NOP",
2045        addr_mode: AddressingMode::Implied,
2046        cycles: 2,
2047        page_cross_penalty: false,
2048
2049        unofficial: true,
2050    }, // 0xFA (unofficial)
2051    OpcodeInfo {
2052        mnemonic: "ISB",
2053        addr_mode: AddressingMode::AbsoluteY,
2054        cycles: 7,
2055        page_cross_penalty: false,
2056
2057        unofficial: true,
2058    }, // 0xFB (unofficial)
2059    OpcodeInfo {
2060        mnemonic: "NOP",
2061        addr_mode: AddressingMode::AbsoluteX,
2062        cycles: 4,
2063        page_cross_penalty: true,
2064
2065        unofficial: true,
2066    }, // 0xFC (unofficial)
2067    OpcodeInfo {
2068        mnemonic: "SBC",
2069        addr_mode: AddressingMode::AbsoluteX,
2070        cycles: 4,
2071        page_cross_penalty: true,
2072
2073        unofficial: false,
2074    }, // 0xFD
2075    OpcodeInfo {
2076        mnemonic: "INC",
2077        addr_mode: AddressingMode::AbsoluteX,
2078        cycles: 7,
2079        page_cross_penalty: false,
2080
2081        unofficial: false,
2082    }, // 0xFE
2083    OpcodeInfo {
2084        mnemonic: "ISB",
2085        addr_mode: AddressingMode::AbsoluteX,
2086        cycles: 7,
2087        page_cross_penalty: false,
2088
2089        unofficial: true,
2090    }, // 0xFF (unofficial)
2091];
2092
2093#[cfg(test)]
2094mod tests {
2095    use super::*;
2096
2097    #[test]
2098    fn test_opcode_table_size() {
2099        assert_eq!(OPCODE_TABLE.len(), 256);
2100    }
2101
2102    #[test]
2103    fn test_known_opcodes() {
2104        // Official opcodes
2105        assert_eq!(OPCODE_TABLE[0x00].mnemonic, "BRK");
2106        assert_eq!(OPCODE_TABLE[0xA9].mnemonic, "LDA");
2107        assert_eq!(OPCODE_TABLE[0xEA].mnemonic, "NOP");
2108
2109        // Unofficial opcodes
2110        assert_eq!(OPCODE_TABLE[0xA7].mnemonic, "LAX");
2111        assert_eq!(OPCODE_TABLE[0x87].mnemonic, "SAX");
2112        assert_eq!(OPCODE_TABLE[0xC7].mnemonic, "DCP");
2113    }
2114
2115    #[test]
2116    fn test_cycle_counts() {
2117        assert_eq!(OPCODE_TABLE[0xA9].cycles, 2); // LDA immediate
2118        assert_eq!(OPCODE_TABLE[0xAD].cycles, 4); // LDA absolute
2119        assert_eq!(OPCODE_TABLE[0x00].cycles, 7); // BRK
2120    }
2121
2122    #[test]
2123    fn test_page_cross_penalties() {
2124        assert!(OPCODE_TABLE[0xBD].page_cross_penalty); // LDA absolute,X
2125        assert!(!OPCODE_TABLE[0x8D].page_cross_penalty); // STA absolute
2126    }
2127}