FabGL
ESP32 Display Controller and Graphics Library
MOS6502.cpp
1/*
2 Created by Fabrizio Di Vittorio (fdivitto2013@gmail.com) - <http://www.fabgl.com>
3 Copyright (c) 2019-2022 Fabrizio Di Vittorio.
4 All rights reserved.
5
6
7* Please contact fdivitto2013@gmail.com if you need a commercial license.
8
9
10* This library and related software is available under GPL v3.
11
12 FabGL is free software: you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation, either version 3 of the License, or
15 (at your option) any later version.
16
17 FabGL is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
21
22 You should have received a copy of the GNU General Public License
23 along with FabGL. If not, see <http://www.gnu.org/licenses/>.
24 */
25
26
27#include "MOS6502.h"
28
29
30#pragma GCC optimize ("O2")
31
32
33namespace fabgl {
34
35
36// compose status word
37#define COMPOSE_STATUS (0x20 | ((int)m_carry) | ((int)m_zero << 1) | ((int)m_intDisable << 2) | ((int)m_decimal << 3) | ((int)m_overflow << 6) | ((int) m_negative << 7))
38
39
40// decompose status word
41#define DECOMPOSE_STATUS(status) { \
42 int s = (status); \
43 m_carry = s & 0x01; \
44 m_zero = s & 0x02; \
45 m_intDisable = s & 0x04; \
46 m_decimal = s & 0x08; \
47 m_overflow = s & 0x40; \
48 m_negative = s & 0x80; \
49 setADCSBC(); \
50}
51
52
53#define BUSREAD(addr) (m_readByte(m_context, (addr)))
54#define BUSWRITE(addr, value) (m_writeByte(m_context, (addr), (value)))
55#define PAGE0READ(addr) (m_page0ReadByte(m_context, (addr)))
56#define PAGE0WRITE(addr, value) (m_page0WriteByte(m_context, (addr), (value)))
57#define PAGE1READ(addr) (m_page1ReadByte(m_context, (addr)))
58#define PAGE1WRITE(addr, value) (m_page1WriteByte(m_context, (addr), (value)))
59
60
61#define STACKPUSHBYTE(v) PAGE1WRITE(m_SP--, (v))
62
63#define STACKPUSHWORD(v) { PAGE1WRITE(m_SP--, (v) >> 8); PAGE1WRITE(m_SP--, (v) & 0xff); }
64
65#define STACKPOPBYTE() PAGE1READ(++m_SP)
66
67#define STACKPOPWORD() (m_SP += 2, (PAGE1READ(m_SP - 1) | (PAGE1READ(m_SP) << 8)))
68
69
70int MOS6502::reset()
71{
72 m_A = m_X = m_Y = 0;
73 m_SP = 0xfd; // transistor level simulators reset SP to 0xfd
74 m_PC = (BUSREAD(0xfffd) << 8) + BUSREAD(0xfffc); // reset vector at 0xfffc
75 m_decimal = false;
76 setADCSBC();
77 return 6;
78}
79
80
81int MOS6502::IRQ()
82{
83 if (!m_intDisable) {
84 STACKPUSHWORD(m_PC);
85 STACKPUSHBYTE(COMPOSE_STATUS);
86 m_PC = (BUSREAD(0xffff) << 8) + BUSREAD(0xfffe); // IRQ vector at 0xfffe
87 m_intDisable = true;
88 return 7;
89 }
90 return 0;
91}
92
93
94int MOS6502::NMI()
95{
96 STACKPUSHWORD(m_PC);
97 STACKPUSHBYTE(COMPOSE_STATUS);
98 m_PC = (BUSREAD(0xfffb) << 8) + BUSREAD(0xfffa); // NMI vector at 0xfffa
99 m_intDisable = true;
100 return 7;
101}
102
103
104void MOS6502::setADCSBC()
105{
106 if (m_decimal) {
107 m_OP_ADC = &MOS6502::OP_BCDADC;
108 m_OP_SBC = &MOS6502::OP_BCDSBC;
109 } else {
110 m_OP_ADC = &MOS6502::OP_BINADC;
111 m_OP_SBC = &MOS6502::OP_BINSBC;
112 }
113}
114
115
116void MOS6502::OP_BINADC(uint8_t m)
117{
118 uint32_t t = m + m_A + (int)m_carry;
119 m_zero = !(t & 0xff);
120 m_negative = t & 0x80;
121 m_overflow = !((m_A ^ m) & 0x80) && ((m_A ^ t) & 0x80);
122 m_carry = t & 0x100;
123 m_A = t & 0xff;
124}
125
126
127void MOS6502::OP_BINSBC(uint8_t m)
128{
129 uint32_t t = m_A - m - (int)(!m_carry);
130 m_zero = !(t & 0xff);
131 m_negative = t & 0x80;
132 m_overflow = ((m_A ^ t) & 0x80) && ((m_A ^ m) & 0x80);
133 m_carry = !(t & 0x100);
134 m_A = t & 0xff;
135}
136
137
138void MOS6502::OP_BCDADC(uint8_t m)
139{
140 uint32_t t = m + m_A + (int)m_carry;
141 m_zero = !(t & 0xff);
142 if (((m_A & 0x0f) + (m & 0x0f) + (int)m_carry) > 9)
143 t += 6;
144 m_negative = t & 0x80;
145 m_overflow = !((m_A ^ m) & 0x80) && ((m_A ^ t) & 0x80);
146 if (t > 0x99)
147 t += 96;
148 m_carry = t > 0x99;
149 m_A = t & 0xff;
150}
151
152
153void MOS6502::OP_BCDSBC(uint8_t m)
154{
155 uint32_t t = m_A - m - (int)(!m_carry);
156 m_zero = !(t & 0xff);
157 m_negative = t & 0x80;
158 m_overflow = ((m_A ^ t) & 0x80) && ((m_A ^ m) & 0x80);
159 if (((m_A & 0x0f) - (int)(!m_carry)) < (m & 0x0f))
160 t -= 6;
161 if (t > 0x99)
162 t -= 0x60;
163 m_carry = t < 0x100;
164 m_A = t & 0xff;
165}
166
167
168#define OP_AND { \
169 m_A = m & m_A; \
170 m_zero = !m_A; \
171 m_negative = m_A & 0x80; \
172}
173
174
175#define OP_ASL { \
176 m_carry = m & 0x80; \
177 m = (m << 1) & 0xff; \
178 m_zero = !m; \
179 m_negative = m & 0x80; \
180}
181
182
183#define OP_BIT { \
184 m_zero = !(m & m_A); \
185 m_overflow = m & 0x40; \
186 m_negative = m & 0x80; \
187}
188
189
190#define OP_CMP { \
191 uint32_t t = m_A - m; \
192 m_zero = !(t & 0xff); \
193 m_carry = !(t & 0x100); \
194 m_negative = t & 0x80; \
195}
196
197
198#define OP_CPX { \
199 uint32_t t = m_X - m; \
200 m_zero = !(t & 0xff); \
201 m_carry = !(t & 0x100); \
202 m_negative = t & 0x80; \
203}
204
205
206#define OP_CPY { \
207 uint32_t t = m_Y - m; \
208 m_zero = !(t & 0xff); \
209 m_carry = !(t & 0x100); \
210 m_negative = t & 0x80; \
211}
212
213
214#define OP_DEC { \
215 m = (m - 1) & 0xff; \
216 m_zero = !m; \
217 m_negative = m & 0x80; \
218}
219
220
221#define OP_EOR { \
222 m_A ^= m; \
223 m_zero = !m_A; \
224 m_negative = m_A & 0x80; \
225}
226
227
228#define OP_INC { \
229 m = (m + 1) & 0xff; \
230 m_negative = m & 0x80; \
231 m_zero = !m; \
232}
233
234
235#define OP_LDA { \
236 m_zero = !m; \
237 m_negative = m & 0x80; \
238 m_A = m; \
239}
240
241
242#define OP_LDX { \
243 m_zero = !m; \
244 m_negative = m & 0x80; \
245 m_X = m; \
246}
247
248
249#define OP_LDY { \
250 m_zero = !m; \
251 m_negative = m & 0x80; \
252 m_Y = m; \
253}
254
255
256#define OP_LSR { \
257 m_negative = false; \
258 m_carry = m & 0x01; \
259 m >>= 1; \
260 m_zero = !m; \
261}
262
263
264#define OP_ORA { \
265 m_A |= m; \
266 m_negative = m_A & 0x80; \
267 m_zero = !m_A; \
268}
269
270
271#define OP_ROL { \
272 m = (m << 1) | (int)m_carry; \
273 m_carry = m & 0x100; \
274 m &= 0xff; \
275 m_negative = m & 0x80; \
276 m_zero = !m; \
277}
278
279
280#define OP_ROR { \
281 m |= (int)m_carry << 8; \
282 m_carry = m & 0x01; \
283 m = (m >> 1) & 0xff; \
284 m_negative = m & 0x80; \
285 m_zero = !m; \
286}
287
288
289#define PAGECROSS() (al >> 8)
290
291
292// immediate: op #dd
293#define ADR_IMM { \
294 m = BUSREAD(m_PC++); \
295}
296
297
298// zero page absolute: op aa
299#define ADR_ZABS_GETADDR { \
300 a = BUSREAD(m_PC++); \
301}
302#define ADR_ZABS { \
303 ADR_ZABS_GETADDR; \
304 m = PAGE0READ(a); \
305}
306
307
308// zero page absolute + X: op aa, X
309#define ADR_ZABSX_GETADDR { \
310 a = (BUSREAD(m_PC++) + m_X) & 0xff; \
311}
312#define ADR_ZABSX { \
313 ADR_ZABSX_GETADDR; \
314 m = PAGE0READ(a); \
315}
316
317
318// zero page absolute + Y: op aa, Y
319#define ADR_ZABSY_GETADDR { \
320 a = (BUSREAD(m_PC++) + m_Y) & 0xff; \
321}
322#define ADR_ZABSY { \
323 ADR_ZABSY_GETADDR; \
324 m = PAGE0READ(a); \
325}
326
327
328// absolute: op aaaa
329#define ADR_ABS_GETADDR { \
330 a = BUSREAD(m_PC) | (BUSREAD(m_PC + 1) << 8); \
331 m_PC += 2; \
332}
333#define ADR_ABS { \
334 ADR_ABS_GETADDR; \
335 m = BUSREAD(a); \
336}
337
338
339// absolute + X: op aaaa, X
340#define ADR_ABSX_GETADDR { \
341 al = BUSREAD(m_PC++) + m_X; \
342 a = al + (BUSREAD(m_PC++) << 8); \
343}
344#define ADR_ABSX { \
345 ADR_ABSX_GETADDR; \
346 m = BUSREAD(a); \
347}
348
349
350// absolute + Y: op aaaa, Y
351#define ADR_ABSY_GETADDR { \
352 al = BUSREAD(m_PC++) + m_Y; \
353 a = al + (BUSREAD(m_PC++) << 8); \
354}
355#define ADR_ABSY { \
356 ADR_ABSY_GETADDR; \
357 m = BUSREAD(a); \
358}
359
360
361// indexed indirect: op (aa, X)
362#define ADR_IIND_GETADDR { \
363 int l = (BUSREAD(m_PC++) + m_X) & 0xff; \
364 int h = (l + 1) & 0xff; \
365 a = PAGE0READ(l) | (PAGE0READ(h) << 8); \
366}
367#define ADR_IIND { \
368 ADR_IIND_GETADDR; \
369 m = BUSREAD(a); \
370}
371
372
373// indirect index: op (aa), Y
374#define ADR_INDI_GETADDR { \
375 int l = BUSREAD(m_PC++); \
376 int h = (l + 1) & 0xff; \
377 al = PAGE0READ(l) + m_Y; \
378 a = al + (PAGE0READ(h) << 8); \
379}
380#define ADR_INDI { \
381 ADR_INDI_GETADDR; \
382 m = BUSREAD(a); \
383}
384
385
386// relative: op aa
387#define ADR_REL { \
388 m = (int8_t)BUSREAD(m_PC++); \
389 a = m_PC + m; \
390 al = (m_PC & 0xff) + m; \
391}
392
393
394// indirect: op (aaaa)
395#define ADR_IND { \
396 int l = BUSREAD(m_PC++); \
397 int h = BUSREAD(m_PC++); \
398 a = l | (h << 8); \
399 l = BUSREAD(a); \
400 h = BUSREAD((a & 0xff00) | ((a + 1) & 0xff)); \
401 a = l | (h << 8); \
402}
403
404
405int MOS6502::step()
406{
407 int m; // operand value
408 int al; // address low + index
409 int a; // complete address
410
411 switch (BUSREAD(m_PC++)) {
412
414
415 // ADC #dd
416 case 0x69:
417 ADR_IMM;
418 (this->*m_OP_ADC)(m);
419 return 2;
420
421 // ADC aa
422 case 0x65:
423 ADR_ZABS;
424 (this->*m_OP_ADC)(m);
425 return 3;
426
427 // ADC aa, X
428 case 0x75:
429 ADR_ZABSX;
430 (this->*m_OP_ADC)(m);
431 return 4;
432
433 // ADC aaaa
434 case 0x6d:
435 ADR_ABS;
436 (this->*m_OP_ADC)(m);
437 return 4;
438
439 // ADC aaaa, X
440 case 0x7d:
441 ADR_ABSX;
442 (this->*m_OP_ADC)(m);
443 return 4 + PAGECROSS();
444
445 // ADC aaaa, Y
446 case 0x79:
447 ADR_ABSY;
448 (this->*m_OP_ADC)(m);
449 return 4 + PAGECROSS();
450
451 // ADC (aa, X)
452 case 0x61:
453 ADR_IIND;
454 (this->*m_OP_ADC)(m);
455 return 6;
456
457 // ADC (aa), Y
458 case 0x71:
459 ADR_INDI;
460 (this->*m_OP_ADC)(m);
461 return 5 + PAGECROSS();
462
464
465 // AND #dd
466 case 0x29:
467 ADR_IMM;
468 OP_AND;
469 return 2;
470
471 // AND aa
472 case 0x25:
473 ADR_ZABS;
474 OP_AND;
475 return 3;
476
477 // AND aa, X
478 case 0x35:
479 ADR_ZABSX;
480 OP_AND;
481 return 4;
482
483 // AND aaaa
484 case 0x2d:
485 ADR_ABS;
486 OP_AND;
487 return 4;
488
489 // AND aaaa, X
490 case 0x3d:
491 ADR_ABSX;
492 OP_AND;
493 return 4 + PAGECROSS();
494
495 // AND aaaa, Y
496 case 0x39:
497 ADR_ABSY;
498 OP_AND;
499 return 4 + PAGECROSS();
500
501 // AND (aa, X)
502 case 0x21:
503 ADR_IIND;
504 OP_AND;
505 return 6;
506
507 // AND (aa), Y
508 case 0x31:
509 ADR_INDI;
510 OP_AND;
511 return 5 + PAGECROSS();
512
514
515 // ASL A
516 case 0x0a:
517 m = m_A;
518 OP_ASL;
519 m_A = m;
520 return 2;
521
522 // ASL aa
523 case 0x06:
524 ADR_ZABS;
525 OP_ASL;
526 PAGE0WRITE(a, m);
527 return 5;
528
529 // ASL aa, X
530 case 0x16:
531 ADR_ZABSX;
532 OP_ASL;
533 PAGE0WRITE(a, m);
534 return 6;
535
536 // ASL aaaa
537 case 0x0e:
538 ADR_ABS;
539 OP_ASL;
540 BUSWRITE(a, m);
541 return 6;
542
543 // ASL aaaa, X
544 case 0x1e:
545 ADR_ABSX;
546 OP_ASL;
547 BUSWRITE(a, m);
548 return 7;
549
551
552 // BCC aa
553 case 0x90:
554 if (m_carry) {
555 ++m_PC;
556 return 2;
557 } else {
558 ADR_REL;
559 m_PC = a;
560 return 3 + PAGECROSS();
561 }
562
564
565 // BCS aa
566 case 0xb0:
567 if (m_carry) {
568 ADR_REL;
569 m_PC = a;
570 return 3 + PAGECROSS();
571 } else {
572 ++m_PC;
573 return 2;
574 }
575
577
578 // BEQ aa
579 case 0xf0:
580 if (m_zero) {
581 ADR_REL;
582 m_PC = a;
583 return 3 + PAGECROSS();
584 } else {
585 ++m_PC;
586 return 2;
587 }
588
590
591 // BIT aa
592 case 0x24:
593 ADR_ZABS;
594 OP_BIT;
595 return 3;
596
597 // BIT aaaa
598 case 0x2c:
599 ADR_ABS;
600 OP_BIT;
601 return 4;
602
604
605 // BMI aa
606 case 0x30:
607 if (m_negative) {
608 ADR_REL;
609 m_PC = a;
610 return 3 + PAGECROSS();
611 } else {
612 ++m_PC;
613 return 2;
614 }
615
617
618 // BNE aa
619 case 0xd0:
620 if (m_zero) {
621 ++m_PC;
622 return 2;
623 } else {
624 ADR_REL;
625 m_PC = a;
626 return 3 + PAGECROSS();
627 }
628
630
631 // BPL aa
632 case 0x10:
633 if (m_negative) {
634 ++m_PC;
635 return 2;
636 } else {
637 ADR_REL;
638 m_PC = a;
639 return 3 + PAGECROSS();
640 }
641
643
644 // BRK
645 case 0x00:
646 ++m_PC;
647 STACKPUSHWORD(m_PC);
648 STACKPUSHBYTE(COMPOSE_STATUS | 0x10); // set BREAK bit
649 m_intDisable = true;
650 m_PC = (BUSREAD(0xffff) << 8) + BUSREAD(0xfffe); // BRK (IRQ) vector at 0xfffe
651 return 7;
652
654
655 // BVC aa
656 case 0x50:
657 if (m_overflow) {
658 ++m_PC;
659 return 2;
660 } else {
661 ADR_REL;
662 m_PC = a;
663 return 3 + PAGECROSS();
664 }
665
667
668 // BVS aa
669 case 0x70:
670 if (m_overflow) {
671 ADR_REL;
672 m_PC = a;
673 return 3 + PAGECROSS();
674 } else {
675 ++m_PC;
676 return 2;
677 }
678
680
681 case 0x18:
682 m_carry = false;
683 return 2;
684
686
687 case 0xd8:
688 m_decimal = false;
689 setADCSBC();
690 return 2;
691
693
694 case 0x58:
695 m_intDisable = false;
696 return 2;
697
699
700 case 0xb8:
701 m_overflow = false;
702 return 2;
703
705
706 // CMP #dd
707 case 0xc9:
708 ADR_IMM;
709 OP_CMP;
710 return 2;
711
712 // CMP aa
713 case 0xc5:
714 ADR_ZABS;
715 OP_CMP;
716 return 3;
717
718 // CMP aa, X
719 case 0xd5:
720 ADR_ZABSX;
721 OP_CMP;
722 return 4;
723
724 // CMP aaaa
725 case 0xcd:
726 ADR_ABS;
727 OP_CMP;
728 return 4;
729
730 // CMP aaaa, X
731 case 0xdd:
732 ADR_ABSX;
733 OP_CMP;
734 return 4 + PAGECROSS();
735
736 // CMP aaaa, Y
737 case 0xd9:
738 ADR_ABSY;
739 OP_CMP;
740 return 4 + PAGECROSS();
741
742 // CMP (aa, X)
743 case 0xc1:
744 ADR_IIND;
745 OP_CMP;
746 return 6;
747
748 // CMP (aa), Y
749 case 0xd1:
750 ADR_INDI;
751 OP_CMP;
752 return 5 + PAGECROSS();
753
755
756 // CPX #dd
757 case 0xe0:
758 ADR_IMM;
759 OP_CPX;
760 return 2;
761
762 // CPX aa
763 case 0xe4:
764 ADR_ZABS;
765 OP_CPX;
766 return 3;
767
768 // CPX aaaa
769 case 0xec:
770 ADR_ABS;
771 OP_CPX;
772 return 4;
773
775
776 // CPY #dd
777 case 0xc0:
778 ADR_IMM;
779 OP_CPY;
780 return 2;
781
782 // CPY aa
783 case 0xc4:
784 ADR_ZABS;
785 OP_CPY;
786 return 3;
787
788 // CPY aaaa
789 case 0xcc:
790 ADR_ABS;
791 OP_CPY;
792 return 4;
793
795
796 // DEC aa
797 case 0xc6:
798 ADR_ZABS;
799 OP_DEC;
800 PAGE0WRITE(a, m);
801 return 5;
802
803 // DEC aa, X
804 case 0xd6:
805 ADR_ZABSX;
806 OP_DEC;
807 PAGE0WRITE(a, m);
808 return 6;
809
810 // DEC aaaa
811 case 0xce:
812 ADR_ABS;
813 OP_DEC;
814 BUSWRITE(a, m);
815 return 6;
816
817 // DEC aaaa, X
818 case 0xde:
819 ADR_ABSX;
820 OP_DEC;
821 BUSWRITE(a, m);
822 return 7;
823
825
826 case 0xca:
827 m_X = (m_X - 1) & 0xff;
828 m_negative = m_X & 0x80;
829 m_zero = !m_X;
830 return 2;
831
833
834 case 0x88:
835 m_Y = (m_Y - 1) & 0xff;
836 m_negative = m_Y & 0x80;
837 m_zero = !m_Y;
838 return 2;
839
841
842 // EOR #dd
843 case 0x49:
844 ADR_IMM;
845 OP_EOR;
846 return 2;
847
848 // EOR aa
849 case 0x45:
850 ADR_ZABS;
851 OP_EOR;
852 return 3;
853
854 // EOR aa, X
855 case 0x55:
856 ADR_ZABSX;
857 OP_EOR;
858 return 4;
859
860 // EOR aaaa
861 case 0x4d:
862 ADR_ABS;
863 OP_EOR;
864 return 4;
865
866 // EOR aaaa, X
867 case 0x5d:
868 ADR_ABSX;
869 OP_EOR;
870 return 4 + PAGECROSS();
871
872 // EOR aaaa, Y
873 case 0x59:
874 ADR_ABSY;
875 OP_EOR;
876 return 4 + PAGECROSS();
877
878 // EOR (aa, X)
879 case 0x41:
880 ADR_IIND;
881 OP_EOR;
882 return 6;
883
884 // EOR (aa), Y
885 case 0x51:
886 ADR_INDI;
887 OP_EOR;
888 return 5 + PAGECROSS();
889
891
892 // INC aa
893 case 0xe6:
894 ADR_ZABS;
895 OP_INC;
896 PAGE0WRITE(a, m);
897 return 5;
898
899 // INC aa, X
900 case 0xf6:
901 ADR_ZABSX;
902 OP_INC;
903 PAGE0WRITE(a, m);
904 return 6;
905
906 // INC aaaa
907 case 0xee:
908 ADR_ABS;
909 OP_INC;
910 BUSWRITE(a, m);
911 return 6;
912
913 // INC aaaa, X
914 case 0xfe:
915 ADR_ABSX;
916 OP_INC;
917 BUSWRITE(a, m);
918 return 7;
919
921
922 case 0xe8:
923 m_X = (m_X + 1) & 0xff;
924 m_negative = m_X & 0x80;
925 m_zero = !m_X;
926 return 2;
927
929
930 case 0xc8:
931 m_Y = (m_Y + 1) & 0xff;
932 m_negative = m_Y & 0x80;
933 m_zero = !m_Y;
934 return 2;
935
937
938 // JMP aaaa
939 case 0x4c:
940 ADR_ABS;
941 m_PC = a;
942 return 3;
943
944 // JMP (aaaa)
945 case 0x6c:
946 ADR_IND;
947 m_PC = a;
948 return 5;
949
951
952 // JSR aaaa
953 case 0x20:
954 a = (m_PC + 1) & 0xffff;
955 STACKPUSHWORD(a);
956 ADR_ABS;
957 m_PC = a;
958 return 6;
959
961
962 // LDA #dd
963 case 0xa9:
964 ADR_IMM;
965 OP_LDA;
966 return 2;
967
968 // LDA aa
969 case 0xa5:
970 ADR_ZABS;
971 OP_LDA;
972 return 3;
973
974 // LDA aa, X
975 case 0xb5:
976 ADR_ZABSX;
977 OP_LDA;
978 return 4;
979
980 // LDA aaaa
981 case 0xad:
982 ADR_ABS;
983 OP_LDA;
984 return 4;
985
986 // LDA aaaa, X
987 case 0xbd:
988 ADR_ABSX;
989 OP_LDA;
990 return 4 + PAGECROSS();
991
992 // LDA aaaa, Y
993 case 0xb9:
994 ADR_ABSY;
995 OP_LDA;
996 return 4 + PAGECROSS();
997
998 // LDA (aa, X)
999 case 0xa1:
1000 ADR_IIND;
1001 OP_LDA;
1002 return 6;
1003
1004 // LDA (aa), Y
1005 case 0xb1:
1006 ADR_INDI;
1007 OP_LDA;
1008 return 5 + PAGECROSS();
1009
1011
1012 // LDX #dd
1013 case 0xa2:
1014 ADR_IMM;
1015 OP_LDX;
1016 return 2;
1017
1018 // LDX aa
1019 case 0xa6:
1020 ADR_ZABS;
1021 OP_LDX;
1022 return 3;
1023
1024 // LDX aa, Y
1025 case 0xb6:
1026 ADR_ZABSY;
1027 OP_LDX;
1028 return 4;
1029
1030 // LDX aaaa
1031 case 0xae:
1032 ADR_ABS;
1033 OP_LDX;
1034 return 4;
1035
1036 // LDX aaaa, Y
1037 case 0xbe:
1038 ADR_ABSY;
1039 OP_LDX;
1040 return 4 + PAGECROSS();
1041
1043
1044 // LDY #dd
1045 case 0xa0:
1046 ADR_IMM;
1047 OP_LDY;
1048 return 2;
1049
1050 // LDY aa
1051 case 0xa4:
1052 ADR_ZABS;
1053 OP_LDY;
1054 return 3;
1055
1056 // LDY aa, X
1057 case 0xb4:
1058 ADR_ZABSX;
1059 OP_LDY;
1060 return 4;
1061
1062 // LDY aaaa
1063 case 0xac:
1064 ADR_ABS;
1065 OP_LDY;
1066 return 4;
1067
1068 // LDY aaaa, X
1069 case 0xbc:
1070 ADR_ABSX;
1071 OP_LDY;
1072 return 4 + PAGECROSS();
1073
1075
1076 // LSR A
1077 case 0x4a:
1078 m = m_A;
1079 OP_LSR;
1080 m_A = m;
1081 return 2;
1082
1083 // LSR aa
1084 case 0x46:
1085 ADR_ZABS;
1086 OP_LSR;
1087 PAGE0WRITE(a, m);
1088 return 5;
1089
1090 // LSR aa, X
1091 case 0x56:
1092 ADR_ZABSX;
1093 OP_LSR;
1094 PAGE0WRITE(a, m);
1095 return 6;
1096
1097 // LSR aaaa
1098 case 0x4e:
1099 ADR_ABS;
1100 OP_LSR;
1101 BUSWRITE(a, m);
1102 return 6;
1103
1104 // LSR aaaa, X
1105 case 0x5e:
1106 ADR_ABSX;
1107 OP_LSR;
1108 BUSWRITE(a, m);
1109 return 7;
1110
1112
1113 case 0xea:
1114 return 2;
1115
1117
1118 // ORA #dd
1119 case 0x09:
1120 ADR_IMM;
1121 OP_ORA;
1122 return 2;
1123
1124 // ORA aa
1125 case 0x05:
1126 ADR_ZABS;
1127 OP_ORA;
1128 return 3;
1129
1130 // ORA aa, X
1131 case 0x15:
1132 ADR_ZABSX;
1133 OP_ORA;
1134 return 4;
1135
1136 // ORA aaaa
1137 case 0x0d:
1138 ADR_ABS;
1139 OP_ORA;
1140 return 4;
1141
1142 // ORA aaaa, X
1143 case 0x1d:
1144 ADR_ABSX;
1145 OP_ORA;
1146 return 4 + PAGECROSS();
1147
1148 // ORA aaaa, Y
1149 case 0x19:
1150 ADR_ABSY;
1151 OP_ORA;
1152 return 4 + PAGECROSS();
1153
1154 // ORA (aa, X)
1155 case 0x01:
1156 ADR_IIND;
1157 OP_ORA;
1158 return 6;
1159
1160 // ORA (aa), Y
1161 case 0x11:
1162 ADR_INDI;
1163 OP_ORA;
1164 return 5 + PAGECROSS();
1165
1167
1168 case 0x48:
1169 STACKPUSHBYTE(m_A);
1170 return 3;
1171
1173
1174 case 0x08:
1175 STACKPUSHBYTE(COMPOSE_STATUS | 0x10); // set BREAK bit
1176 return 3;
1177
1179
1180 case 0x68:
1181 m_A = STACKPOPBYTE();
1182 m_zero = !m_A;
1183 m_negative = m_A & 0x80;
1184 return 4;
1185
1187
1188 case 0x28:
1189 DECOMPOSE_STATUS(STACKPOPBYTE());
1190 return 4;
1191
1193
1194 // ROL A
1195 case 0x2a:
1196 m = m_A;
1197 OP_ROL;
1198 m_A = m;
1199 return 2;
1200
1201 // ROL aa
1202 case 0x26:
1203 ADR_ZABS;
1204 OP_ROL;
1205 PAGE0WRITE(a, m);
1206 return 5;
1207
1208 // ROL aa, X
1209 case 0x36:
1210 ADR_ZABSX;
1211 OP_ROL;
1212 PAGE0WRITE(a, m);
1213 return 6;
1214
1215 // ROL aaaa
1216 case 0x2e:
1217 ADR_ABS;
1218 OP_ROL;
1219 BUSWRITE(a, m);
1220 return 6;
1221
1222 // ROL aaaa, X
1223 case 0x3e:
1224 ADR_ABSX;
1225 OP_ROL;
1226 BUSWRITE(a, m);
1227 return 7;
1228
1230
1231 // ROR A
1232 case 0x6a:
1233 m = m_A;
1234 OP_ROR;
1235 m_A = m;
1236 return 2;
1237
1238 // ROR aa
1239 case 0x66:
1240 ADR_ZABS;
1241 OP_ROR;
1242 PAGE0WRITE(a, m);
1243 return 5;
1244
1245 // ROR aa, X
1246 case 0x76:
1247 ADR_ZABSX;
1248 OP_ROR;
1249 PAGE0WRITE(a, m);
1250 return 6;
1251
1252 // ROR aaaa
1253 case 0x6e:
1254 ADR_ABS;
1255 OP_ROR;
1256 BUSWRITE(a, m);
1257 return 6;
1258
1259 // ROR aaaa, X
1260 case 0x7e:
1261 ADR_ABSX;
1262 OP_ROR;
1263 BUSWRITE(a, m);
1264 return 7;
1265
1267
1268 case 0x40:
1269 {
1270 DECOMPOSE_STATUS(STACKPOPBYTE());
1271 m_PC = STACKPOPWORD();
1272 return 6;
1273 }
1274
1276
1277 case 0x60:
1278 {
1279 m_PC = STACKPOPWORD() + 1;
1280 return 6;
1281 }
1282
1284
1285 // SBC #dd
1286 case 0xe9:
1287 ADR_IMM;
1288 (this->*m_OP_SBC)(m);
1289 return 2;
1290
1291 // SBC aa
1292 case 0xe5:
1293 ADR_ZABS;
1294 (this->*m_OP_SBC)(m);
1295 return 3;
1296
1297 // SBC aa, X
1298 case 0xf5:
1299 ADR_ZABSX;
1300 (this->*m_OP_SBC)(m);
1301 return 4;
1302
1303 // SBC aaaa
1304 case 0xed:
1305 ADR_ABS;
1306 (this->*m_OP_SBC)(m);
1307 return 4;
1308
1309 // SBC aaaa, X
1310 case 0xfd:
1311 ADR_ABSX;
1312 (this->*m_OP_SBC)(m);
1313 return 4 + PAGECROSS();
1314
1315 // SBC aaaa, Y
1316 case 0xf9:
1317 ADR_ABSY;
1318 (this->*m_OP_SBC)(m);
1319 return 4 + PAGECROSS();
1320
1321 // SBC (aa, X)
1322 case 0xe1:
1323 ADR_IIND;
1324 (this->*m_OP_SBC)(m);
1325 return 6;
1326
1327 // SBC (aa), Y
1328 case 0xf1:
1329 ADR_INDI;
1330 (this->*m_OP_SBC)(m);
1331 return 5 + PAGECROSS();
1332
1334
1335 case 0x38:
1336 m_carry = true;
1337 return 2;
1338
1340
1341 case 0xf8:
1342 m_decimal = true;
1343 setADCSBC();
1344 return 2;
1345
1347
1348 case 0x78:
1349 m_intDisable = true;
1350 return 2;
1351
1353
1354 // STA aa
1355 case 0x85:
1356 ADR_ZABS_GETADDR;
1357 PAGE0WRITE(a, m_A);
1358 return 3;
1359
1360 // STA aa, X
1361 case 0x95:
1362 ADR_ZABSX_GETADDR;
1363 PAGE0WRITE(a, m_A);
1364 return 4;
1365
1366 // STA aaaa
1367 case 0x8d:
1368 ADR_ABS_GETADDR;
1369 BUSWRITE(a, m_A);
1370 return 4;
1371
1372 // STA aaaa, X
1373 case 0x9d:
1374 ADR_ABSX_GETADDR;
1375 BUSWRITE(a, m_A);
1376 return 5;
1377
1378 // STA aaaa, Y
1379 case 0x99:
1380 ADR_ABSY_GETADDR;
1381 BUSWRITE(a, m_A);
1382 return 5;
1383
1384 // STA (aa, X)
1385 case 0x81:
1386 ADR_IIND_GETADDR;
1387 BUSWRITE(a, m_A);
1388 return 6;
1389
1390 // STA (aa), Y
1391 case 0x91:
1392 ADR_INDI_GETADDR;
1393 BUSWRITE(a, m_A);
1394 return 6;
1395
1397
1398 // STX aa
1399 case 0x86:
1400 ADR_ZABS_GETADDR;
1401 PAGE0WRITE(a, m_X);
1402 return 3;
1403
1404 // STX aa, Y
1405 case 0x96:
1406 ADR_ZABSY_GETADDR;
1407 PAGE0WRITE(a, m_X);
1408 return 4;
1409
1410 // STX aaaa
1411 case 0x8e:
1412 ADR_ABS_GETADDR;
1413 BUSWRITE(a, m_X);
1414 return 4;
1415
1417
1418 // STY aa
1419 case 0x84:
1420 ADR_ZABS_GETADDR;
1421 PAGE0WRITE(a, m_Y);
1422 return 3;
1423
1424 // STY aa, X
1425 case 0x94:
1426 ADR_ZABSX_GETADDR;
1427 PAGE0WRITE(a, m_Y);
1428 return 4;
1429
1430 // STY aaaa
1431 case 0x8c:
1432 ADR_ABS_GETADDR;
1433 BUSWRITE(a, m_Y);
1434 return 4;
1435
1437
1438 case 0xaa:
1439 m_X = m_A;
1440 m_zero = !m_X;
1441 m_negative = m_X & 0x80;
1442 return 2;
1443
1445
1446 case 0xa8:
1447 m_Y = m_A;
1448 m_zero = !m_Y;
1449 m_negative = m_Y & 0x80;
1450 return 2;
1451
1453
1454 case 0xba:
1455 m_X = m_SP;
1456 m_zero = !m_X;
1457 m_negative = m_X & 0x80;
1458 return 2;
1459
1461
1462 case 0x8a:
1463 m_A = m_X;
1464 m_zero = !m_A;
1465 m_negative = m_A & 0x80;
1466 return 2;
1467
1469
1470 case 0x9a:
1471 m_SP = m_X;
1472 return 2;
1473
1475
1476 case 0x98:
1477 m_A = m_Y;
1478 m_zero = !m_A;
1479 m_negative = m_A & 0x80;
1480 return 2;
1481
1483
1484 case 0x1a:
1485 case 0x3a:
1486 case 0x5a:
1487 case 0x7a:
1488 case 0xda:
1489 case 0xfa:
1490 return 2;
1491
1493
1494 // DOP aa
1495 case 0x04:
1496 case 0x44:
1497 case 0x64:
1498 ADR_ZABS;
1499 return 3;
1500
1501 // DOP aa, X
1502 case 0x14:
1503 case 0x34:
1504 case 0x54:
1505 case 0x74:
1506 case 0xd4:
1507 case 0xf4:
1508 ADR_ZABSX;
1509 return 4;
1510
1511 // DOP #dd
1512 case 0x80:
1513 case 0x82:
1514 case 0x89:
1515 case 0xc2:
1516 case 0xe2:
1517 ADR_IMM;
1518 return 2;
1519
1521
1522 // ISC aa
1523 case 0xe7:
1524 ADR_ZABS;
1525 OP_INC;
1526 (this->*m_OP_SBC)(m);
1527 return 5;
1528
1529 // ISC aa, X
1530 case 0xf7:
1531 ADR_ZABSX;
1532 OP_INC;
1533 (this->*m_OP_SBC)(m);
1534 return 6;
1535
1536 // ISC aaaa
1537 case 0xef:
1538 ADR_ABS;
1539 OP_INC;
1540 (this->*m_OP_SBC)(m);
1541 return 6;
1542
1543 // ISC aaaa, X
1544 case 0xff:
1545 ADR_ABSX;
1546 OP_INC;
1547 (this->*m_OP_SBC)(m);
1548 return 7;
1549
1550 // ISC aaaa, Y
1551 case 0xfb:
1552 ADR_ABSY;
1553 OP_INC;
1554 (this->*m_OP_SBC)(m);
1555 return 7;
1556
1557 // ISC (aa, X)
1558 case 0xe3:
1559 ADR_IIND;
1560 OP_INC;
1561 (this->*m_OP_SBC)(m);
1562 return 8;
1563
1564 // ISC (aa), Y
1565 case 0xf3:
1566 ADR_INDI;
1567 OP_INC;
1568 (this->*m_OP_SBC)(m);
1569 return 8;
1570
1571 default:
1572 // unsupported opcode
1573 //Serial.printf("6502 illegal 0x%02x\n", BUSREAD(m_PC - 1));
1574 return 0;
1575
1576 }
1577}
1578
1579
1580}; // namespace fabgl
This file contains fabgl::MOS6502 definition.