1#[derive(Copy, Clone, Debug, PartialEq, Eq)]
29pub enum Instruction {
30 ADC,
32
33 ADCnd,
35
36 AND,
38
39 ASL,
41
42 BCC,
44
45 BCS,
47
48 BEQ,
50
51 BIT,
53
54 BMI,
56
57 BNE,
59
60 BPL,
62
63 BRA,
65
66 BRK,
68
69 BRKcld,
71
72 BVC,
74
75 BVS,
77
78 CLC,
80
81 CLD,
83
84 CLI,
86
87 CLV,
89
90 CMP,
92
93 CPX,
95
96 CPY,
98
99 DEC,
101
102 DEX,
104
105 DEY,
107
108 EOR,
110
111 INC,
113
114 INX,
116
117 INY,
119
120 JMP,
122
123 JSR,
125
126 LDA,
128
129 LDX,
131
132 LDY,
134
135 LSR,
137
138 NOP,
140
141 ORA,
143
144 PHA,
146
147 PHX,
149
150 PHY,
152
153 PHP,
155
156 PLA,
158
159 PLX,
161
162 PLY,
164
165 PLP,
167
168 ROL,
170
171 ROR,
173
174 RTI,
176
177 RTS,
179
180 SBC,
182
183 SBCnd,
185
186 SEC,
188
189 SED,
191
192 SEI,
194
195 STA,
197
198 STX,
200
201 STY,
203
204 STZ,
206
207 TAX,
209
210 TAY,
212
213 TRB,
215
216 TSB,
218
219 TSX,
221
222 TXA,
224
225 TXS,
227
228 TYA,
230}
231
232#[derive(Copy, Clone, Debug)]
233pub enum OpInput {
234 UseImplied,
235 UseImmediate(u8),
236 UseRelative(u16),
237 UseAddress(u16),
238}
239
240#[derive(Copy, Clone, Debug)]
241pub enum AddressingMode {
242 Accumulator,
244
245 Implied,
247
248 Immediate,
250
251 ZeroPage,
253
254 ZeroPageX,
256
257 ZeroPageY,
259
260 Relative,
262
263 Absolute,
265
266 AbsoluteX,
268
269 AbsoluteY,
271
272 BuggyIndirect,
274
275 Indirect,
277
278 IndexedIndirectX,
280
281 IndirectIndexedY,
283
284 ZeroPageIndirect,
286}
287
288impl AddressingMode {
289 #[must_use]
290 pub const fn extra_bytes(self) -> u16 {
291 match self {
292 AddressingMode::Accumulator => 0,
293 AddressingMode::Implied => 0,
294 AddressingMode::Immediate => 1,
295 AddressingMode::ZeroPage => 1,
296 AddressingMode::ZeroPageX => 1,
297 AddressingMode::ZeroPageY => 1,
298 AddressingMode::Relative => 1,
299 AddressingMode::Absolute => 2,
300 AddressingMode::AbsoluteX => 2,
301 AddressingMode::AbsoluteY => 2,
302 AddressingMode::Indirect => 2,
303 AddressingMode::BuggyIndirect => 2,
304 AddressingMode::IndexedIndirectX => 1,
305 AddressingMode::IndirectIndexedY => 1,
306 AddressingMode::ZeroPageIndirect => 1,
307 }
308 }
309}
310
311pub type DecodedInstr = (Instruction, OpInput);
312
313#[derive(Copy, Clone, Debug, Default)]
315pub struct Nmos6502;
316
317impl crate::Variant for Nmos6502 {
318 fn decode(opcode: u8) -> Option<(Instruction, AddressingMode)> {
319 match opcode {
320 0x00 => Some((Instruction::BRK, AddressingMode::Implied)),
321 0x01 => Some((Instruction::ORA, AddressingMode::IndexedIndirectX)),
322 0x02 => None,
323 0x03 => None,
324 0x04 => None,
325 0x05 => Some((Instruction::ORA, AddressingMode::ZeroPage)),
326 0x06 => Some((Instruction::ASL, AddressingMode::ZeroPage)),
327 0x07 => None,
328 0x08 => Some((Instruction::PHP, AddressingMode::Implied)),
329 0x09 => Some((Instruction::ORA, AddressingMode::Immediate)),
330 0x0a => Some((Instruction::ASL, AddressingMode::Accumulator)),
331 0x0b => None,
332 0x0c => None,
333 0x0d => Some((Instruction::ORA, AddressingMode::Absolute)),
334 0x0e => Some((Instruction::ASL, AddressingMode::Absolute)),
335 0x0f => None,
336 0x10 => Some((Instruction::BPL, AddressingMode::Relative)),
337 0x11 => Some((Instruction::ORA, AddressingMode::IndirectIndexedY)),
338 0x12 => None,
339 0x13 => None,
340 0x14 => None,
341 0x15 => Some((Instruction::ORA, AddressingMode::ZeroPageX)),
342 0x16 => Some((Instruction::ASL, AddressingMode::ZeroPageX)),
343 0x17 => None,
344 0x18 => Some((Instruction::CLC, AddressingMode::Implied)),
345 0x19 => Some((Instruction::ORA, AddressingMode::AbsoluteY)),
346 0x1a => None,
347 0x1b => None,
348 0x1c => None,
349 0x1d => Some((Instruction::ORA, AddressingMode::AbsoluteX)),
350 0x1e => Some((Instruction::ASL, AddressingMode::AbsoluteX)),
351 0x1f => None,
352 0x20 => Some((Instruction::JSR, AddressingMode::Absolute)),
353 0x21 => Some((Instruction::AND, AddressingMode::IndexedIndirectX)),
354 0x22 => None,
355 0x23 => None,
356 0x24 => Some((Instruction::BIT, AddressingMode::ZeroPage)),
357 0x25 => Some((Instruction::AND, AddressingMode::ZeroPage)),
358 0x26 => Some((Instruction::ROL, AddressingMode::ZeroPage)),
359 0x27 => None,
360 0x28 => Some((Instruction::PLP, AddressingMode::Implied)),
361 0x29 => Some((Instruction::AND, AddressingMode::Immediate)),
362 0x2a => Some((Instruction::ROL, AddressingMode::Accumulator)),
363 0x2b => None,
364 0x2c => Some((Instruction::BIT, AddressingMode::Absolute)),
365 0x2d => Some((Instruction::AND, AddressingMode::Absolute)),
366 0x2e => Some((Instruction::ROL, AddressingMode::Absolute)),
367 0x2f => None,
368 0x30 => Some((Instruction::BMI, AddressingMode::Relative)),
369 0x31 => Some((Instruction::AND, AddressingMode::IndirectIndexedY)),
370 0x32 => None,
371 0x33 => None,
372 0x34 => None,
373 0x35 => Some((Instruction::AND, AddressingMode::ZeroPageX)),
374 0x36 => Some((Instruction::ROL, AddressingMode::ZeroPageX)),
375 0x37 => None,
376 0x38 => Some((Instruction::SEC, AddressingMode::Implied)),
377 0x39 => Some((Instruction::AND, AddressingMode::AbsoluteY)),
378 0x3a => None,
379 0x3b => None,
380 0x3c => None,
381 0x3d => Some((Instruction::AND, AddressingMode::AbsoluteX)),
382 0x3e => Some((Instruction::ROL, AddressingMode::AbsoluteX)),
383 0x3f => None,
384 0x40 => Some((Instruction::RTI, AddressingMode::Implied)),
385 0x41 => Some((Instruction::EOR, AddressingMode::IndexedIndirectX)),
386 0x42 => None,
387 0x43 => None,
388 0x44 => None,
389 0x45 => Some((Instruction::EOR, AddressingMode::ZeroPage)),
390 0x46 => Some((Instruction::LSR, AddressingMode::ZeroPage)),
391 0x47 => None,
392 0x48 => Some((Instruction::PHA, AddressingMode::Implied)),
393 0x49 => Some((Instruction::EOR, AddressingMode::Immediate)),
394 0x4a => Some((Instruction::LSR, AddressingMode::Accumulator)),
395 0x4b => None,
396 0x4c => Some((Instruction::JMP, AddressingMode::Absolute)),
397 0x4d => Some((Instruction::EOR, AddressingMode::Absolute)),
398 0x4e => Some((Instruction::LSR, AddressingMode::Absolute)),
399 0x4f => None,
400 0x50 => Some((Instruction::BVC, AddressingMode::Relative)),
401 0x51 => Some((Instruction::EOR, AddressingMode::IndirectIndexedY)),
402 0x52 => None,
403 0x53 => None,
404 0x54 => None,
405 0x55 => Some((Instruction::EOR, AddressingMode::ZeroPageX)),
406 0x56 => Some((Instruction::LSR, AddressingMode::ZeroPageX)),
407 0x57 => None,
408 0x58 => Some((Instruction::CLI, AddressingMode::Implied)),
409 0x59 => Some((Instruction::EOR, AddressingMode::AbsoluteY)),
410 0x5a => None,
411 0x5b => None,
412 0x5c => None,
413 0x5d => Some((Instruction::EOR, AddressingMode::AbsoluteX)),
414 0x5e => Some((Instruction::LSR, AddressingMode::AbsoluteX)),
415 0x5f => None,
416 0x60 => Some((Instruction::RTS, AddressingMode::Implied)),
417 0x61 => Some((Instruction::ADC, AddressingMode::IndexedIndirectX)),
418 0x62 => None,
419 0x63 => None,
420 0x64 => None,
421 0x65 => Some((Instruction::ADC, AddressingMode::ZeroPage)),
422 0x66 => Some((Instruction::ROR, AddressingMode::ZeroPage)),
423 0x67 => None,
424 0x68 => Some((Instruction::PLA, AddressingMode::Implied)),
425 0x69 => Some((Instruction::ADC, AddressingMode::Immediate)),
426 0x6a => Some((Instruction::ROR, AddressingMode::Accumulator)),
427 0x6b => None,
428 0x6c => Some((Instruction::JMP, AddressingMode::BuggyIndirect)),
429 0x6d => Some((Instruction::ADC, AddressingMode::Absolute)),
430 0x6e => Some((Instruction::ROR, AddressingMode::Absolute)),
431 0x6f => None,
432 0x70 => Some((Instruction::BVS, AddressingMode::Relative)),
433 0x71 => Some((Instruction::ADC, AddressingMode::IndirectIndexedY)),
434 0x72 => None,
435 0x73 => None,
436 0x74 => None,
437 0x75 => Some((Instruction::ADC, AddressingMode::ZeroPageX)),
438 0x76 => Some((Instruction::ROR, AddressingMode::ZeroPageX)),
439 0x77 => None,
440 0x78 => Some((Instruction::SEI, AddressingMode::Implied)),
441 0x79 => Some((Instruction::ADC, AddressingMode::AbsoluteY)),
442 0x7a => None,
443 0x7b => None,
444 0x7c => None,
445 0x7d => Some((Instruction::ADC, AddressingMode::AbsoluteX)),
446 0x7e => Some((Instruction::ROR, AddressingMode::AbsoluteX)),
447 0x7f => None,
448 0x80 => None,
449 0x81 => Some((Instruction::STA, AddressingMode::IndexedIndirectX)),
450 0x82 => None,
451 0x83 => None,
452 0x84 => Some((Instruction::STY, AddressingMode::ZeroPage)),
453 0x85 => Some((Instruction::STA, AddressingMode::ZeroPage)),
454 0x86 => Some((Instruction::STX, AddressingMode::ZeroPage)),
455 0x87 => None,
456 0x88 => Some((Instruction::DEY, AddressingMode::Implied)),
457 0x89 => None,
458 0x8a => Some((Instruction::TXA, AddressingMode::Implied)),
459 0x8b => None,
460 0x8c => Some((Instruction::STY, AddressingMode::Absolute)),
461 0x8d => Some((Instruction::STA, AddressingMode::Absolute)),
462 0x8e => Some((Instruction::STX, AddressingMode::Absolute)),
463 0x8f => None,
464 0x90 => Some((Instruction::BCC, AddressingMode::Relative)),
465 0x91 => Some((Instruction::STA, AddressingMode::IndirectIndexedY)),
466 0x92 => None,
467 0x93 => None,
468 0x94 => Some((Instruction::STY, AddressingMode::ZeroPageX)),
469 0x95 => Some((Instruction::STA, AddressingMode::ZeroPageX)),
470 0x96 => Some((Instruction::STX, AddressingMode::ZeroPageY)),
471 0x97 => None,
472 0x98 => Some((Instruction::TYA, AddressingMode::Implied)),
473 0x99 => Some((Instruction::STA, AddressingMode::AbsoluteY)),
474 0x9a => Some((Instruction::TXS, AddressingMode::Implied)),
475 0x9b => None,
476 0x9c => None,
477 0x9d => Some((Instruction::STA, AddressingMode::AbsoluteX)),
478 0x9e => None,
479 0x9f => None,
480 0xa0 => Some((Instruction::LDY, AddressingMode::Immediate)),
481 0xa1 => Some((Instruction::LDA, AddressingMode::IndexedIndirectX)),
482 0xa2 => Some((Instruction::LDX, AddressingMode::Immediate)),
483 0xa3 => None,
484 0xa4 => Some((Instruction::LDY, AddressingMode::ZeroPage)),
485 0xa5 => Some((Instruction::LDA, AddressingMode::ZeroPage)),
486 0xa6 => Some((Instruction::LDX, AddressingMode::ZeroPage)),
487 0xa7 => None,
488 0xa8 => Some((Instruction::TAY, AddressingMode::Implied)),
489 0xa9 => Some((Instruction::LDA, AddressingMode::Immediate)),
490 0xaa => Some((Instruction::TAX, AddressingMode::Implied)),
491 0xab => None,
492 0xac => Some((Instruction::LDY, AddressingMode::Absolute)),
493 0xad => Some((Instruction::LDA, AddressingMode::Absolute)),
494 0xae => Some((Instruction::LDX, AddressingMode::Absolute)),
495 0xaf => None,
496 0xb0 => Some((Instruction::BCS, AddressingMode::Relative)),
497 0xb1 => Some((Instruction::LDA, AddressingMode::IndirectIndexedY)),
498 0xb2 => None,
499 0xb3 => None,
500 0xb4 => Some((Instruction::LDY, AddressingMode::ZeroPageX)),
501 0xb5 => Some((Instruction::LDA, AddressingMode::ZeroPageX)),
502 0xb6 => Some((Instruction::LDX, AddressingMode::ZeroPageY)),
503 0xb7 => None,
504 0xb8 => Some((Instruction::CLV, AddressingMode::Implied)),
505 0xb9 => Some((Instruction::LDA, AddressingMode::AbsoluteY)),
506 0xba => Some((Instruction::TSX, AddressingMode::Implied)),
507 0xbb => None,
508 0xbc => Some((Instruction::LDY, AddressingMode::AbsoluteX)),
509 0xbd => Some((Instruction::LDA, AddressingMode::AbsoluteX)),
510 0xbe => Some((Instruction::LDX, AddressingMode::AbsoluteY)),
511 0xbf => None,
512 0xc0 => Some((Instruction::CPY, AddressingMode::Immediate)),
513 0xc1 => Some((Instruction::CMP, AddressingMode::IndexedIndirectX)),
514 0xc2 => None,
515 0xc3 => None,
516 0xc4 => Some((Instruction::CPY, AddressingMode::ZeroPage)),
517 0xc5 => Some((Instruction::CMP, AddressingMode::ZeroPage)),
518 0xc6 => Some((Instruction::DEC, AddressingMode::ZeroPage)),
519 0xc7 => None,
520 0xc8 => Some((Instruction::INY, AddressingMode::Implied)),
521 0xc9 => Some((Instruction::CMP, AddressingMode::Immediate)),
522 0xca => Some((Instruction::DEX, AddressingMode::Implied)),
523 0xcb => None,
524 0xcc => Some((Instruction::CPY, AddressingMode::Absolute)),
525 0xcd => Some((Instruction::CMP, AddressingMode::Absolute)),
526 0xce => Some((Instruction::DEC, AddressingMode::Absolute)),
527 0xcf => None,
528 0xd0 => Some((Instruction::BNE, AddressingMode::Relative)),
529 0xd1 => Some((Instruction::CMP, AddressingMode::IndirectIndexedY)),
530 0xd2 => None,
531 0xd3 => None,
532 0xd4 => None,
533 0xd5 => Some((Instruction::CMP, AddressingMode::ZeroPageX)),
534 0xd6 => Some((Instruction::DEC, AddressingMode::ZeroPageX)),
535 0xd7 => None,
536 0xd8 => Some((Instruction::CLD, AddressingMode::Implied)),
537 0xd9 => Some((Instruction::CMP, AddressingMode::AbsoluteY)),
538 0xda => None,
539 0xdb => None,
540 0xdc => None,
541 0xdd => Some((Instruction::CMP, AddressingMode::AbsoluteX)),
542 0xde => Some((Instruction::DEC, AddressingMode::AbsoluteX)),
543 0xdf => None,
544 0xe0 => Some((Instruction::CPX, AddressingMode::Immediate)),
545 0xe1 => Some((Instruction::SBC, AddressingMode::IndexedIndirectX)),
546 0xe2 => None,
547 0xe3 => None,
548 0xe4 => Some((Instruction::CPX, AddressingMode::ZeroPage)),
549 0xe5 => Some((Instruction::SBC, AddressingMode::ZeroPage)),
550 0xe6 => Some((Instruction::INC, AddressingMode::ZeroPage)),
551 0xe7 => None,
552 0xe8 => Some((Instruction::INX, AddressingMode::Implied)),
553 0xe9 => Some((Instruction::SBC, AddressingMode::Immediate)),
554 0xea => Some((Instruction::NOP, AddressingMode::Implied)),
555 0xeb => None,
556 0xec => Some((Instruction::CPX, AddressingMode::Absolute)),
557 0xed => Some((Instruction::SBC, AddressingMode::Absolute)),
558 0xee => Some((Instruction::INC, AddressingMode::Absolute)),
559 0xef => None,
560 0xf0 => Some((Instruction::BEQ, AddressingMode::Relative)),
561 0xf1 => Some((Instruction::SBC, AddressingMode::IndirectIndexedY)),
562 0xf2 => None,
563 0xf3 => None,
564 0xf4 => None,
565 0xf5 => Some((Instruction::SBC, AddressingMode::ZeroPageX)),
566 0xf6 => Some((Instruction::INC, AddressingMode::ZeroPageX)),
567 0xf7 => None,
568 0xf8 => Some((Instruction::SED, AddressingMode::Implied)),
569 0xf9 => Some((Instruction::SBC, AddressingMode::AbsoluteY)),
570 0xfa => None,
571 0xfb => None,
572 0xfc => None,
573 0xfd => Some((Instruction::SBC, AddressingMode::AbsoluteX)),
574 0xfe => Some((Instruction::INC, AddressingMode::AbsoluteX)),
575 0xff => None,
576 }
577 }
578}
579
580#[derive(Copy, Clone, Debug, Default)]
583pub struct Ricoh2a03;
584
585impl crate::Variant for Ricoh2a03 {
586 fn decode(opcode: u8) -> Option<(Instruction, AddressingMode)> {
587 match Nmos6502::decode(opcode) {
589 Some((Instruction::ADC, addressing_mode)) => {
590 Some((Instruction::ADCnd, addressing_mode))
591 }
592 Some((Instruction::SBC, addressing_mode)) => {
593 Some((Instruction::SBCnd, addressing_mode))
594 }
595 something_else => something_else,
596 }
597 }
598}
599
600#[derive(Copy, Clone, Debug, Default)]
603pub struct RevisionA;
604
605impl crate::Variant for RevisionA {
606 fn decode(opcode: u8) -> Option<(Instruction, AddressingMode)> {
607 match Nmos6502::decode(opcode) {
609 Some((Instruction::ROR, _)) => None,
610 something_else => something_else,
611 }
612 }
613}
614
615#[derive(Copy, Clone, Debug, Default)]
617pub struct Cmos6502;
618
619impl crate::Variant for Cmos6502 {
620 fn decode(opcode: u8) -> Option<(Instruction, AddressingMode)> {
621 match opcode {
623 0x00 => Some((Instruction::BRKcld, AddressingMode::Implied)),
624 0x1a => Some((Instruction::INC, AddressingMode::Accumulator)),
625 0x3a => Some((Instruction::DEC, AddressingMode::Accumulator)),
626 0x6c => Some((Instruction::JMP, AddressingMode::Indirect)),
627 0x80 => Some((Instruction::BRA, AddressingMode::Relative)),
628 0x64 => Some((Instruction::STZ, AddressingMode::ZeroPage)),
629 0x74 => Some((Instruction::STZ, AddressingMode::ZeroPageX)),
630 0x9c => Some((Instruction::STZ, AddressingMode::Absolute)),
631 0x9e => Some((Instruction::STZ, AddressingMode::AbsoluteX)),
632 0x7a => Some((Instruction::PLY, AddressingMode::Implied)),
633 0xfa => Some((Instruction::PLX, AddressingMode::Implied)),
634 0x5a => Some((Instruction::PHY, AddressingMode::Implied)),
635 0xda => Some((Instruction::PHX, AddressingMode::Implied)),
636 0x04 => Some((Instruction::TSB, AddressingMode::ZeroPage)),
637 0x14 => Some((Instruction::TRB, AddressingMode::ZeroPage)),
638 0x0c => Some((Instruction::TSB, AddressingMode::Absolute)),
639 0x1c => Some((Instruction::TRB, AddressingMode::Absolute)),
640 0x12 => Some((Instruction::ORA, AddressingMode::ZeroPageIndirect)),
641 0x32 => Some((Instruction::AND, AddressingMode::ZeroPageIndirect)),
642 0x52 => Some((Instruction::EOR, AddressingMode::ZeroPageIndirect)),
643 0x72 => Some((Instruction::ADC, AddressingMode::ZeroPageIndirect)),
644 0x92 => Some((Instruction::STA, AddressingMode::ZeroPageIndirect)),
645 0xb2 => Some((Instruction::LDA, AddressingMode::ZeroPageIndirect)),
646 0xd2 => Some((Instruction::CMP, AddressingMode::ZeroPageIndirect)),
647 0xf2 => Some((Instruction::SBC, AddressingMode::ZeroPageIndirect)),
648 0x89 => Some((Instruction::BIT, AddressingMode::Immediate)),
649 _ => Nmos6502::decode(opcode),
650 }
651 }
652}