2 Skelton for retropc emulator
5 Author : Takeda.Toshiya
17 #define NMI_VEC 0xfffa
18 #define RST_VEC 0xfffc
19 #define IRQ_VEC 0xfffe
31 // some shortcuts for improved readability
41 P = (P & ~F_N) | F_Z; \
43 P = (P & ~(F_N | F_Z)) | ((n) & F_N)
66 // virtual machine interface
68 #define RDMEM_ID(addr) d_mem->read_data8(addr)
69 #define WRMEM_ID(addr, data) d_mem->write_data8(addr, data)
71 #define RDOP() d_mem->read_data8(PCW++)
72 #define PEEKOP() d_mem->read_data8(PCW)
73 #define RDOPARG() d_mem->read_data8(PCW++)
75 #define RDMEM(addr) d_mem->read_data8(addr)
76 #define WRMEM(addr, data) d_mem->write_data8(addr, data)
78 #define CYCLES(c) icount -= (c)
83 int8_t tmp2 = RDOPARG(); \
86 EAW = PCW + (int8_t)tmp2; \
88 RDMEM((PCH << 8) | EAL) ; \
96 // Helper macros to build the effective address
120 if(EAL + X > 0xff) { \
121 RDMEM((EAH << 8) | ((EAL + X) & 0xff)); \
128 RDMEM((EAH << 8) | ((EAL + X) & 0xff)); \
133 if(EAL + Y > 0xff) { \
134 RDMEM((EAH << 8) | ((EAL + Y) & 0xff)); \
141 RDMEM((EAH << 8) | ((EAL + Y) & 0xff)); \
157 if(EAL + Y > 0xff) { \
158 RDMEM((EAH << 8) | ((EAL + Y) & 0xff)); \
168 RDMEM((EAH << 8) | ((EAL + Y) & 0xff)); \
184 // read a value into tmp
186 #define RD_IMM tmp = RDOPARG()
187 #define RD_DUM RDMEM(PCW)
188 #define RD_ACC tmp = A
189 #define RD_ZPG EA_ZPG; tmp = RDMEM(EAD)
190 #define RD_ZPX EA_ZPX; tmp = RDMEM(EAD)
191 #define RD_ZPY EA_ZPY; tmp = RDMEM(EAD)
192 #define RD_ABS EA_ABS; tmp = RDMEM(EAD)
193 #define RD_ABX_P EA_ABX_P; tmp = RDMEM(EAD)
194 #define RD_ABX_NP EA_ABX_NP; tmp = RDMEM(EAD)
195 #define RD_ABY_P EA_ABY_P; tmp = RDMEM(EAD)
196 #define RD_ABY_NP EA_ABY_NP; tmp = RDMEM(EAD)
197 #define RD_IDX EA_IDX; tmp = RDMEM_ID(EAD)
198 #define RD_IDY_P EA_IDY_P; tmp = RDMEM_ID(EAD)
199 #define RD_IDY_NP EA_IDY_NP; tmp = RDMEM_ID(EAD)
200 #define RD_ZPI EA_ZPI; tmp = RDMEM(EAD)
202 // write a value from tmp
204 #define WR_ZPG EA_ZPG; WRMEM(EAD, tmp)
205 #define WR_ZPX EA_ZPX; WRMEM(EAD, tmp)
206 #define WR_ZPY EA_ZPY; WRMEM(EAD, tmp)
207 #define WR_ABS EA_ABS; WRMEM(EAD, tmp)
208 #define WR_ABX_NP EA_ABX_NP; WRMEM(EAD, tmp)
209 #define WR_ABY_NP EA_ABY_NP; WRMEM(EAD, tmp)
210 #define WR_IDX EA_IDX; WRMEM_ID(EAD, tmp)
211 #define WR_IDY_NP EA_IDY_NP; WRMEM_ID(EAD, tmp)
212 #define WR_ZPI EA_ZPI; WRMEM(EAD, tmp)
214 // dummy read from the last EA
216 #define RD_EA RDMEM(EAD)
218 // write back a value from tmp to the last EA
220 #define WB_ACC A = (uint8_t)tmp;
221 #define WB_EA WRMEM(EAD, tmp)
225 #define PUSH(Rg) WRMEM(SPD, Rg); S--
226 #define PULL(Rg) S++; Rg = RDMEM(SPD)
232 int sum = A + tmp + c; \
234 if(~(A ^ tmp) & (A ^ sum) & F_N) { \
247 int lo = (A & 0x0f) + (tmp & 0x0f) + c; \
248 int hi = (A & 0xf0) + (tmp & 0xf0); \
249 P &= ~(F_V | F_C | F_N | F_Z); \
250 if(!((lo + hi) & 0xff)) { \
260 if(~(A ^ tmp) & (A ^ hi) & F_N) { \
269 A = (lo & 0x0f) + (hi & 0xf0); \
272 int sum = A + tmp + c; \
274 if(~(A ^ tmp) & (A ^ sum) & F_N) { \
286 A = (uint8_t)(A & tmp); \
290 P = (P & ~F_C) | ((tmp >> 7) & F_C); \
291 tmp = (uint8_t)(tmp << 1); \
294 #define BCC BRA(!(P & F_C))
295 #define BCS BRA(P & F_C)
296 #define BEQ BRA(P & F_Z)
299 P &= ~(F_N | F_V | F_Z); \
300 P |= tmp & (F_N | F_V); \
304 #define BMI BRA(P & F_N)
305 #define BNE BRA(!(P & F_Z))
306 #define BPL BRA(!(P & F_N))
314 PCL = RDMEM(IRQ_VEC); \
315 PCH = RDMEM(IRQ_VEC + 1)
317 #define BVC BRA(!(P & F_V))
318 #define BVS BRA(P & F_V)
320 #define CLC P &= ~F_C
321 #define CLD P &= ~F_D
323 if(irq_state && (P & F_I)) { \
324 if(PEEKOP() != 0x40) { \
329 #define CLV P &= ~F_V
336 SET_NZ((uint8_t)(A - tmp))
342 SET_NZ((uint8_t)(X - tmp))
348 SET_NZ((uint8_t)(Y - tmp))
351 tmp = (uint8_t)(tmp - 1); \
354 X = (uint8_t)(X - 1); \
357 Y = (uint8_t)(Y - 1); \
361 A = (uint8_t)(A ^ tmp); \
365 tmp = (uint8_t)(tmp + 1); \
368 X = (uint8_t)(X + 1); \
371 Y = (uint8_t)(Y + 1); \
374 #define JMP PCD = EAD
394 P = (P & ~F_C) | (tmp & F_C); \
395 tmp = (uint8_t)tmp >> 1; \
401 A = (uint8_t)(A | tmp); \
415 if(irq_state && !(P & F_I)) { \
424 tmp = (tmp << 1) | (P & F_C); \
425 P = (P & ~F_C) | ((tmp >> 8) & F_C); \
426 tmp = (uint8_t)tmp; \
429 tmp |= (P & F_C) << 8; \
430 P = (P & ~F_C) | (tmp & F_C); \
431 tmp = (uint8_t)(tmp >> 1); \
441 if(irq_state && !(P & F_I)) { \
455 int c = (P & F_C) ^ F_C; \
456 int sum = A - tmp - c; \
458 if((A ^ tmp) & (A ^ sum) & F_N) { \
461 if((sum & 0xff00) == 0) { \
470 int c = (P & F_C) ^ F_C; \
471 int sum = A - tmp - c; \
472 int lo = (A & 0x0f) - (tmp & 0x0f) - c; \
473 int hi = (A & 0xf0) - (tmp & 0xf0); \
478 P &= ~(F_V | F_C | F_Z | F_N); \
479 if((A ^ tmp) & (A ^ sum) & F_N) { \
485 if((sum & 0xff00) == 0) { \
488 if(!((A - tmp - c) & 0xff)) { \
491 if((A - tmp - c) & 0x80) { \
494 A = (lo & 0x0f) | (hi & 0xf0); \
496 int c = (P & F_C) ^ F_C; \
497 int sum = A - tmp - c; \
499 if((A ^ tmp) & (A ^ sum) & F_N) { \
502 if((sum & 0xff00) == 0) { \
537 A = (uint8_t)(A & tmp); \
561 if((tmp & 0x60) == 0x20 || (tmp & 0x60) == 0x40) { \
570 int hi = tmp & 0xf0; \
571 int lo = tmp & 0x0f; \
573 tmp = (tmp >> 1) | 0x80; \
584 if((t ^ tmp) & 0x40) { \
589 if(lo + (lo & 0x01) > 0x05) { \
590 tmp = (tmp & 0xf0) | ((tmp + 6) & 0x0f); \
592 if(hi + (hi & 0x10) > 0x50) { \
594 tmp = (tmp+0x60) & 0xff; \
605 if((tmp & 0x60) == 0x20 || (tmp & 0x60) == 0x40) { \
617 X = (uint8_t)(X - tmp); \
621 A = (uint8_t)((A | 0xee) & X & tmp); \
625 tmp = (uint8_t)(tmp - 1); \
630 SET_NZ((uint8_t)(A - tmp))
632 #define DOP RDOPARG()
635 tmp = (uint8_t)(tmp + 1); \
639 A = X = (uint8_t)tmp; \
644 A = X = (uint8_t)((A | 0xff) & tmp); \
648 A = X = (uint8_t)((A | 0xee) & tmp); \
653 tmp = (tmp << 1) | (P & F_C); \
654 P = (P & ~F_C) | ((tmp >> 8) & F_C); \
655 tmp = (uint8_t)tmp; \
659 tmp |= (P & F_C) << 8; \
660 P = (P & ~F_C) | (tmp & F_C); \
661 tmp = (uint8_t)(tmp >> 1); \
664 #define SAX tmp = A & X
667 P = (P & ~F_C) | ((tmp >> 7) & F_C); \
668 tmp = (uint8_t)(tmp << 1); \
673 P = (P & ~F_C) | (tmp & F_C); \
674 tmp = (uint8_t)tmp >> 1; \
678 #define SAH tmp = A & X & (EAH + 1)
696 #define SXH tmp = X & (EAH + 1)
697 #define SYH tmp = Y & (EAH + 1)
703 void M6502::OP(uint8_t code)
708 case 0x00: { CYCLES(7); BRK; } break; /* 7 BRK */
709 case 0x01: { CYCLES(6); RD_IDX; ORA; } break; /* 6 ORA IDX */
710 case 0x02: { CYCLES(1); KIL; } break; /* 1 KIL */
711 case 0x03: { CYCLES(7); RD_IDX; RD_EA; SLO; WB_EA; } break; /* 7 SLO IDX */
712 case 0x04: { CYCLES(3); RD_ZPG; NOP; } break; /* 3 NOP ZPG */
713 case 0x05: { CYCLES(3); RD_ZPG; ORA; } break; /* 3 ORA ZPG */
714 case 0x06: { CYCLES(5); RD_ZPG; RD_EA; ASL; WB_EA; } break; /* 5 ASL ZPG */
715 case 0x07: { CYCLES(5); RD_ZPG; RD_EA; SLO; WB_EA; } break; /* 5 SLO ZPG */
716 case 0x08: { CYCLES(3); RD_DUM; PHP; } break; /* 3 PHP */
717 case 0x09: { CYCLES(2); RD_IMM; ORA; } break; /* 2 ORA IMM */
718 case 0x0a: { CYCLES(2); RD_DUM; RD_ACC; ASL; WB_ACC; } break; /* 2 ASL A */
719 case 0x0b: { CYCLES(2); RD_IMM; ANC; } break; /* 2 ANC IMM */
720 case 0x0c: { CYCLES(4); RD_ABS; NOP; } break; /* 4 NOP ABS */
721 case 0x0d: { CYCLES(4); RD_ABS; ORA; } break; /* 4 ORA ABS */
722 case 0x0e: { CYCLES(6); RD_ABS; RD_EA; ASL; WB_EA; } break; /* 6 ASL ABS */
723 case 0x0f: { CYCLES(6); RD_ABS; RD_EA; SLO; WB_EA; } break; /* 6 SLO ABS */
724 case 0x10: { CYCLES(2); BPL; } break; /* 2-4 BPL REL */
725 case 0x11: { CYCLES(5); RD_IDY_P; ORA; } break; /* 5 ORA IDY page penalty */
726 case 0x12: { CYCLES(1); KIL; } break; /* 1 KIL */
727 case 0x13: { CYCLES(7); RD_IDY_NP; RD_EA; SLO; WB_EA; } break; /* 7 SLO IDY */
728 case 0x14: { CYCLES(4); RD_ZPX; NOP; } break; /* 4 NOP ZPX */
729 case 0x15: { CYCLES(4); RD_ZPX; ORA; } break; /* 4 ORA ZPX */
730 case 0x16: { CYCLES(6); RD_ZPX; RD_EA; ASL; WB_EA; } break; /* 6 ASL ZPX */
731 case 0x17: { CYCLES(6); RD_ZPX; RD_EA; SLO; WB_EA; } break; /* 6 SLO ZPX */
732 case 0x18: { CYCLES(2); RD_DUM; CLC; } break; /* 2 CLC */
733 case 0x19: { CYCLES(4); RD_ABY_P; ORA; } break; /* 4 ORA ABY page penalty */
734 case 0x1a: { CYCLES(2); RD_DUM; NOP; } break; /* 2 NOP */
735 case 0x1b: { CYCLES(7); RD_ABY_NP; RD_EA; SLO; WB_EA; } break; /* 7 SLO ABY */
736 case 0x1c: { CYCLES(4); RD_ABX_P; NOP; } break; /* 4 NOP ABX page penalty */
737 case 0x1d: { CYCLES(4); RD_ABX_P; ORA; } break; /* 4 ORA ABX page penalty */
738 case 0x1e: { CYCLES(7); RD_ABX_NP; RD_EA; ASL; WB_EA; } break; /* 7 ASL ABX */
739 case 0x1f: { CYCLES(7); RD_ABX_NP; RD_EA; SLO; WB_EA; } break; /* 7 SLO ABX */
740 case 0x20: { CYCLES(6); JSR; } break; /* 6 JSR */
741 case 0x21: { CYCLES(6); RD_IDX; AND; } break; /* 6 AND IDX */
742 case 0x22: { CYCLES(1); KIL; } break; /* 1 KIL */
743 case 0x23: { CYCLES(7); RD_IDX; RD_EA; RLA; WB_EA; } break; /* 7 RLA IDX */
744 case 0x24: { CYCLES(3); RD_ZPG; BIT; } break; /* 3 BIT ZPG */
745 case 0x25: { CYCLES(3); RD_ZPG; AND; } break; /* 3 AND ZPG */
746 case 0x26: { CYCLES(5); RD_ZPG; RD_EA; ROL; WB_EA; } break; /* 5 ROL ZPG */
747 case 0x27: { CYCLES(5); RD_ZPG; RD_EA; RLA; WB_EA; } break; /* 5 RLA ZPG */
748 case 0x28: { CYCLES(4); RD_DUM; PLP; } break; /* 4 PLP */
749 case 0x29: { CYCLES(2); RD_IMM; AND; } break; /* 2 AND IMM */
750 case 0x2a: { CYCLES(2); RD_DUM; RD_ACC; ROL; WB_ACC; } break; /* 2 ROL A */
751 case 0x2b: { CYCLES(2); RD_IMM; ANC; } break; /* 2 ANC IMM */
752 case 0x2c: { CYCLES(4); RD_ABS; BIT; } break; /* 4 BIT ABS */
753 case 0x2d: { CYCLES(4); RD_ABS; AND; } break; /* 4 AND ABS */
754 case 0x2e: { CYCLES(6); RD_ABS; RD_EA; ROL; WB_EA; } break; /* 6 ROL ABS */
755 case 0x2f: { CYCLES(6); RD_ABS; RD_EA; RLA; WB_EA; } break; /* 6 RLA ABS */
756 case 0x30: { CYCLES(2); BMI; } break; /* 2-4 BMI REL */
757 case 0x31: { CYCLES(5); RD_IDY_P; AND; } break; /* 5 AND IDY page penalty */
758 case 0x32: { CYCLES(1); KIL; } break; /* 1 KIL */
759 case 0x33: { CYCLES(7); RD_IDY_NP; RD_EA; RLA; WB_EA; } break; /* 7 RLA IDY */
760 case 0x34: { CYCLES(4); RD_ZPX; NOP; } break; /* 4 NOP ZPX */
761 case 0x35: { CYCLES(4); RD_ZPX; AND; } break; /* 4 AND ZPX */
762 case 0x36: { CYCLES(6); RD_ZPX; RD_EA; ROL; WB_EA; } break; /* 6 ROL ZPX */
763 case 0x37: { CYCLES(6); RD_ZPX; RD_EA; RLA; WB_EA; } break; /* 6 RLA ZPX */
764 case 0x38: { CYCLES(2); RD_DUM; SEC; } break; /* 2 SEC */
765 case 0x39: { CYCLES(4); RD_ABY_P; AND; } break; /* 4 AND ABY page penalty */
766 case 0x3a: { CYCLES(2); RD_DUM; NOP; } break; /* 2 NOP */
767 case 0x3b: { CYCLES(7); RD_ABY_NP; RD_EA; RLA; WB_EA; } break; /* 7 RLA ABY */
768 case 0x3c: { CYCLES(4); RD_ABX_P; NOP; } break; /* 4 NOP ABX page penalty */
769 case 0x3d: { CYCLES(4); RD_ABX_P; AND; } break; /* 4 AND ABX page penalty */
770 case 0x3e: { CYCLES(7); RD_ABX_NP; RD_EA; ROL; WB_EA; } break; /* 7 ROL ABX */
771 case 0x3f: { CYCLES(7); RD_ABX_NP; RD_EA; RLA; WB_EA; } break; /* 7 RLA ABX */
772 case 0x40: { CYCLES(6); RTI; } break; /* 6 RTI */
773 case 0x41: { CYCLES(6); RD_IDX; EOR; } break; /* 6 EOR IDX */
774 case 0x42: { CYCLES(1); KIL; } break; /* 1 KIL */
775 case 0x43: { CYCLES(7); RD_IDX; RD_EA; SRE; WB_EA; } break; /* 7 SRE IDX */
776 case 0x44: { CYCLES(3); RD_ZPG; NOP; } break; /* 3 NOP ZPG */
777 case 0x45: { CYCLES(3); RD_ZPG; EOR; } break; /* 3 EOR ZPG */
778 case 0x46: { CYCLES(5); RD_ZPG; RD_EA; LSR; WB_EA; } break; /* 5 LSR ZPG */
779 case 0x47: { CYCLES(5); RD_ZPG; RD_EA; SRE; WB_EA; } break; /* 5 SRE ZPG */
780 case 0x48: { CYCLES(3); RD_DUM; PHA; } break; /* 3 PHA */
781 case 0x49: { CYCLES(2); RD_IMM; EOR; } break; /* 2 EOR IMM */
782 case 0x4a: { CYCLES(2); RD_DUM; RD_ACC; LSR; WB_ACC; } break; /* 2 LSR A */
783 case 0x4b: { CYCLES(2); RD_IMM; ASR; WB_ACC; } break; /* 2 ASR IMM */
784 case 0x4c: { CYCLES(3); EA_ABS; JMP; } break; /* 3 JMP ABS */
785 case 0x4d: { CYCLES(4); RD_ABS; EOR; } break; /* 4 EOR ABS */
786 case 0x4e: { CYCLES(6); RD_ABS; RD_EA; LSR; WB_EA; } break; /* 6 LSR ABS */
787 case 0x4f: { CYCLES(6); RD_ABS; RD_EA; SRE; WB_EA; } break; /* 6 SRE ABS */
788 case 0x50: { CYCLES(2); BVC; } break; /* 2-4 BVC REL */
789 case 0x51: { CYCLES(5); RD_IDY_P; EOR; } break; /* 5 EOR IDY page penalty */
790 case 0x52: { CYCLES(1); KIL; } break; /* 1 KIL */
791 case 0x53: { CYCLES(7); RD_IDY_NP; RD_EA; SRE; WB_EA; } break; /* 7 SRE IDY */
792 case 0x54: { CYCLES(4); RD_ZPX; NOP; } break; /* 4 NOP ZPX */
793 case 0x55: { CYCLES(4); RD_ZPX; EOR; } break; /* 4 EOR ZPX */
794 case 0x56: { CYCLES(6); RD_ZPX; RD_EA; LSR; WB_EA; } break; /* 6 LSR ZPX */
795 case 0x57: { CYCLES(6); RD_ZPX; RD_EA; SRE; WB_EA; } break; /* 6 SRE ZPX */
796 case 0x58: { CYCLES(2); RD_DUM; CLI; } break; /* 2 CLI */
797 case 0x59: { CYCLES(4); RD_ABY_P; EOR; } break; /* 4 EOR ABY page penalty */
798 case 0x5a: { CYCLES(2); RD_DUM; NOP; } break; /* 2 NOP */
799 case 0x5b: { CYCLES(7); RD_ABY_NP; RD_EA; SRE; WB_EA; } break; /* 7 SRE ABY */
800 case 0x5c: { CYCLES(4); RD_ABX_P; NOP; } break; /* 4 NOP ABX page penalty */
801 case 0x5d: { CYCLES(4); RD_ABX_P; EOR; } break; /* 4 EOR ABX page penalty */
802 case 0x5e: { CYCLES(7); RD_ABX_NP; RD_EA; LSR; WB_EA; } break; /* 7 LSR ABX */
803 case 0x5f: { CYCLES(7); RD_ABX_NP; RD_EA; SRE; WB_EA; } break; /* 7 SRE ABX */
804 case 0x60: { CYCLES(6); RTS; } break; /* 6 RTS */
805 case 0x61: { CYCLES(6); RD_IDX; ADC; } break; /* 6 ADC IDX */
806 case 0x62: { CYCLES(1); KIL; } break; /* 1 KIL */
807 case 0x63: { CYCLES(7); RD_IDX; RD_EA; RRA; WB_EA; } break; /* 7 RRA IDX */
808 case 0x64: { CYCLES(3); RD_ZPG; NOP; } break; /* 3 NOP ZPG */
809 case 0x65: { CYCLES(3); RD_ZPG; ADC; } break; /* 3 ADC ZPG */
810 case 0x66: { CYCLES(5); RD_ZPG; RD_EA; ROR; WB_EA; } break; /* 5 ROR ZPG */
811 case 0x67: { CYCLES(5); RD_ZPG; RD_EA; RRA; WB_EA; } break; /* 5 RRA ZPG */
812 case 0x68: { CYCLES(4); RD_DUM; PLA; } break; /* 4 PLA */
813 case 0x69: { CYCLES(2); RD_IMM; ADC; } break; /* 2 ADC IMM */
814 case 0x6a: { CYCLES(2); RD_DUM; RD_ACC; ROR; WB_ACC; } break; /* 2 ROR A */
815 case 0x6b: { CYCLES(2); RD_IMM; ARR; WB_ACC; } break; /* 2 ARR IMM */
816 case 0x6c: { CYCLES(5); EA_IND; JMP; } break; /* 5 JMP IND */
817 case 0x6d: { CYCLES(4); RD_ABS; ADC; } break; /* 4 ADC ABS */
818 case 0x6e: { CYCLES(6); RD_ABS; RD_EA; ROR; WB_EA; } break; /* 6 ROR ABS */
819 case 0x6f: { CYCLES(6); RD_ABS; RD_EA; RRA; WB_EA; } break; /* 6 RRA ABS */
820 case 0x70: { CYCLES(2); BVS; } break; /* 2-4 BVS REL */
821 case 0x71: { CYCLES(5); RD_IDY_P; ADC; } break; /* 5 ADC IDY page penalty */
822 case 0x72: { CYCLES(1); KIL; } break; /* 1 KIL */
823 case 0x73: { CYCLES(7); RD_IDY_NP; RD_EA; RRA; WB_EA; } break; /* 7 RRA IDY */
824 case 0x74: { CYCLES(4); RD_ZPX; NOP; } break; /* 4 NOP ZPX */
825 case 0x75: { CYCLES(4); RD_ZPX; ADC; } break; /* 4 ADC ZPX */
826 case 0x76: { CYCLES(6); RD_ZPX; RD_EA; ROR; WB_EA; } break; /* 6 ROR ZPX */
827 case 0x77: { CYCLES(6); RD_ZPX; RD_EA; RRA; WB_EA; } break; /* 6 RRA ZPX */
828 case 0x78: { CYCLES(2); RD_DUM; SEI; } break; /* 2 SEI */
829 case 0x79: { CYCLES(4); RD_ABY_P; ADC; } break; /* 4 ADC ABY page penalty */
830 case 0x7a: { CYCLES(2); RD_DUM; NOP; } break; /* 2 NOP */
831 case 0x7b: { CYCLES(7); RD_ABY_NP; RD_EA; RRA; WB_EA; } break; /* 7 RRA ABY */
832 case 0x7c: { CYCLES(4); RD_ABX_P; NOP; } break; /* 4 NOP ABX page penalty */
833 case 0x7d: { CYCLES(4); RD_ABX_P; ADC; } break; /* 4 ADC ABX page penalty */
834 case 0x7e: { CYCLES(7); RD_ABX_NP; RD_EA; ROR; WB_EA; } break; /* 7 ROR ABX */
835 case 0x7f: { CYCLES(7); RD_ABX_NP; RD_EA; RRA; WB_EA; } break; /* 7 RRA ABX */
836 case 0x80: { CYCLES(2); RD_IMM; NOP; } break; /* 2 NOP IMM */
837 case 0x81: { CYCLES(6); STA; WR_IDX; } break; /* 6 STA IDX */
838 case 0x82: { CYCLES(2); RD_IMM; NOP; } break; /* 2 NOP IMM */
839 case 0x83: { CYCLES(6); SAX; WR_IDX; } break; /* 6 SAX IDX */
840 case 0x84: { CYCLES(3); STY; WR_ZPG; } break; /* 3 STY ZPG */
841 case 0x85: { CYCLES(3); STA; WR_ZPG; } break; /* 3 STA ZPG */
842 case 0x86: { CYCLES(3); STX; WR_ZPG; } break; /* 3 STX ZPG */
843 case 0x87: { CYCLES(3); SAX; WR_ZPG; } break; /* 3 SAX ZPG */
844 case 0x88: { CYCLES(2); RD_DUM; DEY; } break; /* 2 DEY */
845 case 0x89: { CYCLES(2); RD_IMM; NOP; } break; /* 2 NOP IMM */
846 case 0x8a: { CYCLES(2); RD_DUM; TXA; } break; /* 2 TXA */
847 case 0x8b: { CYCLES(2); RD_IMM; AXA; } break; /* 2 AXA IMM */
848 case 0x8c: { CYCLES(4); STY; WR_ABS; } break; /* 4 STY ABS */
849 case 0x8d: { CYCLES(4); STA; WR_ABS; } break; /* 4 STA ABS */
850 case 0x8e: { CYCLES(4); STX; WR_ABS; } break; /* 4 STX ABS */
851 case 0x8f: { CYCLES(4); SAX; WR_ABS; } break; /* 4 SAX ABS */
852 case 0x90: { CYCLES(2); BCC; } break; /* 2-4 BCC REL */
853 case 0x91: { CYCLES(6); STA; WR_IDY_NP; } break; /* 6 STA IDY */
854 case 0x92: { CYCLES(1); KIL; } break; /* 1 KIL */
855 case 0x93: { CYCLES(5); EA_IDY_NP; SAH; WB_EA; } break; /* 5 SAH IDY */
856 case 0x94: { CYCLES(4); STY; WR_ZPX; } break; /* 4 STY ZPX */
857 case 0x95: { CYCLES(4); STA; WR_ZPX; } break; /* 4 STA ZPX */
858 case 0x96: { CYCLES(4); STX; WR_ZPY; } break; /* 4 STX ZPY */
859 case 0x97: { CYCLES(4); SAX; WR_ZPY; } break; /* 4 SAX ZPY */
860 case 0x98: { CYCLES(2); RD_DUM; TYA; } break; /* 2 TYA */
861 case 0x99: { CYCLES(5); STA; WR_ABY_NP; } break; /* 5 STA ABY */
862 case 0x9a: { CYCLES(2); RD_DUM; TXS; } break; /* 2 TXS */
863 case 0x9b: { CYCLES(5); EA_ABY_NP; SSH; WB_EA; } break; /* 5 SSH ABY */
864 case 0x9c: { CYCLES(5); EA_ABX_NP; SYH; WB_EA; } break; /* 5 SYH ABX */
865 case 0x9d: { CYCLES(5); STA; WR_ABX_NP; } break; /* 5 STA ABX */
866 case 0x9e: { CYCLES(5); EA_ABY_NP; SXH; WB_EA; } break; /* 5 SXH ABY */
867 case 0x9f: { CYCLES(5); EA_ABY_NP; SAH; WB_EA; } break; /* 5 SAH ABY */
868 case 0xa0: { CYCLES(2); RD_IMM; LDY; } break; /* 2 LDY IMM */
869 case 0xa1: { CYCLES(6); RD_IDX; LDA; } break; /* 6 LDA IDX */
870 case 0xa2: { CYCLES(2); RD_IMM; LDX; } break; /* 2 LDX IMM */
871 case 0xa3: { CYCLES(6); RD_IDX; LAX; } break; /* 6 LAX IDX */
872 case 0xa4: { CYCLES(3); RD_ZPG; LDY; } break; /* 3 LDY ZPG */
873 case 0xa5: { CYCLES(3); RD_ZPG; LDA; } break; /* 3 LDA ZPG */
874 case 0xa6: { CYCLES(3); RD_ZPG; LDX; } break; /* 3 LDX ZPG */
875 case 0xa7: { CYCLES(3); RD_ZPG; LAX; } break; /* 3 LAX ZPG */
876 case 0xa8: { CYCLES(2); RD_DUM; TAY; } break; /* 2 TAY */
877 case 0xa9: { CYCLES(2); RD_IMM; LDA; } break; /* 2 LDA IMM */
878 case 0xaa: { CYCLES(2); RD_DUM; TAX; } break; /* 2 TAX */
879 case 0xab: { CYCLES(2); RD_IMM; OAL; } break; /* 2 OAL IMM */
880 case 0xac: { CYCLES(4); RD_ABS; LDY; } break; /* 4 LDY ABS */
881 case 0xad: { CYCLES(4); RD_ABS; LDA; } break; /* 4 LDA ABS */
882 case 0xae: { CYCLES(4); RD_ABS; LDX; } break; /* 4 LDX ABS */
883 case 0xaf: { CYCLES(4); RD_ABS; LAX; } break; /* 4 LAX ABS */
884 case 0xb0: { CYCLES(2); BCS; } break; /* 2-4 BCS REL */
885 case 0xb1: { CYCLES(5); RD_IDY_P; LDA; } break; /* 5 LDA IDY page penalty */
886 case 0xb2: { CYCLES(1); KIL; } break; /* 1 KIL */
887 case 0xb3: { CYCLES(5); RD_IDY_P; LAX; } break; /* 5 LAX IDY page penalty */
888 case 0xb4: { CYCLES(4); RD_ZPX; LDY; } break; /* 4 LDY ZPX */
889 case 0xb5: { CYCLES(4); RD_ZPX; LDA; } break; /* 4 LDA ZPX */
890 case 0xb6: { CYCLES(4); RD_ZPY; LDX; } break; /* 4 LDX ZPY */
891 case 0xb7: { CYCLES(4); RD_ZPY; LAX; } break; /* 4 LAX ZPY */
892 case 0xb8: { CYCLES(2); RD_DUM; CLV; } break; /* 2 CLV */
893 case 0xb9: { CYCLES(4); RD_ABY_P; LDA; } break; /* 4 LDA ABY page penalty */
894 case 0xba: { CYCLES(2); RD_DUM; TSX; } break; /* 2 TSX */
895 case 0xbb: { CYCLES(4); RD_ABY_P; AST; } break; /* 4 AST ABY page penalty */
896 case 0xbc: { CYCLES(4); RD_ABX_P; LDY; } break; /* 4 LDY ABX page penalty */
897 case 0xbd: { CYCLES(4); RD_ABX_P; LDA; } break; /* 4 LDA ABX page penalty */
898 case 0xbe: { CYCLES(4); RD_ABY_P; LDX; } break; /* 4 LDX ABY page penalty */
899 case 0xbf: { CYCLES(4); RD_ABY_P; LAX; } break; /* 4 LAX ABY page penalty */
900 case 0xc0: { CYCLES(2); RD_IMM; CPY; } break; /* 2 CPY IMM */
901 case 0xc1: { CYCLES(6); RD_IDX; CMP; } break; /* 6 CMP IDX */
902 case 0xc2: { CYCLES(2); RD_IMM; NOP; } break; /* 2 NOP IMM */
903 case 0xc3: { CYCLES(7); RD_IDX; RD_EA; DCP; WB_EA; } break; /* 7 DCP IDX */
904 case 0xc4: { CYCLES(3); RD_ZPG; CPY; } break; /* 3 CPY ZPG */
905 case 0xc5: { CYCLES(3); RD_ZPG; CMP; } break; /* 3 CMP ZPG */
906 case 0xc6: { CYCLES(5); RD_ZPG; RD_EA; DEC; WB_EA; } break; /* 5 DEC ZPG */
907 case 0xc7: { CYCLES(5); RD_ZPG; RD_EA; DCP; WB_EA; } break; /* 5 DCP ZPG */
908 case 0xc8: { CYCLES(2); RD_DUM; INY; } break; /* 2 INY */
909 case 0xc9: { CYCLES(2); RD_IMM; CMP; } break; /* 2 CMP IMM */
910 case 0xca: { CYCLES(2); RD_DUM; DEX; } break; /* 2 DEX */
911 case 0xcb: { CYCLES(2); RD_IMM; ASX; } break; /* 2 ASX IMM */
912 case 0xcc: { CYCLES(4); RD_ABS; CPY; } break; /* 4 CPY ABS */
913 case 0xcd: { CYCLES(4); RD_ABS; CMP; } break; /* 4 CMP ABS */
914 case 0xce: { CYCLES(6); RD_ABS; RD_EA; DEC; WB_EA; } break; /* 6 DEC ABS */
915 case 0xcf: { CYCLES(6); RD_ABS; RD_EA; DCP; WB_EA; } break; /* 6 DCP ABS */
916 case 0xd0: { CYCLES(2); BNE; } break; /* 2-4 BNE REL */
917 case 0xd1: { CYCLES(5); RD_IDY_P; CMP; } break; /* 5 CMP IDY page penalty */
918 case 0xd2: { CYCLES(1); KIL; } break; /* 1 KIL */
919 case 0xd3: { CYCLES(7); RD_IDY_NP; RD_EA; DCP; WB_EA; } break; /* 7 DCP IDY */
920 case 0xd4: { CYCLES(4); RD_ZPX; NOP; } break; /* 4 NOP ZPX */
921 case 0xd5: { CYCLES(4); RD_ZPX; CMP; } break; /* 4 CMP ZPX */
922 case 0xd6: { CYCLES(6); RD_ZPX; RD_EA; DEC; WB_EA; } break; /* 6 DEC ZPX */
923 case 0xd7: { CYCLES(6); RD_ZPX; RD_EA; DCP; WB_EA; } break; /* 6 DCP ZPX */
924 case 0xd8: { CYCLES(2); RD_DUM; CLD; } break; /* 2 CLD */
925 case 0xd9: { CYCLES(4); RD_ABY_P; CMP; } break; /* 4 CMP ABY page penalty */
926 case 0xda: { CYCLES(2); RD_DUM; NOP; } break; /* 2 NOP */
927 case 0xdb: { CYCLES(7); RD_ABY_NP; RD_EA; DCP; WB_EA; } break; /* 7 DCP ABY */
928 case 0xdc: { CYCLES(4); RD_ABX_P; NOP; } break; /* 4 NOP ABX page penalty */
929 case 0xdd: { CYCLES(4); RD_ABX_P; CMP; } break; /* 4 CMP ABX page penalty */
930 case 0xde: { CYCLES(7); RD_ABX_NP; RD_EA; DEC; WB_EA; } break; /* 7 DEC ABX */
931 case 0xdf: { CYCLES(7); RD_ABX_NP; RD_EA; DCP; WB_EA; } break; /* 7 DCP ABX */
932 case 0xe0: { CYCLES(2); RD_IMM; CPX; } break; /* 2 CPX IMM */
933 case 0xe1: { CYCLES(6); RD_IDX; SBC; } break; /* 6 SBC IDX */
934 case 0xe2: { CYCLES(2); RD_IMM; NOP; } break; /* 2 NOP IMM */
935 case 0xe3: { CYCLES(7); RD_IDX; RD_EA; ISB; WB_EA; } break; /* 7 ISB IDX */
936 case 0xe4: { CYCLES(3); RD_ZPG; CPX; } break; /* 3 CPX ZPG */
937 case 0xe5: { CYCLES(3); RD_ZPG; SBC; } break; /* 3 SBC ZPG */
938 case 0xe6: { CYCLES(5); RD_ZPG; RD_EA; INC; WB_EA; } break; /* 5 INC ZPG */
939 case 0xe7: { CYCLES(5); RD_ZPG; RD_EA; ISB; WB_EA; } break; /* 5 ISB ZPG */
940 case 0xe8: { CYCLES(2); RD_DUM; INX; } break; /* 2 INX */
941 case 0xe9: { CYCLES(2); RD_IMM; SBC; } break; /* 2 SBC IMM */
942 case 0xea: { CYCLES(2); RD_DUM; NOP; } break; /* 2 NOP */
943 case 0xeb: { CYCLES(2); RD_IMM; SBC; } break; /* 2 SBC IMM */
944 case 0xec: { CYCLES(4); RD_ABS; CPX; } break; /* 4 CPX ABS */
945 case 0xed: { CYCLES(4); RD_ABS; SBC; } break; /* 4 SBC ABS */
946 case 0xee: { CYCLES(6); RD_ABS; RD_EA; INC; WB_EA; } break; /* 6 INC ABS */
947 case 0xef: { CYCLES(6); RD_ABS; RD_EA; ISB; WB_EA; } break; /* 6 ISB ABS */
948 case 0xf0: { CYCLES(2); BEQ; } break; /* 2-4 BEQ REL */
949 case 0xf1: { CYCLES(5); RD_IDY_P; SBC; } break; /* 5 SBC IDY page penalty */
950 case 0xf2: { CYCLES(1); KIL; } break; /* 1 KIL */
951 case 0xf3: { CYCLES(7); RD_IDY_NP; RD_EA; ISB; WB_EA; } break; /* 7 ISB IDY */
952 case 0xf4: { CYCLES(4); RD_ZPX; NOP; } break; /* 4 NOP ZPX */
953 case 0xf5: { CYCLES(4); RD_ZPX; SBC; } break; /* 4 SBC ZPX */
954 case 0xf6: { CYCLES(6); RD_ZPX; RD_EA; INC; WB_EA; } break; /* 6 INC ZPX */
955 case 0xf7: { CYCLES(6); RD_ZPX; RD_EA; ISB; WB_EA; } break; /* 6 ISB ZPX */
956 case 0xf8: { CYCLES(2); RD_DUM; SED; } break; /* 2 SED */
957 case 0xf9: { CYCLES(4); RD_ABY_P; SBC; } break; /* 4 SBC ABY page penalty */
958 case 0xfa: { CYCLES(2); RD_DUM; NOP; } break; /* 2 NOP */
959 case 0xfb: { CYCLES(7); RD_ABY_NP; RD_EA; ISB; WB_EA; } break; /* 7 ISB ABY */
960 case 0xfc: { CYCLES(4); RD_ABX_P; NOP; } break; /* 4 NOP ABX page penalty */
961 case 0xfd: { CYCLES(4); RD_ABX_P; SBC; } break; /* 4 SBC ABX page penalty */
962 case 0xfe: { CYCLES(7); RD_ABX_NP; RD_EA; INC; WB_EA; } break; /* 7 INC ABX */
963 case 0xff: { CYCLES(7); RD_ABX_NP; RD_EA; ISB; WB_EA; } break; /* 7 ISB ABX */
964 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
965 default: __assume(0);
970 inline void M6502::update_irq()
980 PCH = RDMEM(EAD + 1);
981 // call back the cpuintrf to let it clear the line
982 d_pic->notify_intr_reti();
990 void M6502::initialize()
993 SPD = EAD = ZPD = PCD = 0;
995 d_mem_stored = d_mem;
996 d_debugger->set_context_mem(d_mem);
1002 PCL = RDMEM(RST_VEC);
1003 PCH = RDMEM(RST_VEC + 1);
1005 P = F_T | F_I | F_Z | F_B | (P & F_D);
1008 pending_irq = after_cli = false;
1009 irq_state = nmi_state = so_state = false;
1012 int M6502::run(int clock)
1019 // run only one opcode
1022 bool now_debugging = d_debugger->now_debugging;
1024 d_debugger->check_break_points(PCW);
1025 if(d_debugger->now_suspended) {
1027 while(d_debugger->now_debugging && d_debugger->now_suspended) {
1031 if(d_debugger->now_debugging) {
1034 now_debugging = false;
1040 if(!d_debugger->now_going) {
1041 d_debugger->now_suspended = true;
1043 d_mem = d_mem_stored;
1055 int first_icount = icount;
1057 // run cpu while given clocks
1058 while(icount > 0 && !busreq) {
1060 bool now_debugging = d_debugger->now_debugging;
1062 d_debugger->check_break_points(PCW);
1063 if(d_debugger->now_suspended) {
1065 while(d_debugger->now_debugging && d_debugger->now_suspended) {
1069 if(d_debugger->now_debugging) {
1072 now_debugging = false;
1078 if(!d_debugger->now_going) {
1079 d_debugger->now_suspended = true;
1081 d_mem = d_mem_stored;
1090 // if busreq is raised, spin cpu while remained clock
1091 if(icount > 0 && busreq) {
1094 return first_icount - icount;
1098 void M6502::run_one_opecode()
1100 // if an irq is pending, take it now
1107 P |= F_I; // set I flag
1109 PCH = RDMEM(EAD + 1);
1111 } else if(pending_irq) {
1115 uint8_t code = RDOP();
1118 // check if the I flag was just reset (interrupts enabled)
1124 } else if(pending_irq) {
1129 void M6502::write_signal(int id, uint32_t data, uint32_t mask)
1131 bool state = ((data & mask) != 0);
1133 if(id == SIG_CPU_NMI) {
1135 } else if(id == SIG_CPU_IRQ) {
1140 } else if(id == SIG_M6502_OVERFLOW) {
1141 if(so_state && !state) {
1145 } else if(id == SIG_CPU_BUSREQ) {
1146 busreq = ((data & mask) != 0);
1151 void M6502::write_debug_data8(uint32_t addr, uint32_t data)
1154 d_mem_stored->write_data8w(addr, data, &wait);
1157 uint32_t M6502::read_debug_data8(uint32_t addr)
1160 return d_mem_stored->read_data8w(addr, &wait);
1163 bool M6502::write_debug_reg(const _TCHAR *reg, uint32_t data)
1165 if(_tcsicmp(reg, _T("PC")) == 0) {
1167 } else if(_tcsicmp(reg, _T("A")) == 0) {
1169 } else if(_tcsicmp(reg, _T("X")) == 0) {
1171 } else if(_tcsicmp(reg, _T("Y")) == 0) {
1173 } else if(_tcsicmp(reg, _T("S")) == 0) {
1175 } else if(_tcsicmp(reg, _T("P")) == 0) {
1183 void M6502::get_debug_regs_info(_TCHAR *buffer, size_t buffer_len)
1185 my_stprintf_s(buffer, buffer_len,
1186 _T("PC = %04X A = %02X X = %02X Y = %02X S = %02X P = %02X [%c%c%c%c%c%c%c%c]"),
1188 (P & F_N) ? _T('N') : _T('-'), (P & F_V) ? _T('V') : _T('-'), (P & F_T) ? _T('T') : _T('-'), (P & F_B) ? _T('B') : _T('-'),
1189 (P & F_D) ? _T('D') : _T('-'), (P & F_I) ? _T('I') : _T('-'), (P & F_Z) ? _T('Z') : _T('-'), (P & F_C) ? _T('C') : _T('-'));
1194 #define offs_t UINT16
1196 /*****************************************************************************/
1197 /* src/emu/devcpu.h */
1199 // CPU interface functions
1200 #define CPU_DISASSEMBLE_NAME(name) cpu_disassemble_##name
1201 #define CPU_DISASSEMBLE(name) int CPU_DISASSEMBLE_NAME(name)(_TCHAR *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, symbol_t *first_symbol)
1202 #define CPU_DISASSEMBLE_CALL(name) CPU_DISASSEMBLE_NAME(name)(buffer, pc, oprom, oprom, d_debugger->first_symbol)
1204 /*****************************************************************************/
1205 /* src/emu/didisasm.h */
1207 // Disassembler constants
1208 const UINT32 DASMFLAG_SUPPORTED = 0x80000000; // are disassembly flags supported?
1209 const UINT32 DASMFLAG_STEP_OUT = 0x40000000; // this instruction should be the end of a step out sequence
1210 const UINT32 DASMFLAG_STEP_OVER = 0x20000000; // this instruction should be stepped over by setting a breakpoint afterwards
1211 const UINT32 DASMFLAG_OVERINSTMASK = 0x18000000; // number of extra instructions to skip when stepping over
1212 const UINT32 DASMFLAG_OVERINSTSHIFT = 27; // bits to shift after masking to get the value
1213 const UINT32 DASMFLAG_LENGTHMASK = 0x0000ffff; // the low 16-bits contain the actual length
1215 #include "mame/emu/cpu/m6502/6502dasm.c"
1217 int M6502::debug_dasm(uint32_t pc, _TCHAR *buffer, size_t buffer_len)
1220 uint8_t *opram = oprom;
1222 for(int i = 0; i < 4; i++) {
1224 oprom[i] = d_mem->read_data8w(pc + i, &wait);
1226 return CPU_DISASSEMBLE_CALL(m6502) & DASMFLAG_LENGTHMASK;
1230 #define STATE_VERSION 1
1232 void M6502::save_state(FILEIO* state_fio)
1234 state_fio->FputUint32(STATE_VERSION);
1235 state_fio->FputInt32(this_device_id);
1237 state_fio->FputUint32(pc.d);
1238 state_fio->FputUint32(sp.d);
1239 state_fio->FputUint32(zp.d);
1240 state_fio->FputUint32(ea.d);
1241 state_fio->FputUint16(prev_pc);
1242 state_fio->FputUint8(a);
1243 state_fio->FputUint8(x);
1244 state_fio->FputUint8(y);
1245 state_fio->FputUint8(p);
1246 state_fio->FputBool(pending_irq);
1247 state_fio->FputBool(after_cli);
1248 state_fio->FputBool(nmi_state);
1249 state_fio->FputBool(irq_state);
1250 state_fio->FputBool(so_state);
1251 state_fio->FputInt32(icount);
1252 state_fio->FputBool(busreq);
1255 bool M6502::load_state(FILEIO* state_fio)
1257 if(state_fio->FgetUint32() != STATE_VERSION) {
1260 if(state_fio->FgetInt32() != this_device_id) {
1263 pc.d = state_fio->FgetUint32();
1264 sp.d = state_fio->FgetUint32();
1265 zp.d = state_fio->FgetUint32();
1266 ea.d = state_fio->FgetUint32();
1267 prev_pc = state_fio->FgetUint16();
1268 a = state_fio->FgetUint8();
1269 x = state_fio->FgetUint8();
1270 y = state_fio->FgetUint8();
1271 p = state_fio->FgetUint8();
1272 pending_irq = state_fio->FgetBool();
1273 after_cli = state_fio->FgetBool();
1274 nmi_state = state_fio->FgetBool();
1275 irq_state = state_fio->FgetBool();
1276 so_state = state_fio->FgetBool();
1277 icount = state_fio->FgetInt32();
1278 busreq = state_fio->FgetBool();